@chelone/core 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller/calendar-events.js +5 -8
- package/dist/controller/client-list-controller.js +4 -13
- package/dist/controller/record-tree.js +2 -5
- package/dist/controller/record-workflow.d.ts +27 -11
- package/dist/controller/record-workflow.js +5 -1
- package/dist/data/cache-ops.d.ts +8 -0
- package/dist/data/cache-ops.js +80 -0
- package/dist/data/mutation-options.d.ts +5 -1
- package/dist/data/mutation-options.js +33 -3
- package/dist/form/array-binding.d.ts +4 -3
- package/dist/form/input-binding.d.ts +6 -4
- package/dist/form/source.d.ts +22 -4
- package/dist/form/source.js +32 -2
- package/dist/i18n/english-messages.d.ts +250 -0
- package/dist/i18n/english-messages.js +193 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/resource/get-at-path.d.ts +18 -0
- package/dist/resource/get-at-path.js +16 -0
- package/dist/resource/register.d.ts +26 -0
- package/dist/resource/registry.d.ts +16 -1
- package/dist/resource/source-path.d.ts +114 -0
- package/package.json +4 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Get, Paths } from "dot.paths";
|
|
2
|
+
import type { LooseRecord } from "./record.js";
|
|
3
|
+
import type { RegisteredResources } from "./register.js";
|
|
4
|
+
import type { RecordOf, ResourceMap } from "./registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Source-path types for a registered resource's record.
|
|
7
|
+
*
|
|
8
|
+
* Every path prop in Chelone is composed at runtime (`source.ts`,
|
|
9
|
+
* `input-binding.ts`); these types say which paths are legal for a given
|
|
10
|
+
* record, so `<TextInput source="titel" />` stops compiling once an app
|
|
11
|
+
* registers its resources. They are built on `dot.paths`' `Paths` and `Get`,
|
|
12
|
+
* and accept the bracket grammar only (`tags[0].label`) — the syntax
|
|
13
|
+
* `composeSource` and form-core's `DeepKeys` use. A dot index
|
|
14
|
+
* (`tags.0.label`) still works at runtime but is not a legal prop type.
|
|
15
|
+
*/
|
|
16
|
+
/** Object levels walked while looking for arrays in a record. */
|
|
17
|
+
type _WalkDepth = 8;
|
|
18
|
+
/** How deep `RowSourcePath` follows nested arrays. */
|
|
19
|
+
type _MaxArrayNesting = 3;
|
|
20
|
+
/** Decrement tables for the two counters above (`_Prev[N]` is `N - 1`). */
|
|
21
|
+
type _PrevWalk = [never, 0, 1, 2, 3, 4, 5, 6, 7];
|
|
22
|
+
type _PrevNesting = [never, 0, 1, 2];
|
|
23
|
+
/**
|
|
24
|
+
* The item type of every array reachable in `T`. Object members are walked up
|
|
25
|
+
* to `_WalkDepth` levels; array nesting up to `_MaxArrayNesting`, so a
|
|
26
|
+
* recursive record type terminates and the resulting path union stays small.
|
|
27
|
+
*
|
|
28
|
+
* The union is walked one member at a time (`T extends unknown` distributes,
|
|
29
|
+
* and object members are walked per key) because `any` absorbs a union: walked
|
|
30
|
+
* as one type, a single `any`-typed field would turn every array in the record
|
|
31
|
+
* into `any`.
|
|
32
|
+
*/
|
|
33
|
+
type _ArrayItems<T, Walk extends number, Nesting extends number> = [
|
|
34
|
+
Walk
|
|
35
|
+
] extends [0] ? never : [Nesting] extends [0] ? never : T extends unknown ? _ItemsOf<T, Walk, Nesting> : never;
|
|
36
|
+
type _ItemsOf<T, Walk extends number, Nesting extends number> = 0 extends 1 & T ? never : T extends readonly unknown[] ? T extends readonly [] ? never : _Row<NonNullable<T[number]>> | _ArrayItems<NonNullable<T[number]>, _PrevWalk[Walk], _PrevNesting[Nesting]> : T extends object ? {
|
|
37
|
+
[K in keyof T]: _ArrayItems<T[K], _PrevWalk[Walk], Nesting>;
|
|
38
|
+
}[keyof T] : never;
|
|
39
|
+
/**
|
|
40
|
+
* The item type of an array, minus `any` (it names no key set) and minus any
|
|
41
|
+
* member that is itself an array: a row that is an array has no named path
|
|
42
|
+
* under it, and `Paths` of it is a wall of `[${number}]` patterns.
|
|
43
|
+
*/
|
|
44
|
+
type _Row<T> = Exclude<0 extends 1 & T ? never : T, readonly unknown[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Every legal `source` path into `TRecord`: dotted object paths and bracket
|
|
47
|
+
* array indices (`items[0].sku`).
|
|
48
|
+
*
|
|
49
|
+
* The `unknown` guard is load-bearing: `Paths<unknown>` is `never`, which would
|
|
50
|
+
* reject every source of a resource with no schema, while
|
|
51
|
+
* `Paths<LooseRecord, { arrays: "bracket" }>` is `string`.
|
|
52
|
+
*/
|
|
53
|
+
export type SourcePath<TRecord> = unknown extends TRecord ? string : Paths<TRecord, {
|
|
54
|
+
arrays: "bracket";
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* The value type at `TPath`, including the `null`/`undefined` of every parent
|
|
58
|
+
* along it — what reading `record.author?.name` gives. `unknown` for a loose
|
|
59
|
+
* record.
|
|
60
|
+
*/
|
|
61
|
+
export type SourceValue<TRecord, TPath extends string> = unknown extends TRecord ? unknown : Get<TRecord, TPath, {
|
|
62
|
+
nullish: "path";
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* The top-level keys of `TRecord`, for props that read or write one flat key
|
|
66
|
+
* (a filter's field, a reference's target). `string` for a loose record.
|
|
67
|
+
*/
|
|
68
|
+
export type SourceKey<TRecord> = unknown extends TRecord ? string : keyof TRecord & string;
|
|
69
|
+
/**
|
|
70
|
+
* The paths *relative to an array item* of every array in `TRecord`: `sku` is
|
|
71
|
+
* one for a record with `items: { sku: string }[]`.
|
|
72
|
+
*
|
|
73
|
+
* Children of an `ArrayInput` bind a path relative to their row
|
|
74
|
+
* (`createRowSourceScope`), so a root-only path type would reject every
|
|
75
|
+
* iterator child.
|
|
76
|
+
*
|
|
77
|
+
* A row whose type names no keys contributes nothing, and it is filtered per
|
|
78
|
+
* member so it cannot poison the rest: a `z.record` column, a jsonb `Json`
|
|
79
|
+
* member and a `z.any()` field all give `Paths` = `string`, and one `string`
|
|
80
|
+
* here would swallow every other array's paths and let every typo through
|
|
81
|
+
* again. A record that wants its jsonb rows checked gives them a schema.
|
|
82
|
+
*/
|
|
83
|
+
export type RowSourcePath<TRecord> = unknown extends TRecord ? string : string extends keyof TRecord ? string : _ArrayItems<TRecord, _WalkDepth, _MaxArrayNesting> extends infer TItem ? TItem extends unknown ? Paths<TItem, {
|
|
84
|
+
arrays: "bracket";
|
|
85
|
+
}> extends infer TPath extends string ? string extends TPath ? never : TPath : never : never : never;
|
|
86
|
+
/**
|
|
87
|
+
* A filter key: the free-text `q`, or a source path with an operator suffix —
|
|
88
|
+
* the keys Chelone writes itself (`calendarRangeFilter` builds
|
|
89
|
+
* `` `${startSource}_gte` ``) and a filter input's `source` is named with.
|
|
90
|
+
*/
|
|
91
|
+
export type FilterSourceKey<TRecord> = "q" | `${SourcePath<TRecord>}_${string}`;
|
|
92
|
+
/** The source props one record accepts: its paths, its row paths, its filter keys. */
|
|
93
|
+
type _RecordSourcePath<TRecord> = SourcePath<TRecord> | RowSourcePath<TRecord> | FilterSourceKey<TRecord>;
|
|
94
|
+
/**
|
|
95
|
+
* The union of every registered resource's source paths.
|
|
96
|
+
*
|
|
97
|
+
* `string` when the name set is `string` — the unregistered case, and the one
|
|
98
|
+
* that keeps `AnySourcePath` from recursing on itself through
|
|
99
|
+
* {@link SourceProp} — and `string` when any resource has no schema.
|
|
100
|
+
*/
|
|
101
|
+
export type AnySourcePathOf<TResources extends ResourceMap> = string extends keyof TResources ? string : {
|
|
102
|
+
[TName in keyof TResources & string]: _RecordSourcePath<RecordOf<TResources, TName>>;
|
|
103
|
+
}[keyof TResources & string];
|
|
104
|
+
/** {@link AnySourcePathOf} over the app's registered resources. */
|
|
105
|
+
export type AnySourcePath = AnySourcePathOf<RegisteredResources>;
|
|
106
|
+
/**
|
|
107
|
+
* The type a `source` prop takes.
|
|
108
|
+
*
|
|
109
|
+
* A loose record (the default, and every app that registers nothing) gets
|
|
110
|
+
* {@link AnySourcePath}, which is `string` until `Register` is augmented; a
|
|
111
|
+
* typed record gets its own paths.
|
|
112
|
+
*/
|
|
113
|
+
export type SourceProp<TRecord = LooseRecord> = LooseRecord extends TRecord ? AnySourcePath : _RecordSourcePath<TRecord>;
|
|
114
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chelone/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,6 +43,9 @@
|
|
|
43
43
|
"vitest": "^3.0.0",
|
|
44
44
|
"zod": "^3.25.0"
|
|
45
45
|
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"dot.paths": "^0.2.0"
|
|
48
|
+
},
|
|
46
49
|
"scripts": {
|
|
47
50
|
"build": "vite build && tsc -p tsconfig.build.json && node ../../scripts/dts-extensions.mjs dist",
|
|
48
51
|
"check:pack": "publint --pack pnpm --strict && d=$(mktemp -d) && trap 'rm -rf $d' EXIT && pnpm pack --pack-destination $d && attw $d/*.tgz --profile esm-only",
|