@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 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/check/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./routes.js";
|
|
2
|
+
export * from "./lenses.js";
|
|
3
|
+
export * from "./beginnings.js";
|
|
4
|
+
export * from "./intelligence.js";
|
|
5
|
+
export * from "./city.js";
|
|
6
|
+
export * from "./settings.js";
|
|
7
|
+
export * from "./migrations.js";
|
|
8
|
+
export * from "./brand.js";
|
|
9
|
+
export * from "./modules.js";
|
|
10
|
+
export * from "./relations.js";
|
|
11
|
+
export * from "./fields.js";
|
|
12
|
+
export * from "./policy.js";
|
|
13
|
+
export * from "./arrangement.js";
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/check/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AnySchema } from "../../schema/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* `note` is a QUESTION ASKED OUT LOUD, not a problem.
|
|
4
|
+
*
|
|
5
|
+
* Some things a checker can see are legitimate designs that the author
|
|
6
|
+
* should nonetheless have looked at once: a lens written for this app and
|
|
7
|
+
* never proved against another domain, a role name two vocabularies both
|
|
8
|
+
* use, a kind unreachable on an empty graph. Filed as warnings they would
|
|
9
|
+
* be warnings that can only ever be acknowledged, and those are the ones
|
|
10
|
+
* people learn to scroll past — which costs the checker its authority on
|
|
11
|
+
* the warnings that matter. So they have their own voice: counted, printed,
|
|
12
|
+
* and never a failure.
|
|
13
|
+
*/
|
|
14
|
+
import type { CheckContext } from "./context.js";
|
|
15
|
+
export declare function checkProviders<S extends AnySchema>(ctx: CheckContext<S>): void;
|
|
16
|
+
export declare function checkModelWritten<S extends AnySchema>(ctx: CheckContext<S>): ReadonlySet<string>;
|
|
17
|
+
//# sourceMappingURL=intelligence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../../../src/cli/check/intelligence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAuG9E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CA0BhG"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { undecidableArguments } from "../../mutations/decidable.js";
|
|
2
|
+
export function checkProviders(ctx) {
|
|
3
|
+
const { app, mutations, add } = ctx;
|
|
4
|
+
/*
|
|
5
|
+
* A declared provider's allowlist must name real mutations — a metering
|
|
6
|
+
* or narrowing rule pointing at nothing enforces nothing.
|
|
7
|
+
*/
|
|
8
|
+
const DOORS = ["paste", "mcp", "key", "local"];
|
|
9
|
+
for (const provider of app.intelligence ?? []) {
|
|
10
|
+
for (const may of provider.may ?? []) {
|
|
11
|
+
if (!mutations.has(may)) {
|
|
12
|
+
add({
|
|
13
|
+
severity: "error",
|
|
14
|
+
code: "intelligence-unknown-mutation",
|
|
15
|
+
where: `intelligence["${provider.name}"].may`,
|
|
16
|
+
message: `Provider "${provider.name}" is allowed "${may}", which is not registered.`,
|
|
17
|
+
fix: `Register the mutation, or remove it from the allowlist.`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/*
|
|
22
|
+
* THE DOORS, asked about. A declaration that says how a provider is
|
|
23
|
+
* reached is worth having only if the answers are the ones the seat and
|
|
24
|
+
* the docs can act on, and if the two that owe a second sentence are
|
|
25
|
+
* made to give it: a local reach with nothing serving it is a door onto
|
|
26
|
+
* a wall, and a key typed into a browser with no storage story is the
|
|
27
|
+
* kind of thing nobody notices until it is somebody's key.
|
|
28
|
+
*/
|
|
29
|
+
const reach = provider.reach ?? [];
|
|
30
|
+
for (const door of reach) {
|
|
31
|
+
if (!DOORS.includes(door)) {
|
|
32
|
+
add({
|
|
33
|
+
severity: "error",
|
|
34
|
+
code: "intelligence-reach-unknown",
|
|
35
|
+
where: `intelligence["${provider.name}"].reach`,
|
|
36
|
+
message: `"${door}" is not a way a provider can be reached.`,
|
|
37
|
+
fix: `Use one of: ${DOORS.join(", ")}.`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (reach.length > 0 && provider.kind === "graph") {
|
|
42
|
+
add({
|
|
43
|
+
severity: "warning",
|
|
44
|
+
code: "intelligence-reach-on-graph",
|
|
45
|
+
where: `intelligence["${provider.name}"].reach`,
|
|
46
|
+
message: `"${provider.name}" is a graph provider: it IS the graph, so there is no door to it.`,
|
|
47
|
+
fix: `Drop reach, or declare the provider as "llm", "external" or "decision".`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (reach.includes("local") && !provider.bridge) {
|
|
51
|
+
add({
|
|
52
|
+
severity: "warning",
|
|
53
|
+
code: "intelligence-local-without-bridge",
|
|
54
|
+
where: `intelligence["${provider.name}"]`,
|
|
55
|
+
message: `"${provider.name}" says it can be reached locally and names no bridge, so nothing serves that door.`,
|
|
56
|
+
fix: `Add bridge: "<path>" and serve it with localIntelligence() from @graview/ship/dev.`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/*
|
|
60
|
+
* A DECISION PROVIDER IS HELD TO WHAT IT CAN DECIDE. It answers in a
|
|
61
|
+
* choice, a truth or a score and never in prose, so an act on its
|
|
62
|
+
* allowlist that wants a label or a note is an act it could never call
|
|
63
|
+
* — and an allowlist that promises one is a promise the seat would
|
|
64
|
+
* break silently, by asking a question that has no typed answer. Absent
|
|
65
|
+
* `may` means every act, and is held to every act.
|
|
66
|
+
*/
|
|
67
|
+
if (provider.kind === "decision") {
|
|
68
|
+
for (const mutation of app.mutations ?? []) {
|
|
69
|
+
if (provider.may !== undefined && !provider.may.includes(mutation.name))
|
|
70
|
+
continue;
|
|
71
|
+
const wants = undecidableArguments(mutation);
|
|
72
|
+
if (wants.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
add({
|
|
75
|
+
severity: "error",
|
|
76
|
+
code: "intelligence-decision-cannot-call",
|
|
77
|
+
where: `intelligence["${provider.name}"].may`,
|
|
78
|
+
message: `"${provider.name}" decides and does not write, and "${mutation.name}" needs ${wants
|
|
79
|
+
.map((want) => `${want.name} (${want.control})`)
|
|
80
|
+
.join(", ")} — which no typed answer can supply.`,
|
|
81
|
+
fix: provider.may === undefined
|
|
82
|
+
? `Give "${provider.name}" a may: [...] naming only the acts whose arguments are choices, node references, truths or bounded numbers.`
|
|
83
|
+
: `Drop "${mutation.name}" from may, or make its ${wants.map((want) => want.name).join(", ")} optional.`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (reach.includes("paste") || reach.includes("mcp")) {
|
|
87
|
+
add({
|
|
88
|
+
severity: "warning",
|
|
89
|
+
code: "intelligence-decision-prose-door",
|
|
90
|
+
where: `intelligence["${provider.name}"].reach`,
|
|
91
|
+
message: `"${provider.name}" decides and has no prose, so a paste or MCP door — words out, words back — leads nowhere.`,
|
|
92
|
+
fix: `Reach a decision provider by "key" or "local".`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (reach.includes("key") && !provider.keyStorage) {
|
|
97
|
+
add({
|
|
98
|
+
severity: "warning",
|
|
99
|
+
code: "intelligence-key-without-storage",
|
|
100
|
+
where: `intelligence["${provider.name}"]`,
|
|
101
|
+
message: `"${provider.name}" takes a person's own key and does not say where it is kept.`,
|
|
102
|
+
fix: `Add keyStorage: "<where, in your own words>" — a person handing over a key is owed the sentence.`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export function checkModelWritten(ctx) {
|
|
108
|
+
const { app, kinds, add } = ctx;
|
|
109
|
+
/*
|
|
110
|
+
* The kinds a declared intelligence provider can bring into existence —
|
|
111
|
+
* which is the set whose labels are written by something that has never
|
|
112
|
+
* been told what a label is for.
|
|
113
|
+
*/
|
|
114
|
+
const writtenByAModel = new Set();
|
|
115
|
+
for (const provider of app.intelligence ?? []) {
|
|
116
|
+
for (const mutation of app.mutations ?? []) {
|
|
117
|
+
if (provider.may !== undefined && !provider.may.includes(mutation.name))
|
|
118
|
+
continue;
|
|
119
|
+
for (const made of mutation.creates ?? [])
|
|
120
|
+
writtenByAModel.add(made);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (const kind of Object.keys(app.brand?.figures ?? {})) {
|
|
124
|
+
if (kinds.has(kind))
|
|
125
|
+
continue;
|
|
126
|
+
add({
|
|
127
|
+
severity: "error",
|
|
128
|
+
code: "figure-unknown-kind",
|
|
129
|
+
where: `brand.figures["${kind}"]`,
|
|
130
|
+
message: `The brand draws a figure for "${kind}", which this app does not declare.`,
|
|
131
|
+
fix: `Remove it, or declare the kind.`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return writtenByAModel;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=intelligence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.js","sourceRoot":"","sources":["../../../src/cli/check/intelligence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AnySchema } from "../../schema/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* `note` is a QUESTION ASKED OUT LOUD, not a problem.
|
|
4
|
+
*
|
|
5
|
+
* Some things a checker can see are legitimate designs that the author
|
|
6
|
+
* should nonetheless have looked at once: a lens written for this app and
|
|
7
|
+
* never proved against another domain, a role name two vocabularies both
|
|
8
|
+
* use, a kind unreachable on an empty graph. Filed as warnings they would
|
|
9
|
+
* be warnings that can only ever be acknowledged, and those are the ones
|
|
10
|
+
* people learn to scroll past — which costs the checker its authority on
|
|
11
|
+
* the warnings that matter. So they have their own voice: counted, printed,
|
|
12
|
+
* and never a failure.
|
|
13
|
+
*/
|
|
14
|
+
import type { CheckContext } from "./context.js";
|
|
15
|
+
export declare function checkShippedLenses<S extends AnySchema>(ctx: CheckContext<S>): void;
|
|
16
|
+
export declare function checkLensBindings<S extends AnySchema>(ctx: CheckContext<S>): void;
|
|
17
|
+
//# sourceMappingURL=lenses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenses.d.ts","sourceRoot":"","sources":["../../../src/cli/check/lenses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAgClF;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAgNjF"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { fieldOf } from "./context.js";
|
|
2
|
+
export function checkShippedLenses(ctx) {
|
|
3
|
+
const { app, add } = ctx;
|
|
4
|
+
/*
|
|
5
|
+
* THE LENSES THIS FRAMEWORK SHIPS, by name.
|
|
6
|
+
*
|
|
7
|
+
* Names rather than implementations, because the checker lives a tier
|
|
8
|
+
* below the package that draws them. Anything else in `lenses` is a lens
|
|
9
|
+
* this app wrote, which is the one thing worth asking about: the reuse
|
|
10
|
+
* test is the single most valuable instruction in `graview-lens` — build
|
|
11
|
+
* it against a domain it was not designed for, and if you cannot, say so
|
|
12
|
+
* plainly, you wrote a view — and nothing enforces it. This cannot
|
|
13
|
+
* enforce it either. It can make sure the question gets asked out loud
|
|
14
|
+
* every time somebody runs a check, which is most of the distance.
|
|
15
|
+
*/
|
|
16
|
+
const SHIPPED_LENSES = new Set(["timeline", "coverage", "board", "calendar", "reach"]);
|
|
17
|
+
const authored = (app.lenses ?? [])
|
|
18
|
+
.filter((lens) => !SHIPPED_LENSES.has(lens.name))
|
|
19
|
+
/* A lens that says where its reuse was proved has answered this. */
|
|
20
|
+
.filter((lens) => lens.provenBy === undefined);
|
|
21
|
+
if (authored.length > 0) {
|
|
22
|
+
add({
|
|
23
|
+
severity: "note",
|
|
24
|
+
code: "lens-authored-here",
|
|
25
|
+
where: "lenses",
|
|
26
|
+
message: `${authored.map((lens) => `"${lens.name}"`).join(", ")} ${authored.length === 1 ? "is a lens" : "are lenses"} this app wrote. A lens claims to be reusable by a domain it was not designed for.`,
|
|
27
|
+
fix: `Build ${authored.length === 1 ? "it" : "each of them"} against another domain in a test — and if you cannot, say so plainly: it is a view, and there is nothing wrong with a view.`,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function checkLensBindings(ctx) {
|
|
32
|
+
const { app, kinds, add } = ctx;
|
|
33
|
+
/** Every edge kind any node declares, for validating an entity lens. */
|
|
34
|
+
const edgeKinds = new Set();
|
|
35
|
+
for (const kind of kinds) {
|
|
36
|
+
const edges = app.schema.tryDefinition(kind)?.edges;
|
|
37
|
+
for (const edge of Object.keys(edges ?? {}))
|
|
38
|
+
edgeKinds.add(edge);
|
|
39
|
+
}
|
|
40
|
+
for (const lens of app.lenses ?? []) {
|
|
41
|
+
/*
|
|
42
|
+
* An `entities` lens binds roles to whole kinds and edges rather than a
|
|
43
|
+
* kind's fields to roles. Checking it against the field-binding shape
|
|
44
|
+
* reported every role as an undeclared node kind, which is a confident
|
|
45
|
+
* and completely wrong diagnosis — the sort a checker earns distrust for.
|
|
46
|
+
*/
|
|
47
|
+
if (lens.binds === "entities") {
|
|
48
|
+
const bindings = (lens.bindings ?? {});
|
|
49
|
+
for (const role of lens.requiredRoles) {
|
|
50
|
+
if (!(role in bindings)) {
|
|
51
|
+
add({
|
|
52
|
+
severity: "error",
|
|
53
|
+
code: "lens-role-unbound",
|
|
54
|
+
where: `lens "${lens.name}" bindings`,
|
|
55
|
+
message: `Lens "${lens.name}" requires role "${role}", which nothing binds.`,
|
|
56
|
+
fix: `Add ${role}: { kind: "<node kind>" }, { edge: "<edge kind>" } or { path: ["<edge>", …] }.`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** The kind a role names, so a field binding can be checked against it. */
|
|
61
|
+
const kindOfRole = (role) => {
|
|
62
|
+
const named = bindings[role]?.["kind"];
|
|
63
|
+
return typeof named === "string" ? named : undefined;
|
|
64
|
+
};
|
|
65
|
+
for (const [role, binding] of Object.entries(bindings)) {
|
|
66
|
+
const kind = typeof binding["kind"] === "string" ? binding["kind"] : undefined;
|
|
67
|
+
const edge = typeof binding["edge"] === "string" ? binding["edge"] : undefined;
|
|
68
|
+
const field = typeof binding["field"] === "string" ? binding["field"] : undefined;
|
|
69
|
+
/*
|
|
70
|
+
* A relationship that runs THROUGH a node is a walk, and every step
|
|
71
|
+
* of it is an edge kind somebody declared — so the whole path is
|
|
72
|
+
* checkable, which is the point of naming it here rather than
|
|
73
|
+
* reaching for the graph inside a view.
|
|
74
|
+
*/
|
|
75
|
+
const path = Array.isArray(binding["path"]) ? binding["path"] : undefined;
|
|
76
|
+
if (path !== undefined) {
|
|
77
|
+
if (path.length === 0) {
|
|
78
|
+
add({
|
|
79
|
+
severity: "error",
|
|
80
|
+
code: "lens-binding-empty-path",
|
|
81
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
82
|
+
message: `Role "${role}" binds an empty path, which reaches nothing.`,
|
|
83
|
+
fix: `Name the edge kinds from the column end to the row end, e.g. path: ["covers", "applies", "addresses"].`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
for (const step of path) {
|
|
87
|
+
if (typeof step !== "string" || !edgeKinds.has(step)) {
|
|
88
|
+
add({
|
|
89
|
+
severity: "error",
|
|
90
|
+
code: "lens-binding-undeclared-edge",
|
|
91
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
92
|
+
message: `Role "${role}" walks through "${String(step)}", which no defineNode declares as an edge.`,
|
|
93
|
+
fix: `Use one of: ${[...edgeKinds].join(", ")}.`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (kind !== undefined && !kinds.has(kind)) {
|
|
99
|
+
add({
|
|
100
|
+
severity: "error",
|
|
101
|
+
code: "lens-binding-undeclared-kind",
|
|
102
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
103
|
+
message: `Role "${role}" names kind "${kind}", which no defineNode declares.`,
|
|
104
|
+
fix: `Use one of: ${[...kinds].join(", ")}.`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (edge !== undefined && !edgeKinds.has(edge)) {
|
|
108
|
+
add({
|
|
109
|
+
severity: "error",
|
|
110
|
+
code: "lens-binding-undeclared-edge",
|
|
111
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
112
|
+
message: `Role "${role}" names edge "${edge}", which no defineNode declares.`,
|
|
113
|
+
fix: `Use one of: ${[...edgeKinds].join(", ")}.`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (field !== undefined) {
|
|
117
|
+
const owner = typeof binding["on"] === "string" ? binding["on"] : undefined;
|
|
118
|
+
const ownerKind = owner === undefined ? undefined : kindOfRole(owner);
|
|
119
|
+
if (owner === undefined || ownerKind === undefined) {
|
|
120
|
+
add({
|
|
121
|
+
severity: "error",
|
|
122
|
+
code: "lens-binding-fieldless-owner",
|
|
123
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
124
|
+
message: `Role "${role}" binds field "${field}" but does not say which role's kind it belongs to.`,
|
|
125
|
+
fix: `Add on: "<role that binds a kind>".`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const shape = app.schema.tryDefinition(ownerKind)?.fields.shape;
|
|
130
|
+
if (shape && !(field in shape)) {
|
|
131
|
+
add({
|
|
132
|
+
severity: "error",
|
|
133
|
+
code: "lens-binding-missing-field",
|
|
134
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
135
|
+
message: `Role "${role}" maps to field "${field}", which "${ownerKind}" does not declare.`,
|
|
136
|
+
fix: `Point it at one of: ${Object.keys(shape).join(", ")}.`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (kind === undefined && edge === undefined && field === undefined && path === undefined) {
|
|
142
|
+
add({
|
|
143
|
+
severity: "error",
|
|
144
|
+
code: "lens-binding-empty",
|
|
145
|
+
where: `lens "${lens.name}" bindings.${role}`,
|
|
146
|
+
message: `Role "${role}" binds nothing.`,
|
|
147
|
+
fix: `Give it { kind: "<node kind>" }, { edge: "<edge kind>" }, { path: ["<edge>", …] } or { field: "<field>", on: "<role>" }.`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
for (const [kind, rawBindings] of Object.entries(lens.bindings ?? {})) {
|
|
154
|
+
const bindings = rawBindings;
|
|
155
|
+
if (!kinds.has(kind)) {
|
|
156
|
+
add({
|
|
157
|
+
severity: "error",
|
|
158
|
+
code: "lens-binding-undeclared-kind",
|
|
159
|
+
where: `lens "${lens.name}" bindings`,
|
|
160
|
+
message: `Binds roles for "${kind}", which no defineNode declares.`,
|
|
161
|
+
fix: `Use one of: ${[...kinds].join(", ")}.`,
|
|
162
|
+
});
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const definition = app.schema.tryDefinition(kind);
|
|
166
|
+
if (!definition)
|
|
167
|
+
continue;
|
|
168
|
+
const shape = definition.fields.shape;
|
|
169
|
+
for (const [role, bound] of Object.entries(bindings)) {
|
|
170
|
+
/*
|
|
171
|
+
* A ROLE IS A FIELD NAME, OR A FIELD AND THE VALUES THAT MAKE IT
|
|
172
|
+
* TRUE. The second shape — `{ field: "status", is: ["done"] }` — is
|
|
173
|
+
* how `lifecycle` already reads a state, and a role that reads
|
|
174
|
+
* completion has to accept it or most domains cannot bind it at all.
|
|
175
|
+
* The checker asks the same question of both: is that a field this
|
|
176
|
+
* kind declares?
|
|
177
|
+
*/
|
|
178
|
+
const field = fieldOf(bound);
|
|
179
|
+
if (field === undefined) {
|
|
180
|
+
add({
|
|
181
|
+
severity: "error",
|
|
182
|
+
code: "lens-binding-not-a-field",
|
|
183
|
+
where: `lens "${lens.name}" bindings.${kind}.${role}`,
|
|
184
|
+
message: `Role "${role}" is bound to ${JSON.stringify(bound)}, which is neither a field name nor { field, is }.`,
|
|
185
|
+
fix: `Use a field name, or { field: "<field>", is: ["<value>", …] }.`,
|
|
186
|
+
});
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (!(field in shape)) {
|
|
190
|
+
add({
|
|
191
|
+
severity: "error",
|
|
192
|
+
code: "lens-binding-missing-field",
|
|
193
|
+
where: `lens "${lens.name}" bindings.${kind}.${role}`,
|
|
194
|
+
message: `Role "${role}" maps to field "${field}", which "${kind}" does not declare.`,
|
|
195
|
+
fix: `Point it at one of: ${Object.keys(shape).join(", ")}.`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const role of lens.requiredRoles) {
|
|
200
|
+
if (!(role in bindings)) {
|
|
201
|
+
add({
|
|
202
|
+
severity: "error",
|
|
203
|
+
code: "lens-role-unbound",
|
|
204
|
+
where: `lens "${lens.name}" bindings.${kind}`,
|
|
205
|
+
message: `Lens "${lens.name}" requires role "${role}", which "${kind}" does not bind.`,
|
|
206
|
+
fix: `Add ${role}: "<field name>" to the bindings for "${kind}".`,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/*
|
|
211
|
+
* TWO PLACES NAME A ROLE, AND THEY DO DIFFERENT JOBS.
|
|
212
|
+
*
|
|
213
|
+
* `fieldRoles` on the kind is what everything that is not a lens reads
|
|
214
|
+
* — the graph's own responder answering "when is it", the generated
|
|
215
|
+
* docs. A lens reads `bindings` and only `bindings`. Neither overrides
|
|
216
|
+
* the other, because neither is looking at the other.
|
|
217
|
+
*
|
|
218
|
+
* Which is fine until they disagree, and then one surface answers with
|
|
219
|
+
* one field and the next surface answers with another, both truthfully.
|
|
220
|
+
* Nothing could see it before: each half is valid on its own.
|
|
221
|
+
*/
|
|
222
|
+
const declaredRoles = (definition.fieldRoles ?? {});
|
|
223
|
+
for (const [role, bound] of Object.entries(bindings)) {
|
|
224
|
+
const field = fieldOf(bound);
|
|
225
|
+
const declared = declaredRoles[role];
|
|
226
|
+
if (field === undefined || declared === undefined || declared === field)
|
|
227
|
+
continue;
|
|
228
|
+
add({
|
|
229
|
+
severity: "note",
|
|
230
|
+
code: "lens-binding-disagrees-with-field-role",
|
|
231
|
+
where: `lens "${lens.name}" bindings.${kind}.${role}`,
|
|
232
|
+
message: `The lens binds "${role}" to "${field}"; defineNode("${kind}").fieldRoles binds it to "${declared}". A lens reads bindings and everything else reads fieldRoles, so the picture and the sentence will answer differently.`,
|
|
233
|
+
fix: `Point both at the same field — or keep them apart deliberately, which is right when two lenses mean different things by one role name (a day and a time of day both being a "start").`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=lenses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenses.js","sourceRoot":"","sources":["../../../src/cli/check/lenses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnySchema } from "../../schema/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* `note` is a QUESTION ASKED OUT LOUD, not a problem.
|
|
4
|
+
*
|
|
5
|
+
* Some things a checker can see are legitimate designs that the author
|
|
6
|
+
* should nonetheless have looked at once: a lens written for this app and
|
|
7
|
+
* never proved against another domain, a role name two vocabularies both
|
|
8
|
+
* use, a kind unreachable on an empty graph. Filed as warnings they would
|
|
9
|
+
* be warnings that can only ever be acknowledged, and those are the ones
|
|
10
|
+
* people learn to scroll past — which costs the checker its authority on
|
|
11
|
+
* the warnings that matter. So they have their own voice: counted, printed,
|
|
12
|
+
* and never a failure.
|
|
13
|
+
*/
|
|
14
|
+
import type { CheckContext } from "./context.js";
|
|
15
|
+
export declare function checkMigrations<S extends AnySchema>(ctx: CheckContext<S>): void;
|
|
16
|
+
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/cli/check/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAwC/E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function checkMigrations(ctx) {
|
|
2
|
+
const { app, add } = ctx;
|
|
3
|
+
/*
|
|
4
|
+
* The migration chain must actually reach the declared version. A stored
|
|
5
|
+
* graph at version 1 with a declaration at 3 and a hole at 2 is a
|
|
6
|
+
* deployment that cannot start — findable here instead of there.
|
|
7
|
+
*/
|
|
8
|
+
if (app.version !== undefined) {
|
|
9
|
+
const steps = new Map((app.migrations ?? []).map((m) => [m.from, m]));
|
|
10
|
+
for (const migration of app.migrations ?? []) {
|
|
11
|
+
if (migration.to !== migration.from + 1) {
|
|
12
|
+
add({
|
|
13
|
+
severity: "error",
|
|
14
|
+
code: "migration-not-single-step",
|
|
15
|
+
where: `migrations[${migration.from}→${migration.to}]`,
|
|
16
|
+
message: `Migrations move one version at a time; this one jumps ${migration.from}→${migration.to}.`,
|
|
17
|
+
fix: `Split it into single steps so any stored version has a path.`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
for (let at = 1; at < app.version; at++) {
|
|
22
|
+
if (!steps.has(at)) {
|
|
23
|
+
add({
|
|
24
|
+
severity: "error",
|
|
25
|
+
code: "migration-gap",
|
|
26
|
+
where: `defineApp("${app.name}").migrations`,
|
|
27
|
+
message: `No migration from version ${at}, so a graph stored at ${at} cannot reach ${app.version}.`,
|
|
28
|
+
fix: `Declare a migration { from: ${at}, to: ${at + 1}, ... }.`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if ((app.migrations ?? []).length > 0) {
|
|
34
|
+
add({
|
|
35
|
+
severity: "error",
|
|
36
|
+
code: "migration-without-version",
|
|
37
|
+
where: `defineApp("${app.name}").version`,
|
|
38
|
+
message: `Migrations are declared but the app declares no version to migrate to.`,
|
|
39
|
+
fix: `Declare version: <n> alongside the migrations.`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/cli/check/migrations.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,eAAe,CAAsB,GAAoB;IACvE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACzB;;;;OAIG;IACH,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;YAC7C,IAAI,SAAS,CAAC,EAAE,KAAK,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACxC,GAAG,CAAC;oBACF,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,2BAA2B;oBACjC,KAAK,EAAE,cAAc,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,GAAG;oBACtD,OAAO,EAAE,yDAAyD,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,GAAG;oBACnG,GAAG,EAAE,8DAA8D;iBACpE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,GAAG,CAAC;oBACF,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,eAAe;oBACrB,KAAK,EAAE,cAAc,GAAG,CAAC,IAAI,eAAe;oBAC5C,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,iBAAiB,GAAG,CAAC,OAAO,GAAG;oBACnG,GAAG,EAAE,+BAA+B,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU;iBAChE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC;YACF,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,2BAA2B;YACjC,KAAK,EAAE,cAAc,GAAG,CAAC,IAAI,YAAY;YACzC,OAAO,EAAE,wEAAwE;YACjF,GAAG,EAAE,gDAAgD;SACtD,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AnySchema } from "../../schema/schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* `note` is a QUESTION ASKED OUT LOUD, not a problem.
|
|
4
|
+
*
|
|
5
|
+
* Some things a checker can see are legitimate designs that the author
|
|
6
|
+
* should nonetheless have looked at once: a lens written for this app and
|
|
7
|
+
* never proved against another domain, a role name two vocabularies both
|
|
8
|
+
* use, a kind unreachable on an empty graph. Filed as warnings they would
|
|
9
|
+
* be warnings that can only ever be acknowledged, and those are the ones
|
|
10
|
+
* people learn to scroll past — which costs the checker its authority on
|
|
11
|
+
* the warnings that matter. So they have their own voice: counted, printed,
|
|
12
|
+
* and never a failure.
|
|
13
|
+
*/
|
|
14
|
+
import type { CheckContext } from "./context.js";
|
|
15
|
+
export declare function checkModules<S extends AnySchema>(ctx: CheckContext<S>): void;
|
|
16
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../../src/cli/check/modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAuH5E"}
|