@adminiumjs/engine 0.1.0-rc.1

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 (94) hide show
  1. package/LICENSE +661 -0
  2. package/dist/adapter-registry.d.ts +62 -0
  3. package/dist/adapter-registry.d.ts.map +1 -0
  4. package/dist/adapter-registry.js +75 -0
  5. package/dist/adapter-registry.js.map +1 -0
  6. package/dist/adapter.d.ts +384 -0
  7. package/dist/adapter.d.ts.map +1 -0
  8. package/dist/adapter.js +54 -0
  9. package/dist/adapter.js.map +1 -0
  10. package/dist/capabilities.d.ts +57 -0
  11. package/dist/capabilities.d.ts.map +1 -0
  12. package/dist/capabilities.js +131 -0
  13. package/dist/capabilities.js.map +1 -0
  14. package/dist/classify/columns.d.ts +57 -0
  15. package/dist/classify/columns.d.ts.map +1 -0
  16. package/dist/classify/columns.js +535 -0
  17. package/dist/classify/columns.js.map +1 -0
  18. package/dist/classify/index.d.ts +29 -0
  19. package/dist/classify/index.d.ts.map +1 -0
  20. package/dist/classify/index.js +44 -0
  21. package/dist/classify/index.js.map +1 -0
  22. package/dist/classify/names.d.ts +11 -0
  23. package/dist/classify/names.d.ts.map +1 -0
  24. package/dist/classify/names.js +19 -0
  25. package/dist/classify/names.js.map +1 -0
  26. package/dist/classify/pii.d.ts +29 -0
  27. package/dist/classify/pii.d.ts.map +1 -0
  28. package/dist/classify/pii.js +55 -0
  29. package/dist/classify/pii.js.map +1 -0
  30. package/dist/classify/tables.d.ts +64 -0
  31. package/dist/classify/tables.d.ts.map +1 -0
  32. package/dist/classify/tables.js +303 -0
  33. package/dist/classify/tables.js.map +1 -0
  34. package/dist/config-schema/envelope.d.ts +83 -0
  35. package/dist/config-schema/envelope.d.ts.map +1 -0
  36. package/dist/config-schema/envelope.js +87 -0
  37. package/dist/config-schema/envelope.js.map +1 -0
  38. package/dist/config-schema/index.d.ts +14 -0
  39. package/dist/config-schema/index.d.ts.map +1 -0
  40. package/dist/config-schema/index.js +15 -0
  41. package/dist/config-schema/index.js.map +1 -0
  42. package/dist/config-schema/migrations.d.ts +44 -0
  43. package/dist/config-schema/migrations.d.ts.map +1 -0
  44. package/dist/config-schema/migrations.js +62 -0
  45. package/dist/config-schema/migrations.js.map +1 -0
  46. package/dist/generate/archetype.d.ts +76 -0
  47. package/dist/generate/archetype.d.ts.map +1 -0
  48. package/dist/generate/archetype.js +250 -0
  49. package/dist/generate/archetype.js.map +1 -0
  50. package/dist/generate/crud.d.ts +36 -0
  51. package/dist/generate/crud.d.ts.map +1 -0
  52. package/dist/generate/crud.js +45 -0
  53. package/dist/generate/crud.js.map +1 -0
  54. package/dist/generate/dashboard.d.ts +43 -0
  55. package/dist/generate/dashboard.d.ts.map +1 -0
  56. package/dist/generate/dashboard.js +61 -0
  57. package/dist/generate/dashboard.js.map +1 -0
  58. package/dist/generate/domains.d.ts +29 -0
  59. package/dist/generate/domains.d.ts.map +1 -0
  60. package/dist/generate/domains.js +145 -0
  61. package/dist/generate/domains.js.map +1 -0
  62. package/dist/generate/index.d.ts +78 -0
  63. package/dist/generate/index.d.ts.map +1 -0
  64. package/dist/generate/index.js +301 -0
  65. package/dist/generate/index.js.map +1 -0
  66. package/dist/generate/util.d.ts +46 -0
  67. package/dist/generate/util.d.ts.map +1 -0
  68. package/dist/generate/util.js +123 -0
  69. package/dist/generate/util.js.map +1 -0
  70. package/dist/index.d.ts +8 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +8 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/schema-model.d.ts +1853 -0
  75. package/dist/schema-model.d.ts.map +1 -0
  76. package/dist/schema-model.js +463 -0
  77. package/dist/schema-model.js.map +1 -0
  78. package/dist/snapshot/diff.d.ts +258 -0
  79. package/dist/snapshot/diff.d.ts.map +1 -0
  80. package/dist/snapshot/diff.js +151 -0
  81. package/dist/snapshot/diff.js.map +1 -0
  82. package/dist/snapshot/hash.d.ts +23 -0
  83. package/dist/snapshot/hash.d.ts.map +1 -0
  84. package/dist/snapshot/hash.js +47 -0
  85. package/dist/snapshot/hash.js.map +1 -0
  86. package/dist/snapshot/index.d.ts +28 -0
  87. package/dist/snapshot/index.d.ts.map +1 -0
  88. package/dist/snapshot/index.js +26 -0
  89. package/dist/snapshot/index.js.map +1 -0
  90. package/dist/snapshot/sha256.d.ts +14 -0
  91. package/dist/snapshot/sha256.d.ts.map +1 -0
  92. package/dist/snapshot/sha256.js +99 -0
  93. package/dist/snapshot/sha256.js.map +1 -0
  94. package/package.json +37 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Name normalization for classifier rules — 05-introspection-engine.md §7:
3
+ * "Name matching operates on a normalized token form: lowercase, camelCase
4
+ * split to snake_case." Every regex in columns.ts/pii.ts/tables.ts runs
5
+ * against `normalizeName(name)`, never the raw identifier.
6
+ */
7
+ /** `userId` → `user_id`, `HTMLBody` → `html_body`, `Created-At` → `created_at`. */
8
+ export declare function normalizeName(name: string): string;
9
+ /** Split a normalized name into tokens (`unit_price` → ['unit','price']). */
10
+ export declare function nameTokens(name: string): string[];
11
+ //# sourceMappingURL=names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/classify/names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Name normalization for classifier rules — 05-introspection-engine.md §7:
3
+ * "Name matching operates on a normalized token form: lowercase, camelCase
4
+ * split to snake_case." Every regex in columns.ts/pii.ts/tables.ts runs
5
+ * against `normalizeName(name)`, never the raw identifier.
6
+ */
7
+ /** `userId` → `user_id`, `HTMLBody` → `html_body`, `Created-At` → `created_at`. */
8
+ export function normalizeName(name) {
9
+ return name
10
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
11
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
12
+ .replace(/[\s-]+/g, '_')
13
+ .toLowerCase();
14
+ }
15
+ /** Split a normalized name into tokens (`unit_price` → ['unit','price']). */
16
+ export function nameTokens(name) {
17
+ return normalizeName(name).split('_').filter(Boolean);
18
+ }
19
+ //# sourceMappingURL=names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/classify/names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI;SACR,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PII detection and masking defaults — 05-introspection-engine.md §7.2.
3
+ *
4
+ * PII is a flag layer INDEPENDENT of the primary semantic: it runs after the
5
+ * §7.1 rule pipeline and can flag any column regardless of which primary tag
6
+ * won. Masking is a display/export transform applied downstream by the
7
+ * server serialization layer (08-server-api.md) — this module only decides
8
+ * `pii` kind and `maskedByDefault`.
9
+ */
10
+ import type { ColumnModel, PiiKind, SemanticTag } from '../schema-model.js';
11
+ export interface PiiResult {
12
+ pii: PiiKind | null;
13
+ maskedByDefault: boolean;
14
+ reasons: string[];
15
+ }
16
+ export interface PiiContext {
17
+ /** People-shaped table per the §8 directory trigger (see tables.ts). */
18
+ peopleish: boolean;
19
+ /** Set when the column is half of a classified geo lat/lng pair. */
20
+ isGeoPointPair: boolean;
21
+ }
22
+ /**
23
+ * §7.2 kinds and triggers. Rules 17/18/26 (email/phone/ip) arrive as the
24
+ * already-decided primary tag; person-name PII only applies to
25
+ * first/last/full name columns on people-shaped tables; geo-precise only to
26
+ * lat/lng pairs on people-shaped tables.
27
+ */
28
+ export declare function detectPii(column: ColumnModel, primary: SemanticTag, ctx: PiiContext): PiiResult;
29
+ //# sourceMappingURL=pii.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../../src/classify/pii.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAe5E,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,cAAc,EAAE,OAAO,CAAC;CACzB;AAID;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,UAAU,GACd,SAAS,CAmCX"}
@@ -0,0 +1,55 @@
1
+ import { normalizeName } from './names.js';
2
+ /** §7.2 name triggers that are independent of the §7.1 primary tag. */
3
+ const ADDRESS_RE = /(^|_)(address|street|city|zip|postal_code|postcode)(_|$)/;
4
+ const DOB_RE = /(^|_)(birth(date|day)?|dob|date_of_birth)(_|$)/;
5
+ const GOV_ID_RE = /(ssn|social_security|tax_id|vat(_number)?|passport|national_id|driver_licen[cs]e)/;
6
+ /**
7
+ * §7.2 lists this unanchored, but short tokens (`pan`, `bic`) then match as
8
+ * substrings of ordinary words — `company_name` contains "pan". We anchor
9
+ * every alternative on token boundaries to avoid that false positive.
10
+ */
11
+ const PAYMENT_ID_RE = /(^|_)(card_number|pan|iban|account_number|routing_number|bic|swift)(_|$)/;
12
+ const TEXTISH = new Set(['text', 'varchar', 'unknown']);
13
+ /**
14
+ * §7.2 kinds and triggers. Rules 17/18/26 (email/phone/ip) arrive as the
15
+ * already-decided primary tag; person-name PII only applies to
16
+ * first/last/full name columns on people-shaped tables; geo-precise only to
17
+ * lat/lng pairs on people-shaped tables.
18
+ */
19
+ export function detectPii(column, primary, ctx) {
20
+ const name = normalizeName(column.name);
21
+ if (primary === 'email') {
22
+ return pii('email', 'primary semantic is email (§7.1 rule 17)');
23
+ }
24
+ if (primary === 'phone') {
25
+ return pii('phone', 'primary semantic is phone (§7.1 rule 18)');
26
+ }
27
+ if (primary === 'ip-address') {
28
+ return pii('ip', 'primary semantic is ip-address (§7.1 rule 26)');
29
+ }
30
+ if (primary === 'person-name' &&
31
+ ctx.peopleish &&
32
+ /^(first_name|last_name|full_name)$/.test(name)) {
33
+ return pii('person-name', 'first/last/full name on a people-shaped table (§7.2)');
34
+ }
35
+ if (primary === 'geo-point' && ctx.peopleish && ctx.isGeoPointPair) {
36
+ return pii('geo-precise', 'lat/lng pair on a people-shaped table (§7.2)');
37
+ }
38
+ if (GOV_ID_RE.test(name)) {
39
+ return pii('gov-id', `name matches gov-id pattern (§7.2)`);
40
+ }
41
+ if (PAYMENT_ID_RE.test(name)) {
42
+ return pii('payment-id', `name matches payment-id pattern (§7.2)`);
43
+ }
44
+ if (DOB_RE.test(name)) {
45
+ return pii('dob', `name matches date-of-birth pattern (§7.2)`);
46
+ }
47
+ if (ADDRESS_RE.test(name) && TEXTISH.has(column.logicalType)) {
48
+ return pii('address', `name matches address pattern (§7.2)`);
49
+ }
50
+ return { pii: null, maskedByDefault: false, reasons: [] };
51
+ }
52
+ function pii(kind, reason) {
53
+ return { pii: kind, maskedByDefault: true, reasons: [`pii:${kind} — ${reason}`] };
54
+ }
55
+ //# sourceMappingURL=pii.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii.js","sourceRoot":"","sources":["../../src/classify/pii.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,uEAAuE;AACvE,MAAM,UAAU,GAAG,0DAA0D,CAAC;AAC9E,MAAM,MAAM,GAAG,gDAAgD,CAAC;AAChE,MAAM,SAAS,GAAG,mFAAmF,CAAC;AACtG;;;;GAIG;AACH,MAAM,aAAa,GACjB,0EAA0E,CAAC;AAe7E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,MAAmB,EACnB,OAAoB,EACpB,GAAe;IAEf,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAExC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,OAAO,EAAE,0CAA0C,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,OAAO,EAAE,0CAA0C,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC,IAAI,EAAE,+CAA+C,CAAC,CAAC;IACpE,CAAC;IACD,IACE,OAAO,KAAK,aAAa;QACzB,GAAG,CAAC,SAAS;QACb,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,EAC/C,CAAC;QACD,OAAO,GAAG,CAAC,aAAa,EAAE,sDAAsD,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,OAAO,KAAK,WAAW,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;QACnE,OAAO,GAAG,CAAC,aAAa,EAAE,8CAA8C,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,QAAQ,EAAE,oCAAoC,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC,YAAY,EAAE,wCAAwC,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,GAAG,CAAC,KAAK,EAAE,2CAA2C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7D,OAAO,GAAG,CAAC,SAAS,EAAE,qCAAqC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,SAAS,GAAG,CAAC,IAAa,EAAE,MAAc;IACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,IAAI,MAAM,MAAM,EAAE,CAAC,EAAE,CAAC;AACpF,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Table-shape classification — 05-introspection-engine.md §8 (roles) plus
3
+ * the §6 structural detectors that live at table granularity: join-table
4
+ * detection (rule 2), self-FK hierarchy (rule 3), and the polymorphic
5
+ * pattern flag (rule 4). Also selects each table's display column and
6
+ * natural key, which the generator uses for FK chips, cards, and detail
7
+ * titles (research/widget-registry.md §15).
8
+ *
9
+ * Two outputs per table:
10
+ * - `semantics`: the persisted `TableSemantics` (role/hierarchy/polymorphic
11
+ * per the schema-model enum: entity | join-table | log | people |
12
+ * messages | line-items | system).
13
+ * - `shape`: the broader generator-facing `TableShape` kind used by
14
+ * template scoring (people | workflow | events | catalog | join | log |
15
+ * settings | geo | generic) with human-readable reasons.
16
+ */
17
+ import type { DatabaseModel, TableModel, TableSemantics } from '../schema-model.js';
18
+ import { type ClassifiedColumn } from './columns.js';
19
+ export declare const TABLE_SHAPE_KINDS: readonly ["people", "workflow", "events", "catalog", "join", "log", "settings", "geo", "generic"];
20
+ export type TableShapeKind = (typeof TABLE_SHAPE_KINDS)[number];
21
+ export interface TableShape {
22
+ kind: TableShapeKind;
23
+ reasons: string[];
24
+ }
25
+ export interface ClassifiedTable {
26
+ tableId: string;
27
+ shape: TableShape;
28
+ semantics: TableSemantics;
29
+ /**
30
+ * First text-ish unique/title/name column — what grids, FK chips, and
31
+ * detail headers render for a row. Null when the table has no text-ish
32
+ * candidate (pure join tables, numeric-only tables).
33
+ */
34
+ displayColumn: string | null;
35
+ /** First unique text-ish column (slug/email/username/code) — human key. */
36
+ naturalKey: string | null;
37
+ columns: ClassifiedColumn[];
38
+ }
39
+ export interface JoinTableResult {
40
+ isJoin: boolean;
41
+ confidence: number;
42
+ fkColumns: string[];
43
+ reasons: string[];
44
+ }
45
+ /**
46
+ * A table qualifies when: exactly 2 FK-like columns referencing two tables
47
+ * (possibly the same one), and at most 2 additional columns drawn from
48
+ * {surrogate id, created-at-classified, position/sort_order, one small
49
+ * metadata column}. Boosters: composite PK/unique over the pair (+0.1),
50
+ * name matching the two target names (+0.1). Base 0.7 → typical 0.8–0.9;
51
+ * accepted at ≥ 0.8 (§6 thresholds).
52
+ */
53
+ export declare function detectJoinTable(table: TableModel, columns: ClassifiedColumn[]): JoinTableResult;
54
+ /**
55
+ * Per 05 (assignment note): "first text-ish unique/title/name column".
56
+ * Preference order: exact title/name → `_name`-suffixed → unique text-ish
57
+ * (slug/email/username) → first text-ish non-PK non-secret column.
58
+ */
59
+ export declare function selectDisplayColumn(table: TableModel, columns: ClassifiedColumn[]): string | null;
60
+ /** First unique text-ish column — the human-facing natural key, if any. */
61
+ export declare function selectNaturalKey(table: TableModel, columns: ClassifiedColumn[]): string | null;
62
+ /** Classify a single table (columns are classified as part of this). */
63
+ export declare function classifyTable(model: DatabaseModel, table: TableModel): ClassifiedTable;
64
+ //# sourceMappingURL=tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/classify/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EACV,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAOtB,eAAO,MAAM,iBAAiB,mGAUpB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,cAAc,CAAC;IAC1B;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAqCD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,eAAe,CA6DjB;AAyDD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,MAAM,GAAG,IAAI,CAcf;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,GAAG,IAAI,CAe9F;AAMD,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,eAAe,CAwItF"}
@@ -0,0 +1,303 @@
1
+ import { buildColumnClassifyContext, classifyColumn, PEOPLE_TABLE_RE, } from './columns.js';
2
+ import { normalizeName } from './names.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Output shapes
5
+ // ---------------------------------------------------------------------------
6
+ export const TABLE_SHAPE_KINDS = [
7
+ 'people',
8
+ 'workflow',
9
+ 'events',
10
+ 'catalog',
11
+ 'join',
12
+ 'log',
13
+ 'settings',
14
+ 'geo',
15
+ 'generic',
16
+ ];
17
+ // ---------------------------------------------------------------------------
18
+ // Vocab
19
+ // ---------------------------------------------------------------------------
20
+ /** §8 trigger: `page-log-viewer` name pattern. */
21
+ const LOG_TABLE_RE = /(^|_)(audit|logs?|events?|history|deliveries)(_|$)/;
22
+ const SETTINGS_TABLE_RE = /(^|_)(settings?|preferences?|configs?|configurations?|options)(_|$)/;
23
+ /** §8.2 system-table vocabulary. */
24
+ const SYSTEM_TABLE_RE = /^(adminium_.*|_prisma_migrations|schema_migrations|ar_internal_metadata|django_migrations|knex_migrations.*|sqlite_sequence|mysql\..*)$/;
25
+ /** §6 rule 3 — self-FK column names that imply a hierarchy. */
26
+ const HIERARCHY_COLUMN_RE = /^(parent|manager|supervisor|reports_to|superior)(_id)?$/;
27
+ /** Join-table "allowed extra" columns (§6 rule 2). */
28
+ const POSITION_RE = /^(position|sort_order|rank|ordering)$/;
29
+ /** Line-items detection: quantity × rate numerics on a 2-FK child table. */
30
+ const QTY_RE = /(^|_)(qty|quantity|units|count)(_|$)/;
31
+ const RATE_RE = /(^|_)(price|rate|amount|cost|unit_price)(_|$)/;
32
+ /** Messages detection: sender FK + body text + created-at. */
33
+ const SENDER_RE = /(^|_)(sender|author|user|from_user|creator)(_id)?$/;
34
+ const BODY_RE = /^(body|message|content|text)$/;
35
+ /** §8 log shape: "verb-ish text" = a short action/event/verb column. */
36
+ const VERBISH_RE = /(^|_)(action|event|activity|verb|operation)(_type|_name)?(_|$)/;
37
+ /** Events-shaped table names (guards the calendar trigger against orders-like tables). */
38
+ const EVENTS_TABLE_RE = /(^|_)(events?|meetings?|appointments?|schedules?|shifts?|bookings?|sessions?|releases?)(_|$)/;
39
+ /** Display-column name preference. */
40
+ const TITLE_RE = /^(title|name|label|subject|headline|summary)$/;
41
+ const TITLE_SUFFIX_RE = /_(title|name|label|subject)$/;
42
+ const TEXTISH = new Set(['text', 'varchar']);
43
+ /**
44
+ * A table qualifies when: exactly 2 FK-like columns referencing two tables
45
+ * (possibly the same one), and at most 2 additional columns drawn from
46
+ * {surrogate id, created-at-classified, position/sort_order, one small
47
+ * metadata column}. Boosters: composite PK/unique over the pair (+0.1),
48
+ * name matching the two target names (+0.1). Base 0.7 → typical 0.8–0.9;
49
+ * accepted at ≥ 0.8 (§6 thresholds).
50
+ */
51
+ export function detectJoinTable(table, columns) {
52
+ const none = { isJoin: false, confidence: 0, fkColumns: [], reasons: [] };
53
+ const byName = new Map(columns.map((c) => [c.column, c]));
54
+ const fkCols = table.columns.filter((c) => byName.get(c.name)?.semantics.primary === 'fk'
55
+ || (c.references !== null));
56
+ // Composite-PK FK columns classify as pk-id (rule 2 precedes rule 3), so
57
+ // count declared references too — the structural signal is the FK itself.
58
+ const fkNames = [...new Set(fkCols.map((c) => c.name))];
59
+ if (fkNames.length !== 2)
60
+ return none;
61
+ const extras = table.columns.filter((c) => !fkNames.includes(c.name));
62
+ if (extras.length > 2)
63
+ return none;
64
+ let metadataBudget = 1;
65
+ for (const extra of extras) {
66
+ const name = normalizeName(extra.name);
67
+ const primary = byName.get(extra.name)?.semantics.primary;
68
+ const surrogateId = primary === 'pk-id';
69
+ const createdAt = primary === 'created-at';
70
+ const position = POSITION_RE.test(name);
71
+ if (surrogateId || createdAt || position)
72
+ continue;
73
+ if (metadataBudget > 0) {
74
+ metadataBudget -= 1;
75
+ continue;
76
+ }
77
+ return none;
78
+ }
79
+ // Accumulate in integer hundredths — 0.7 + 0.1 must reach the 0.8 gate
80
+ // exactly, not as 0.7999999999999999.
81
+ let confidenceHundredths = 70;
82
+ const reasons = [`exactly 2 FK columns (${fkNames.join(', ')}) and no other data columns`];
83
+ const pairSet = new Set(fkNames);
84
+ const coveredByPk = table.primaryKey.length === 2 && table.primaryKey.every((c) => pairSet.has(c));
85
+ const coveredByUnique = table.uniques.some((u) => u.columns.length === 2 && u.columns.every((c) => pairSet.has(c)));
86
+ if (coveredByPk || coveredByUnique) {
87
+ confidenceHundredths += 10;
88
+ reasons.push('composite PK/unique constraint covers the FK pair (+0.1)');
89
+ }
90
+ const targets = fkCols
91
+ .map((c) => c.references?.tableId.split('.').pop() ?? '')
92
+ .filter(Boolean)
93
+ .map((t) => t.replace(/s$/, ''));
94
+ if (targets.length === 2) {
95
+ const tableName = normalizeName(table.name);
96
+ const [a, b] = targets;
97
+ if (tableName.includes(a) && tableName.includes(b)) {
98
+ confidenceHundredths += 10;
99
+ reasons.push('table name is composed of both target names (+0.1)');
100
+ }
101
+ }
102
+ const confidence = Math.min(100, confidenceHundredths) / 100;
103
+ return { isJoin: confidenceHundredths >= 80, confidence, fkColumns: fkNames, reasons };
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // §6 rules 3–4 — hierarchy + polymorphic flags
107
+ // ---------------------------------------------------------------------------
108
+ function detectHierarchy(model, table) {
109
+ for (const column of table.columns) {
110
+ if (!HIERARCHY_COLUMN_RE.test(normalizeName(column.name)))
111
+ continue;
112
+ if (column.references?.tableId === table.id)
113
+ return { parentColumn: column.name };
114
+ const selfRelation = model.relations.some((r) => r.selfReferential &&
115
+ r.from.tableId === table.id &&
116
+ r.from.columns.includes(column.name) &&
117
+ r.confidence >= 0.8);
118
+ if (selfRelation)
119
+ return { parentColumn: column.name };
120
+ }
121
+ return null;
122
+ }
123
+ function detectPolymorphic(model, table) {
124
+ const results = [];
125
+ const names = new Map(table.columns.map((c) => [normalizeName(c.name), c]));
126
+ const tableNames = new Set(model.tables.map((t) => normalizeName(t.name)));
127
+ const enumsById = new Map(model.enums.map((e) => [e.id, e]));
128
+ for (const column of table.columns) {
129
+ const name = normalizeName(column.name);
130
+ const match = /^(?<base>[a-z0-9_]+)_type$/.exec(name);
131
+ if (match?.groups === undefined)
132
+ continue;
133
+ if (!TEXTISH.has(column.logicalType) && column.logicalType !== 'enum')
134
+ continue;
135
+ const idColumn = names.get(`${match.groups['base']}_id`);
136
+ if (idColumn === undefined)
137
+ continue;
138
+ // Rails-style `commentable_type/commentable_id` also matches this shape.
139
+ let targets = [];
140
+ if (column.enumRef !== null) {
141
+ const values = enumsById.get(column.enumRef)?.values ?? [];
142
+ targets = values.map((v) => normalizeName(v)).filter((v) => tableNames.has(v));
143
+ }
144
+ results.push({ typeColumn: column.name, idColumn: idColumn.name, targets });
145
+ }
146
+ return results;
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Display column + natural key
150
+ // ---------------------------------------------------------------------------
151
+ function isTextish(column) {
152
+ return TEXTISH.has(column.logicalType);
153
+ }
154
+ /**
155
+ * Per 05 (assignment note): "first text-ish unique/title/name column".
156
+ * Preference order: exact title/name → `_name`-suffixed → unique text-ish
157
+ * (slug/email/username) → first text-ish non-PK non-secret column.
158
+ */
159
+ export function selectDisplayColumn(table, columns) {
160
+ const secret = new Set(columns.filter((c) => c.semantics.flags.secret).map((c) => c.column));
161
+ const candidates = table.columns.filter((c) => isTextish(c) && !c.isPrimaryKey && !secret.has(c.name));
162
+ const exact = candidates.find((c) => TITLE_RE.test(normalizeName(c.name)));
163
+ if (exact)
164
+ return exact.name;
165
+ const suffixed = candidates.find((c) => TITLE_SUFFIX_RE.test(normalizeName(c.name)));
166
+ if (suffixed)
167
+ return suffixed.name;
168
+ const unique = candidates.find((c) => c.isUnique);
169
+ if (unique)
170
+ return unique.name;
171
+ return candidates[0]?.name ?? null;
172
+ }
173
+ /** First unique text-ish column — the human-facing natural key, if any. */
174
+ export function selectNaturalKey(table, columns) {
175
+ const secret = new Set(columns.filter((c) => c.semantics.flags.secret).map((c) => c.column));
176
+ const singleColumnUniques = new Set(table.uniques.filter((u) => u.columns.length === 1).map((u) => u.columns[0]));
177
+ const candidate = table.columns.find((c) => isTextish(c) &&
178
+ !c.isPrimaryKey &&
179
+ !secret.has(c.name) &&
180
+ (c.isUnique || singleColumnUniques.has(c.name)));
181
+ return candidate?.name ?? null;
182
+ }
183
+ // ---------------------------------------------------------------------------
184
+ // Shape + role classification
185
+ // ---------------------------------------------------------------------------
186
+ /** Classify a single table (columns are classified as part of this). */
187
+ export function classifyTable(model, table) {
188
+ const ctx = buildColumnClassifyContext(model, table);
189
+ const columns = table.columns.map((column) => classifyColumn(column, ctx));
190
+ const primaryOf = (name) => columns.find((c) => c.column === name)?.semantics.primary ?? 'plain';
191
+ const has = (tag) => columns.some((c) => c.semantics.primary === tag);
192
+ const join = detectJoinTable(table, columns);
193
+ const hierarchy = detectHierarchy(model, table);
194
+ const polymorphic = detectPolymorphic(model, table);
195
+ const tableName = normalizeName(table.name);
196
+ const reasons = [];
197
+ let kind = 'generic';
198
+ let role = 'entity';
199
+ const fkTargetIsPeopleish = (column) => {
200
+ const target = column.references?.tableId;
201
+ if (target === undefined || target === null)
202
+ return false;
203
+ const targetTable = model.tables.find((t) => t.id === target);
204
+ return targetTable !== undefined && PEOPLE_TABLE_RE.test(normalizeName(targetTable.name));
205
+ };
206
+ const actorFk = table.columns.some((c) => (primaryOf(c.name) === 'fk' || c.references !== null) &&
207
+ (SENDER_RE.test(normalizeName(c.name)) || fkTargetIsPeopleish(c)));
208
+ // -- precedence: structural/system signals first, generic last ----------
209
+ if (table.system || SYSTEM_TABLE_RE.test(tableName)) {
210
+ kind = 'generic';
211
+ role = 'system';
212
+ reasons.push('system/migration table (§8.2) — excluded and hidden by default');
213
+ }
214
+ else if (join.isJoin) {
215
+ kind = 'join';
216
+ role = 'join-table';
217
+ reasons.push(...join.reasons, `join-table confidence ${join.confidence.toFixed(2)}`);
218
+ }
219
+ else if (LOG_TABLE_RE.test(tableName) ||
220
+ (has('created-at') &&
221
+ !has('updated-at') &&
222
+ actorFk &&
223
+ table.columns.some((c) => TEXTISH.has(c.logicalType) &&
224
+ (c.maxLength === null || c.maxLength <= 64) &&
225
+ VERBISH_RE.test(normalizeName(c.name))))) {
226
+ kind = 'log';
227
+ role = 'log';
228
+ reasons.push(LOG_TABLE_RE.test(tableName)
229
+ ? 'table name matches audit/log/events/history vocabulary (§8)'
230
+ : 'append-only shape: created-at + actor FK + text, no updated-at (§8)');
231
+ }
232
+ else if (SETTINGS_TABLE_RE.test(tableName)) {
233
+ kind = 'settings';
234
+ reasons.push('table name matches settings/preferences vocabulary');
235
+ }
236
+ else if (ctx.peopleish && (has('person-name') || has('email'))) {
237
+ kind = 'people';
238
+ role = 'people';
239
+ reasons.push('people shape: person-name/email columns on a people-ish table (§8 directory trigger)');
240
+ }
241
+ else if (has('status-workflow')) {
242
+ kind = 'workflow';
243
+ reasons.push('status-workflow enum present (§7.1 rule 7 → kanban trigger)');
244
+ }
245
+ else if ((has('event-timestamp') || has('date-range')) &&
246
+ (EVENTS_TABLE_RE.test(tableName) || has('date-range'))) {
247
+ kind = 'events';
248
+ reasons.push('event timestamps with an events-shaped name or start/end pair (§8 calendar trigger)');
249
+ }
250
+ else {
251
+ // Line-items / messages roles are orthogonal to the remaining kinds.
252
+ const geoColumns = columns.filter((c) => c.semantics.primary === 'geo-region' || c.semantics.primary === 'geo-point');
253
+ const dataColumns = table.columns.filter((c) => !c.isPrimaryKey);
254
+ if (geoColumns.length >= 2 &&
255
+ dataColumns.length > 0 &&
256
+ geoColumns.length / dataColumns.length >= 0.6) {
257
+ kind = 'geo';
258
+ reasons.push(`${geoColumns.length}/${dataColumns.length} data columns are geographic (§7.1 rules 14–15)`);
259
+ }
260
+ else {
261
+ const displayColumn = selectDisplayColumn(table, columns);
262
+ const catalogSignal = has('money') || has('category-enum') || has('image-url');
263
+ if (displayColumn !== null && catalogSignal) {
264
+ kind = 'catalog';
265
+ reasons.push('display column plus money/category/image columns — catalog shape');
266
+ }
267
+ else {
268
+ reasons.push('no §8 trigger matched');
269
+ }
270
+ }
271
+ }
272
+ // -- roles that refine `entity` without changing the shape kind ---------
273
+ if (role === 'entity') {
274
+ const fkCount = table.columns.filter((c) => c.references !== null).length;
275
+ const hasQty = table.columns.some((c) => QTY_RE.test(normalizeName(c.name)) && ['integer', 'bigint', 'decimal', 'float'].includes(c.logicalType));
276
+ const hasRate = table.columns.some((c) => RATE_RE.test(normalizeName(c.name)) && ['integer', 'bigint', 'decimal', 'float'].includes(c.logicalType));
277
+ const hasBody = table.columns.some((c) => BODY_RE.test(normalizeName(c.name)) && TEXTISH.has(c.logicalType));
278
+ if (fkCount >= 2 && hasQty && hasRate) {
279
+ role = 'line-items';
280
+ reasons.push('line-items role: child of 2 FKs with qty × rate numerics (§8 invoice trigger)');
281
+ }
282
+ else if (actorFk && hasBody && has('created-at')) {
283
+ role = 'messages';
284
+ reasons.push('messages role: sender FK + body text + created-at (§8 chat trigger)');
285
+ }
286
+ }
287
+ const semantics = { role, hierarchy, polymorphic };
288
+ if (hierarchy !== null) {
289
+ reasons.push(`self-FK hierarchy via "${hierarchy.parentColumn}" (§6 rule 3)`);
290
+ }
291
+ for (const p of polymorphic) {
292
+ reasons.push(`polymorphic pair ${p.typeColumn}/${p.idColumn} (§6 rule 4 — no relation fabricated)`);
293
+ }
294
+ return {
295
+ tableId: table.id,
296
+ shape: { kind, reasons },
297
+ semantics,
298
+ displayColumn: selectDisplayColumn(table, columns),
299
+ naturalKey: selectNaturalKey(table, columns),
300
+ columns,
301
+ };
302
+ }
303
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/classify/tables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The config envelope every stored config document uses (01-architecture.md
4
+ * §6.1, 07-meta-store.md §3.17). The envelope persists verbatim into
5
+ * `adminium_pages.config`; the stored version path the config-migration
6
+ * runner keys on is `config.v`.
7
+ */
8
+ export declare const CONFIG_KINDS: readonly ["page", "dashboard", "view", "nav", "manifest-module"];
9
+ export declare const configKindSchema: z.ZodEnum<{
10
+ view: "view";
11
+ page: "page";
12
+ dashboard: "dashboard";
13
+ nav: "nav";
14
+ "manifest-module": "manifest-module";
15
+ }>;
16
+ export type ConfigKind = z.infer<typeof configKindSchema>;
17
+ /**
18
+ * Prefixed document id: `page_`/`view_`/`nav_` + slug or ULID suffix.
19
+ * Engine-generated ids carry ULID suffixes (`page_01HZX…`); hand-authored and
20
+ * seeded documents may use readable slugs (`page_customers`, per the §3.17
21
+ * examples), so the suffix alphabet is not restricted to Crockford base32.
22
+ */
23
+ export declare const configIdPattern: RegExp;
24
+ /** Nav placement block (01-architecture.md §6.1). */
25
+ export declare const navConfigSchema: z.ZodObject<{
26
+ group: z.ZodString;
27
+ icon: z.ZodString;
28
+ order: z.ZodNumber;
29
+ slug: z.ZodOptional<z.ZodString>;
30
+ badge: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strip>;
32
+ export type NavConfig = z.infer<typeof navConfigSchema>;
33
+ export declare const pageEnvelopeSchema: z.ZodObject<{
34
+ v: z.ZodLiteral<1>;
35
+ kind: z.ZodEnum<{
36
+ view: "view";
37
+ page: "page";
38
+ dashboard: "dashboard";
39
+ nav: "nav";
40
+ "manifest-module": "manifest-module";
41
+ }>;
42
+ id: z.ZodString;
43
+ template: z.ZodString;
44
+ title: z.ZodObject<{
45
+ key: z.ZodString;
46
+ fallback: z.ZodString;
47
+ }, z.core.$strip>;
48
+ source: z.ZodObject<{
49
+ connectionId: z.ZodNullable<z.ZodString>;
50
+ table: z.ZodNullable<z.ZodString>;
51
+ }, z.core.$strip>;
52
+ nav: z.ZodObject<{
53
+ group: z.ZodString;
54
+ icon: z.ZodString;
55
+ order: z.ZodNumber;
56
+ slug: z.ZodOptional<z.ZodString>;
57
+ badge: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strip>;
59
+ access: z.ZodObject<{
60
+ minRole: z.ZodString;
61
+ permissions: z.ZodArray<z.ZodString>;
62
+ }, z.core.$strip>;
63
+ config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
64
+ }, z.core.$strip>;
65
+ export type PageEnvelope = z.infer<typeof pageEnvelopeSchema>;
66
+ /** Canonical alias used across the workplan documents. */
67
+ export type PageConfig = PageEnvelope;
68
+ /**
69
+ * A validated dashboard widget instance (01-architecture.md §6.1): a grid
70
+ * layout item whose `config.binding`, when present, must be a declarative
71
+ * query descriptor (04-widget-registry.md §5.1).
72
+ */
73
+ export declare const widgetConfigSchema: z.ZodObject<{
74
+ i: z.ZodString;
75
+ widget: z.ZodString;
76
+ x: z.ZodNumber;
77
+ y: z.ZodNumber;
78
+ w: z.ZodNumber;
79
+ h: z.ZodNumber;
80
+ config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
81
+ }, z.core.$strip>;
82
+ export type WidgetConfig = z.infer<typeof widgetConfigSchema>;
83
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/config-schema/envelope.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,kEAAmE,CAAC;AAC7F,eAAO,MAAM,gBAAgB;;;;;;EAAuB,CAAC;AACrD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAAgD,CAAC;AAI7E,qDAAqD;AACrD,eAAO,MAAM,eAAe;;;;;;iBAM1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AA6BxD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,YAAY,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;iBAY7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}