@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,301 @@
|
|
|
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 { domainHasDashboardSignal, emitCandidates, isRegisteredWidgetId, selectArchetype, } from '@adminium/widgets/generate';
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { classifyModel } from '../classify/index.js';
|
|
15
|
+
import { pageEnvelopeSchema, widgetConfigSchema, } from '../config-schema/envelope.js';
|
|
16
|
+
import { archetypeSlug, buildArchetypeEnvelope, toCandidateModel } from './archetype.js';
|
|
17
|
+
import { buildCrudEnvelope } from './crud.js';
|
|
18
|
+
import { buildDashboardEnvelope } from './dashboard.js';
|
|
19
|
+
import { detectDomains } from './domains.js';
|
|
20
|
+
import { hashEnvelope, humanize, slugify, SlugRegistry } from './util.js';
|
|
21
|
+
export { archetypeSlug, buildArchetypeEnvelope, composeRequestedArchetype, toCandidateModel, } from './archetype.js';
|
|
22
|
+
export { buildCrudEnvelope, enumTones } from './crud.js';
|
|
23
|
+
export { buildDashboardEnvelope, hasDashboardSignal, } from './dashboard.js';
|
|
24
|
+
export { detectDomains } from './domains.js';
|
|
25
|
+
export { ID_SLUG_BUDGET, MAX_SLUG_LENGTH, hashEnvelope, humanize, pageIdFor, pluralizeWord, slugify, SlugRegistry, } from './util.js';
|
|
26
|
+
/** 09 §8.4 generation intent variants (adminium_connections.settings.intent). */
|
|
27
|
+
export const GENERATE_INTENTS = [
|
|
28
|
+
'full-admin',
|
|
29
|
+
'read-only-analytics',
|
|
30
|
+
'crud',
|
|
31
|
+
'support-console',
|
|
32
|
+
];
|
|
33
|
+
export const generateIntentSchema = z.enum(GENERATE_INTENTS);
|
|
34
|
+
/** One `page-dashboard` per major domain, cap 3 for v1. */
|
|
35
|
+
export const DASHBOARD_CAP = 3;
|
|
36
|
+
/**
|
|
37
|
+
* The §14 archetypes each 09 §8.4 intent OMITS (empty ⇒ it admits them all).
|
|
38
|
+
* `crud` is absent because it skips the archetype pass wholesale ("`page-crud`
|
|
39
|
+
* per table … no dashboards beyond a minimal home").
|
|
40
|
+
*
|
|
41
|
+
* An archetype is omitted when the intent's §8.4 row rules out the *surface*, not
|
|
42
|
+
* merely the permission: capping roles at Viewer still leaves a kanban whose
|
|
43
|
+
* whole affordance is dragging a row to a new status, and a page's `toolbar` /
|
|
44
|
+
* `overlays` chrome is generated per template, not per role. Dropping the page is
|
|
45
|
+
* what makes the intent mean what §8.4 says it means.
|
|
46
|
+
*/
|
|
47
|
+
const INTENT_OMITTED_ARCHETYPES = {
|
|
48
|
+
'full-admin': [],
|
|
49
|
+
// §8.4: "dashboards, analytics, data grids (read-only), search, exports; no
|
|
50
|
+
// forms/boards/imports". page-board is the board; page-files is the import
|
|
51
|
+
// surface (upload-dropzone); page-queue-inbox (modal-wizard approvals) and
|
|
52
|
+
// page-chat (message compose) are the form surfaces.
|
|
53
|
+
'read-only-analytics': ['page-board', 'page-chat', 'page-files', 'page-queue-inbox'],
|
|
54
|
+
// §8.4: "queue/master-detail templates prioritized …; boards/analytics omitted".
|
|
55
|
+
'support-console': ['page-board'],
|
|
56
|
+
};
|
|
57
|
+
/** Nav icon per table shape (lucide names, 09 §2.2). */
|
|
58
|
+
const SHAPE_ICONS = {
|
|
59
|
+
people: 'users',
|
|
60
|
+
workflow: 'kanban-square',
|
|
61
|
+
events: 'calendar',
|
|
62
|
+
catalog: 'package',
|
|
63
|
+
log: 'scroll-text',
|
|
64
|
+
settings: 'settings',
|
|
65
|
+
geo: 'map',
|
|
66
|
+
join: 'link',
|
|
67
|
+
generic: 'table',
|
|
68
|
+
};
|
|
69
|
+
function splitTables(model, classified, warnings) {
|
|
70
|
+
const included = [];
|
|
71
|
+
const graph = [];
|
|
72
|
+
for (const table of [...model.tables].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
73
|
+
const info = classified.get(table.id);
|
|
74
|
+
const role = info?.semantics.role ?? table.semantics?.role ?? 'entity';
|
|
75
|
+
if (table.system || role === 'system') {
|
|
76
|
+
warnings.push(`skipped system table ${table.id} (05 §8.2)`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (role === 'join-table') {
|
|
80
|
+
warnings.push(`skipped join table ${table.id} — hidden from nav, relation still powers M2M (05 §8.2)`);
|
|
81
|
+
graph.push(table);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
included.push(table);
|
|
85
|
+
graph.push(table);
|
|
86
|
+
}
|
|
87
|
+
return { included, graph };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The §14 archetype pass: for every included table, the highest-scoring §14
|
|
91
|
+
* trigger (04 §8 H2: "1 page archetype per table … `page-crud` always emitted
|
|
92
|
+
* regardless") composed into a page. Tables that trigger nothing, tie, or whose
|
|
93
|
+
* template has an unfillable `required` slot yield nothing.
|
|
94
|
+
*/
|
|
95
|
+
function archetypePages(candidateModel, tables, opts) {
|
|
96
|
+
const { connectionId, warnings } = opts;
|
|
97
|
+
if (connectionId === null) {
|
|
98
|
+
warnings.push('no connection id — §14 archetype pages skipped (query descriptors bind to a connection)');
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const ctx = {
|
|
102
|
+
connectionId,
|
|
103
|
+
model: candidateModel,
|
|
104
|
+
isRegistered: opts.isRegistered,
|
|
105
|
+
};
|
|
106
|
+
const byId = new Map(tables.map((table) => [table.id, table]));
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const entry of candidateModel) {
|
|
109
|
+
const table = byId.get(entry.table.id);
|
|
110
|
+
const placement = opts.crudPlacement.get(entry.table.id);
|
|
111
|
+
if (table === undefined || placement === undefined)
|
|
112
|
+
continue;
|
|
113
|
+
const selection = selectArchetype(entry.table, entry.classified, ctx);
|
|
114
|
+
if (selection === null)
|
|
115
|
+
continue;
|
|
116
|
+
if (opts.omittedArchetypes.has(selection.template)) {
|
|
117
|
+
warnings.push(`${selection.template} for ${table.id} skipped — the generation intent omits this archetype (09 §8.4)`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const candidates = emitCandidates(entry.table, entry.classified, ctx);
|
|
121
|
+
const slug = opts.slugs.claim(archetypeSlug(placement.slug, selection.template));
|
|
122
|
+
const built = buildArchetypeEnvelope(table, selection, candidates, {
|
|
123
|
+
connectionId,
|
|
124
|
+
slug,
|
|
125
|
+
// Sits directly under its table's page-crud in the nav (crud orders step
|
|
126
|
+
// by 10), so the archetype never shifts a crud page's position.
|
|
127
|
+
navOrder: placement.navOrder + 5,
|
|
128
|
+
isRegistered: opts.isRegistered,
|
|
129
|
+
});
|
|
130
|
+
if (built.envelope === null) {
|
|
131
|
+
const detail = built.warnings
|
|
132
|
+
.filter((w) => w.code === 'required-slot-unfillable' || w.code === 'invalid-layout')
|
|
133
|
+
.map((w) => w.message)
|
|
134
|
+
.join('; ');
|
|
135
|
+
warnings.push(`${selection.template} for ${table.id} skipped — ${detail || 'composition produced no page'}`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const id = built.envelope['id'];
|
|
139
|
+
if (opts.emittedIds.has(id)) {
|
|
140
|
+
// Two slugs colliding after the char(36) id budget (util.ts `pageIdFor`).
|
|
141
|
+
// Dropping the archetype is the safe branch: a crud page must never be
|
|
142
|
+
// overwritten by an upsert on a duplicate id.
|
|
143
|
+
warnings.push(`${selection.template} for ${table.id} skipped — page id "${id}" already taken`);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
opts.emittedIds.add(id);
|
|
147
|
+
out.push(built.envelope);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Generate the v1 page set for a classified model: one `page-crud` per
|
|
153
|
+
* included table plus one `page-dashboard` per FK-cluster domain (cap
|
|
154
|
+
* {@link DASHBOARD_CAP}), honoring the 09 §8.4 intent. The model should come
|
|
155
|
+
* out of `applyClassification` (snapshots persist that form); classification
|
|
156
|
+
* is recomputed here regardless — `classifyModel` is pure and cheap, and the
|
|
157
|
+
* generator also needs the non-persisted shape/displayColumn outputs. Column
|
|
158
|
+
* stamps with `source: 'llm' | 'override'` still beat the recomputed tags
|
|
159
|
+
* (05 §7, `archetype.ts#toClassifiedInput`); heuristic stamps do not — the
|
|
160
|
+
* recomputed classification of the model as handed in (post `includedTables`
|
|
161
|
+
* filtering) is authoritative.
|
|
162
|
+
*/
|
|
163
|
+
export function generatePages(model, opts = {}) {
|
|
164
|
+
const intent = opts.intent ?? 'full-admin';
|
|
165
|
+
const isRegistered = opts.isRegistered ?? isRegisteredWidgetId;
|
|
166
|
+
const warnings = [];
|
|
167
|
+
const connectionId = opts.connectionId !== undefined
|
|
168
|
+
? opts.connectionId
|
|
169
|
+
: model.source.kind === 'live'
|
|
170
|
+
? model.source.connectionId
|
|
171
|
+
: null;
|
|
172
|
+
const classified = new Map(classifyModel(model).tables.map((t) => [t.tableId, t]));
|
|
173
|
+
const { included: tables, graph } = splitTables(model, classified, warnings);
|
|
174
|
+
const includedIdSet = new Set(tables.map((t) => t.id));
|
|
175
|
+
const slugs = new SlugRegistry();
|
|
176
|
+
const rawPages = [];
|
|
177
|
+
// The Engine↔Registry adapter runs ONCE — crud bodies, domain dashboards and
|
|
178
|
+
// the archetype pass all read the same mirrored model (archetype.ts is where
|
|
179
|
+
// the two vocabularies meet).
|
|
180
|
+
const candidateModel = toCandidateModel(model, tables, classified);
|
|
181
|
+
const entryById = new Map(candidateModel.map((entry) => [entry.table.id, entry]));
|
|
182
|
+
// -- dashboards first: they own the WORKSPACE group and low nav orders ----
|
|
183
|
+
// `crud` gets "no dashboards beyond a minimal home" and `support-console` has
|
|
184
|
+
// "analytics omitted" — both per 09 §8.4.
|
|
185
|
+
const wantDashboards = intent !== 'crud' && intent !== 'support-console';
|
|
186
|
+
if (wantDashboards) {
|
|
187
|
+
if (connectionId === null) {
|
|
188
|
+
warnings.push('no connection id — dashboards skipped (query descriptors bind to a connection)');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Join tables participate in the graph (they connect M2M sides) but
|
|
192
|
+
// never appear as domain members downstream.
|
|
193
|
+
const domains = detectDomains(model, graph)
|
|
194
|
+
.map((domain) => ({
|
|
195
|
+
...domain,
|
|
196
|
+
tableIds: domain.tableIds.filter((id) => includedIdSet.has(id)),
|
|
197
|
+
}))
|
|
198
|
+
.filter((domain) => domain.tableIds.length > 0);
|
|
199
|
+
const eligible = domains.filter((domain) => {
|
|
200
|
+
if (domainHasDashboardSignal(domain, candidateModel, model.relations))
|
|
201
|
+
return true;
|
|
202
|
+
warnings.push(`domain ${domain.key} has no timestamp column — dashboard skipped (05 §8)`);
|
|
203
|
+
return false;
|
|
204
|
+
});
|
|
205
|
+
if (eligible.length > DASHBOARD_CAP) {
|
|
206
|
+
warnings.push(`${eligible.length} dashboard-eligible domains — capped at ${DASHBOARD_CAP} for v1`);
|
|
207
|
+
}
|
|
208
|
+
const chosen = eligible.slice(0, DASHBOARD_CAP);
|
|
209
|
+
const multi = chosen.length > 1;
|
|
210
|
+
let navOrder = 10;
|
|
211
|
+
for (const domain of chosen) {
|
|
212
|
+
const slug = slugs.claim(multi ? slugify(`dashboard-${domain.key}`) : 'dashboard');
|
|
213
|
+
const title = multi ? `${domain.label} Dashboard` : 'Dashboard';
|
|
214
|
+
const built = buildDashboardEnvelope(domain, candidateModel, model.relations, {
|
|
215
|
+
connectionId,
|
|
216
|
+
slug,
|
|
217
|
+
title,
|
|
218
|
+
navOrder,
|
|
219
|
+
isRegistered,
|
|
220
|
+
});
|
|
221
|
+
if (built.envelope === null) {
|
|
222
|
+
// Unreachable after eligibility unless a required slot cannot fill
|
|
223
|
+
// (a registry stripped of kpi/line widgets) — the domain keeps no page.
|
|
224
|
+
const detail = built.warnings
|
|
225
|
+
.filter((w) => w.code === 'required-slot-unfillable' || w.code === 'invalid-layout')
|
|
226
|
+
.map((w) => w.message)
|
|
227
|
+
.join('; ');
|
|
228
|
+
warnings.push(`page-dashboard for domain ${domain.key} skipped — ${detail || 'composition produced no page'}`);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
rawPages.push(built.envelope);
|
|
232
|
+
navOrder += 1;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// -- one page-crud per included table (research/widget-registry.md §14) --
|
|
237
|
+
const readOnly = intent === 'read-only-analytics';
|
|
238
|
+
const includedIds = includedIdSet;
|
|
239
|
+
const counters = { library: 0, people: 0 };
|
|
240
|
+
/** Each table's page-crud slug + nav order — the archetype pass sits beside them. */
|
|
241
|
+
const crudPlacement = new Map();
|
|
242
|
+
for (const table of tables) {
|
|
243
|
+
const info = classified.get(table.id);
|
|
244
|
+
const entry = entryById.get(table.id);
|
|
245
|
+
const people = info.shape.kind === 'people' || info.semantics.role === 'people';
|
|
246
|
+
const group = people ? 'people' : 'library';
|
|
247
|
+
const order = 20 + 10 * (people ? counters.people++ : counters.library++);
|
|
248
|
+
const ctx = {
|
|
249
|
+
connectionId,
|
|
250
|
+
slug: slugs.claim(slugify(table.name)),
|
|
251
|
+
navGroup: group,
|
|
252
|
+
navIcon: SHAPE_ICONS[info.shape.kind] ?? 'table',
|
|
253
|
+
navOrder: order,
|
|
254
|
+
readOnly,
|
|
255
|
+
includedTableIds: includedIds,
|
|
256
|
+
relations: model.relations,
|
|
257
|
+
};
|
|
258
|
+
crudPlacement.set(table.id, { slug: ctx.slug, navOrder: order });
|
|
259
|
+
rawPages.push(buildCrudEnvelope(entry, ctx));
|
|
260
|
+
}
|
|
261
|
+
// -- plus the highest-scoring §14 archetype per table (§15 step 3) -------
|
|
262
|
+
//
|
|
263
|
+
// Strictly additive, and strictly LAST: the crud/dashboard envelopes above
|
|
264
|
+
// are the v0.1-gate-proven output, so this pass may not perturb them. Running
|
|
265
|
+
// after the crud loop is what guarantees it — archetype slugs are claimed from
|
|
266
|
+
// the same `SlugRegistry` only once every crud slug already holds its name,
|
|
267
|
+
// and nav orders slot between the crud orders (+5) without touching the
|
|
268
|
+
// counters. `test/generate-baseline.test.ts` is the regression guard.
|
|
269
|
+
if (intent !== 'crud') {
|
|
270
|
+
for (const raw of archetypePages(candidateModel, tables, {
|
|
271
|
+
connectionId,
|
|
272
|
+
slugs,
|
|
273
|
+
crudPlacement,
|
|
274
|
+
warnings,
|
|
275
|
+
isRegistered,
|
|
276
|
+
omittedArchetypes: new Set(INTENT_OMITTED_ARCHETYPES[intent] ?? []),
|
|
277
|
+
emittedIds: new Set(rawPages.map((page) => page['id'])),
|
|
278
|
+
})) {
|
|
279
|
+
rawPages.push(raw);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// -- stamp generated hashes + validate against the frozen contract -------
|
|
283
|
+
const pages = [];
|
|
284
|
+
for (const raw of rawPages) {
|
|
285
|
+
const config = raw['config'];
|
|
286
|
+
config['generatedHash'] = hashEnvelope(raw);
|
|
287
|
+
const envelope = pageEnvelopeSchema.parse(raw);
|
|
288
|
+
if (envelope.kind === 'dashboard') {
|
|
289
|
+
const layout = envelope.config['layout'];
|
|
290
|
+
for (const item of layout.items)
|
|
291
|
+
widgetConfigSchema.parse(item);
|
|
292
|
+
}
|
|
293
|
+
pages.push(envelope);
|
|
294
|
+
}
|
|
295
|
+
return { pages, warnings };
|
|
296
|
+
}
|
|
297
|
+
/** Human-readable page label — used by server replies and the demo script. */
|
|
298
|
+
export function pageLabel(page) {
|
|
299
|
+
return page.title.fallback || humanize(page.id.replace(/^page_/, ''));
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generate/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the generator (05-introspection-engine.md generation
|
|
3
|
+
* section, 09-generated-app.md §2.2 slug rules).
|
|
4
|
+
*
|
|
5
|
+
* Everything here is pure and deterministic — `generatePages()` promises
|
|
6
|
+
* "same inputs, same output" (05 §9), so no randomness, no Date.now().
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Meta `id` columns are char(36) (07-meta-store.md §2.1); generated page ids
|
|
10
|
+
* are `page_<slug>` (5 + slug), so slugs cap at 31 characters.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_SLUG_LENGTH = 31;
|
|
13
|
+
/** `Order_Details` / `orderDetails` → `order-details` (kebab-case, 09 §2.2). */
|
|
14
|
+
export declare function slugify(name: string): string;
|
|
15
|
+
/** Deterministic unique-slug allocator: `orders`, `orders-2`, `orders-3`, … */
|
|
16
|
+
export declare class SlugRegistry {
|
|
17
|
+
private readonly taken;
|
|
18
|
+
claim(base: string): string;
|
|
19
|
+
}
|
|
20
|
+
/** `order_details` → `Order Details`; `public.orders` → `Orders`. */
|
|
21
|
+
export declare function humanize(name: string): string;
|
|
22
|
+
/** Tiny pluralizer for domain/table labels ("Order" → "Orders"). */
|
|
23
|
+
export declare function pluralizeWord(word: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* `generated_hash` for a page document (01-architecture.md §6.1 / 04 §6.3):
|
|
26
|
+
* sha256 over the canonical (sorted-keys) JSON of the envelope with the
|
|
27
|
+
* embedded `config.generatedHash` itself excluded. M5 regeneration compares
|
|
28
|
+
* this against the stored document to tell user-edited pages ("user delta
|
|
29
|
+
* wins") from untouched generated ones (updated in place).
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* How many characters of the slug fit into a connection-scoped page id:
|
|
33
|
+
* 'page_' (5) + hash8 (8) + '_' (1) = 14, leaving 22 of the char(36) PK.
|
|
34
|
+
*/
|
|
35
|
+
export declare const ID_SLUG_BUDGET = 22;
|
|
36
|
+
/**
|
|
37
|
+
* Stable, connection-scoped page id. Ids are GLOBALLY unique in
|
|
38
|
+
* adminium_pages (char(36) PK), while slugs are only unique per connection —
|
|
39
|
+
* so multi-connection installs need the connection folded into the id
|
|
40
|
+
* (regression: second connection's 'page_customers' collided with the
|
|
41
|
+
* first's). Connection-less (universal) pages keep the bare readable form
|
|
42
|
+
* ('page_' + a slug already capped at 31 = 36).
|
|
43
|
+
*/
|
|
44
|
+
export declare function pageIdFor(connectionId: string | null, slug: string): string;
|
|
45
|
+
export declare function hashEnvelope(envelope: Record<string, unknown>): string;
|
|
46
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the generator (05-introspection-engine.md generation
|
|
3
|
+
* section, 09-generated-app.md §2.2 slug rules).
|
|
4
|
+
*
|
|
5
|
+
* Everything here is pure and deterministic — `generatePages()` promises
|
|
6
|
+
* "same inputs, same output" (05 §9), so no randomness, no Date.now().
|
|
7
|
+
*/
|
|
8
|
+
import { sha256Hex } from '../snapshot/sha256.js';
|
|
9
|
+
/**
|
|
10
|
+
* Meta `id` columns are char(36) (07-meta-store.md §2.1); generated page ids
|
|
11
|
+
* are `page_<slug>` (5 + slug), so slugs cap at 31 characters.
|
|
12
|
+
*/
|
|
13
|
+
export const MAX_SLUG_LENGTH = 31;
|
|
14
|
+
/** `Order_Details` / `orderDetails` → `order-details` (kebab-case, 09 §2.2). */
|
|
15
|
+
export function slugify(name) {
|
|
16
|
+
const slug = name
|
|
17
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
18
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
19
|
+
.toLowerCase()
|
|
20
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
21
|
+
.replace(/^-+|-+$/g, '')
|
|
22
|
+
.replace(/^[^a-z]+/, ''); // slugs must start with a letter (kebab pattern)
|
|
23
|
+
return (slug === '' ? 'page' : slug).slice(0, MAX_SLUG_LENGTH).replace(/-+$/, '');
|
|
24
|
+
}
|
|
25
|
+
/** Deterministic unique-slug allocator: `orders`, `orders-2`, `orders-3`, … */
|
|
26
|
+
export class SlugRegistry {
|
|
27
|
+
taken = new Set();
|
|
28
|
+
claim(base) {
|
|
29
|
+
let candidate = base;
|
|
30
|
+
for (let n = 2; this.taken.has(candidate); n += 1) {
|
|
31
|
+
const suffix = `-${n}`;
|
|
32
|
+
candidate = `${base.slice(0, MAX_SLUG_LENGTH - suffix.length)}${suffix}`;
|
|
33
|
+
}
|
|
34
|
+
this.taken.add(candidate);
|
|
35
|
+
return candidate;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** `order_details` → `Order Details`; `public.orders` → `Orders`. */
|
|
39
|
+
export function humanize(name) {
|
|
40
|
+
const bare = name.includes('.') ? (name.split('.').pop() ?? name) : name;
|
|
41
|
+
return bare
|
|
42
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
43
|
+
.replace(/[_-]+/g, ' ')
|
|
44
|
+
.trim()
|
|
45
|
+
.split(/\s+/)
|
|
46
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
47
|
+
.join(' ');
|
|
48
|
+
}
|
|
49
|
+
/** Tiny pluralizer for domain/table labels ("Order" → "Orders"). */
|
|
50
|
+
export function pluralizeWord(word) {
|
|
51
|
+
if (/s$/i.test(word))
|
|
52
|
+
return word; // already plural (or an s-final noun)
|
|
53
|
+
if (/(x|z|ch|sh)$/i.test(word))
|
|
54
|
+
return `${word}es`;
|
|
55
|
+
if (/[^aeiou]y$/i.test(word))
|
|
56
|
+
return `${word.slice(0, -1)}ies`;
|
|
57
|
+
return `${word}s`;
|
|
58
|
+
}
|
|
59
|
+
function sortKeysDeep(value) {
|
|
60
|
+
if (Array.isArray(value))
|
|
61
|
+
return value.map(sortKeysDeep);
|
|
62
|
+
if (value !== null && typeof value === 'object') {
|
|
63
|
+
const record = value;
|
|
64
|
+
const sorted = {};
|
|
65
|
+
for (const key of Object.keys(record).sort())
|
|
66
|
+
sorted[key] = sortKeysDeep(record[key]);
|
|
67
|
+
return sorted;
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* `generated_hash` for a page document (01-architecture.md §6.1 / 04 §6.3):
|
|
73
|
+
* sha256 over the canonical (sorted-keys) JSON of the envelope with the
|
|
74
|
+
* embedded `config.generatedHash` itself excluded. M5 regeneration compares
|
|
75
|
+
* this against the stored document to tell user-edited pages ("user delta
|
|
76
|
+
* wins") from untouched generated ones (updated in place).
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* How many characters of the slug fit into a connection-scoped page id:
|
|
80
|
+
* 'page_' (5) + hash8 (8) + '_' (1) = 14, leaving 22 of the char(36) PK.
|
|
81
|
+
*/
|
|
82
|
+
export const ID_SLUG_BUDGET = 22;
|
|
83
|
+
/**
|
|
84
|
+
* The slug as it appears inside a page id, within {@link ID_SLUG_BUDGET}.
|
|
85
|
+
*
|
|
86
|
+
* Must be INJECTIVE: `SlugRegistry` only de-duplicates against the full
|
|
87
|
+
* {@link MAX_SLUG_LENGTH} slug, so a plain `slice(0, 22)` maps distinct slugs to
|
|
88
|
+
* one id — `order_details_archive_2024` and `..._2025` both became
|
|
89
|
+
* `page_<scope>_order-details-archive-`. `pagesRepo.upsertGenerated` rejects
|
|
90
|
+
* duplicate ids, so that collision failed the WHOLE connection's generation run,
|
|
91
|
+
* not just the colliding pair. Over-budget slugs therefore keep a readable head
|
|
92
|
+
* and earn a digest of the full slug, which distinct slugs cannot share.
|
|
93
|
+
*/
|
|
94
|
+
function idSlug(slug) {
|
|
95
|
+
if (slug.length <= ID_SLUG_BUDGET)
|
|
96
|
+
return slug;
|
|
97
|
+
const digest = sha256Hex(slug).slice(0, 8);
|
|
98
|
+
const head = slug.slice(0, ID_SLUG_BUDGET - digest.length - 1).replace(/-+$/, '');
|
|
99
|
+
return `${head}-${digest}`;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Stable, connection-scoped page id. Ids are GLOBALLY unique in
|
|
103
|
+
* adminium_pages (char(36) PK), while slugs are only unique per connection —
|
|
104
|
+
* so multi-connection installs need the connection folded into the id
|
|
105
|
+
* (regression: second connection's 'page_customers' collided with the
|
|
106
|
+
* first's). Connection-less (universal) pages keep the bare readable form
|
|
107
|
+
* ('page_' + a slug already capped at 31 = 36).
|
|
108
|
+
*/
|
|
109
|
+
export function pageIdFor(connectionId, slug) {
|
|
110
|
+
if (connectionId === null)
|
|
111
|
+
return `page_${slug}`;
|
|
112
|
+
const scope = sha256Hex(connectionId).slice(0, 8);
|
|
113
|
+
return `page_${scope}_${idSlug(slug)}`;
|
|
114
|
+
}
|
|
115
|
+
export function hashEnvelope(envelope) {
|
|
116
|
+
const plain = JSON.parse(JSON.stringify(envelope));
|
|
117
|
+
const config = plain['config'];
|
|
118
|
+
if (config !== null && typeof config === 'object') {
|
|
119
|
+
delete config['generatedHash'];
|
|
120
|
+
}
|
|
121
|
+
return sha256Hex(JSON.stringify(sortKeysDeep(plain)));
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/generate/util.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @adminium/engine — SchemaModel, Adapter interface, classification, config generation. See workplan/05-introspection-engine.md. */
|
|
2
|
+
export declare const PACKAGE_NAME = "@adminium/engine";
|
|
3
|
+
export * from './schema-model.js';
|
|
4
|
+
export * from './adapter.js';
|
|
5
|
+
export * from './classify/index.js';
|
|
6
|
+
export * from './snapshot/index.js';
|
|
7
|
+
export * from './generate/index.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qIAAqI;AACrI,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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @adminium/engine — SchemaModel, Adapter interface, classification, config generation. See workplan/05-introspection-engine.md. */
|
|
2
|
+
export const PACKAGE_NAME = '@adminium/engine';
|
|
3
|
+
export * from './schema-model.js';
|
|
4
|
+
export * from './adapter.js';
|
|
5
|
+
export * from './classify/index.js';
|
|
6
|
+
export * from './snapshot/index.js';
|
|
7
|
+
export * from './generate/index.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qIAAqI;AACrI,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"}
|