@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.
- package/LICENSE +661 -0
- package/dist/adapter-registry.d.ts +62 -0
- package/dist/adapter-registry.d.ts.map +1 -0
- package/dist/adapter-registry.js +75 -0
- package/dist/adapter-registry.js.map +1 -0
- package/dist/adapter.d.ts +384 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +54 -0
- package/dist/adapter.js.map +1 -0
- package/dist/capabilities.d.ts +57 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +131 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/classify/columns.d.ts +57 -0
- package/dist/classify/columns.d.ts.map +1 -0
- package/dist/classify/columns.js +535 -0
- package/dist/classify/columns.js.map +1 -0
- package/dist/classify/index.d.ts +29 -0
- package/dist/classify/index.d.ts.map +1 -0
- package/dist/classify/index.js +44 -0
- package/dist/classify/index.js.map +1 -0
- package/dist/classify/names.d.ts +11 -0
- package/dist/classify/names.d.ts.map +1 -0
- package/dist/classify/names.js +19 -0
- package/dist/classify/names.js.map +1 -0
- package/dist/classify/pii.d.ts +29 -0
- package/dist/classify/pii.d.ts.map +1 -0
- package/dist/classify/pii.js +55 -0
- package/dist/classify/pii.js.map +1 -0
- package/dist/classify/tables.d.ts +64 -0
- package/dist/classify/tables.d.ts.map +1 -0
- package/dist/classify/tables.js +303 -0
- package/dist/classify/tables.js.map +1 -0
- package/dist/config-schema/envelope.d.ts +83 -0
- package/dist/config-schema/envelope.d.ts.map +1 -0
- package/dist/config-schema/envelope.js +87 -0
- package/dist/config-schema/envelope.js.map +1 -0
- package/dist/config-schema/index.d.ts +14 -0
- package/dist/config-schema/index.d.ts.map +1 -0
- package/dist/config-schema/index.js +15 -0
- package/dist/config-schema/index.js.map +1 -0
- package/dist/config-schema/migrations.d.ts +44 -0
- package/dist/config-schema/migrations.d.ts.map +1 -0
- package/dist/config-schema/migrations.js +62 -0
- package/dist/config-schema/migrations.js.map +1 -0
- package/dist/generate/archetype.d.ts +76 -0
- package/dist/generate/archetype.d.ts.map +1 -0
- package/dist/generate/archetype.js +250 -0
- package/dist/generate/archetype.js.map +1 -0
- package/dist/generate/crud.d.ts +36 -0
- package/dist/generate/crud.d.ts.map +1 -0
- package/dist/generate/crud.js +45 -0
- package/dist/generate/crud.js.map +1 -0
- package/dist/generate/dashboard.d.ts +43 -0
- package/dist/generate/dashboard.d.ts.map +1 -0
- package/dist/generate/dashboard.js +61 -0
- package/dist/generate/dashboard.js.map +1 -0
- package/dist/generate/domains.d.ts +29 -0
- package/dist/generate/domains.d.ts.map +1 -0
- package/dist/generate/domains.js +145 -0
- package/dist/generate/domains.js.map +1 -0
- package/dist/generate/index.d.ts +78 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +301 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate/util.d.ts +46 -0
- package/dist/generate/util.d.ts.map +1 -0
- package/dist/generate/util.js +123 -0
- package/dist/generate/util.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/schema-model.d.ts +1853 -0
- package/dist/schema-model.d.ts.map +1 -0
- package/dist/schema-model.js +463 -0
- package/dist/schema-model.js.map +1 -0
- package/dist/snapshot/diff.d.ts +258 -0
- package/dist/snapshot/diff.d.ts.map +1 -0
- package/dist/snapshot/diff.js +151 -0
- package/dist/snapshot/diff.js.map +1 -0
- package/dist/snapshot/hash.d.ts +23 -0
- package/dist/snapshot/hash.d.ts.map +1 -0
- package/dist/snapshot/hash.js +47 -0
- package/dist/snapshot/hash.js.map +1 -0
- package/dist/snapshot/index.d.ts +28 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +26 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/snapshot/sha256.d.ts +14 -0
- package/dist/snapshot/sha256.d.ts.map +1 -0
- package/dist/snapshot/sha256.js +99 -0
- package/dist/snapshot/sha256.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../src/generate/crud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AAIpC;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,iFAAiF;IACjF,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACzC;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,mBAAmB,EAC1B,GAAG,EAAE,gBAAgB,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsBzB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `page-crud` envelope generation — one per included table (research/
|
|
3
|
+
* widget-registry.md §14: "Every included table"; 01-architecture.md §6.1
|
|
4
|
+
* fixes the config body shape: `columns[]`, `defaultSort`, `pageSize`,
|
|
5
|
+
* `detail`).
|
|
6
|
+
*
|
|
7
|
+
* The body vocabulary — column selection, tones, form-field mapping — lives in
|
|
8
|
+
* `@adminium/widgets/generate` (`composeCrudBody`; 04 §8: the Registry owns
|
|
9
|
+
* what a generated page contains). This module keeps only what the leaf cannot
|
|
10
|
+
* know: slug/id allocation, nav placement, and the §6.1 envelope wrap. Inputs
|
|
11
|
+
* arrive pre-adapted through `./archetype.ts`'s `toCandidateModel` — the single
|
|
12
|
+
* place the engine and registry vocabularies meet.
|
|
13
|
+
*/
|
|
14
|
+
import { composeCrudBody, } from '@adminium/widgets/generate';
|
|
15
|
+
import { humanize, pageIdFor } from './util.js';
|
|
16
|
+
/**
|
|
17
|
+
* The §7.1 rule-7 tone map moved into the leaf with the rest of the body
|
|
18
|
+
* vocabulary; re-exported because the generate surface is public API of the
|
|
19
|
+
* self-host package (`@adminium/engine` root re-exports this module).
|
|
20
|
+
*/
|
|
21
|
+
export { enumTones } from '@adminium/widgets/generate';
|
|
22
|
+
/** Build the (unhashed, unvalidated) `page-crud` envelope for one table. */
|
|
23
|
+
export function buildCrudEnvelope(entry, ctx) {
|
|
24
|
+
const { table, classified } = entry;
|
|
25
|
+
const body = composeCrudBody(table, classified, {
|
|
26
|
+
readOnly: ctx.readOnly,
|
|
27
|
+
includedTableIds: ctx.includedTableIds,
|
|
28
|
+
relations: ctx.relations,
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
v: 1,
|
|
32
|
+
kind: 'page',
|
|
33
|
+
id: pageIdFor(ctx.connectionId, ctx.slug),
|
|
34
|
+
template: 'page-crud',
|
|
35
|
+
title: { key: `nav.${ctx.slug}`, fallback: table.label ?? humanize(table.name) },
|
|
36
|
+
source: { connectionId: ctx.connectionId, table: table.id },
|
|
37
|
+
nav: { group: ctx.navGroup, icon: ctx.navIcon, order: ctx.navOrder, slug: ctx.slug },
|
|
38
|
+
access: {
|
|
39
|
+
minRole: 'viewer',
|
|
40
|
+
permissions: [`table:${table.id}:read`],
|
|
41
|
+
},
|
|
42
|
+
config: { ...body },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=crud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.js","sourceRoot":"","sources":["../../src/generate/crud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,eAAe,GAGhB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAqB,MAAM,4BAA4B,CAAC;AAgB1E,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAC/B,KAA0B,EAC1B,GAAqB;IAErB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IACpC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE;QAC9C,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC,CAAC;IAEH,OAAO;QACL,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC;QACzC,QAAQ,EAAE,WAAW;QACrB,KAAK,EAAE,EAAE,GAAG,EAAE,OAAO,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QAChF,MAAM,EAAE,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;QAC3D,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE;QACpF,MAAM,EAAE;YACN,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,CAAC,SAAS,KAAK,CAAC,EAAE,OAAO,CAAC;SACxC;QACD,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE;KACpB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `page-dashboard` envelope generation — one per FK-cluster domain, cap 3
|
|
3
|
+
* for v1 (research/widget-registry.md §14 trigger, §15 decision summary).
|
|
4
|
+
*
|
|
5
|
+
* The §15 widget set (4 KPIs, hero `chart-line-area`, `chart-donut`) is
|
|
6
|
+
* assembled by `@adminium/widgets/generate`'s `emitDomainDashboardCandidates`
|
|
7
|
+
* and laid out by `composeTemplate` against the `page-dashboard` manifest —
|
|
8
|
+
* geometry comes from the manifest's v2 slot areas, not hand-stamped x/y/w/h.
|
|
9
|
+
* This module keeps only what the leaf cannot know: the §6.1 envelope wrap,
|
|
10
|
+
* nav placement, and the stored `config.domain` block (`ComposedPage` carries
|
|
11
|
+
* none of them). Domain detection itself stays in `./domains.js`.
|
|
12
|
+
*/
|
|
13
|
+
import { type CandidateRelation, type CandidateTableInput, type ComposeWarning } from '@adminium/widgets/generate';
|
|
14
|
+
import type { DatabaseModel, TableModel } from '../schema-model.js';
|
|
15
|
+
import type { Domain } from './domains.js';
|
|
16
|
+
export interface DashboardBuildContext {
|
|
17
|
+
connectionId: string;
|
|
18
|
+
slug: string;
|
|
19
|
+
title: string;
|
|
20
|
+
navOrder: number;
|
|
21
|
+
/** Live registry membership test, threaded to H4 (04 §10). */
|
|
22
|
+
isRegistered?: ((widgetId: string) => boolean) | undefined;
|
|
23
|
+
}
|
|
24
|
+
export interface DashboardBuildResult {
|
|
25
|
+
/**
|
|
26
|
+
* Unhashed, unvalidated envelope — `generatePages` stamps + validates it.
|
|
27
|
+
* `null` ⇔ the domain has no time axis at all (05 §8 trigger requires ≥ 1
|
|
28
|
+
* timestamp) or composition failed — the caller records a warning.
|
|
29
|
+
*/
|
|
30
|
+
envelope: Record<string, unknown> | null;
|
|
31
|
+
warnings: readonly ComposeWarning[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* §8 trigger in the pre-migration signature (`DatabaseModel` + `TableModel[]`):
|
|
35
|
+
* a domain can host a dashboard only with ≥ 1 time axis. Kept as public API of
|
|
36
|
+
* the self-host package (the root re-exports this module); `generatePages`
|
|
37
|
+
* itself asks the leaf's `domainHasDashboardSignal` over the shared candidate
|
|
38
|
+
* mirror instead of re-adapting per domain.
|
|
39
|
+
*/
|
|
40
|
+
export declare function hasDashboardSignal(model: DatabaseModel, domain: Domain, tables: readonly TableModel[]): boolean;
|
|
41
|
+
/** Build the `page-dashboard` envelope for a domain and wrap it per §6.1. */
|
|
42
|
+
export declare function buildDashboardEnvelope(domain: Domain, model: readonly CandidateTableInput[], relations: readonly CandidateRelation[], ctx: DashboardBuildContext): DashboardBuildResult;
|
|
43
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/generate/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAC5D;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,UAAU,EAAE,GAC5B,OAAO,CAOT;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,SAAS,EAAE,SAAS,iBAAiB,EAAE,EACvC,GAAG,EAAE,qBAAqB,GACzB,oBAAoB,CAmCtB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `page-dashboard` envelope generation — one per FK-cluster domain, cap 3
|
|
3
|
+
* for v1 (research/widget-registry.md §14 trigger, §15 decision summary).
|
|
4
|
+
*
|
|
5
|
+
* The §15 widget set (4 KPIs, hero `chart-line-area`, `chart-donut`) is
|
|
6
|
+
* assembled by `@adminium/widgets/generate`'s `emitDomainDashboardCandidates`
|
|
7
|
+
* and laid out by `composeTemplate` against the `page-dashboard` manifest —
|
|
8
|
+
* geometry comes from the manifest's v2 slot areas, not hand-stamped x/y/w/h.
|
|
9
|
+
* This module keeps only what the leaf cannot know: the §6.1 envelope wrap,
|
|
10
|
+
* nav placement, and the stored `config.domain` block (`ComposedPage` carries
|
|
11
|
+
* none of them). Domain detection itself stays in `./domains.js`.
|
|
12
|
+
*/
|
|
13
|
+
import { composeTemplate, domainHasDashboardSignal, emitDomainDashboardCandidates, } from '@adminium/widgets/generate';
|
|
14
|
+
import { classifyModel } from '../classify/index.js';
|
|
15
|
+
import { toCandidateModel } from './archetype.js';
|
|
16
|
+
import { pageIdFor } from './util.js';
|
|
17
|
+
/**
|
|
18
|
+
* §8 trigger in the pre-migration signature (`DatabaseModel` + `TableModel[]`):
|
|
19
|
+
* a domain can host a dashboard only with ≥ 1 time axis. Kept as public API of
|
|
20
|
+
* the self-host package (the root re-exports this module); `generatePages`
|
|
21
|
+
* itself asks the leaf's `domainHasDashboardSignal` over the shared candidate
|
|
22
|
+
* mirror instead of re-adapting per domain.
|
|
23
|
+
*/
|
|
24
|
+
export function hasDashboardSignal(model, domain, tables) {
|
|
25
|
+
const classified = new Map(classifyModel(model).tables.map((t) => [t.tableId, t]));
|
|
26
|
+
return domainHasDashboardSignal(domain, toCandidateModel(model, tables, classified), model.relations);
|
|
27
|
+
}
|
|
28
|
+
/** Build the `page-dashboard` envelope for a domain and wrap it per §6.1. */
|
|
29
|
+
export function buildDashboardEnvelope(domain, model, relations, ctx) {
|
|
30
|
+
const candidates = emitDomainDashboardCandidates(domain, model, relations, {
|
|
31
|
+
connectionId: ctx.connectionId,
|
|
32
|
+
});
|
|
33
|
+
if (candidates === null)
|
|
34
|
+
return { envelope: null, warnings: [] };
|
|
35
|
+
const composed = composeTemplate('page-dashboard', candidates, ctx.isRegistered === undefined ? {} : { isRegistered: ctx.isRegistered });
|
|
36
|
+
if (composed.page === null)
|
|
37
|
+
return { envelope: null, warnings: composed.warnings };
|
|
38
|
+
return {
|
|
39
|
+
warnings: composed.warnings,
|
|
40
|
+
envelope: {
|
|
41
|
+
v: 1,
|
|
42
|
+
kind: composed.page.type,
|
|
43
|
+
id: pageIdFor(ctx.connectionId, ctx.slug),
|
|
44
|
+
template: composed.page.template,
|
|
45
|
+
title: { key: `nav.${ctx.slug}`, fallback: ctx.title },
|
|
46
|
+
source: { connectionId: ctx.connectionId, table: null },
|
|
47
|
+
nav: { group: 'workspace', icon: 'layout-dashboard', order: ctx.navOrder, slug: ctx.slug },
|
|
48
|
+
access: { minRole: 'viewer', permissions: [] },
|
|
49
|
+
config: {
|
|
50
|
+
templateVersion: composed.page.templateVersion,
|
|
51
|
+
toolbar: composed.page.toolbar,
|
|
52
|
+
overlays: composed.page.overlays,
|
|
53
|
+
// What the page aggregates — kept on the stored document so the domain
|
|
54
|
+
// membership survives without re-running detection.
|
|
55
|
+
domain: { key: domain.key, label: domain.label, tables: domain.tableIds },
|
|
56
|
+
layout: composed.page.layout,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/generate/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FK-cluster domain detection — 05-introspection-engine.md §8.3.
|
|
3
|
+
*
|
|
4
|
+
* Domains drive "one `page-dashboard` per domain" (research/widget-registry.md
|
|
5
|
+
* §15): connected components over the relation graph (declared + accepted
|
|
6
|
+
* inferred, confidence ≥ 0.8); singleton tables attach to the component they
|
|
7
|
+
* share a name prefix with, else to a "General" domain. Domain naming: schema
|
|
8
|
+
* name when meaningful, else the most-central (weighted hub) table's plural
|
|
9
|
+
* label.
|
|
10
|
+
*/
|
|
11
|
+
import type { DatabaseModel, TableModel } from '../schema-model.js';
|
|
12
|
+
export interface Domain {
|
|
13
|
+
/** Deterministic kebab-case key, e.g. `orders`. */
|
|
14
|
+
key: string;
|
|
15
|
+
/** Human label, e.g. `Orders`. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** All member table ids, sorted. */
|
|
18
|
+
tableIds: string[];
|
|
19
|
+
/** The weighted hub — highest relation degree, ties by row estimate then name. */
|
|
20
|
+
hubTableId: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Detect FK-cluster domains over the model's non-system tables. Join tables
|
|
24
|
+
* participate as edges (their relations connect the sides) but are never
|
|
25
|
+
* chosen as hubs. Components larger than 12 tables would split by schema per
|
|
26
|
+
* §8.3 — with a single schema they stay one domain.
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectDomains(model: DatabaseModel, tables: readonly TableModel[]): Domain[];
|
|
29
|
+
//# sourceMappingURL=domains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../src/generate/domains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGpE,MAAM,WAAW,MAAM;IACrB,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;CACpB;AAiCD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,EAAE,CAkG3F"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FK-cluster domain detection — 05-introspection-engine.md §8.3.
|
|
3
|
+
*
|
|
4
|
+
* Domains drive "one `page-dashboard` per domain" (research/widget-registry.md
|
|
5
|
+
* §15): connected components over the relation graph (declared + accepted
|
|
6
|
+
* inferred, confidence ≥ 0.8); singleton tables attach to the component they
|
|
7
|
+
* share a name prefix with, else to a "General" domain. Domain naming: schema
|
|
8
|
+
* name when meaningful, else the most-central (weighted hub) table's plural
|
|
9
|
+
* label.
|
|
10
|
+
*/
|
|
11
|
+
import { humanize, pluralizeWord, slugify } from './util.js';
|
|
12
|
+
/** Relations that count as domain edges (§6 thresholds: accepted at ≥ 0.8). */
|
|
13
|
+
const EDGE_CONFIDENCE = 0.8;
|
|
14
|
+
class UnionFind {
|
|
15
|
+
parent = new Map();
|
|
16
|
+
find(x) {
|
|
17
|
+
let root = this.parent.get(x) ?? x;
|
|
18
|
+
if (root !== x) {
|
|
19
|
+
root = this.find(root);
|
|
20
|
+
this.parent.set(x, root);
|
|
21
|
+
}
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
union(a, b) {
|
|
25
|
+
const ra = this.find(a);
|
|
26
|
+
const rb = this.find(b);
|
|
27
|
+
// Deterministic root selection: smaller id wins.
|
|
28
|
+
if (ra === rb)
|
|
29
|
+
return;
|
|
30
|
+
if (ra < rb)
|
|
31
|
+
this.parent.set(rb, ra);
|
|
32
|
+
else
|
|
33
|
+
this.parent.set(ra, rb);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function sharedPrefix(a, b) {
|
|
37
|
+
const ta = (a.split('.').pop() ?? a).split('_')[0] ?? '';
|
|
38
|
+
const tb = (b.split('.').pop() ?? b).split('_')[0] ?? '';
|
|
39
|
+
return ta.length >= 3 && ta === tb;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detect FK-cluster domains over the model's non-system tables. Join tables
|
|
43
|
+
* participate as edges (their relations connect the sides) but are never
|
|
44
|
+
* chosen as hubs. Components larger than 12 tables would split by schema per
|
|
45
|
+
* §8.3 — with a single schema they stay one domain.
|
|
46
|
+
*/
|
|
47
|
+
export function detectDomains(model, tables) {
|
|
48
|
+
const ids = new Set(tables.map((t) => t.id));
|
|
49
|
+
const uf = new UnionFind();
|
|
50
|
+
const degree = new Map();
|
|
51
|
+
for (const id of ids)
|
|
52
|
+
degree.set(id, 0);
|
|
53
|
+
for (const relation of model.relations) {
|
|
54
|
+
if (relation.confidence < EDGE_CONFIDENCE)
|
|
55
|
+
continue;
|
|
56
|
+
const { tableId: fromId } = relation.from;
|
|
57
|
+
const { tableId: toId } = relation.to;
|
|
58
|
+
if (!ids.has(fromId) || !ids.has(toId))
|
|
59
|
+
continue;
|
|
60
|
+
uf.union(fromId, toId);
|
|
61
|
+
if (fromId !== toId) {
|
|
62
|
+
degree.set(fromId, (degree.get(fromId) ?? 0) + 1);
|
|
63
|
+
degree.set(toId, (degree.get(toId) ?? 0) + 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const components = new Map();
|
|
67
|
+
const singletons = [];
|
|
68
|
+
for (const table of [...tables].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
69
|
+
const root = uf.find(table.id);
|
|
70
|
+
const members = components.get(root) ?? [];
|
|
71
|
+
members.push(table.id);
|
|
72
|
+
components.set(root, members);
|
|
73
|
+
}
|
|
74
|
+
for (const [root, members] of [...components]) {
|
|
75
|
+
if (members.length === 1) {
|
|
76
|
+
singletons.push(members[0]);
|
|
77
|
+
components.delete(root);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Singletons attach to a component sharing a name prefix, else "General".
|
|
81
|
+
const general = [];
|
|
82
|
+
for (const singleton of singletons) {
|
|
83
|
+
let attached = false;
|
|
84
|
+
for (const members of components.values()) {
|
|
85
|
+
if (members.some((member) => sharedPrefix(member, singleton))) {
|
|
86
|
+
members.push(singleton);
|
|
87
|
+
members.sort();
|
|
88
|
+
attached = true;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!attached)
|
|
93
|
+
general.push(singleton);
|
|
94
|
+
}
|
|
95
|
+
const byId = new Map(tables.map((t) => [t.id, t]));
|
|
96
|
+
const hubOf = (members) => {
|
|
97
|
+
const candidates = members.filter((id) => byId.get(id)?.semantics?.role !== 'join-table');
|
|
98
|
+
const pool = candidates.length > 0 ? candidates : [...members];
|
|
99
|
+
return [...pool].sort((a, b) => {
|
|
100
|
+
const dd = (degree.get(b) ?? 0) - (degree.get(a) ?? 0);
|
|
101
|
+
if (dd !== 0)
|
|
102
|
+
return dd;
|
|
103
|
+
const rr = (byId.get(b)?.rowCountEstimate ?? 0) - (byId.get(a)?.rowCountEstimate ?? 0);
|
|
104
|
+
if (rr !== 0)
|
|
105
|
+
return rr;
|
|
106
|
+
return a.localeCompare(b);
|
|
107
|
+
})[0];
|
|
108
|
+
};
|
|
109
|
+
const named = (members) => {
|
|
110
|
+
const hub = hubOf(members);
|
|
111
|
+
const hubTable = byId.get(hub);
|
|
112
|
+
// Schema name when meaningful (§8.3), else the hub table's plural label.
|
|
113
|
+
const schema = hubTable?.schema ?? 'public';
|
|
114
|
+
const meaningful = schema !== 'public' && schema !== 'main' && schema !== model.name;
|
|
115
|
+
const rawLabel = meaningful ? humanize(schema) : humanize(hub);
|
|
116
|
+
const heuristic = meaningful
|
|
117
|
+
? rawLabel
|
|
118
|
+
: rawLabel
|
|
119
|
+
.split(' ')
|
|
120
|
+
.map((w, i, all) => (i === all.length - 1 ? pluralizeWord(w) : w))
|
|
121
|
+
.join(' ');
|
|
122
|
+
// A hub table carrying an effective label (Studio remap / accepted LLM
|
|
123
|
+
// rename) names the domain verbatim — it is already human-authored, so it
|
|
124
|
+
// is never pluralized. The KEY stays heuristic-derived: it feeds dashboard
|
|
125
|
+
// slugs and page ids, which must not move when a table is renamed.
|
|
126
|
+
// DELIBERATE asymmetry: in a meaningful (named) schema the SCHEMA names
|
|
127
|
+
// the domain, so renaming the hub table retitles its crud/archetype pages
|
|
128
|
+
// but NOT the '<Domain> Dashboard' — the schema name stays authoritative.
|
|
129
|
+
const label = meaningful ? heuristic : (hubTable?.label ?? heuristic);
|
|
130
|
+
return { key: slugify(heuristic), label, tableIds: members, hubTableId: hub };
|
|
131
|
+
};
|
|
132
|
+
const domains = [...components.values()].map(named);
|
|
133
|
+
if (general.length > 0) {
|
|
134
|
+
domains.push({
|
|
135
|
+
key: 'general',
|
|
136
|
+
label: 'General',
|
|
137
|
+
tableIds: [...general].sort(),
|
|
138
|
+
hubTableId: hubOf(general),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Largest first; ties break on key for determinism.
|
|
142
|
+
domains.sort((a, b) => b.tableIds.length - a.tableIds.length || a.key.localeCompare(b.key));
|
|
143
|
+
return domains;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.js","sourceRoot":"","sources":["../../src/generate/domains.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `generatePages()` — Generator v1 (M4-T08, 05-introspection-engine.md
|
|
3
|
+
* generation section, research/widget-registry.md §14–§15, 09-generated-app.md
|
|
4
|
+
* §2.2 nav rules, §8.4 intent variants).
|
|
5
|
+
*
|
|
6
|
+
* Pure and deterministic: same classified model + options in, same
|
|
7
|
+
* `PageEnvelope[]` out (05 §9 — regeneration is safe to re-run). Every
|
|
8
|
+
* emitted envelope is validated against `pageEnvelopeSchema` (and dashboard
|
|
9
|
+
* widget instances against `widgetConfigSchema`) before return — outputs
|
|
10
|
+
* cannot drift from the frozen config contract.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { type PageEnvelope } from '../config-schema/envelope.js';
|
|
14
|
+
import type { DatabaseModel } from '../schema-model.js';
|
|
15
|
+
export { archetypeSlug, buildArchetypeEnvelope, composeRequestedArchetype, toCandidateModel, type ArchetypeBuildContext, type ArchetypeBuildResult, } from './archetype.js';
|
|
16
|
+
export { buildCrudEnvelope, enumTones, type CrudBuildContext, type CrudEnumTone } from './crud.js';
|
|
17
|
+
export { buildDashboardEnvelope, hasDashboardSignal, type DashboardBuildContext, type DashboardBuildResult, } from './dashboard.js';
|
|
18
|
+
export { detectDomains, type Domain } from './domains.js';
|
|
19
|
+
export { ID_SLUG_BUDGET, MAX_SLUG_LENGTH, hashEnvelope, humanize, pageIdFor, pluralizeWord, slugify, SlugRegistry, } from './util.js';
|
|
20
|
+
/** 09 §8.4 generation intent variants (adminium_connections.settings.intent). */
|
|
21
|
+
export declare const GENERATE_INTENTS: readonly ["full-admin", "read-only-analytics", "crud", "support-console"];
|
|
22
|
+
export declare const generateIntentSchema: z.ZodEnum<{
|
|
23
|
+
"full-admin": "full-admin";
|
|
24
|
+
"read-only-analytics": "read-only-analytics";
|
|
25
|
+
crud: "crud";
|
|
26
|
+
"support-console": "support-console";
|
|
27
|
+
}>;
|
|
28
|
+
export type GenerateIntent = z.infer<typeof generateIntentSchema>;
|
|
29
|
+
/** One `page-dashboard` per major domain, cap 3 for v1. */
|
|
30
|
+
export declare const DASHBOARD_CAP = 3;
|
|
31
|
+
export interface GenerateOptions {
|
|
32
|
+
/** 09 §8.4; default 'full-admin'. */
|
|
33
|
+
intent?: GenerateIntent | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Connection the pages bind to. Defaults to the model's live-source
|
|
36
|
+
* connection id; import models without one get CRUD pages with a null
|
|
37
|
+
* source connection and no dashboards (descriptors need a connection).
|
|
38
|
+
*/
|
|
39
|
+
connectionId?: string | null | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Widget-registry membership test, threaded into the §14 archetype step
|
|
42
|
+
* (04 §8 H1/H4) so unregistered ids are dropped before they reach a stored
|
|
43
|
+
* page.
|
|
44
|
+
*
|
|
45
|
+
* **Defaults to `isRegisteredWidgetId`** — the checked-in mirror of
|
|
46
|
+
* `widgetRegistry` that `@adminium/widgets/generate` exports (the Engine is
|
|
47
|
+
* Node-only and cannot import the registry map itself, and neither can the
|
|
48
|
+
* server, 01 §2.3). Defaulting rather than requiring is deliberate: this option
|
|
49
|
+
* being *optional and omitted* by the sole production caller is what made every
|
|
50
|
+
* registry filter in the archetype pipeline dead code, persisting chrome ids
|
|
51
|
+
* like `toast-stack`/`date-range-picker` into real page envelopes.
|
|
52
|
+
*
|
|
53
|
+
* Pass an explicit test only to override that catalog — a Studio preview
|
|
54
|
+
* against a marketplace registry, or `() => true` in a unit test driving
|
|
55
|
+
* synthetic widget ids.
|
|
56
|
+
*/
|
|
57
|
+
isRegistered?: ((widgetId: string) => boolean) | undefined;
|
|
58
|
+
}
|
|
59
|
+
export interface GenerateResult {
|
|
60
|
+
pages: PageEnvelope[];
|
|
61
|
+
warnings: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generate the v1 page set for a classified model: one `page-crud` per
|
|
65
|
+
* included table plus one `page-dashboard` per FK-cluster domain (cap
|
|
66
|
+
* {@link DASHBOARD_CAP}), honoring the 09 §8.4 intent. The model should come
|
|
67
|
+
* out of `applyClassification` (snapshots persist that form); classification
|
|
68
|
+
* is recomputed here regardless — `classifyModel` is pure and cheap, and the
|
|
69
|
+
* generator also needs the non-persisted shape/displayColumn outputs. Column
|
|
70
|
+
* stamps with `source: 'llm' | 'override'` still beat the recomputed tags
|
|
71
|
+
* (05 §7, `archetype.ts#toClassifiedInput`); heuristic stamps do not — the
|
|
72
|
+
* recomputed classification of the model as handed in (post `includedTables`
|
|
73
|
+
* filtering) is authoritative.
|
|
74
|
+
*/
|
|
75
|
+
export declare function generatePages(model: DatabaseModel, opts?: GenerateOptions): GenerateResult;
|
|
76
|
+
/** Human-readable page label — used by server replies and the demo script. */
|
|
77
|
+
export declare function pageLabel(page: PageEnvelope): string;
|
|
78
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,oBAAoB,CAAC;AAOpE,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EACL,cAAc,EACd,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,aAAa,EACb,OAAO,EACP,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,2EAKnB,CAAC;AACX,eAAO,MAAM,oBAAoB;;;;;EAA2B,CAAC;AAC7D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,2DAA2D;AAC3D,eAAO,MAAM,aAAa,IAAI,CAAC;AAwB/B,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAC5D;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAyID;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,GAAE,eAAoB,GAAG,cAAc,CA+I9F;AAED,8EAA8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAEpD"}
|