@adminiumjs/engine 0.1.2 → 0.2.2-rc.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.
Files changed (87) hide show
  1. package/dist/adapter-registry.d.ts.map +1 -1
  2. package/dist/adapter-registry.js.map +1 -1
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +1 -0
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/capabilities.d.ts.map +1 -1
  7. package/dist/capabilities.js.map +1 -1
  8. package/dist/classify/columns.d.ts.map +1 -1
  9. package/dist/classify/columns.js.map +1 -1
  10. package/dist/classify/index.d.ts +1 -1
  11. package/dist/classify/index.d.ts.map +1 -1
  12. package/dist/classify/index.js +1 -1
  13. package/dist/classify/index.js.map +1 -1
  14. package/dist/classify/names.d.ts.map +1 -1
  15. package/dist/classify/names.js +1 -0
  16. package/dist/classify/names.js.map +1 -1
  17. package/dist/classify/pii.d.ts.map +1 -1
  18. package/dist/classify/pii.js +10 -1
  19. package/dist/classify/pii.js.map +1 -1
  20. package/dist/classify/tables.d.ts +49 -0
  21. package/dist/classify/tables.d.ts.map +1 -1
  22. package/dist/classify/tables.js +72 -2
  23. package/dist/classify/tables.js.map +1 -1
  24. package/dist/config-schema/envelope.d.ts +20 -0
  25. package/dist/config-schema/envelope.d.ts.map +1 -1
  26. package/dist/config-schema/envelope.js +24 -0
  27. package/dist/config-schema/envelope.js.map +1 -1
  28. package/dist/config-schema/index.d.ts +4 -2
  29. package/dist/config-schema/index.d.ts.map +1 -1
  30. package/dist/config-schema/index.js +10 -2
  31. package/dist/config-schema/index.js.map +1 -1
  32. package/dist/config-schema/migrations.d.ts.map +1 -1
  33. package/dist/config-schema/migrations.js +1 -0
  34. package/dist/config-schema/migrations.js.map +1 -1
  35. package/dist/config-schema/table-bound.d.ts +20 -0
  36. package/dist/config-schema/table-bound.d.ts.map +1 -0
  37. package/dist/config-schema/table-bound.js +34 -0
  38. package/dist/config-schema/table-bound.js.map +1 -0
  39. package/dist/generate/archetype.d.ts.map +1 -1
  40. package/dist/generate/archetype.js +1 -0
  41. package/dist/generate/archetype.js.map +1 -1
  42. package/dist/generate/crud.d.ts.map +1 -1
  43. package/dist/generate/crud.js +1 -0
  44. package/dist/generate/crud.js.map +1 -1
  45. package/dist/generate/dashboard.d.ts.map +1 -1
  46. package/dist/generate/dashboard.js +1 -0
  47. package/dist/generate/dashboard.js.map +1 -1
  48. package/dist/generate/domains.d.ts.map +1 -1
  49. package/dist/generate/domains.js +1 -0
  50. package/dist/generate/domains.js.map +1 -1
  51. package/dist/generate/index.d.ts +16 -0
  52. package/dist/generate/index.d.ts.map +1 -1
  53. package/dist/generate/index.js +17 -0
  54. package/dist/generate/index.js.map +1 -1
  55. package/dist/generate/recompose.d.ts +51 -0
  56. package/dist/generate/recompose.d.ts.map +1 -0
  57. package/dist/generate/recompose.js +100 -0
  58. package/dist/generate/recompose.js.map +1 -0
  59. package/dist/generate/util.d.ts.map +1 -1
  60. package/dist/generate/util.js +1 -0
  61. package/dist/generate/util.js.map +1 -1
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +2 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/infer/index.d.ts +10 -0
  67. package/dist/infer/index.d.ts.map +1 -0
  68. package/dist/infer/index.js +11 -0
  69. package/dist/infer/index.js.map +1 -0
  70. package/dist/infer/relations.d.ts +41 -0
  71. package/dist/infer/relations.d.ts.map +1 -0
  72. package/dist/infer/relations.js +473 -0
  73. package/dist/infer/relations.js.map +1 -0
  74. package/dist/schema-model.d.ts.map +1 -1
  75. package/dist/schema-model.js +1 -0
  76. package/dist/schema-model.js.map +1 -1
  77. package/dist/snapshot/diff.d.ts.map +1 -1
  78. package/dist/snapshot/diff.js +1 -0
  79. package/dist/snapshot/diff.js.map +1 -1
  80. package/dist/snapshot/hash.d.ts.map +1 -1
  81. package/dist/snapshot/hash.js.map +1 -1
  82. package/dist/snapshot/index.d.ts.map +1 -1
  83. package/dist/snapshot/index.js.map +1 -1
  84. package/dist/snapshot/sha256.d.ts.map +1 -1
  85. package/dist/snapshot/sha256.js +1 -0
  86. package/dist/snapshot/sha256.js.map +1 -1
  87. package/package.json +2 -2
@@ -0,0 +1,100 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ /**
3
+ * Recompose ONE page against a chosen table — the Studio page editor's
4
+ * "change the data this page shows" write.
5
+ *
6
+ * `generatePages` composes the whole app from a snapshot and decides every
7
+ * template itself. `composeRequestedArchetype` (06 §8.3) composes one page but
8
+ * only for the nine §14 archetypes, because it delegates to
9
+ * `buildArchetypeEnvelope`, which returns null for anything outside
10
+ * `ARCHETYPE_NAV`. Neither serves an admin who picked `page-crud` for a table
11
+ * by hand, which is the most common thing to pick.
12
+ *
13
+ * This is the missing third entry point: same classify → candidates → compose
14
+ * prelude those two share, dispatching to `buildCrudEnvelope` for `page-crud`
15
+ * and `buildArchetypeEnvelope` for the archetypes. It exists so the server can
16
+ * rebuild a page's body from live schema instead of leaving hand-created pages
17
+ * permanently empty.
18
+ *
19
+ * NOT every template is table-bound. `page-dashboard` composes from a DOMAIN
20
+ * (a cluster of tables) rather than one table and is edited widget-by-widget in
21
+ * the dashboard builder; `page-builder`, `page-wizard` and `page-settings` are
22
+ * tool surfaces whose bodies the renderers ignore. Asking for those returns
23
+ * `bindable: false` with a null envelope, so the caller can keep whatever the
24
+ * page already had rather than blanking it.
25
+ */
26
+ import { emitCandidates, isRegisteredWidgetId, } from '@adminium/widgets/generate';
27
+ import { classifyModel } from '../classify/index.js';
28
+ import { isTableBoundTemplate } from '../config-schema/table-bound.js';
29
+ import { buildArchetypeEnvelope, toCandidateModel } from './archetype.js';
30
+ import { buildCrudEnvelope } from './crud.js';
31
+ export { TABLE_BOUND_TEMPLATES, isTableBoundTemplate } from '../config-schema/table-bound.js';
32
+ export function composeRequestedPage(model, tableId, template, ctx) {
33
+ if (!isTableBoundTemplate(template)) {
34
+ return { envelope: null, bindable: false, reason: '' };
35
+ }
36
+ const classified = new Map(classifyModel(model).tables.map((t) => [t.tableId, t]));
37
+ // The same include rule `generatePages`' splitTables applies: system and
38
+ // join tables never earn a page (05 §8.2). Offering one in the picker and
39
+ // then composing it anyway would produce a page the next generation run
40
+ // deletes.
41
+ const tables = [...model.tables]
42
+ .filter((table) => {
43
+ const role = classified.get(table.id)?.semantics.role ?? table.semantics?.role ?? 'entity';
44
+ return !table.system && role !== 'system' && role !== 'join-table';
45
+ })
46
+ .sort((a, b) => a.id.localeCompare(b.id));
47
+ const table = tables.find((t) => t.id === tableId);
48
+ if (table === undefined) {
49
+ return {
50
+ envelope: null,
51
+ bindable: true,
52
+ reason: `table ${tableId} is not available (excluded from this connection, or a system/join table)`,
53
+ };
54
+ }
55
+ const isRegistered = ctx.isRegistered ?? isRegisteredWidgetId;
56
+ const candidateModel = toCandidateModel(model, tables, classified);
57
+ const entry = candidateModel.find((e) => e.table.id === tableId);
58
+ if (entry === undefined) {
59
+ return { envelope: null, bindable: true, reason: `table ${tableId} could not be classified` };
60
+ }
61
+ if (template === 'page-crud') {
62
+ const envelope = buildCrudEnvelope(entry, {
63
+ connectionId: ctx.connectionId,
64
+ slug: ctx.slug,
65
+ navGroup: ctx.navGroup,
66
+ navIcon: ctx.navIcon,
67
+ navOrder: ctx.navOrder,
68
+ readOnly: ctx.readOnly ?? false,
69
+ // Detail tabs may only link tables that actually have pages. Every
70
+ // non-system table of this connection qualifies — the generator emits a
71
+ // page-crud for each — so the full set is the honest allowlist here.
72
+ includedTableIds: new Set(tables.map((t) => t.id)),
73
+ relations: model.relations,
74
+ });
75
+ // `CrudBuildContext` has no `id`: the generator derives one with
76
+ // `pageIdFor(connectionId, slug)` because it is MINTING pages. Here the
77
+ // page already exists and is stored under `ctx.id`, so letting the derived
78
+ // id through would leave the document claiming to be a different page than
79
+ // the row holding it. `buildArchetypeEnvelope` already accepts `ctx.id`;
80
+ // this is the crud path catching up.
81
+ return { bindable: true, reason: '', envelope: { ...envelope, id: ctx.id } };
82
+ }
83
+ const candidateCtx = {
84
+ connectionId: ctx.connectionId,
85
+ model: candidateModel,
86
+ isRegistered,
87
+ };
88
+ const candidates = emitCandidates(entry.table, entry.classified, candidateCtx);
89
+ const built = buildArchetypeEnvelope(table, { template, score: 0, reasons: ['chosen in Studio → Pages'] }, candidates, { ...ctx, isRegistered });
90
+ if (built.envelope === null) {
91
+ const detail = built.warnings.map((w) => w.message).join('; ');
92
+ return {
93
+ envelope: null,
94
+ bindable: true,
95
+ reason: detail || `this table has no columns the ${template} layout can bind`,
96
+ };
97
+ }
98
+ return { envelope: built.envelope, bindable: true, reason: '' };
99
+ }
100
+ //# sourceMappingURL=recompose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recompose.js","sourceRoot":"","sources":["../../src/generate/recompose.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/generate/util.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED,+EAA+E;AAC/E,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAS5B;AAED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7C;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlD;AAaD;;;;;;GAMG;AACH;;;GAGG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAoBjC;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAOtE"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/generate/util.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAIH;;;GAGG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS5C;AAED,+EAA+E;AAC/E,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAS5B;AAED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7C;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlD;AAaD;;;;;;GAMG;AACH;;;GAGG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAoBjC;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAOtE"}
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
1
2
  /**
2
3
  * Shared helpers for the generator (05-introspection-engine.md generation
3
4
  * section, 09-generated-app.md §2.2 slug rules).
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/generate/util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/generate/util.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  export declare const PACKAGE_NAME = "@adminium/engine";
3
3
  export * from './schema-model.js';
4
4
  export * from './adapter.js';
5
+ export * from './infer/index.js';
5
6
  export * from './classify/index.js';
6
7
  export * from './snapshot/index.js';
7
8
  export * from './generate/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4HAA4H;AAC5H,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,4HAA4H;AAC5H,eAAO,MAAM,YAAY,qBAAqB,CAAC;AAE/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
1
2
  /** @adminium/engine — SchemaModel, Adapter interface, classification, config generation. See 05-introspection-engine.md. */
2
3
  export const PACKAGE_NAME = '@adminium/engine';
3
4
  export * from './schema-model.js';
4
5
  export * from './adapter.js';
6
+ export * from './infer/index.js';
5
7
  export * from './classify/index.js';
6
8
  export * from './snapshot/index.js';
7
9
  export * from './generate/index.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4HAA4H;AAC5H,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,4HAA4H;AAC5H,MAAM,CAAC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AAE/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `@adminium/engine` inference entry point — 05-introspection-engine.md §6
3
+ * rules 1–2, the relations a schema implies but never declares.
4
+ *
5
+ * Runs BEFORE classification (`applyInference` → `applyClassification`), not
6
+ * inside it: both classifiers read `model.relations`, and the whole point of
7
+ * inferring a relation is that they should see it.
8
+ */
9
+ export { applyInference, inferJoinTableRelations, inferNameRelations, inferRelations, type InferredRelation, } from './relations.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/infer/index.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AACH,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ /**
3
+ * `@adminium/engine` inference entry point — 05-introspection-engine.md §6
4
+ * rules 1–2, the relations a schema implies but never declares.
5
+ *
6
+ * Runs BEFORE classification (`applyInference` → `applyClassification`), not
7
+ * inside it: both classifiers read `model.relations`, and the whole point of
8
+ * inferring a relation is that they should see it.
9
+ */
10
+ export { applyInference, inferJoinTableRelations, inferNameRelations, inferRelations, } from './relations.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infer/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC;;;;;;;GAOG;AACH,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,GAEf,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { DatabaseModel, Relation } from '../schema-model.js';
2
+ /** An inferred relation plus the evidence that produced it. */
3
+ export interface InferredRelation {
4
+ relation: Relation;
5
+ /** Human-readable evidence, for tests and the Studio remap editor. */
6
+ reasons: string[];
7
+ }
8
+ /**
9
+ * Rule 1: `customer_id` → `customers.id`.
10
+ *
11
+ * The canonical case — exact singular/plural name match, agreeing types, a
12
+ * declared single-column PK on the far side — reaches 0.90 and behaves like
13
+ * a declared FK everywhere. Every weakening (a role prefix dropped, a
14
+ * cross-schema hop, an ambiguous name, a non-unique target column, types
15
+ * that merely rhyme) costs enough to fall into the 0.5–0.79 suggestion band.
16
+ */
17
+ export declare function inferNameRelations(model: DatabaseModel): InferredRelation[];
18
+ /**
19
+ * Rule 2: a table that is nothing but two FKs is an M2M edge, not an entity.
20
+ *
21
+ * Idempotence matters here beyond re-runs: `@adminium/schema-import`'s Django
22
+ * parser already emits `inferred-join-table` relations for every
23
+ * `ManyToManyField`, so an imported model arrives with M2M relations a live
24
+ * introspection of the same database does not have. A through table already
25
+ * covered by ANY relation is left alone, which keeps the two paths from
26
+ * disagreeing and keeps `databaseModelSchema.superRefine` (which throws on a
27
+ * duplicate relation id) satisfied.
28
+ */
29
+ export declare function inferJoinTableRelations(model: DatabaseModel): InferredRelation[];
30
+ /** Both rules, in the only order that works. Rule 2 sees rule 1's output. */
31
+ export declare function inferRelations(model: DatabaseModel): InferredRelation[];
32
+ /**
33
+ * Return a NEW model with §6 rules 1–2 relations appended. Call it BEFORE
34
+ * `applyClassification` — the column and table classifiers both read
35
+ * `model.relations`, and that is the entire point of inferring them.
36
+ *
37
+ * Idempotent: a second pass finds every column already claimed and every
38
+ * join table already covered, so it returns the model untouched.
39
+ */
40
+ export declare function applyInference(model: DatabaseModel): DatabaseModel;
41
+ //# sourceMappingURL=relations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/infer/relations.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAe,aAAa,EAAE,QAAQ,EAAc,MAAM,oBAAoB,CAAC;AAgC3F,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAsMD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,EAAE,CAiH3E;AAsDD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,EAAE,CA+ChF;AAMD,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,EAAE,CAOvE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,CAKlE"}