@graview/core 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 +96 -0
- package/README.md +35 -0
- package/dist/app.d.ts +294 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +49 -0
- package/dist/app.js.map +1 -0
- package/dist/arrange.d.ts +185 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +456 -0
- package/dist/arrange.js.map +1 -0
- package/dist/beginning.d.ts +65 -0
- package/dist/beginning.d.ts.map +1 -0
- package/dist/beginning.js +94 -0
- package/dist/beginning.js.map +1 -0
- package/dist/bind.d.ts +42 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +26 -0
- package/dist/bind.js.map +1 -0
- package/dist/city.d.ts +93 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +160 -0
- package/dist/city.js.map +1 -0
- package/dist/cli/check/arrangement.d.ts +13 -0
- package/dist/cli/check/arrangement.d.ts.map +1 -0
- package/dist/cli/check/arrangement.js +63 -0
- package/dist/cli/check/arrangement.js.map +1 -0
- package/dist/cli/check/beginnings.d.ts +16 -0
- package/dist/cli/check/beginnings.d.ts.map +1 -0
- package/dist/cli/check/beginnings.js +53 -0
- package/dist/cli/check/beginnings.js.map +1 -0
- package/dist/cli/check/brand.d.ts +17 -0
- package/dist/cli/check/brand.d.ts.map +1 -0
- package/dist/cli/check/brand.js +153 -0
- package/dist/cli/check/brand.js.map +1 -0
- package/dist/cli/check/city.d.ts +17 -0
- package/dist/cli/check/city.d.ts.map +1 -0
- package/dist/cli/check/city.js +58 -0
- package/dist/cli/check/city.js.map +1 -0
- package/dist/cli/check/context.d.ts +50 -0
- package/dist/cli/check/context.d.ts.map +1 -0
- package/dist/cli/check/context.js +37 -0
- package/dist/cli/check/context.js.map +1 -0
- package/dist/cli/check/fields.d.ts +16 -0
- package/dist/cli/check/fields.d.ts.map +1 -0
- package/dist/cli/check/fields.js +237 -0
- package/dist/cli/check/fields.js.map +1 -0
- package/dist/cli/check/index.d.ts +14 -0
- package/dist/cli/check/index.d.ts.map +1 -0
- package/dist/cli/check/index.js +14 -0
- package/dist/cli/check/index.js.map +1 -0
- package/dist/cli/check/intelligence.d.ts +17 -0
- package/dist/cli/check/intelligence.d.ts.map +1 -0
- package/dist/cli/check/intelligence.js +136 -0
- package/dist/cli/check/intelligence.js.map +1 -0
- package/dist/cli/check/lenses.d.ts +17 -0
- package/dist/cli/check/lenses.d.ts.map +1 -0
- package/dist/cli/check/lenses.js +239 -0
- package/dist/cli/check/lenses.js.map +1 -0
- package/dist/cli/check/migrations.d.ts +16 -0
- package/dist/cli/check/migrations.d.ts.map +1 -0
- package/dist/cli/check/migrations.js +43 -0
- package/dist/cli/check/migrations.js.map +1 -0
- package/dist/cli/check/modules.d.ts +16 -0
- package/dist/cli/check/modules.d.ts.map +1 -0
- package/dist/cli/check/modules.js +123 -0
- package/dist/cli/check/modules.js.map +1 -0
- package/dist/cli/check/policy.d.ts +16 -0
- package/dist/cli/check/policy.d.ts.map +1 -0
- package/dist/cli/check/policy.js +90 -0
- package/dist/cli/check/policy.js.map +1 -0
- package/dist/cli/check/relations.d.ts +29 -0
- package/dist/cli/check/relations.d.ts.map +1 -0
- package/dist/cli/check/relations.js +279 -0
- package/dist/cli/check/relations.js.map +1 -0
- package/dist/cli/check/routes.d.ts +16 -0
- package/dist/cli/check/routes.d.ts.map +1 -0
- package/dist/cli/check/routes.js +31 -0
- package/dist/cli/check/routes.js.map +1 -0
- package/dist/cli/check/settings.d.ts +16 -0
- package/dist/cli/check/settings.d.ts.map +1 -0
- package/dist/cli/check/settings.js +81 -0
- package/dist/cli/check/settings.js.map +1 -0
- package/dist/cli/check.d.ts +36 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +76 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/create.d.ts +20 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +251 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/describe.d.ts +35 -0
- package/dist/cli/describe.d.ts.map +1 -0
- package/dist/cli/describe.js +230 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/docs.d.ts +11 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/docs.js +152 -0
- package/dist/cli/docs.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extend.d.ts +23 -0
- package/dist/extend.d.ts.map +1 -0
- package/dist/extend.js +53 -0
- package/dist/extend.js.map +1 -0
- package/dist/graph/diff.d.ts +31 -0
- package/dist/graph/diff.d.ts.map +1 -0
- package/dist/graph/diff.js +71 -0
- package/dist/graph/diff.js.map +1 -0
- package/dist/graph/graph.d.ts +69 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +284 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/primitives.d.ts +52 -0
- package/dist/graph/primitives.d.ts.map +1 -0
- package/dist/graph/primitives.js +62 -0
- package/dist/graph/primitives.js.map +1 -0
- package/dist/graph/tracked.d.ts +31 -0
- package/dist/graph/tracked.d.ts.map +1 -0
- package/dist/graph/tracked.js +69 -0
- package/dist/graph/tracked.js.map +1 -0
- package/dist/graph/types.d.ts +34 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +0 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +112 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +193 -0
- package/dist/installation.js.map +1 -0
- package/dist/intelligence-bridge.d.ts +73 -0
- package/dist/intelligence-bridge.d.ts.map +1 -0
- package/dist/intelligence-bridge.js +31 -0
- package/dist/intelligence-bridge.js.map +1 -0
- package/dist/invariants/engine.d.ts +36 -0
- package/dist/invariants/engine.d.ts.map +1 -0
- package/dist/invariants/engine.js +88 -0
- package/dist/invariants/engine.js.map +1 -0
- package/dist/invariants/types.d.ts +75 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +2 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/modules.d.ts +75 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +87 -0
- package/dist/modules.js.map +1 -0
- package/dist/mutations/decidable.d.ts +26 -0
- package/dist/mutations/decidable.d.ts.map +1 -0
- package/dist/mutations/decidable.js +39 -0
- package/dist/mutations/decidable.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts +32 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -0
- package/dist/mutations/define-mutation.js +181 -0
- package/dist/mutations/define-mutation.js.map +1 -0
- package/dist/mutations/derive-edits.d.ts +75 -0
- package/dist/mutations/derive-edits.d.ts.map +1 -0
- package/dist/mutations/derive-edits.js +240 -0
- package/dist/mutations/derive-edits.js.map +1 -0
- package/dist/mutations/form.d.ts +63 -0
- package/dist/mutations/form.d.ts.map +1 -0
- package/dist/mutations/form.js +113 -0
- package/dist/mutations/form.js.map +1 -0
- package/dist/mutations/node-ref.d.ts +83 -0
- package/dist/mutations/node-ref.d.ts.map +1 -0
- package/dist/mutations/node-ref.js +113 -0
- package/dist/mutations/node-ref.js.map +1 -0
- package/dist/mutations/types.d.ts +136 -0
- package/dist/mutations/types.d.ts.map +1 -0
- package/dist/mutations/types.js +2 -0
- package/dist/mutations/types.js.map +1 -0
- package/dist/ops/log.d.ts +35 -0
- package/dist/ops/log.d.ts.map +1 -0
- package/dist/ops/log.js +103 -0
- package/dist/ops/log.js.map +1 -0
- package/dist/ops/types.d.ts +52 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +2 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/undo.d.ts +33 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +65 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/permissions/policy.d.ts +68 -0
- package/dist/permissions/policy.d.ts.map +1 -0
- package/dist/permissions/policy.js +191 -0
- package/dist/permissions/policy.js.map +1 -0
- package/dist/permissions/types.d.ts +78 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/persistence/memory.d.ts +6 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +31 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +59 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +22 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/presence.d.ts +38 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +50 -0
- package/dist/presence.js.map +1 -0
- package/dist/scaffold/domain.d.ts +8 -0
- package/dist/scaffold/domain.d.ts.map +1 -0
- package/dist/scaffold/domain.js +331 -0
- package/dist/scaffold/domain.js.map +1 -0
- package/dist/scaffold/index.d.ts +66 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +142 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lens.d.ts +31 -0
- package/dist/scaffold/lens.d.ts.map +1 -0
- package/dist/scaffold/lens.js +176 -0
- package/dist/scaffold/lens.js.map +1 -0
- package/dist/scaffold/names.d.ts +44 -0
- package/dist/scaffold/names.d.ts.map +1 -0
- package/dist/scaffold/names.js +69 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +41 -0
- package/dist/scaffold/project.d.ts.map +1 -0
- package/dist/scaffold/project.js +604 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/ui.d.ts +15 -0
- package/dist/scaffold/ui.d.ts.map +1 -0
- package/dist/scaffold/ui.js +536 -0
- package/dist/scaffold/ui.js.map +1 -0
- package/dist/schema/define-node.d.ts +132 -0
- package/dist/schema/define-node.d.ts.map +1 -0
- package/dist/schema/define-node.js +254 -0
- package/dist/schema/define-node.js.map +1 -0
- package/dist/schema/figures.d.ts +42 -0
- package/dist/schema/figures.d.ts.map +1 -0
- package/dist/schema/figures.js +220 -0
- package/dist/schema/figures.js.map +1 -0
- package/dist/schema/json-schema.d.ts +39 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +74 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +43 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +102 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/search.d.ts +215 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/settings.d.ts +30 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +284 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +660 -0
- package/dist/store.js.map +1 -0
- package/dist/studio-door.d.ts +187 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +20 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync/conflict.d.ts +37 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +56 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/engine.d.ts +118 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +341 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/google-calendar.d.ts +54 -0
- package/dist/sync/google-calendar.d.ts.map +1 -0
- package/dist/sync/google-calendar.js +167 -0
- package/dist/sync/google-calendar.js.map +1 -0
- package/dist/sync/types.d.ts +125 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/temporal/effectivity.d.ts +75 -0
- package/dist/temporal/effectivity.d.ts.map +1 -0
- package/dist/temporal/effectivity.js +89 -0
- package/dist/temporal/effectivity.js.map +1 -0
- package/dist/testing.d.ts +63 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +194 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contrast.d.ts +47 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +172 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/derive.d.ts +81 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +171 -0
- package/dist/theme/derive.js.map +1 -0
- package/dist/theme/kit.d.ts +106 -0
- package/dist/theme/kit.d.ts.map +1 -0
- package/dist/theme/kit.js +84 -0
- package/dist/theme/kit.js.map +1 -0
- package/dist/theme/palettes.d.ts +32 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +96 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/types.d.ts +131 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +23 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/views/types.d.ts +89 -0
- package/dist/views/types.d.ts.map +1 -0
- package/dist/views/types.js +88 -0
- package/dist/views/types.js.map +1 -0
- package/dist/watched.d.ts +33 -0
- package/dist/watched.d.ts.map +1 -0
- package/dist/watched.js +50 -0
- package/dist/watched.js.map +1 -0
- package/dist/who.d.ts +26 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +20 -0
- package/dist/who.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LOCAL DOOR'S CONTRACT — what a page and a dev server agree on.
|
|
3
|
+
*
|
|
4
|
+
* `reach: ["local"]` says a provider can be reached by a process on this
|
|
5
|
+
* machine. This is the whole of what the two sides share: one path and three
|
|
6
|
+
* message shapes. It carries no Node and no DOM, so the browser bundle and
|
|
7
|
+
* the dev-server plugin can both hold it, and neither has to import the
|
|
8
|
+
* other — which matters here, because the plugin lives a tier above the
|
|
9
|
+
* hook that probes it.
|
|
10
|
+
*
|
|
11
|
+
* Not to be confused with a model running IN the browser (`localCompletion`
|
|
12
|
+
* in `@graview/tools`, which downloads weights and runs them on WebGPU).
|
|
13
|
+
* This door is a process on the machine the dev server is running on:
|
|
14
|
+
* somebody's own CLI, already installed, already logged in, already paid
|
|
15
|
+
* for, and reachable for as long as `pnpm dev` is up.
|
|
16
|
+
*/
|
|
17
|
+
/** Where the bridge answers unless an app says otherwise. */
|
|
18
|
+
export const LOCAL_BRIDGE_PATH = "/__graview/local";
|
|
19
|
+
/* ---------------------------------------------------- the decision door */
|
|
20
|
+
/**
|
|
21
|
+
* THE DOOR A DECISION PROVIDER IS REACHED BY from a browser: the dev server
|
|
22
|
+
* holds the key, the page holds the questions. Same three shapes as the
|
|
23
|
+
* local door — a probe, an ask, an answer — and the same rule about who may
|
|
24
|
+
* knock: the page this server serves, and nobody else.
|
|
25
|
+
*
|
|
26
|
+
* The key is read on the SERVER side from the environment, so it is never
|
|
27
|
+
* in a bundle, a repo or the browser's storage: the person running
|
|
28
|
+
* `pnpm dev` set it once, and the page never sees it.
|
|
29
|
+
*/
|
|
30
|
+
export const DECISION_BRIDGE_PATH = "/__graview/decide";
|
|
31
|
+
//# sourceMappingURL=intelligence-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence-bridge.js","sourceRoot":"","sources":["../src/intelligence-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAgBpD,4EAA4E;AAE5E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Graph } from "../graph/graph.js";
|
|
2
|
+
import type { AnySchema, KindOfSchema, NodeOfKind } from "../schema/schema.js";
|
|
3
|
+
import type { EvaluateOptions, InvariantDefinition, InvariantEvalArgs, Violation } from "./types.js";
|
|
4
|
+
export declare class UnregisteredInvariantError extends Error {
|
|
5
|
+
readonly invariant: string;
|
|
6
|
+
readonly nodeId: string;
|
|
7
|
+
constructor(invariant: string, nodeId: string);
|
|
8
|
+
}
|
|
9
|
+
export declare function defineInvariant<S extends AnySchema, K extends KindOfSchema<S>>(name: string, spec: {
|
|
10
|
+
readonly scope: {
|
|
11
|
+
readonly kind: K;
|
|
12
|
+
readonly match?: (node: NodeOfKind<S, K>) => boolean;
|
|
13
|
+
};
|
|
14
|
+
readonly label?: string;
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
readonly repairs?: readonly string[];
|
|
17
|
+
readonly judgesPast?: boolean;
|
|
18
|
+
readonly evaluate: (args: InvariantEvalArgs<S, NodeOfKind<S, K>>) => Violation[];
|
|
19
|
+
}): InvariantDefinition<S>;
|
|
20
|
+
export declare function defineInvariant<S extends AnySchema>(name: string, spec: {
|
|
21
|
+
readonly scope: "graph";
|
|
22
|
+
readonly label?: string;
|
|
23
|
+
readonly description?: string;
|
|
24
|
+
readonly repairs?: readonly string[];
|
|
25
|
+
readonly judgesPast?: boolean;
|
|
26
|
+
readonly evaluate: (args: InvariantEvalArgs<S, undefined>) => Violation[];
|
|
27
|
+
}): InvariantDefinition<S>;
|
|
28
|
+
/**
|
|
29
|
+
* Pure evaluation: same graph, context and `today` in, same violations out.
|
|
30
|
+
* The one clock read is the lifecycle horizon's date fallback when no
|
|
31
|
+
* `options.today` is pinned — pin it and the whole tier runs headlessly in CI.
|
|
32
|
+
*/
|
|
33
|
+
export declare function evaluate<S extends AnySchema>(graph: Graph<S>, invariants: readonly InvariantDefinition<S>[], options?: EvaluateOptions<S>): Violation[];
|
|
34
|
+
/** Violations that implicate any of the given node ids. */
|
|
35
|
+
export declare function violationsTouching(violations: readonly Violation[], nodeIds: readonly string[]): Violation[];
|
|
36
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/invariants/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAgB,MAAM,qBAAqB,CAAC;AAC7F,OAAO,KAAK,EACV,eAAe,EAEf,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM;CAO1B;AAED,wBAAgB,eAAe,CAC7B,CAAC,SAAS,SAAS,EACnB,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,EAEzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IACJ,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAA;KAAE,CAAC;IAC3F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;CAClF,GACA,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC1B,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IACJ,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;CAC3E,GACA,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAe1B;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,SAAS,EAC1C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,UAAU,EAAE,SAAS,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAC7C,OAAO,GAAE,eAAe,CAAC,CAAC,CAAM,GAC/B,SAAS,EAAE,CAmEb;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,SAAS,EAAE,CAKb"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { isCurrent } from "../schema/define-node.js";
|
|
2
|
+
export class UnregisteredInvariantError extends Error {
|
|
3
|
+
invariant;
|
|
4
|
+
nodeId;
|
|
5
|
+
constructor(invariant, nodeId) {
|
|
6
|
+
super(`No invariant registered under "${invariant}" (required by node "${nodeId}")`);
|
|
7
|
+
this.invariant = invariant;
|
|
8
|
+
this.nodeId = nodeId;
|
|
9
|
+
this.name = "UnregisteredInvariantError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function defineInvariant(name, spec) {
|
|
13
|
+
return { ...spec, name };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Pure evaluation: same graph, context and `today` in, same violations out.
|
|
17
|
+
* The one clock read is the lifecycle horizon's date fallback when no
|
|
18
|
+
* `options.today` is pinned — pin it and the whole tier runs headlessly in CI.
|
|
19
|
+
*/
|
|
20
|
+
export function evaluate(graph, invariants, options = {}) {
|
|
21
|
+
const context = options.context ?? {};
|
|
22
|
+
const onUnregistered = options.onUnregistered ?? "skip";
|
|
23
|
+
const registered = new Set(invariants.map((i) => i.name));
|
|
24
|
+
const violations = [];
|
|
25
|
+
for (const invariant of invariants) {
|
|
26
|
+
if (invariant.scope !== "graph")
|
|
27
|
+
continue;
|
|
28
|
+
violations.push(...invariant.evaluate({ graph, subject: undefined, context }));
|
|
29
|
+
}
|
|
30
|
+
const scoped = invariants.filter((i) => i.scope !== "graph");
|
|
31
|
+
const byKind = new Map();
|
|
32
|
+
for (const invariant of scoped) {
|
|
33
|
+
const kind = invariant.scope.kind;
|
|
34
|
+
const list = byKind.get(kind);
|
|
35
|
+
if (list)
|
|
36
|
+
list.push(invariant);
|
|
37
|
+
else
|
|
38
|
+
byKind.set(kind, [invariant]);
|
|
39
|
+
}
|
|
40
|
+
for (const node of graph.allNodes()) {
|
|
41
|
+
const definition = graph.schema.tryDefinition(node.kind);
|
|
42
|
+
const required = definition?.requiresInvariant?.(node) ?? null;
|
|
43
|
+
if (options.subjectFilter && !options.subjectFilter(node, context))
|
|
44
|
+
continue;
|
|
45
|
+
if (required !== null && !registered.has(required)) {
|
|
46
|
+
if (onUnregistered === "throw") {
|
|
47
|
+
throw new UnregisteredInvariantError(required, node.id);
|
|
48
|
+
}
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
/*
|
|
52
|
+
* The horizon applies to judgement, not just display: a retired subject
|
|
53
|
+
* is only examined by invariants that opted into the past. Graph-scoped
|
|
54
|
+
* invariants read whatever they read — they have no subject to retire.
|
|
55
|
+
*/
|
|
56
|
+
const retired = !isCurrent(definition, node, options.today);
|
|
57
|
+
for (const invariant of byKind.get(node.kind) ?? []) {
|
|
58
|
+
if (retired && invariant.judgesPast !== true)
|
|
59
|
+
continue;
|
|
60
|
+
const match = invariant.scope.match;
|
|
61
|
+
if (match && !match(node))
|
|
62
|
+
continue;
|
|
63
|
+
violations.push(...invariant.evaluate({ graph, subject: node, context }));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/*
|
|
67
|
+
* IDENTICAL claims collapse to one. Two rule nodes carrying the same spec
|
|
68
|
+
* each evaluate honestly, and every surface downstream — the standing
|
|
69
|
+
* count, the board, the inspector — would repeat the same sentence twice
|
|
70
|
+
* for what a reader rightly regards as one problem. Distinct facts always
|
|
71
|
+
* differ in message or in the nodes they implicate, so this only removes
|
|
72
|
+
* true twins.
|
|
73
|
+
*/
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
return violations.filter((violation) => {
|
|
76
|
+
const key = `${violation.message}|${[...violation.nodeIds].sort().join(",")}`;
|
|
77
|
+
if (seen.has(key))
|
|
78
|
+
return false;
|
|
79
|
+
seen.add(key);
|
|
80
|
+
return true;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/** Violations that implicate any of the given node ids. */
|
|
84
|
+
export function violationsTouching(violations, nodeIds) {
|
|
85
|
+
const wanted = new Set(nodeIds);
|
|
86
|
+
return violations.filter((v) => v.nodeIds.some((id) => wanted.has(id)) || (v.subjectId !== undefined && wanted.has(v.subjectId)));
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/invariants/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { GraphReader } from "../graph/types.js";
|
|
2
|
+
import type { AnySchema, KindOfSchema, NodeOfKind, NodeOfSchema } from "../schema/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* A mutation that would resolve a violation. This field is the seam between
|
|
5
|
+
* the invariant engine and derived affordances: it is why selecting an
|
|
6
|
+
* out-of-balance set of duties can surface "rebalance" without anyone
|
|
7
|
+
* writing a rule to produce that suggestion.
|
|
8
|
+
*/
|
|
9
|
+
export interface Repair {
|
|
10
|
+
readonly mutation: string;
|
|
11
|
+
/** Arguments already determined by the violation. */
|
|
12
|
+
readonly args?: Readonly<Record<string, unknown>>;
|
|
13
|
+
/** Arguments the caller still has to choose. */
|
|
14
|
+
readonly missing?: readonly string[];
|
|
15
|
+
readonly label: string;
|
|
16
|
+
}
|
|
17
|
+
export interface Violation {
|
|
18
|
+
readonly invariant: string;
|
|
19
|
+
/** The node whose declaration produced the check, when there is one. */
|
|
20
|
+
readonly subjectId?: string;
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly message: string;
|
|
23
|
+
/** Ids of the nodes that cause the violation, for cross-plane highlighting. */
|
|
24
|
+
readonly nodeIds: readonly string[];
|
|
25
|
+
readonly repairs: readonly Repair[];
|
|
26
|
+
}
|
|
27
|
+
/** Free-form evaluation context an app threads through (e.g. a week start). */
|
|
28
|
+
export type InvariantContext = Readonly<Record<string, unknown>>;
|
|
29
|
+
export interface InvariantScope<S extends AnySchema, K extends KindOfSchema<S>> {
|
|
30
|
+
readonly kind: K;
|
|
31
|
+
/** Narrows which nodes of the kind this invariant judges. */
|
|
32
|
+
readonly match?: (node: NodeOfKind<S, K>) => boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface InvariantEvalArgs<S extends AnySchema, Subject> {
|
|
35
|
+
readonly graph: GraphReader<NodeOfSchema<S>>;
|
|
36
|
+
readonly subject: Subject;
|
|
37
|
+
readonly context: InvariantContext;
|
|
38
|
+
}
|
|
39
|
+
export interface InvariantDefinition<S extends AnySchema = AnySchema> {
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly label?: string;
|
|
42
|
+
readonly description?: string;
|
|
43
|
+
readonly scope: {
|
|
44
|
+
readonly kind: string;
|
|
45
|
+
readonly match?: (node: never) => boolean;
|
|
46
|
+
} | "graph";
|
|
47
|
+
/**
|
|
48
|
+
* Mutation names this invariant may name as repairs. Declared statically so
|
|
49
|
+
* `graview check` can catch a repair that points at a mutation nobody
|
|
50
|
+
* registered, instead of discovering it when a violation fires.
|
|
51
|
+
*/
|
|
52
|
+
readonly repairs?: readonly string[];
|
|
53
|
+
/**
|
|
54
|
+
* Judge retired subjects too. By default a scoped invariant sees only the
|
|
55
|
+
* HORIZON — nodes current under their kind's lifecycle — because a rule
|
|
56
|
+
* about last term's agreement is noise, not a violation. An invariant that
|
|
57
|
+
* genuinely audits history says so here, explicitly.
|
|
58
|
+
*/
|
|
59
|
+
readonly judgesPast?: boolean;
|
|
60
|
+
readonly evaluate: (args: InvariantEvalArgs<S, never>) => Violation[];
|
|
61
|
+
}
|
|
62
|
+
export interface EvaluateOptions<S extends AnySchema = AnySchema> {
|
|
63
|
+
readonly context?: InvariantContext;
|
|
64
|
+
/** What to do when a node requires an invariant nobody registered. */
|
|
65
|
+
readonly onUnregistered?: "skip" | "throw";
|
|
66
|
+
/**
|
|
67
|
+
* Pins "today" for the lifecycle horizon (YYYY-MM-DD). Without it the
|
|
68
|
+
* date-retired check reads the real clock — pass this wherever determinism
|
|
69
|
+
* matters (tests, replays).
|
|
70
|
+
*/
|
|
71
|
+
readonly today?: string;
|
|
72
|
+
/** Filters subject nodes before evaluation, e.g. by effectivity window. */
|
|
73
|
+
readonly subjectFilter?: (node: NodeOfSchema<S>, context: InvariantContext) => boolean;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/invariants/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/invariants/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MODULES: named parts of a declaration a workspace can turn on and off.
|
|
3
|
+
*
|
|
4
|
+
* A deployed app needs to scope itself per workspace — one household wants
|
|
5
|
+
* Vehicles, another does not — and "comment out the import" is not a thing a
|
|
6
|
+
* hosted product can offer. A module is a declared subset of the app's
|
|
7
|
+
* surface: node kinds, mutations, invariants. The enabled set is plain
|
|
8
|
+
* serialisable config, which is what lets a platform bind it to entitlements.
|
|
9
|
+
*
|
|
10
|
+
* Two rules keep this honest. Anything no module claims is CORE and always
|
|
11
|
+
* on — an app pays for the concept only where it opts in. And disabling
|
|
12
|
+
* never deletes: nodes of a disabled kind stay in the graph and simply stop
|
|
13
|
+
* being drawn, counted or judged, so re-enabling brings a workspace back
|
|
14
|
+
* intact. "Module off" is a horizon, not a delete.
|
|
15
|
+
*/
|
|
16
|
+
export interface ModuleDeclaration {
|
|
17
|
+
readonly description?: string;
|
|
18
|
+
/** Node kinds this module owns. */
|
|
19
|
+
readonly kinds?: readonly string[];
|
|
20
|
+
/** Mutation names this module owns. */
|
|
21
|
+
readonly mutations?: readonly string[];
|
|
22
|
+
/** Invariant names this module owns. */
|
|
23
|
+
readonly invariants?: readonly string[];
|
|
24
|
+
/** Modules this one cannot stand without. */
|
|
25
|
+
readonly requires?: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* A module that is never off.
|
|
28
|
+
*
|
|
29
|
+
* People are not a bolt-on for a grounds app, or a rota, or anything else
|
|
30
|
+
* several people use: an installation without people is a household of one,
|
|
31
|
+
* which is a graph with no user NODES rather than a disabled module. An app
|
|
32
|
+
* in that position had two options, both bad — drop the module, which draws
|
|
33
|
+
* the installation for everybody and loses the thing the module is for, or
|
|
34
|
+
* carry a permanent `module-edge-leak` warning for every edge the domain
|
|
35
|
+
* points at a person and hope nobody stops reading them.
|
|
36
|
+
*
|
|
37
|
+
* A warning that can only ever be acknowledged costs the checker its
|
|
38
|
+
* authority on the warnings that matter, so the declaration can say the
|
|
39
|
+
* thing that makes the question moot: this cannot be off, so no line
|
|
40
|
+
* dangles. `resolveModules` keeps it on whatever the enabled set says, and
|
|
41
|
+
* `graview check` skips the leak warning for edges reaching into it.
|
|
42
|
+
*/
|
|
43
|
+
readonly required?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Who the module's kinds are drawn for. `always` (the default) is every
|
|
46
|
+
* seat; `admin` keeps them out of the picture until a seat that may run
|
|
47
|
+
* one of the module's acts asks to see them — the installation's own
|
|
48
|
+
* users and invitations sit beside the domain for the person who keeps
|
|
49
|
+
* it, and are never a district for anyone else.
|
|
50
|
+
*/
|
|
51
|
+
readonly visibility?: "always" | "admin";
|
|
52
|
+
}
|
|
53
|
+
export type ModuleMap = Readonly<Record<string, ModuleDeclaration>>;
|
|
54
|
+
/** What an enabled set works out to, asked once and shared by every surface. */
|
|
55
|
+
export interface ModuleProjection {
|
|
56
|
+
/** Module names actually on, requirements included. */
|
|
57
|
+
readonly enabled: ReadonlySet<string>;
|
|
58
|
+
readonly disabledKinds: ReadonlySet<string>;
|
|
59
|
+
readonly disabledMutations: ReadonlySet<string>;
|
|
60
|
+
readonly disabledInvariants: ReadonlySet<string>;
|
|
61
|
+
/** Enabled modules drawn only for those who administer them, by name. */
|
|
62
|
+
readonly administered: ReadonlyMap<string, ModuleDeclaration>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolves an enabled set against the declared modules.
|
|
66
|
+
*
|
|
67
|
+
* `enabled: undefined` means everything — the default install is the whole
|
|
68
|
+
* app, and a store that never heard of modules behaves exactly as before.
|
|
69
|
+
* Enabling a module quietly enables what it `requires`, transitively: at
|
|
70
|
+
* runtime the forgiving reading is correct (an entitlement flip must not
|
|
71
|
+
* strand a workspace), and the strict reading lives in `graview check`,
|
|
72
|
+
* which reports a requirement pointing at a module nobody declared.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveModules(modules: ModuleMap | undefined, enabled: readonly string[] | undefined): ModuleProjection;
|
|
75
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,mCAAmC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,uCAAuC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,wCAAwC;IACxC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC1C;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEpE,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC/D;AAID;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,GAAG,SAAS,EAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACrC,gBAAgB,CA0ClB"}
|
package/dist/modules.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MODULES: named parts of a declaration a workspace can turn on and off.
|
|
3
|
+
*
|
|
4
|
+
* A deployed app needs to scope itself per workspace — one household wants
|
|
5
|
+
* Vehicles, another does not — and "comment out the import" is not a thing a
|
|
6
|
+
* hosted product can offer. A module is a declared subset of the app's
|
|
7
|
+
* surface: node kinds, mutations, invariants. The enabled set is plain
|
|
8
|
+
* serialisable config, which is what lets a platform bind it to entitlements.
|
|
9
|
+
*
|
|
10
|
+
* Two rules keep this honest. Anything no module claims is CORE and always
|
|
11
|
+
* on — an app pays for the concept only where it opts in. And disabling
|
|
12
|
+
* never deletes: nodes of a disabled kind stay in the graph and simply stop
|
|
13
|
+
* being drawn, counted or judged, so re-enabling brings a workspace back
|
|
14
|
+
* intact. "Module off" is a horizon, not a delete.
|
|
15
|
+
*/
|
|
16
|
+
const NOTHING = new Set();
|
|
17
|
+
/**
|
|
18
|
+
* Resolves an enabled set against the declared modules.
|
|
19
|
+
*
|
|
20
|
+
* `enabled: undefined` means everything — the default install is the whole
|
|
21
|
+
* app, and a store that never heard of modules behaves exactly as before.
|
|
22
|
+
* Enabling a module quietly enables what it `requires`, transitively: at
|
|
23
|
+
* runtime the forgiving reading is correct (an entitlement flip must not
|
|
24
|
+
* strand a workspace), and the strict reading lives in `graview check`,
|
|
25
|
+
* which reports a requirement pointing at a module nobody declared.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveModules(modules, enabled) {
|
|
28
|
+
if (!modules || enabled === undefined) {
|
|
29
|
+
return {
|
|
30
|
+
enabled: new Set(Object.keys(modules ?? {})),
|
|
31
|
+
disabledKinds: NOTHING,
|
|
32
|
+
disabledMutations: NOTHING,
|
|
33
|
+
disabledInvariants: NOTHING,
|
|
34
|
+
administered: administeredOf(modules, new Set(Object.keys(modules ?? {}))),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const on = new Set();
|
|
38
|
+
const turnOn = (name) => {
|
|
39
|
+
if (on.has(name) || !(name in modules))
|
|
40
|
+
return;
|
|
41
|
+
on.add(name);
|
|
42
|
+
for (const required of modules[name]?.requires ?? [])
|
|
43
|
+
turnOn(required);
|
|
44
|
+
};
|
|
45
|
+
for (const name of enabled)
|
|
46
|
+
turnOn(name);
|
|
47
|
+
/* A module that declares itself required is on whatever the config says. */
|
|
48
|
+
for (const [name, module] of Object.entries(modules))
|
|
49
|
+
if (module.required)
|
|
50
|
+
turnOn(name);
|
|
51
|
+
const disabledKinds = new Set();
|
|
52
|
+
const disabledMutations = new Set();
|
|
53
|
+
const disabledInvariants = new Set();
|
|
54
|
+
for (const [name, module] of Object.entries(modules)) {
|
|
55
|
+
if (on.has(name))
|
|
56
|
+
continue;
|
|
57
|
+
for (const kind of module.kinds ?? [])
|
|
58
|
+
disabledKinds.add(kind);
|
|
59
|
+
for (const mutation of module.mutations ?? [])
|
|
60
|
+
disabledMutations.add(mutation);
|
|
61
|
+
for (const invariant of module.invariants ?? [])
|
|
62
|
+
disabledInvariants.add(invariant);
|
|
63
|
+
}
|
|
64
|
+
/*
|
|
65
|
+
* A kind two modules claim stays on while EITHER is enabled — ownership
|
|
66
|
+
* is a union, and the disabled set only holds what nothing enabled wants.
|
|
67
|
+
*/
|
|
68
|
+
for (const name of on) {
|
|
69
|
+
const module = modules[name];
|
|
70
|
+
for (const kind of module?.kinds ?? [])
|
|
71
|
+
disabledKinds.delete(kind);
|
|
72
|
+
for (const mutation of module?.mutations ?? [])
|
|
73
|
+
disabledMutations.delete(mutation);
|
|
74
|
+
for (const invariant of module?.invariants ?? [])
|
|
75
|
+
disabledInvariants.delete(invariant);
|
|
76
|
+
}
|
|
77
|
+
return { enabled: on, disabledKinds, disabledMutations, disabledInvariants, administered: administeredOf(modules, on) };
|
|
78
|
+
}
|
|
79
|
+
function administeredOf(modules, on) {
|
|
80
|
+
const found = new Map();
|
|
81
|
+
for (const [name, module] of Object.entries(modules ?? {})) {
|
|
82
|
+
if (on.has(name) && module.visibility === "admin")
|
|
83
|
+
found.set(name, module);
|
|
84
|
+
}
|
|
85
|
+
return found;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FormField } from "./form.js";
|
|
2
|
+
/**
|
|
3
|
+
* WHAT A DECISION PROVIDER COULD NEVER SUPPLY.
|
|
4
|
+
*
|
|
5
|
+
* A decision provider answers in values the declaration already types: a
|
|
6
|
+
* Choice over named options (an enum, a node of some kind), a truth, a
|
|
7
|
+
* Score over an ordered rubric (a bounded number). It has no prose, so an
|
|
8
|
+
* act whose required arguments include free text — or a date, which is
|
|
9
|
+
* neither chosen from a set nor scored — is an act it could not possibly
|
|
10
|
+
* call, whatever the allowlist says. The checker refuses such a provider;
|
|
11
|
+
* a surface deriving questions skips such an act rather than asking one
|
|
12
|
+
* it cannot fill.
|
|
13
|
+
*
|
|
14
|
+
* Optional arguments are not counted: a decision provider leaves them
|
|
15
|
+
* unset, which is what optional means. A variant's tag is a choice; its
|
|
16
|
+
* arms' fields are judged like any other.
|
|
17
|
+
*/
|
|
18
|
+
export interface UndecidableArgument {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly control: FormField["control"];
|
|
21
|
+
}
|
|
22
|
+
/** The required arguments of an act that no typed answer can fill. */
|
|
23
|
+
export declare function undecidableArguments(mutation: {
|
|
24
|
+
readonly input?: unknown;
|
|
25
|
+
}): readonly UndecidableArgument[];
|
|
26
|
+
//# sourceMappingURL=decidable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decidable.d.ts","sourceRoot":"","sources":["../../src/mutations/decidable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CACxC;AA6BD,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,mBAAmB,EAAE,CAI3G"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { formFields } from "./form.js";
|
|
2
|
+
const walk = (field, path, out) => {
|
|
3
|
+
if (field.optional)
|
|
4
|
+
return;
|
|
5
|
+
switch (field.control) {
|
|
6
|
+
case "choice":
|
|
7
|
+
case "node":
|
|
8
|
+
case "boolean":
|
|
9
|
+
return;
|
|
10
|
+
case "number":
|
|
11
|
+
// A Score needs an ordered rubric; an unbounded number is not one.
|
|
12
|
+
if (field.min === undefined || field.max === undefined)
|
|
13
|
+
out.push({ name: path, control: field.control });
|
|
14
|
+
return;
|
|
15
|
+
case "group":
|
|
16
|
+
for (const child of field.fields)
|
|
17
|
+
walk(child, `${path}.${child.name}`, out);
|
|
18
|
+
return;
|
|
19
|
+
case "variant":
|
|
20
|
+
// The tag is a Choice; every arm must then be decidable for the
|
|
21
|
+
// provider to be able to choose any of them.
|
|
22
|
+
for (const arm of field.options) {
|
|
23
|
+
for (const child of arm.fields)
|
|
24
|
+
walk(child, `${path}.${child.name}`, out);
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
default:
|
|
28
|
+
// text, date, list, opaque: nothing a typed answer can produce.
|
|
29
|
+
out.push({ name: path, control: field.control });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/** The required arguments of an act that no typed answer can fill. */
|
|
33
|
+
export function undecidableArguments(mutation) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const field of formFields(mutation.input))
|
|
36
|
+
walk(field, field.name, out);
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=decidable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decidable.js","sourceRoot":"","sources":["../../src/mutations/decidable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAuBvD,MAAM,IAAI,GAAG,CAAC,KAAgB,EAAE,IAAY,EAAE,GAA0B,EAAQ,EAAE;IAChF,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO;IAC3B,QAAQ,KAAK,CAAC,OAAO,EAAE,CAAC;QACtB,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS;YACZ,OAAO;QACT,KAAK,QAAQ;YACX,mEAAmE;YACnE,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACzG,OAAO;QACT,KAAK,OAAO;YACV,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM;gBAAE,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAC5E,OAAO;QACT,KAAK,SAAS;YACZ,gEAAgE;YAChE,6CAA6C;YAC7C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAChC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM;oBAAE,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAC5E,CAAC;YACD,OAAO;QACT;YACE,gEAAgE;YAChE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC,CAAC;AAEF,sEAAsE;AACtE,MAAM,UAAU,oBAAoB,CAAC,QAAsC;IACzE,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7E,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { Graph } from "../graph/graph.js";
|
|
3
|
+
import type { Primitive } from "../graph/primitives.js";
|
|
4
|
+
import type { AnySchema } from "../schema/schema.js";
|
|
5
|
+
import type { AnyMutationDefinition, MutationDefinition, MutationDefinitionSpec } from "./types.js";
|
|
6
|
+
export declare function defineMutation<S extends AnySchema, const Name extends string, I extends z.ZodType>(name: Name, spec: MutationDefinitionSpec<S, I>): MutationDefinition<S, Name, I>;
|
|
7
|
+
export interface CompiledMutation {
|
|
8
|
+
readonly primitives: readonly Primitive[];
|
|
9
|
+
/** Node ids the mutation looked at while computing its writes. */
|
|
10
|
+
readonly reads: readonly string[];
|
|
11
|
+
readonly writes: readonly string[];
|
|
12
|
+
readonly intent: string;
|
|
13
|
+
}
|
|
14
|
+
/** Whether an act takes the framework's `id` argument: it creates, and has no `id` of its own. */
|
|
15
|
+
export declare function takesAnId(definition: Pick<AnyMutationDefinition, "creates" | "input">): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* An id from a name: the name's own letters, folded and hyphenated.
|
|
18
|
+
*
|
|
19
|
+
* It kept ASCII and dropped everything else, so "Zoë Lamarré" became
|
|
20
|
+
* `artist:zo-lamarr` — an address that is neither her name nor anybody's —
|
|
21
|
+
* and a name in any script without Latin letters became `item`. Accents are
|
|
22
|
+
* folded the way search folds them (`zoe-lamarre`, the id a person would
|
|
23
|
+
* guess), and a letter with no Latin form is kept as the letter it is.
|
|
24
|
+
*/
|
|
25
|
+
export declare function slug(label: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Runs a mutation against the graph WITHOUT applying it, returning the
|
|
28
|
+
* primitives it would emit plus the causal read set. Applying is the op
|
|
29
|
+
* log's job — keeping the two apart is what makes preview-as-diff free.
|
|
30
|
+
*/
|
|
31
|
+
export declare function compileMutation<S extends AnySchema>(graph: Graph<S>, definition: AnyMutationDefinition<S>, rawArgs: unknown): CompiledMutation;
|
|
32
|
+
//# sourceMappingURL=define-mutation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-mutation.d.ts","sourceRoot":"","sources":["../../src/mutations/define-mutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EACV,qBAAqB,EAErB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,cAAc,CAC5B,CAAC,SAAS,SAAS,EACnB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,CAAC,SAAS,CAAC,CAAC,OAAO,EAEnB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GACjC,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAEhC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,qBAAqB,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,OAAO,CAI/F;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS1C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EACjD,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC,EACpC,OAAO,EAAE,OAAO,GACf,gBAAgB,CAwIlB"}
|