Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
42a7686
🚚 move rules to their own package.
loucyx Jan 29, 2026
15a11af
✨ Add SIGIL to @coven/constants.
loucyx Jan 29, 2026
1d18d14
🏗️ use SIGIL instead of MISSING_VALUE in `@coven/compare`.
loucyx Jan 29, 2026
f091a07
🔥 delete old lint files.
loucyx Jan 29, 2026
1539e85
📝 (SIGIL) update description.
loucyx Mar 25, 2026
370b8d8
🎨 (.zed) format config files.
loucyx Mar 25, 2026
3c48922
♻️ (@coven/memo) full refactor.
loucyx Apr 1, 2026
0db6d66
🔥 (@coven/memo) delete unused files.
loucyx Apr 1, 2026
6441569
🔖 (@coven/memo) version bump.
loucyx Apr 1, 2026
b8f7004
✅ (@coven/compare) update tests local imports.
loucyx Apr 1, 2026
1a80bd4
🔖 (@coven/compare) version bump.
loucyx Apr 1, 2026
c683adb
✅ (@coven/constants) update tests local imports.
loucyx Apr 1, 2026
5f5bbf3
🔖 (@coven/constants) version bump.
loucyx Apr 1, 2026
4738c6c
✅ (@coven/pair) update tests local imports.
loucyx Apr 1, 2026
8db5051
🔖 (@coven/pair) version bump.
loucyx Apr 1, 2026
9069810
🔖 (@coven/rules) version bump.
loucyx Apr 1, 2026
9c1cb58
🏗️ (@coven/cron) use `memoFunction` instead of `memo` from `@coven/me…
loucyx Apr 1, 2026
454f8cb
✅ (@coven/cron) update tests local imports.
loucyx Apr 1, 2026
ebec374
🔖 (@coven/cron) version bump.
loucyx Apr 1, 2026
a1cdf29
🏗️ (@coven/expression) use `memoFunction` instead of `memo` from
loucyx Apr 1, 2026
08bf84e
✅ (@coven/expression) update tests local imports.
loucyx Apr 1, 2026
681a4db
🔖 (@coven/expression) version bump.
loucyx Apr 1, 2026
05520ed
✏️ (@coven/utils) fix typo on `fnv1aReducer` docs.
loucyx Apr 1, 2026
03a753d
🐛 (@coven/predicates) add missing `typeOf`.
loucyx Apr 1, 2026
abadec8
✨ (@coven/types) add new types.
loucyx Apr 1, 2026
49c5a4d
✨ (@coven/utils) add new `stringToUint8Array` util.
loucyx Apr 1, 2026
4e08e78
🚚 (@coven/utils) move constants to their own files.
loucyx Apr 1, 2026
65a7917
🎨 (@simulcast/core) improve types.
loucyx Apr 1, 2026
947cd11
✅ (@simulcast/core) update tests local imports.
loucyx Apr 1, 2026
459d484
🔖 (@simulcast/core) version bump.
loucyx Apr 1, 2026
d2c7625
✅ (@simulcast/preact) update tests local imports.
loucyx Apr 1, 2026
2c925a1
🔖 (@simulcast/preact) version bump.
loucyx Apr 1, 2026
00577eb
✅ (@simulcast/react) update tests local imports.
loucyx Apr 1, 2026
dea568c
🔖 (@simulcast/react) version bump.
loucyx Apr 1, 2026
7ed429c
✅ (@simulcast/vue) update tests local imports.
loucyx Apr 1, 2026
b6192b6
🏗️ (@simulcast/vue) update `useBroadcast` to use
loucyx Apr 1, 2026
abfbb09
🔖 (@simulcast/vue) version bump.
loucyx Apr 1, 2026
40dddef
⬆️ (shared) dependency upgrade.
loucyx Apr 1, 2026
7e71434
✨ (@coven/utils) add `stringify` util.
loucyx Apr 1, 2026
b3eb005
🏗️ (@coven/memo) use new `stringify` util.
loucyx Apr 1, 2026
6f88750
🏷️ (@coven/utils) better types for `createObject`.
loucyx Apr 1, 2026
b1eaa1f
✅ (@coven/compare) cleaner compare test.
loucyx Apr 1, 2026
5f01820
🏷️ (@coven/rules) simplify types for rules.
loucyx Apr 1, 2026
91c2a13
🏷️ (@coven/memo) add missing types in `mapMemo`.
loucyx Apr 1, 2026
30ec9a7
✏️ (@coven/predicates) fix typo in test.
loucyx Apr 1, 2026
e24d0af
✨ (@coven/predicates) add new `isSigil` test.
loucyx Apr 1, 2026
c3330ca
🏗️ (@coven/compare) use new `isSigil` util.
loucyx Apr 1, 2026
f8b8625
✨ (@coven/template) new library!
loucyx Apr 1, 2026
7146857
🎨 (.zed) format files using prettier.
loucyx Apr 1, 2026
3b71fa8
⬆️ (.github) upgrade `codecov/codecov-action`
loucyx Apr 1, 2026
65358b3
📝 (root) update README.md to include new library.
loucyx Apr 1, 2026
902f605
🚨 (@coven/rules) fix linting issues.
loucyx Apr 2, 2026
846ba1a
🚨 (@coven/constants) fix linting issues.
loucyx Apr 2, 2026
ff50bb6
✏️ (@coven/template) fix bad import.
loucyx Apr 2, 2026
76d1cf7
📝 (@coven/rules) add small description for the default export.
loucyx Apr 2, 2026
71f595b
📝 (@coven/rules) add logo and docs.
loucyx Apr 2, 2026
e396f3f
💩 (@coven/pair) introducing ugly hack of types until `deno doc --lint`
loucyx Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
coverage.lcov

- name: Publish Coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
publish:
Expand Down
4 changes: 0 additions & 4 deletions @coven/compare/MISSING_VALUE.ts

This file was deleted.

6 changes: 3 additions & 3 deletions @coven/compare/compareIterables.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SIGIL } from "@coven/constants";
import {
getIterator,
iteratorFunctionToIterableIterator,
Expand All @@ -6,7 +7,6 @@ import {
import { compare } from "./compare.ts";
import type { CurriedComparison } from "./CurriedComparison.ts";
import type { Difference } from "./Difference.ts";
import { MISSING_VALUE } from "./MISSING_VALUE.ts";
import { pathPrepend } from "./pathPrepend.ts";

/**
Expand Down Expand Up @@ -55,8 +55,8 @@ export const compareIterables =
rightIterator.next()
) {
yield* map(pathPrepend(index))(
compare(leftDone ? MISSING_VALUE : leftValue)(
rightDone ? MISSING_VALUE : rightValue,
compare(leftDone ? SIGIL : leftValue)(
rightDone ? SIGIL : rightValue,
),
);
}
Expand Down
6 changes: 3 additions & 3 deletions @coven/compare/compareProperties.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SIGIL } from "@coven/constants";
import {
append,
EMPTY_ITERABLE_ITERATOR,
Expand All @@ -10,7 +11,6 @@ import { compare } from "./compare.ts";
import type { CurriedComparison } from "./CurriedComparison.ts";
import { differentiate } from "./differentiate.ts";
import { getKeys } from "./getKeys.ts";
import { MISSING_VALUE } from "./MISSING_VALUE.ts";
import { pathPrepend } from "./pathPrepend.ts";

/**
Expand Down Expand Up @@ -49,11 +49,11 @@ export const compareProperties = (left: object): CurriedComparison<unknown> => {
compare(
key in left ?
left[key as keyof typeof left]
: MISSING_VALUE,
: SIGIL,
)(
key in right ?
right[key as keyof typeof right]
: MISSING_VALUE,
: SIGIL,
),
),
)(unique(append(getKeys(right))(ownKeysLeft))),
Expand Down
2 changes: 1 addition & 1 deletion @coven/compare/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"$schema": "https://raw.githubusercontent.com/denoland/deno/main/cli/schemas/config-file.v1.json",
"exports": "./mod.ts",
"name": "@coven/compare",
"version": "0.8.5"
"version": "0.9.0"
}
19 changes: 9 additions & 10 deletions @coven/compare/differentiate.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { EMPTY_ITERABLE_ITERATOR, toIterable } from "@coven/iterables";
import { is } from "@coven/predicates";
import { is, isSigil } from "@coven/predicates";
import { CREATE_KIND } from "./CREATE_KIND.ts";
import type { CurriedComparison } from "./CurriedComparison.ts";
import { DELETE_KIND } from "./DELETE_KIND.ts";
import { MISSING_VALUE } from "./MISSING_VALUE.ts";
import { UPDATE_KIND } from "./UPDATE_KIND.ts";

/**
Expand All @@ -17,15 +16,15 @@ import { UPDATE_KIND } from "./UPDATE_KIND.ts";
*
* @example Missing right value
* ```typescript
* import { MISSING_VALUE } from "@coven/compare";
* import { SIGIL } from "@coven/constants";
*
* differentiate("✨")(MISSING_VALUE); // Yields { kind: "DELETE", left: "✨", path: [] }
* differentiate("✨")(SIGIL); // Yields { kind: "DELETE", left: "✨", path: [] }
* ```
* @example Missing left value
* ```typescript
* import { MISSING_VALUE } from "@coven/compare";
* import { SIGIL } from "@coven/constants";
*
* differentiate(MISSING_VALUE)("🎃"); // Yields { kind: "CREATE", right: "🎃", path: [] }
* differentiate(SIGIL)("🎃"); // Yields { kind: "CREATE", right: "🎃", path: [] }
* ```
* @example Both values set
* ```typescript
Expand All @@ -34,9 +33,9 @@ import { UPDATE_KIND } from "./UPDATE_KIND.ts";
* ```
* @example Both values missing
* ```typescript
* import { MISSING_VALUE } from "@coven/compare";
* import { SIGIL } from "@coven/constants";
*
* differentiate(MISSING_VALUE)(MISSING_VALUE); // Yields nothing
* differentiate(SIGIL)(SIGIL); // Yields nothing
* ```
* @param left Left/Original value.
* @returns Curried generator with `left` in context.
Expand All @@ -54,8 +53,8 @@ export const differentiate = (left: unknown): CurriedComparison<unknown> => {
isLeft(right) ?
EMPTY_ITERABLE_ITERATOR
: toIterable({
...(right === MISSING_VALUE ? { left, kind: DELETE_KIND }
: left === MISSING_VALUE ? { kind: CREATE_KIND, right }
...(isSigil(right) ? { left, kind: DELETE_KIND }
: isSigil(left) ? { kind: CREATE_KIND, right }
: { left, kind: UPDATE_KIND, right }),
path: EMPTY_ITERABLE_ITERATOR,
});
Expand Down
1 change: 0 additions & 1 deletion @coven/compare/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export type { FlatDifference } from "./FlatDifference.ts";
export type { FlatPath } from "./FlatPath.ts";
export { flatPathMap } from "./flatPathMap.ts";
export { getKeys } from "./getKeys.ts";
export { MISSING_VALUE } from "./MISSING_VALUE.ts";
export { pathPrepend } from "./pathPrepend.ts";
export { setPath } from "./setPath.ts";
export { UPDATE_KIND } from "./UPDATE_KIND.ts";
Expand Down
90 changes: 23 additions & 67 deletions @coven/compare/tests/compare.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import {
compare,
CREATE_KIND,
DELETE_KIND,
flat,
UPDATE_KIND,
} from "@coven/compare";
import { EMPTY_ARRAY, EMPTY_OBJECT } from "@coven/constants";
import { EMPTY_ITERABLE_ITERATOR } from "@coven/iterables";
import { createObject } from "@coven/utils";
import { assertEquals } from "@std/assert";
import { compare } from "../compare.ts";
import { CREATE_KIND } from "../CREATE_KIND.ts";
import { DELETE_KIND } from "../DELETE_KIND.ts";
import { flat } from "../flat.ts";
import { UPDATE_KIND } from "../UPDATE_KIND.ts";

const property1 = "property1";
const property2 = "property2";
Expand Down Expand Up @@ -191,66 +189,24 @@ Deno.test(

Deno.test(
"Comparing a real array and a fake array yields `DeleteDifference`s",
() =>
assertEquals(
flat(
compare(["coven"])(
createObject({
0: "coven",
constructor: Array,
length: 1,
}),
),
),
(
[
"at",
"concat",
"copyWithin",
"fill",
"find",
"findIndex",
"findLast",
"findLastIndex",
"lastIndexOf",
"pop",
"push",
"reverse",
"shift",
"unshift",
"slice",
"sort",
"splice",
"includes",
"indexOf",
"join",
"keys",
"entries",
"values",
"forEach",
"filter",
"flat",
"flatMap",
"map",
"every",
"some",
"reduce",
"reduceRight",
"toReversed",
"toSorted",
"toSpliced",
"with",
"toLocaleString",
"toString",
Symbol.iterator,
Symbol.unscopables,
] as const
).map((key) => ({
kind: DELETE_KIND,
left: Array.prototype[key],
path: [key],
})) as ReturnType<typeof flat>,
),
() => {
const fakeArray = createObject({
0: "coven",
constructor: Array,
length: 1,
});

return assertEquals(
flat(compare(["coven"])(fakeArray)),
Reflect.ownKeys(Array.prototype)
.filter((key) => !Reflect.ownKeys(fakeArray).includes(key))
.map((key) => ({
kind: DELETE_KIND,
left: Array.prototype[key as keyof typeof Array.prototype],
path: [key],
})) as ReturnType<typeof flat>,
);
},
);

Deno.test("Comparing 0 with -0 should yield `UpdateDifference`", () =>
Expand Down
4 changes: 3 additions & 1 deletion @coven/compare/tests/pathPrepend.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { DELETE_KIND, flat, pathPrepend } from "@coven/compare";
import { assertEquals } from "@std/assert";
import { DELETE_KIND } from "../DELETE_KIND.ts";
import { flat } from "../flat.ts";
import { pathPrepend } from "../pathPrepend.ts";

const prepend13 = pathPrepend(13);

Expand Down
10 changes: 4 additions & 6 deletions @coven/compare/tests/valueToDifference.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { differentiate, flat, MISSING_VALUE } from "@coven/compare";
import { EMPTY_ARRAY } from "@coven/constants";
import { EMPTY_ARRAY, SIGIL } from "@coven/constants";
import { assertEquals } from "@std/assert";
import { differentiate } from "../differentiate.ts";
import { flat } from "../flat.ts";

Deno.test("When both values are missing returns an empty difference", () =>
assertEquals(
flat(differentiate(MISSING_VALUE)(MISSING_VALUE)),
EMPTY_ARRAY,
),
assertEquals(flat(differentiate(SIGIL)(SIGIL)), EMPTY_ARRAY),
);
5 changes: 4 additions & 1 deletion @coven/constants/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ mutations throws.

- `EMPTY_ARRAY`: Empty read-only array.
- `EMPTY_OBJECT`: Empty read-only `null` prototype object.
- `SIGIL`: Internal value to be used as bottom value (like `null` and
`undefined`) when native bottom values have to be used.

## Example

```typescript
import { EMPTY_ARRAY, EMPTY_OBJECT } from "@coven/constants";
import { EMPTY_ARRAY, EMPTY_OBJECT, SIGIL } from "@coven/constants";

console.log(EMPTY_ARRAY); // []
console.log(EMPTY_OBJECT); // {}
console.log(SIGIL); // Symbol("⛧")
```

## Other links
Expand Down
5 changes: 5 additions & 0 deletions @coven/constants/SIGIL.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Internal value to be used as bottom value (like `null` and `undefined`) when
* native bottom values have to be used for something else.
*/
export const SIGIL: unique symbol = Symbol.for("⛧");
2 changes: 1 addition & 1 deletion @coven/constants/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"$schema": "https://raw.githubusercontent.com/denoland/deno/main/cli/schemas/config-file.v1.json",
"exports": "./mod.ts",
"name": "@coven/constants",
"version": "0.8.5"
"version": "0.9.0"
}
1 change: 1 addition & 0 deletions @coven/constants/mod.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { EMPTY_ARRAY } from "./EMPTY_ARRAY.ts";
export { EMPTY_OBJECT } from "./EMPTY_OBJECT.ts";
export { SIGIL } from "./SIGIL.ts";
2 changes: 1 addition & 1 deletion @coven/constants/tests/EMPTY_ARRAY.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EMPTY_ARRAY } from "@coven/constants";
import { assertThrows } from "@std/assert";
import { EMPTY_ARRAY } from "../EMPTY_ARRAY.ts";

Deno.test(
"`Array#pop` should throw",
Expand Down
2 changes: 1 addition & 1 deletion @coven/constants/tests/EMPTY_OBJECT.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EMPTY_OBJECT } from "@coven/constants";
import { assertThrows } from "@std/assert";
import { EMPTY_OBJECT } from "../EMPTY_OBJECT.ts";

Deno.test(
"Trying direct mutations should throw",
Expand Down
11 changes: 6 additions & 5 deletions @coven/cron/compareField.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from "@coven/memo";
import { memoFunction } from "@coven/memo";
import type { AllToken } from "./AllToken.ts";
import type { Field } from "./Field.ts";
import { compareRangeOrValue } from "./compareRangeOrValue.ts";
Expand All @@ -25,8 +25,9 @@ import { isListField } from "./isListField.ts";
export const compareField: (
value: number,
field: Exclude<Field<number>, AllToken>,
) => boolean = memo((value: number, field: Exclude<Field<number>, AllToken>) =>
isListField(field) ?
field.some(compareRangeOrValue(value))
: compareRangeOrValue(value)(field),
) => boolean = memoFunction(
(value: number, field: Exclude<Field<number>, AllToken>) =>
isListField(field) ?
field.some(compareRangeOrValue(value))
: compareRangeOrValue(value)(field),
);
6 changes: 3 additions & 3 deletions @coven/cron/compareRangeOrValue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from "@coven/memo";
import { memoFunction } from "@coven/memo";
import type { ValueOrRangeField } from "./ValueOrRangeField.ts";
import { isRangeField } from "./isRangeField.ts";

Expand All @@ -17,9 +17,9 @@ import { isRangeField } from "./isRangeField.ts";
*/
export const compareRangeOrValue: (
value: number,
) => (valueOrRange: ValueOrRangeField<number>) => boolean = memo(
) => (valueOrRange: ValueOrRangeField<number>) => boolean = memoFunction(
(value: number): ((valueOrRange: ValueOrRangeField<number>) => boolean) =>
memo((valueOrRange) =>
memoFunction((valueOrRange) =>
isRangeField(valueOrRange) ?
value >= valueOrRange.from && value <= valueOrRange.to
: value === valueOrRange,
Expand Down
2 changes: 1 addition & 1 deletion @coven/cron/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"$schema": "https://raw.githubusercontent.com/denoland/deno/main/cli/schemas/config-file.v1.json",
"exports": "./mod.ts",
"name": "@coven/cron",
"version": "0.8.5"
"version": "0.9.0"
}
4 changes: 2 additions & 2 deletions @coven/cron/fieldRegExp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { captureNamed, disjunction, escape } from "@coven/expression";
import { memo } from "@coven/memo";
import { memoFunction } from "@coven/memo";
import { ALL_TOKEN } from "./tokens.ts";
import { valueRangeOrListRegExp } from "./valueRangeOrListRegExp.ts";

Expand All @@ -18,7 +18,7 @@ export const fieldRegExp: <Name extends string, Value extends string>(
name: Name,
value: Value,
) => `(?<${Name}>\\*|(?:${Value}(?:-${Value})?|(?:(?:${Value}(?:-${Value})?,)+${Value}(?:-${Value})?)))` =
memo(
memoFunction(
<Name extends string, Value extends string>(name: Name, value: Value) =>
captureNamed(name)(
disjunction(escape(ALL_TOKEN), valueRangeOrListRegExp(value)),
Expand Down
4 changes: 2 additions & 2 deletions @coven/cron/isListField.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { every } from "@coven/iterables";
import { memo } from "@coven/memo";
import { memoFunction } from "@coven/memo";
import { isArray, isNumber } from "@coven/predicates";
import type { Field } from "./Field.ts";
import { isRangeField } from "./isRangeField.ts";
Expand All @@ -18,7 +18,7 @@ const everyIsNumberOrRangeField = every<
* @see {@linkcode isRangeField}
*/
export const isListField: (value: Field<number>) => value is ListField<number> =
memo(
memoFunction(
(value: Field<number>) =>
isArray(value) && everyIsNumberOrRangeField(value),
);
Loading