@inhuman.tools/plexus-expectations 0.0.0-stage → 0.1.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/LICENSE.md +7 -0
- package/README.md +144 -2
- package/dist/driver/ExpectationActor.d.ts +56 -0
- package/dist/driver/ExpectationActor.d.ts.map +1 -0
- package/dist/driver/ExpectationActor.js +210 -0
- package/dist/driver/ExpectationActor.js.map +1 -0
- package/dist/driver/PEWDriver.d.ts +144 -0
- package/dist/driver/PEWDriver.d.ts.map +1 -0
- package/dist/driver/PEWDriver.js +303 -0
- package/dist/driver/PEWDriver.js.map +1 -0
- package/dist/driver/PEWDriverConnection.d.ts +139 -0
- package/dist/driver/PEWDriverConnection.d.ts.map +1 -0
- package/dist/driver/PEWDriverConnection.js +298 -0
- package/dist/driver/PEWDriverConnection.js.map +1 -0
- package/dist/driver/actor-machine.d.ts +28 -0
- package/dist/driver/actor-machine.d.ts.map +1 -0
- package/dist/driver/actor-machine.js +50 -0
- package/dist/driver/actor-machine.js.map +1 -0
- package/dist/driver/connection-miss.d.ts +9 -0
- package/dist/driver/connection-miss.d.ts.map +1 -0
- package/dist/driver/connection-miss.js +13 -0
- package/dist/driver/connection-miss.js.map +1 -0
- package/dist/driver/index.d.ts +6 -0
- package/dist/driver/index.d.ts.map +1 -0
- package/dist/driver/index.js +5 -0
- package/dist/driver/index.js.map +1 -0
- package/dist/error-with-invariant.d.ts +9 -0
- package/dist/error-with-invariant.d.ts.map +1 -0
- package/dist/error-with-invariant.js +12 -0
- package/dist/error-with-invariant.js.map +1 -0
- package/dist/executor/index.d.ts +4 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +4 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/kernel-intern.d.ts +16 -0
- package/dist/executor/kernel-intern.d.ts.map +1 -0
- package/dist/executor/kernel-intern.js +98 -0
- package/dist/executor/kernel-intern.js.map +1 -0
- package/dist/executor/orchestrator.d.ts +97 -0
- package/dist/executor/orchestrator.d.ts.map +1 -0
- package/dist/executor/orchestrator.js +465 -0
- package/dist/executor/orchestrator.js.map +1 -0
- package/dist/executor/types.d.ts +8 -0
- package/dist/executor/types.d.ts.map +1 -0
- package/dist/executor/types.js +2 -0
- package/dist/executor/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/connection.d.ts +4 -0
- package/dist/schemas/connection.d.ts.map +1 -0
- package/dist/schemas/connection.js +4 -0
- package/dist/schemas/connection.js.map +1 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/shared/attention.d.ts +27 -0
- package/dist/shared/attention.d.ts.map +1 -0
- package/dist/shared/attention.js +116 -0
- package/dist/shared/attention.js.map +1 -0
- package/dist/shared/control.d.ts +4 -0
- package/dist/shared/control.d.ts.map +1 -0
- package/dist/shared/control.js +2 -0
- package/dist/shared/control.js.map +1 -0
- package/dist/shared/index.d.ts +7 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +7 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/map-field-awareness.d.ts +19 -0
- package/dist/shared/map-field-awareness.d.ts.map +1 -0
- package/dist/shared/map-field-awareness.js +58 -0
- package/dist/shared/map-field-awareness.js.map +1 -0
- package/dist/shared/models/ApprovableExpectation.d.ts +15 -0
- package/dist/shared/models/ApprovableExpectation.d.ts.map +1 -0
- package/dist/shared/models/ApprovableExpectation.js +138 -0
- package/dist/shared/models/ApprovableExpectation.js.map +1 -0
- package/dist/shared/models/ConnectionSpec.d.ts +44 -0
- package/dist/shared/models/ConnectionSpec.d.ts.map +1 -0
- package/dist/shared/models/ConnectionSpec.js +180 -0
- package/dist/shared/models/ConnectionSpec.js.map +1 -0
- package/dist/shared/models/DriverSpec.d.ts +45 -0
- package/dist/shared/models/DriverSpec.d.ts.map +1 -0
- package/dist/shared/models/DriverSpec.js +221 -0
- package/dist/shared/models/DriverSpec.js.map +1 -0
- package/dist/shared/models/IntrospectingPlexusModel.d.ts +8 -0
- package/dist/shared/models/IntrospectingPlexusModel.d.ts.map +1 -0
- package/dist/shared/models/IntrospectingPlexusModel.js +48 -0
- package/dist/shared/models/IntrospectingPlexusModel.js.map +1 -0
- package/dist/shared/models/Job.d.ts +85 -0
- package/dist/shared/models/Job.d.ts.map +1 -0
- package/dist/shared/models/Job.js +261 -0
- package/dist/shared/models/Job.js.map +1 -0
- package/dist/shared/models/ProgrammaticJob.d.ts +6 -0
- package/dist/shared/models/ProgrammaticJob.d.ts.map +1 -0
- package/dist/shared/models/ProgrammaticJob.js +80 -0
- package/dist/shared/models/ProgrammaticJob.js.map +1 -0
- package/dist/shared/models/WorkContainer.d.ts +36 -0
- package/dist/shared/models/WorkContainer.d.ts.map +1 -0
- package/dist/shared/models/WorkContainer.js +140 -0
- package/dist/shared/models/WorkContainer.js.map +1 -0
- package/dist/shared/models/WorkExpectation.d.ts +63 -0
- package/dist/shared/models/WorkExpectation.d.ts.map +1 -0
- package/dist/shared/models/WorkExpectation.js +290 -0
- package/dist/shared/models/WorkExpectation.js.map +1 -0
- package/dist/shared/models/WorkExpectationWithIntrospection.d.ts +4 -0
- package/dist/shared/models/WorkExpectationWithIntrospection.d.ts.map +1 -0
- package/dist/shared/models/WorkExpectationWithIntrospection.js +28 -0
- package/dist/shared/models/WorkExpectationWithIntrospection.js.map +1 -0
- package/dist/shared/models/index.d.ts +7 -0
- package/dist/shared/models/index.d.ts.map +1 -0
- package/dist/shared/models/index.js +6 -0
- package/dist/shared/models/index.js.map +1 -0
- package/dist/shared/models/jsonRecord.d.ts +14 -0
- package/dist/shared/models/jsonRecord.d.ts.map +1 -0
- package/dist/shared/models/jsonRecord.js +46 -0
- package/dist/shared/models/jsonRecord.js.map +1 -0
- package/dist/shared/resolution.d.ts +39 -0
- package/dist/shared/resolution.d.ts.map +1 -0
- package/dist/shared/resolution.js +124 -0
- package/dist/shared/resolution.js.map +1 -0
- package/dist/shared/revalidation-demand.d.ts +27 -0
- package/dist/shared/revalidation-demand.d.ts.map +1 -0
- package/dist/shared/revalidation-demand.js +116 -0
- package/dist/shared/revalidation-demand.js.map +1 -0
- package/dist/shared/role.d.ts +12 -0
- package/dist/shared/role.d.ts.map +1 -0
- package/dist/shared/role.js +21 -0
- package/dist/shared/role.js.map +1 -0
- package/dist/shared/types.d.ts +43 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +12 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +79 -3
- package/src/driver/ExpectationActor.ts +244 -0
- package/src/driver/PEWDriver.ts +302 -0
- package/src/driver/actor-machine.ts +54 -0
- package/src/driver/connection-miss.ts +13 -0
- package/src/driver/index.ts +5 -0
- package/src/executor/index.ts +3 -0
- package/src/executor/kernel-intern.ts +121 -0
- package/src/executor/orchestrator.ts +463 -0
- package/src/executor/types.ts +3 -0
- package/src/index.ts +1 -0
- package/src/schemas/connection.ts +4 -0
- package/src/schemas/index.ts +1 -0
- package/src/shared/control.ts +4 -0
- package/src/shared/index.ts +6 -0
- package/src/shared/map-field-awareness.ts +65 -0
- package/src/shared/models/ConnectionSpec.ts +84 -0
- package/src/shared/models/DriverSpec.ts +102 -0
- package/src/shared/models/Job.ts +192 -0
- package/src/shared/models/WorkContainer.ts +90 -0
- package/src/shared/models/WorkExpectation.ts +229 -0
- package/src/shared/models/index.ts +6 -0
- package/src/shared/models/jsonRecord.ts +49 -0
- package/src/shared/revalidation-demand.ts +121 -0
- package/src/shared/role.ts +32 -0
- package/src/shared/types.ts +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonRecord.d.ts","sourceRoot":"","sources":["../../../src/shared/models/jsonRecord.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AACF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUnF;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,GAClD,IAAI,CAYN;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAQzC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plexus `@syncing.record` bags are `Record<string, string>`. Values round-trip
|
|
3
|
+
* through JSON.stringify; `undefined` is omitted.
|
|
4
|
+
*/
|
|
5
|
+
export function readJsonRecord(map) {
|
|
6
|
+
const out = {};
|
|
7
|
+
for (const [key, raw] of Object.entries(map)) {
|
|
8
|
+
try {
|
|
9
|
+
out[key] = JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
out[key] = raw;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return deepFreeze(out);
|
|
16
|
+
}
|
|
17
|
+
export function writeJsonRecord(map, next) {
|
|
18
|
+
const encoded = {};
|
|
19
|
+
for (const [key, value] of Object.entries(next ?? {})) {
|
|
20
|
+
if (value === undefined)
|
|
21
|
+
continue;
|
|
22
|
+
encoded[key] = JSON.stringify(value);
|
|
23
|
+
}
|
|
24
|
+
for (const key of Object.keys(map)) {
|
|
25
|
+
if (!(key in encoded))
|
|
26
|
+
delete map[key];
|
|
27
|
+
}
|
|
28
|
+
for (const [key, value] of Object.entries(encoded)) {
|
|
29
|
+
if (map[key] !== value)
|
|
30
|
+
map[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function deepFreeze(value) {
|
|
34
|
+
if (value === null || typeof value !== "object" || Object.isFrozen(value))
|
|
35
|
+
return value;
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
for (const item of value)
|
|
38
|
+
deepFreeze(item);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
for (const item of Object.values(value))
|
|
42
|
+
deepFreeze(item);
|
|
43
|
+
}
|
|
44
|
+
return Object.freeze(value);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=jsonRecord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonRecord.js","sourceRoot":"","sources":["../../../src/shared/models/jsonRecord.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,UAAU,cAAc,CAAC,GAA2B;IACxD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,GAA2B,EAC3B,IAAmD;IAEnD,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAI,KAAQ;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["/**\n * Plexus `@syncing.record` bags are `Record<string, string>`. Values round-trip\n * through JSON.stringify; `undefined` is omitted.\n */\n\n/** Process self-report on ConnectionSpec / DriverSpec. JSON through `liveMap`. */\nexport type LiveFacts = {\n readonly [key: string]: unknown | undefined;\n readonly models?: readonly string[];\n readonly tools?: unknown;\n};\nexport function readJsonRecord(map: Record<string, string>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, raw] of Object.entries(map)) {\n try {\n out[key] = JSON.parse(raw);\n } catch {\n out[key] = raw;\n }\n }\n return deepFreeze(out);\n}\n\nexport function writeJsonRecord(\n map: Record<string, string>,\n next: Readonly<Record<string, unknown>> | undefined,\n): void {\n const encoded: Record<string, string> = {};\n for (const [key, value] of Object.entries(next ?? {})) {\n if (value === undefined) continue;\n encoded[key] = JSON.stringify(value);\n }\n for (const key of Object.keys(map)) {\n if (!(key in encoded)) delete map[key];\n }\n for (const [key, value] of Object.entries(encoded)) {\n if (map[key] !== value) map[key] = value;\n }\n}\n\nexport function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== \"object\" || Object.isFrozen(value)) return value;\n if (Array.isArray(value)) {\n for (const item of value) deepFreeze(item);\n } else {\n for (const item of Object.values(value as Record<string, unknown>)) deepFreeze(item);\n }\n return Object.freeze(value);\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution request / answer shapes. Separate from ordinary TProposal steer.
|
|
3
|
+
* Transport lives on dedicated awareness lanes; parse functions drop junk.
|
|
4
|
+
*/
|
|
5
|
+
/** One choosable value. `label` is display; identity is `value`. */
|
|
6
|
+
export type ProposalOption = {
|
|
7
|
+
readonly value: string;
|
|
8
|
+
readonly label?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Actor → world ask. Default path is `description` + `options` + `defaults`.
|
|
12
|
+
* `type` / `body` are optional enrichment — unknown `type` is ignored, not rejected.
|
|
13
|
+
*/
|
|
14
|
+
export type ProposalRequest = {
|
|
15
|
+
readonly type: string;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
readonly body?: unknown;
|
|
18
|
+
readonly options: readonly ProposalOption[];
|
|
19
|
+
readonly defaults?: {
|
|
20
|
+
readonly confirm?: string;
|
|
21
|
+
readonly break?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
/** Published ask — {@link ProposalRequest} plus the request id on the resolution-request lane. */
|
|
25
|
+
export type ResolutionRequest = ProposalRequest & {
|
|
26
|
+
readonly requestId: string;
|
|
27
|
+
};
|
|
28
|
+
/** Author → actor answer on the resolution lane. */
|
|
29
|
+
export type Resolution = {
|
|
30
|
+
readonly requestId: string;
|
|
31
|
+
readonly value: string;
|
|
32
|
+
};
|
|
33
|
+
export declare function parseProposalOption(raw: unknown): ProposalOption | null;
|
|
34
|
+
/** Untrusted awareness field → published ask, or null. */
|
|
35
|
+
export declare function parseResolutionRequest(raw: unknown): ResolutionRequest | null;
|
|
36
|
+
/** Untrusted awareness field → answer, or null. Missing `requestId` is ignored (no front-run). */
|
|
37
|
+
export declare function parseResolution(raw: unknown): Resolution | null;
|
|
38
|
+
export declare function normalizeProposalRequest(request: ProposalRequest): ProposalRequest;
|
|
39
|
+
//# sourceMappingURL=resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../../src/shared/resolution.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oEAAoE;AACpE,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAClB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAEF,kGAAkG;AAClG,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAUvE;AAED,0DAA0D;AAC1D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAuC7E;AAED,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAU/D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,CA8BlF"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution request / answer shapes. Separate from ordinary TProposal steer.
|
|
3
|
+
* Transport lives on dedicated awareness lanes; parse functions drop junk.
|
|
4
|
+
*/
|
|
5
|
+
export function parseProposalOption(raw) {
|
|
6
|
+
let result = null;
|
|
7
|
+
if (raw != null && typeof raw === "object") {
|
|
8
|
+
const value = raw.value;
|
|
9
|
+
if (typeof value === "string" && value !== "") {
|
|
10
|
+
const label = raw.label;
|
|
11
|
+
result = typeof label === "string" && label !== "" ? { value, label } : { value };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
/** Untrusted awareness field → published ask, or null. */
|
|
17
|
+
export function parseResolutionRequest(raw) {
|
|
18
|
+
let result = null;
|
|
19
|
+
if (raw != null && typeof raw === "object") {
|
|
20
|
+
const o = raw;
|
|
21
|
+
if (typeof o.requestId === "string" &&
|
|
22
|
+
o.requestId !== "" &&
|
|
23
|
+
typeof o.type === "string" &&
|
|
24
|
+
typeof o.description === "string" &&
|
|
25
|
+
o.description.trim() !== "" &&
|
|
26
|
+
Array.isArray(o.options) &&
|
|
27
|
+
o.options.length > 0) {
|
|
28
|
+
const options = [];
|
|
29
|
+
const seen = new Set();
|
|
30
|
+
let valid = true;
|
|
31
|
+
for (const item of o.options) {
|
|
32
|
+
const option = parseProposalOption(item);
|
|
33
|
+
if (option === null || seen.has(option.value)) {
|
|
34
|
+
valid = false;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
seen.add(option.value);
|
|
38
|
+
options.push(option);
|
|
39
|
+
}
|
|
40
|
+
const defaults = parseDefaults(o.defaults, seen);
|
|
41
|
+
if (valid && (o.defaults === undefined || defaults !== undefined)) {
|
|
42
|
+
result = {
|
|
43
|
+
requestId: o.requestId,
|
|
44
|
+
type: o.type,
|
|
45
|
+
description: o.description,
|
|
46
|
+
options,
|
|
47
|
+
body: o.body,
|
|
48
|
+
defaults,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
/** Untrusted awareness field → answer, or null. Missing `requestId` is ignored (no front-run). */
|
|
56
|
+
export function parseResolution(raw) {
|
|
57
|
+
let result = null;
|
|
58
|
+
if (raw != null && typeof raw === "object") {
|
|
59
|
+
const value = raw.value;
|
|
60
|
+
const requestId = raw.requestId;
|
|
61
|
+
if (typeof value === "string" && value !== "" && typeof requestId === "string" && requestId !== "") {
|
|
62
|
+
result = { requestId, value };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
export function normalizeProposalRequest(request) {
|
|
68
|
+
if (typeof request.type !== "string") {
|
|
69
|
+
throw new TypeError("proposal request type must be a string");
|
|
70
|
+
}
|
|
71
|
+
if (typeof request.description !== "string" || request.description.trim() === "") {
|
|
72
|
+
throw new Error("proposal request description is required");
|
|
73
|
+
}
|
|
74
|
+
if (!Array.isArray(request.options) || request.options.length === 0) {
|
|
75
|
+
throw new Error("proposal request options must be a non-empty list");
|
|
76
|
+
}
|
|
77
|
+
const options = [];
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
for (const item of request.options) {
|
|
80
|
+
const option = parseProposalOption(item);
|
|
81
|
+
if (option == null)
|
|
82
|
+
throw new Error("proposal request option value must be a non-empty string");
|
|
83
|
+
if (seen.has(option.value))
|
|
84
|
+
throw new Error(`proposal request option value repeats: ${option.value}`);
|
|
85
|
+
seen.add(option.value);
|
|
86
|
+
options.push(option);
|
|
87
|
+
}
|
|
88
|
+
const defaults = parseDefaults(request.defaults, seen);
|
|
89
|
+
if (request.defaults !== undefined && defaults === undefined) {
|
|
90
|
+
throw new Error("proposal request defaults must name option values");
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
type: request.type,
|
|
94
|
+
description: request.description,
|
|
95
|
+
options,
|
|
96
|
+
body: request.body,
|
|
97
|
+
defaults,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function parseDefaults(raw, values) {
|
|
101
|
+
let result;
|
|
102
|
+
if (raw != null && typeof raw === "object") {
|
|
103
|
+
const confirm = raw.confirm;
|
|
104
|
+
const brk = raw.break;
|
|
105
|
+
const out = {};
|
|
106
|
+
let valid = true;
|
|
107
|
+
if (confirm !== undefined) {
|
|
108
|
+
if (typeof confirm === "string" && values.has(confirm))
|
|
109
|
+
out.confirm = confirm;
|
|
110
|
+
else
|
|
111
|
+
valid = false;
|
|
112
|
+
}
|
|
113
|
+
if (brk !== undefined) {
|
|
114
|
+
if (typeof brk === "string" && values.has(brk))
|
|
115
|
+
out.break = brk;
|
|
116
|
+
else
|
|
117
|
+
valid = false;
|
|
118
|
+
}
|
|
119
|
+
if (valid && Object.keys(out).length > 0)
|
|
120
|
+
result = out;
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/shared/resolution.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolution request / answer shapes. Separate from ordinary TProposal steer.\n * Transport lives on dedicated awareness lanes; parse functions drop junk.\n */\n\n/** One choosable value. `label` is display; identity is `value`. */\nexport type ProposalOption = {\n readonly value: string;\n readonly label?: string;\n};\n\n/**\n * Actor → world ask. Default path is `description` + `options` + `defaults`.\n * `type` / `body` are optional enrichment — unknown `type` is ignored, not rejected.\n */\nexport type ProposalRequest = {\n readonly type: string;\n readonly description: string;\n readonly body?: unknown;\n readonly options: readonly ProposalOption[];\n readonly defaults?: {\n readonly confirm?: string;\n readonly break?: string;\n };\n};\n\n/** Published ask — {@link ProposalRequest} plus the request id on the resolution-request lane. */\nexport type ResolutionRequest = ProposalRequest & {\n readonly requestId: string;\n};\n\n/** Author → actor answer on the resolution lane. */\nexport type Resolution = {\n readonly requestId: string;\n readonly value: string;\n};\n\nexport function parseProposalOption(raw: unknown): ProposalOption | null {\n let result: ProposalOption | null = null;\n if (raw != null && typeof raw === \"object\") {\n const value = (raw as { value?: unknown }).value;\n if (typeof value === \"string\" && value !== \"\") {\n const label = (raw as { label?: unknown }).label;\n result = typeof label === \"string\" && label !== \"\" ? { value, label } : { value };\n }\n }\n return result;\n}\n\n/** Untrusted awareness field → published ask, or null. */\nexport function parseResolutionRequest(raw: unknown): ResolutionRequest | null {\n let result: ResolutionRequest | null = null;\n if (raw != null && typeof raw === \"object\") {\n const o = raw as Record<string, unknown>;\n if (\n typeof o.requestId === \"string\" &&\n o.requestId !== \"\" &&\n typeof o.type === \"string\" &&\n typeof o.description === \"string\" &&\n o.description.trim() !== \"\" &&\n Array.isArray(o.options) &&\n o.options.length > 0\n ) {\n const options: ProposalOption[] = [];\n const seen = new Set<string>();\n let valid = true;\n for (const item of o.options) {\n const option = parseProposalOption(item);\n if (option === null || seen.has(option.value)) {\n valid = false;\n break;\n }\n seen.add(option.value);\n options.push(option);\n }\n const defaults = parseDefaults(o.defaults, seen);\n if (valid && (o.defaults === undefined || defaults !== undefined)) {\n result = {\n requestId: o.requestId,\n type: o.type,\n description: o.description,\n options,\n body: o.body,\n defaults,\n };\n }\n }\n }\n return result;\n}\n\n/** Untrusted awareness field → answer, or null. Missing `requestId` is ignored (no front-run). */\nexport function parseResolution(raw: unknown): Resolution | null {\n let result: Resolution | null = null;\n if (raw != null && typeof raw === \"object\") {\n const value = (raw as { value?: unknown }).value;\n const requestId = (raw as { requestId?: unknown }).requestId;\n if (typeof value === \"string\" && value !== \"\" && typeof requestId === \"string\" && requestId !== \"\") {\n result = { requestId, value };\n }\n }\n return result;\n}\n\nexport function normalizeProposalRequest(request: ProposalRequest): ProposalRequest {\n if (typeof request.type !== \"string\") {\n throw new TypeError(\"proposal request type must be a string\");\n }\n if (typeof request.description !== \"string\" || request.description.trim() === \"\") {\n throw new Error(\"proposal request description is required\");\n }\n if (!Array.isArray(request.options) || request.options.length === 0) {\n throw new Error(\"proposal request options must be a non-empty list\");\n }\n const options: ProposalOption[] = [];\n const seen = new Set<string>();\n for (const item of request.options) {\n const option = parseProposalOption(item);\n if (option == null) throw new Error(\"proposal request option value must be a non-empty string\");\n if (seen.has(option.value)) throw new Error(`proposal request option value repeats: ${option.value}`);\n seen.add(option.value);\n options.push(option);\n }\n const defaults = parseDefaults(request.defaults, seen);\n if (request.defaults !== undefined && defaults === undefined) {\n throw new Error(\"proposal request defaults must name option values\");\n }\n return {\n type: request.type,\n description: request.description,\n options,\n body: request.body,\n defaults,\n };\n}\n\nfunction parseDefaults(\n raw: unknown,\n values: ReadonlySet<string>,\n): { readonly confirm?: string; readonly break?: string } | undefined {\n let result: { readonly confirm?: string; readonly break?: string } | undefined;\n if (raw != null && typeof raw === \"object\") {\n const confirm = (raw as { confirm?: unknown }).confirm;\n const brk = (raw as { break?: unknown }).break;\n const out: { confirm?: string; break?: string } = {};\n let valid = true;\n if (confirm !== undefined) {\n if (typeof confirm === \"string\" && values.has(confirm)) out.confirm = confirm;\n else valid = false;\n }\n if (brk !== undefined) {\n if (typeof brk === \"string\" && values.has(brk)) out.break = brk;\n else valid = false;\n }\n if (valid && Object.keys(out).length > 0) result = out;\n }\n return result;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revalidation demand. Clients publish on kernel awareness; PEW reduces to
|
|
3
|
+
* none | secondary | primary. Interned connections outlive a session wrap, so
|
|
4
|
+
* occupancy is not session-plane. Drivers read the reduced token — never clientIds.
|
|
5
|
+
*/
|
|
6
|
+
import { type PlexusAwareness } from "@here.build/plexus";
|
|
7
|
+
import { ConnectionSpec } from "./models/ConnectionSpec.js";
|
|
8
|
+
import { DriverSpec } from "./models/DriverSpec.js";
|
|
9
|
+
export type RevalidationDemand = "none" | "secondary" | "primary";
|
|
10
|
+
export declare const REVALIDATION_DEMAND_LANE = "revalidationDemand";
|
|
11
|
+
export declare const REVALIDATION_DEMAND_FOCUS_LANE = "revalidationDemandFocus";
|
|
12
|
+
export type RevalidationDemandRef = {
|
|
13
|
+
readonly kind: "driver";
|
|
14
|
+
readonly name: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: "connection";
|
|
17
|
+
readonly id: string;
|
|
18
|
+
};
|
|
19
|
+
export type RevalidationDemandSubject = DriverSpec | ConnectionSpec;
|
|
20
|
+
export type RevalidationDemandSource = RevalidationDemandSubject | Iterable<RevalidationDemandSubject | null | undefined> | null | undefined;
|
|
21
|
+
export declare function revalidationDemandRefFromSpec(spec: RevalidationDemandSubject): RevalidationDemandRef;
|
|
22
|
+
export declare function collectRevalidationDemandRefs(source: RevalidationDemandSource): RevalidationDemandRef[];
|
|
23
|
+
export declare function publishRevalidationDemand(hub: PlexusAwareness, refs: readonly RevalidationDemandRef[]): void;
|
|
24
|
+
export declare function publishRevalidationDemandFocus(hub: PlexusAwareness, ref: RevalidationDemandRef | null): void;
|
|
25
|
+
/** Union of every client's occupancy. Primary wins over secondary. */
|
|
26
|
+
export declare function revalidationDemandOf(hub: PlexusAwareness, target: RevalidationDemandRef): RevalidationDemand;
|
|
27
|
+
//# sourceMappingURL=revalidation-demand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revalidation-demand.d.ts","sourceRoot":"","sources":["../../src/shared/revalidation-demand.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;AAElE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,8BAA8B,4BAA4B,CAAC;AAExE,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,yBAAyB,GAAG,UAAU,GAAG,cAAc,CAAC;AAEpE,MAAM,MAAM,wBAAwB,GAAG,yBAAyB,GAAG,QAAQ,CAAC,yBAAyB,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;AAE7I,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,yBAAyB,GAAG,qBAAqB,CAGpG;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,wBAAwB,GAAG,qBAAqB,EAAE,CAcvG;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,qBAAqB,EAAE,GAAG,IAAI,CAO5G;AAED,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAO5G;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,GAAG,kBAAkB,CAY5G"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revalidation demand. Clients publish on kernel awareness; PEW reduces to
|
|
3
|
+
* none | secondary | primary. Interned connections outlive a session wrap, so
|
|
4
|
+
* occupancy is not session-plane. Drivers read the reduced token — never clientIds.
|
|
5
|
+
*/
|
|
6
|
+
import { FieldAwareness } from "@here.build/plexus";
|
|
7
|
+
import { ConnectionSpec } from "./models/ConnectionSpec.js";
|
|
8
|
+
import { DriverSpec } from "./models/DriverSpec.js";
|
|
9
|
+
export const REVALIDATION_DEMAND_LANE = "revalidationDemand";
|
|
10
|
+
export const REVALIDATION_DEMAND_FOCUS_LANE = "revalidationDemandFocus";
|
|
11
|
+
export function revalidationDemandRefFromSpec(spec) {
|
|
12
|
+
if (isConnectionSubject(spec))
|
|
13
|
+
return { kind: "connection", id: spec.id };
|
|
14
|
+
return { kind: "driver", name: spec.name };
|
|
15
|
+
}
|
|
16
|
+
export function collectRevalidationDemandRefs(source) {
|
|
17
|
+
if (source == null)
|
|
18
|
+
return [];
|
|
19
|
+
if (isRevalidationDemandSubject(source))
|
|
20
|
+
return [revalidationDemandRefFromSpec(source)];
|
|
21
|
+
const out = [];
|
|
22
|
+
const seen = new Set();
|
|
23
|
+
for (const item of source) {
|
|
24
|
+
if (item == null || !isRevalidationDemandSubject(item))
|
|
25
|
+
continue;
|
|
26
|
+
const ref = revalidationDemandRefFromSpec(item);
|
|
27
|
+
const key = refKey(ref);
|
|
28
|
+
if (seen.has(key))
|
|
29
|
+
continue;
|
|
30
|
+
seen.add(key);
|
|
31
|
+
out.push(ref);
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
export function publishRevalidationDemand(hub, refs) {
|
|
36
|
+
const lane = new FieldAwareness(hub, REVALIDATION_DEMAND_LANE);
|
|
37
|
+
if (refs.length === 0) {
|
|
38
|
+
lane.clear();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
lane.set(refs);
|
|
42
|
+
}
|
|
43
|
+
export function publishRevalidationDemandFocus(hub, ref) {
|
|
44
|
+
const lane = new FieldAwareness(hub, REVALIDATION_DEMAND_FOCUS_LANE);
|
|
45
|
+
if (ref == null) {
|
|
46
|
+
lane.clear();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
lane.set(ref);
|
|
50
|
+
}
|
|
51
|
+
/** Union of every client's occupancy. Primary wins over secondary. */
|
|
52
|
+
export function revalidationDemandOf(hub, target) {
|
|
53
|
+
const focus = new FieldAwareness(hub, REVALIDATION_DEMAND_FOCUS_LANE);
|
|
54
|
+
for (const clientId of focus.clientIds) {
|
|
55
|
+
const value = asRevalidationDemandRef(focus.getOther(clientId));
|
|
56
|
+
if (value != null && sameRef(value, target))
|
|
57
|
+
return "primary";
|
|
58
|
+
}
|
|
59
|
+
const ambient = new FieldAwareness(hub, REVALIDATION_DEMAND_LANE);
|
|
60
|
+
for (const clientId of ambient.clientIds) {
|
|
61
|
+
const list = asRevalidationDemandRefList(ambient.getOther(clientId));
|
|
62
|
+
if (list.some((item) => sameRef(item, target)))
|
|
63
|
+
return "secondary";
|
|
64
|
+
}
|
|
65
|
+
return "none";
|
|
66
|
+
}
|
|
67
|
+
function isConnectionSubject(spec) {
|
|
68
|
+
if (spec instanceof ConnectionSpec)
|
|
69
|
+
return true;
|
|
70
|
+
if (spec instanceof DriverSpec)
|
|
71
|
+
return false;
|
|
72
|
+
return "driver" in spec && "configuration" in spec;
|
|
73
|
+
}
|
|
74
|
+
function isRevalidationDemandSubject(value) {
|
|
75
|
+
if (value instanceof ConnectionSpec || value instanceof DriverSpec)
|
|
76
|
+
return true;
|
|
77
|
+
if (typeof value !== "object" || value === null)
|
|
78
|
+
return false;
|
|
79
|
+
if ("driver" in value && "configuration" in value)
|
|
80
|
+
return true;
|
|
81
|
+
return "importPath" in value && "abilityClaim" in value;
|
|
82
|
+
}
|
|
83
|
+
function asRevalidationDemandRef(value) {
|
|
84
|
+
if (typeof value !== "object" || value === null)
|
|
85
|
+
return null;
|
|
86
|
+
const rec = value;
|
|
87
|
+
if (rec.kind === "driver" && typeof rec.name === "string" && rec.name !== "") {
|
|
88
|
+
return { kind: "driver", name: rec.name };
|
|
89
|
+
}
|
|
90
|
+
if (rec.kind === "connection" && typeof rec.id === "string" && rec.id !== "") {
|
|
91
|
+
return { kind: "connection", id: rec.id };
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
function asRevalidationDemandRefList(value) {
|
|
96
|
+
if (!Array.isArray(value))
|
|
97
|
+
return [];
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const item of value) {
|
|
100
|
+
const ref = asRevalidationDemandRef(item);
|
|
101
|
+
if (ref != null)
|
|
102
|
+
out.push(ref);
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function sameRef(a, b) {
|
|
107
|
+
if (a.kind === "driver" && b.kind === "driver")
|
|
108
|
+
return a.name === b.name;
|
|
109
|
+
if (a.kind === "connection" && b.kind === "connection")
|
|
110
|
+
return a.id === b.id;
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
function refKey(ref) {
|
|
114
|
+
return ref.kind === "driver" ? `driver:${ref.name}` : `connection:${ref.id}`;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=revalidation-demand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revalidation-demand.js","sourceRoot":"","sources":["../../src/shared/revalidation-demand.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Revalidation demand. Clients publish on kernel awareness; PEW reduces to\n * none | secondary | primary. Interned connections outlive a session wrap, so\n * occupancy is not session-plane. Drivers read the reduced token — never clientIds.\n */\nimport { FieldAwareness, type PlexusAwareness } from \"@here.build/plexus\";\n\nimport { ConnectionSpec } from \"./models/ConnectionSpec.js\";\nimport { DriverSpec } from \"./models/DriverSpec.js\";\n\nexport type RevalidationDemand = \"none\" | \"secondary\" | \"primary\";\n\nexport const REVALIDATION_DEMAND_LANE = \"revalidationDemand\";\nexport const REVALIDATION_DEMAND_FOCUS_LANE = \"revalidationDemandFocus\";\n\nexport type RevalidationDemandRef =\n | { readonly kind: \"driver\"; readonly name: string }\n | { readonly kind: \"connection\"; readonly id: string };\n\nexport type RevalidationDemandSubject = DriverSpec | ConnectionSpec;\n\nexport type RevalidationDemandSource = RevalidationDemandSubject | Iterable<RevalidationDemandSubject | null | undefined> | null | undefined;\n\nexport function revalidationDemandRefFromSpec(spec: RevalidationDemandSubject): RevalidationDemandRef {\n if (isConnectionSubject(spec)) return { kind: \"connection\", id: spec.id };\n return { kind: \"driver\", name: spec.name };\n}\n\nexport function collectRevalidationDemandRefs(source: RevalidationDemandSource): RevalidationDemandRef[] {\n if (source == null) return [];\n if (isRevalidationDemandSubject(source)) return [revalidationDemandRefFromSpec(source)];\n const out: RevalidationDemandRef[] = [];\n const seen = new Set<string>();\n for (const item of source) {\n if (item == null || !isRevalidationDemandSubject(item)) continue;\n const ref = revalidationDemandRefFromSpec(item);\n const key = refKey(ref);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(ref);\n }\n return out;\n}\n\nexport function publishRevalidationDemand(hub: PlexusAwareness, refs: readonly RevalidationDemandRef[]): void {\n const lane = new FieldAwareness(hub, REVALIDATION_DEMAND_LANE);\n if (refs.length === 0) {\n lane.clear();\n return;\n }\n lane.set(refs as never);\n}\n\nexport function publishRevalidationDemandFocus(hub: PlexusAwareness, ref: RevalidationDemandRef | null): void {\n const lane = new FieldAwareness(hub, REVALIDATION_DEMAND_FOCUS_LANE);\n if (ref == null) {\n lane.clear();\n return;\n }\n lane.set(ref as never);\n}\n\n/** Union of every client's occupancy. Primary wins over secondary. */\nexport function revalidationDemandOf(hub: PlexusAwareness, target: RevalidationDemandRef): RevalidationDemand {\n const focus = new FieldAwareness(hub, REVALIDATION_DEMAND_FOCUS_LANE);\n for (const clientId of focus.clientIds) {\n const value = asRevalidationDemandRef(focus.getOther(clientId));\n if (value != null && sameRef(value, target)) return \"primary\";\n }\n const ambient = new FieldAwareness(hub, REVALIDATION_DEMAND_LANE);\n for (const clientId of ambient.clientIds) {\n const list = asRevalidationDemandRefList(ambient.getOther(clientId));\n if (list.some((item) => sameRef(item, target))) return \"secondary\";\n }\n return \"none\";\n}\n\nfunction isConnectionSubject(spec: RevalidationDemandSubject): spec is ConnectionSpec {\n if (spec instanceof ConnectionSpec) return true;\n if (spec instanceof DriverSpec) return false;\n return \"driver\" in spec && \"configuration\" in spec;\n}\n\nfunction isRevalidationDemandSubject(value: unknown): value is RevalidationDemandSubject {\n if (value instanceof ConnectionSpec || value instanceof DriverSpec) return true;\n if (typeof value !== \"object\" || value === null) return false;\n if (\"driver\" in value && \"configuration\" in value) return true;\n return \"importPath\" in value && \"abilityClaim\" in value;\n}\n\nfunction asRevalidationDemandRef(value: unknown): RevalidationDemandRef | null {\n if (typeof value !== \"object\" || value === null) return null;\n const rec = value as { kind?: unknown; name?: unknown; id?: unknown };\n if (rec.kind === \"driver\" && typeof rec.name === \"string\" && rec.name !== \"\") {\n return { kind: \"driver\", name: rec.name };\n }\n if (rec.kind === \"connection\" && typeof rec.id === \"string\" && rec.id !== \"\") {\n return { kind: \"connection\", id: rec.id };\n }\n return null;\n}\n\nfunction asRevalidationDemandRefList(value: unknown): RevalidationDemandRef[] {\n if (!Array.isArray(value)) return [];\n const out: RevalidationDemandRef[] = [];\n for (const item of value) {\n const ref = asRevalidationDemandRef(item);\n if (ref != null) out.push(ref);\n }\n return out;\n}\n\nfunction sameRef(a: RevalidationDemandRef, b: RevalidationDemandRef): boolean {\n if (a.kind === \"driver\" && b.kind === \"driver\") return a.name === b.name;\n if (a.kind === \"connection\" && b.kind === \"connection\") return a.id === b.id;\n return false;\n}\n\nfunction refKey(ref: RevalidationDemandRef): string {\n return ref.kind === \"driver\" ? `driver:${ref.name}` : `connection:${ref.id}`;\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role occupancy. One awareness lane, keyed by expectation uuid.
|
|
3
|
+
* Schema is append-only (`PlexusAwareness.MAX_LANES` = 64); a lane per
|
|
4
|
+
* expectation exhausts the budget. Retract the uuid on leave — occupancy
|
|
5
|
+
* is presence, not a durable outcome. `""` occupies without a report frame.
|
|
6
|
+
*/
|
|
7
|
+
import { type PlexusAwareness } from "@here.build/plexus";
|
|
8
|
+
export declare function reportRole(hub: PlexusAwareness, uuid: string, value: unknown): void;
|
|
9
|
+
export declare function retractRole(hub: PlexusAwareness, uuid: string): void;
|
|
10
|
+
/** First value for `uuid` across bases. Missing key is `undefined`. */
|
|
11
|
+
export declare function roleOf(hub: PlexusAwareness, uuid: string): unknown;
|
|
12
|
+
//# sourceMappingURL=role.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.d.ts","sourceRoot":"","sources":["../../src/shared/role.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAK1D,wBAAgB,UAAU,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAOnF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEpE;AAED,uEAAuE;AACvE,wBAAgB,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { MapFieldAwareness } from "./map-field-awareness.js";
|
|
2
|
+
import { ROLE_EXPECTATIONS_LANE } from "./types.js";
|
|
3
|
+
export function reportRole(hub, uuid, value) {
|
|
4
|
+
const field = lane(hub);
|
|
5
|
+
if (value === null) {
|
|
6
|
+
field.mapDelete(uuid);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
field.mapSet(uuid, value);
|
|
10
|
+
}
|
|
11
|
+
export function retractRole(hub, uuid) {
|
|
12
|
+
lane(hub).mapDelete(uuid);
|
|
13
|
+
}
|
|
14
|
+
/** First value for `uuid` across bases. Missing key is `undefined`. */
|
|
15
|
+
export function roleOf(hub, uuid) {
|
|
16
|
+
return lane(hub).mapGet(uuid);
|
|
17
|
+
}
|
|
18
|
+
function lane(hub) {
|
|
19
|
+
return new MapFieldAwareness(hub, ROLE_EXPECTATIONS_LANE);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=role.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.js","sourceRoot":"","sources":["../../src/shared/role.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,UAAU,UAAU,CAAC,GAAoB,EAAE,IAAY,EAAE,KAAc;IAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAoB,EAAE,IAAY;IAC5D,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,MAAM,CAAC,GAAoB,EAAE,IAAY;IACvD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,IAAI,CAAC,GAAoB;IAChC,OAAO,IAAI,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;AAC5D,CAAC","sourcesContent":["/**\n * Role occupancy. One awareness lane, keyed by expectation uuid.\n * Schema is append-only (`PlexusAwareness.MAX_LANES` = 64); a lane per\n * expectation exhausts the budget. Retract the uuid on leave — occupancy\n * is presence, not a durable outcome. `\"\"` occupies without a report frame.\n */\nimport { type PlexusAwareness } from \"@here.build/plexus\";\n\nimport { MapFieldAwareness } from \"./map-field-awareness.js\";\nimport { ROLE_EXPECTATIONS_LANE } from \"./types.js\";\n\nexport function reportRole(hub: PlexusAwareness, uuid: string, value: unknown): void {\n const field = lane(hub);\n if (value === null) {\n field.mapDelete(uuid);\n return;\n }\n field.mapSet(uuid, value);\n}\n\nexport function retractRole(hub: PlexusAwareness, uuid: string): void {\n lane(hub).mapDelete(uuid);\n}\n\n/** First value for `uuid` across bases. Missing key is `undefined`. */\nexport function roleOf(hub: PlexusAwareness, uuid: string): unknown {\n return lane(hub).mapGet(uuid);\n}\n\nfunction lane(hub: PlexusAwareness): MapFieldAwareness {\n return new MapFieldAwareness(hub, ROLE_EXPECTATIONS_LANE);\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AwarenessSerializable, AwarenessShape, Plexus, PlexusModel } from "@here.build/plexus";
|
|
2
|
+
import type { ConnectionSpec } from "./models/ConnectionSpec.js";
|
|
3
|
+
import type { DriverSpec } from "./models/DriverSpec.js";
|
|
4
|
+
import type { WorkContainer } from "./models/WorkContainer.js";
|
|
5
|
+
import type { RevalidationDemandRef } from "./revalidation-demand.js";
|
|
6
|
+
/** `null` = never ensured / never loaded. */
|
|
7
|
+
export type ReadyState = null | "bootstrapping" | "ready" | "failed";
|
|
8
|
+
export declare function asReadyState(value: unknown): ReadyState;
|
|
9
|
+
/**
|
|
10
|
+
* Revalidation demand is kernel-plane: interned connections outlive a session wrap.
|
|
11
|
+
* Live catalog faces stay on DriverSpec / ConnectionSpec, not awareness lanes.
|
|
12
|
+
*/
|
|
13
|
+
export type KernelAwareness = AwarenessShape & {
|
|
14
|
+
revalidationDemand?: readonly RevalidationDemandRef[];
|
|
15
|
+
revalidationDemandFocus?: RevalidationDemandRef | null;
|
|
16
|
+
};
|
|
17
|
+
/** Live shell tails: one lane, `Record<job.uuid, frame>`. */
|
|
18
|
+
export declare const SHELL_TAILS_LANE = "shell-tails";
|
|
19
|
+
/** Role occupancy: one lane, `Record<expectation.uuid, frame | "">`. */
|
|
20
|
+
export declare const ROLE_EXPECTATIONS_LANE = "role:expectations";
|
|
21
|
+
/** Statusline left slot: the daemon's last successful eval. */
|
|
22
|
+
export declare const STATUSLINE_LANE = "statusline";
|
|
23
|
+
export type SessionAwareness = AwarenessShape & {
|
|
24
|
+
/** Operator `policy.json` load/eval throw. Presence, not a leaf vote. */
|
|
25
|
+
policyError?: string;
|
|
26
|
+
[STATUSLINE_LANE]?: string;
|
|
27
|
+
[SHELL_TAILS_LANE]?: Record<string, AwarenessSerializable>;
|
|
28
|
+
[ROLE_EXPECTATIONS_LANE]?: Record<string, AwarenessSerializable>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Catalog parent of {@link DriverSpec} / {@link ConnectionSpec}.
|
|
32
|
+
* Ordinary records, not virtual maps.
|
|
33
|
+
*/
|
|
34
|
+
export type SpecCatalog = PlexusModel<null> & {
|
|
35
|
+
readonly drivers: Record<string, DriverSpec>;
|
|
36
|
+
readonly connections: Record<string, ConnectionSpec>;
|
|
37
|
+
};
|
|
38
|
+
/** Product membership is YAML projected onto these records. */
|
|
39
|
+
export type KernelRootModel = SpecCatalog;
|
|
40
|
+
export type SessionRootModel = WorkContainer;
|
|
41
|
+
export type KernelPlexus = Plexus<KernelRootModel, KernelAwareness>;
|
|
42
|
+
export type SessionPlexus = Plexus<SessionRootModel, SessionAwareness>;
|
|
43
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAErG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,6CAA6C;AAC7C,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,eAAe,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAGvD;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG;IAC7C,kBAAkB,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACtD,uBAAuB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACxD,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D,+DAA+D;AAC/D,eAAO,MAAM,eAAe,eAAe,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG;IAC9C,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC3D,CAAC,sBAAsB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAClE,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACtD,CAAC;AAEF,+DAA+D;AAC/D,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC;AAE1C,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AACpE,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function asReadyState(value) {
|
|
2
|
+
if (value === "bootstrapping" || value === "ready" || value === "failed")
|
|
3
|
+
return value;
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
/** Live shell tails: one lane, `Record<job.uuid, frame>`. */
|
|
7
|
+
export const SHELL_TAILS_LANE = "shell-tails";
|
|
8
|
+
/** Role occupancy: one lane, `Record<expectation.uuid, frame | "">`. */
|
|
9
|
+
export const ROLE_EXPECTATIONS_LANE = "role:expectations";
|
|
10
|
+
/** Statusline left slot: the daemon's last successful eval. */
|
|
11
|
+
export const STATUSLINE_LANE = "statusline";
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,KAAK,eAAe,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACvF,OAAO,IAAI,CAAC;AACd,CAAC;AAWD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE9C,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAE1D,+DAA+D;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAC","sourcesContent":["import type { AwarenessSerializable, AwarenessShape, Plexus, PlexusModel } from \"@here.build/plexus\";\n\nimport type { ConnectionSpec } from \"./models/ConnectionSpec.js\";\nimport type { DriverSpec } from \"./models/DriverSpec.js\";\nimport type { WorkContainer } from \"./models/WorkContainer.js\";\nimport type { RevalidationDemandRef } from \"./revalidation-demand.js\";\n\n/** `null` = never ensured / never loaded. */\nexport type ReadyState = null | \"bootstrapping\" | \"ready\" | \"failed\";\n\nexport function asReadyState(value: unknown): ReadyState {\n if (value === \"bootstrapping\" || value === \"ready\" || value === \"failed\") return value;\n return null;\n}\n\n/**\n * Revalidation demand is kernel-plane: interned connections outlive a session wrap.\n * Live catalog faces stay on DriverSpec / ConnectionSpec, not awareness lanes.\n */\nexport type KernelAwareness = AwarenessShape & {\n revalidationDemand?: readonly RevalidationDemandRef[];\n revalidationDemandFocus?: RevalidationDemandRef | null;\n};\n\n/** Live shell tails: one lane, `Record<job.uuid, frame>`. */\nexport const SHELL_TAILS_LANE = \"shell-tails\";\n\n/** Role occupancy: one lane, `Record<expectation.uuid, frame | \"\">`. */\nexport const ROLE_EXPECTATIONS_LANE = \"role:expectations\";\n\n/** Statusline left slot: the daemon's last successful eval. */\nexport const STATUSLINE_LANE = \"statusline\";\n\nexport type SessionAwareness = AwarenessShape & {\n /** Operator `policy.json` load/eval throw. Presence, not a leaf vote. */\n policyError?: string;\n [STATUSLINE_LANE]?: string;\n [SHELL_TAILS_LANE]?: Record<string, AwarenessSerializable>;\n [ROLE_EXPECTATIONS_LANE]?: Record<string, AwarenessSerializable>;\n};\n\n/**\n * Catalog parent of {@link DriverSpec} / {@link ConnectionSpec}.\n * Ordinary records, not virtual maps.\n */\nexport type SpecCatalog = PlexusModel<null> & {\n readonly drivers: Record<string, DriverSpec>;\n readonly connections: Record<string, ConnectionSpec>;\n};\n\n/** Product membership is YAML projected onto these records. */\nexport type KernelRootModel = SpecCatalog;\n\nexport type SessionRootModel = WorkContainer;\n\nexport type KernelPlexus = Plexus<KernelRootModel, KernelAwareness>;\nexport type SessionPlexus = Plexus<SessionRootModel, SessionAwareness>;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inhuman.tools/plexus-expectations",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Work graph: WorkExpectation (PEW), Job + honoring executor.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Merkle Bonsai",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./executor": {
|
|
16
|
+
"types": "./dist/executor/index.d.ts",
|
|
17
|
+
"import": "./dist/executor/index.js",
|
|
18
|
+
"default": "./dist/executor/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./driver": {
|
|
21
|
+
"types": "./dist/driver/index.d.ts",
|
|
22
|
+
"import": "./dist/driver/index.js",
|
|
23
|
+
"default": "./dist/driver/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"src",
|
|
31
|
+
"!**/__tests__",
|
|
32
|
+
"!**/*.test.*"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@here.build/collections": "0.9.0",
|
|
36
|
+
"tiny-invariant": "^1.3.3",
|
|
37
|
+
"zod": "^4.4.3",
|
|
38
|
+
"tslib": "2.8.1",
|
|
39
|
+
"xstate": "5.32.5",
|
|
40
|
+
"@inhuman.tools/error-with-invariant": "^0.1.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^24.0.0",
|
|
44
|
+
"eslint": "9.39.2",
|
|
45
|
+
"prettier": "3.8.1",
|
|
46
|
+
"typescript": "6.0.2",
|
|
47
|
+
"vitest": "4.1.0",
|
|
48
|
+
"yjs": "13.6.33",
|
|
49
|
+
"mobx": "6.16.1",
|
|
50
|
+
"@here.build/plexus": "^0.9.6",
|
|
51
|
+
"@-internal-/tsconfig": "0.0.0",
|
|
52
|
+
"@-internal-/eslint-configs": "0.0.0"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/here-build/inhuman-harness.git",
|
|
57
|
+
"directory": "packages/plexus-expectations"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"mobx": "6.16.1",
|
|
61
|
+
"@here.build/plexus": "^0.9.6"
|
|
62
|
+
},
|
|
63
|
+
"browserslist": [
|
|
64
|
+
"last 2 chrome versions",
|
|
65
|
+
"last 2 firefox versions",
|
|
66
|
+
"last 2 safari versions",
|
|
67
|
+
"ios_saf >= 16.4",
|
|
68
|
+
"node >= 22"
|
|
69
|
+
],
|
|
70
|
+
"publishConfig": {
|
|
71
|
+
"access": "public"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsc -p tsconfig.build.json",
|
|
75
|
+
"lint": "eslint .",
|
|
76
|
+
"lint:fix": "eslint . --fix",
|
|
77
|
+
"format": "prettier --write .",
|
|
78
|
+
"format:check": "prettier --check .",
|
|
79
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
80
|
+
"test": "vitest run"
|
|
81
|
+
}
|
|
6
82
|
}
|