@adminiumjs/manifest 0.3.0-rc.3 → 0.3.0-rc.4

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/dist/index.d.ts CHANGED
@@ -8,7 +8,9 @@
8
8
  * this package does I/O.
9
9
  */
10
10
  export declare const PACKAGE_NAME = "@adminium/manifest";
11
- export { MANIFEST_VERSION, MANIFEST_KINDS, MANIFEST_CATEGORIES, MANIFEST_CAPABILITIES, RESERVED_KEYS, COLUMN_TYPES, COLUMN_SEMANTICS, COLUMN_ROLES, FRONTEND_KINDS, FIRST_PARTY_PUBLISHER_ID, manifestSchema, appManifestSchema, addOnManifestSchema, manifestKindSchema, addOnIssues, isAddOnManifest, identitySchema, compatibilitySchema, requiredSchemaSchema, requiredTableSchema, requiredColumnSchema, pageSchema, roleSchema, settingSchema, seedSchema, frontendSchema, capabilitySchema, categorySchema, publisherSchema, i18nMessageSchema, compareSemver, type Manifest, type AppManifest, type AddOnManifest, type ManifestKind, type AddOnBlock, type Capability, type Publisher, type I18nMessage, type RequiredTable, type RequiredColumn, } from './schema.js';
11
+ export { MANIFEST_VERSION, MANIFEST_KINDS, MANIFEST_CATEGORIES, MANIFEST_CAPABILITIES, RESERVED_KEYS, COLUMN_TYPES, COLUMN_SEMANTICS, COLUMN_ROLES, FRONTEND_KINDS, FIRST_PARTY_PUBLISHER_ID, manifestSchema, appManifestSchema, addOnManifestSchema, manifestKindSchema, addOnIssues, isAddOnManifest, identitySchema, compatibilitySchema, requiredSchemaSchema, requiredTableSchema, requiredColumnSchema, pageSchema, roleSchema, settingSchema, seedSchema, frontendSchema, capabilitySchema, categorySchema, publisherSchema, i18nMessageSchema, compareSemver, defaultIssue, MAX_TEXT_LENGTH, MAX_TABLE_NAME, prefixFor, appReferenceIssues, columnRulesSchema, capacitySchema, navGroupSchema, publicAccessSchema, sampleDataSchema, labelsSchema, type ColumnRules, type PublicAccess, type Manifest, type AppManifest, type AddOnManifest, type ManifestKind, type AddOnBlock, type Capability, type Publisher, type I18nMessage, type RequiredTable, type RequiredColumn, } from './schema.js';
12
12
  export { validateManifest, parseManifest, type ValidateManifestResult, type ValidateManifestOptions, type ManifestIssue, } from './validate.js';
13
13
  export { planInstall, type InstallPlan, type PlannedTable, type PlannedColumn, type PlannedReference, type PlanProblem, type SchemaModelView, type ExistingColumnView, type TableAction, } from './plan.js';
14
+ export { IDENTIFIER_LIMIT, ROLE_SLUG_LIMIT, type PlanContext, type TableChoice, type TableClass, type TableOffer, type PlanEdit, type InstallTablePlan, type TableAction as ContextTableAction, } from './plan-context.js';
15
+ export { SAMPLE_FORMAT, isoDurationMs, sampleBundleIssues, sampleBundleSchema, sampleDirective, sampleRowSchema, sampleValueSchema, type SampleBundle, type SampleIssue, type SampleValue, } from './sample.js';
14
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAEjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,uBAAuB,CAAC;AAEjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,WAAW,IAAI,kBAAkB,GACvC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -9,7 +9,9 @@
9
9
  * this package does I/O.
10
10
  */
11
11
  export const PACKAGE_NAME = '@adminium/manifest';
12
- export { MANIFEST_VERSION, MANIFEST_KINDS, MANIFEST_CATEGORIES, MANIFEST_CAPABILITIES, RESERVED_KEYS, COLUMN_TYPES, COLUMN_SEMANTICS, COLUMN_ROLES, FRONTEND_KINDS, FIRST_PARTY_PUBLISHER_ID, manifestSchema, appManifestSchema, addOnManifestSchema, manifestKindSchema, addOnIssues, isAddOnManifest, identitySchema, compatibilitySchema, requiredSchemaSchema, requiredTableSchema, requiredColumnSchema, pageSchema, roleSchema, settingSchema, seedSchema, frontendSchema, capabilitySchema, categorySchema, publisherSchema, i18nMessageSchema, compareSemver, } from './schema.js';
12
+ export { MANIFEST_VERSION, MANIFEST_KINDS, MANIFEST_CATEGORIES, MANIFEST_CAPABILITIES, RESERVED_KEYS, COLUMN_TYPES, COLUMN_SEMANTICS, COLUMN_ROLES, FRONTEND_KINDS, FIRST_PARTY_PUBLISHER_ID, manifestSchema, appManifestSchema, addOnManifestSchema, manifestKindSchema, addOnIssues, isAddOnManifest, identitySchema, compatibilitySchema, requiredSchemaSchema, requiredTableSchema, requiredColumnSchema, pageSchema, roleSchema, settingSchema, seedSchema, frontendSchema, capabilitySchema, categorySchema, publisherSchema, i18nMessageSchema, compareSemver, defaultIssue, MAX_TEXT_LENGTH, MAX_TABLE_NAME, prefixFor, appReferenceIssues, columnRulesSchema, capacitySchema, navGroupSchema, publicAccessSchema, sampleDataSchema, labelsSchema, } from './schema.js';
13
13
  export { validateManifest, parseManifest, } from './validate.js';
14
14
  export { planInstall, } from './plan.js';
15
+ export { IDENTIFIER_LIMIT, ROLE_SLUG_LIMIT, } from './plan-context.js';
16
+ export { SAMPLE_FORMAT, isoDurationMs, sampleBundleIssues, sampleBundleSchema, sampleDirective, sampleRowSchema, sampleValueSchema, } from './sample.js';
15
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAEjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,aAAa,GAWd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,aAAa,GAId,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,WAAW,GASZ,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAEjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,GAab,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,aAAa,GAId,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,WAAW,GASZ,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,eAAe,GAQhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,GAIlB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Planning an APP install with what the server knows about this connection:
3
+ * the app's prefix, the tables it already recorded here, what other apps
4
+ * record here, and the operator's answers for the tables whose names are taken.
5
+ *
6
+ * ─── Why a context at all ───────────────────────────────────────────────────
7
+ *
8
+ * Without one, a table either exists (reuse) or does not (create), and that
9
+ * was the whole plan. It could not tell the app's own table from an earlier
10
+ * install apart from another app's table of the same name, could not offer
11
+ * to rename a stranger's table out of the way, and could not give an app its
12
+ * own prefix. Each table is now CLASSIFIED first, then given an ACTION:
13
+ *
14
+ * new the real name is free → create
15
+ * own-leftover this app recorded it (an earlier install) → reuse (default)
16
+ * shared another app recorded it under the SAME shape (`menu@1`)
17
+ * → share (default)
18
+ * taken it exists and nothing records it as this app's
19
+ * → the operator chooses
20
+ *
21
+ * For a taken table the operator chooses: REUSE it (offered only when it is
22
+ * not another app's in disguise and every change it needs is safe), RENAME the
23
+ * existing table out of the way (only when no other install records it), or
24
+ * give the whole app a DIFFERENT PREFIX (always offered, and it applies to
25
+ * every table at once). Until each taken table has an answer, the plan is not
26
+ * installable and says which table is waiting.
27
+ *
28
+ * ─── Edits ─────────────────────────────────────────────────────────────────
29
+ *
30
+ * A reused table may need changes before the app can write to it. Only changes
31
+ * that cannot lose data are ever offered: adding a missing column (nullable),
32
+ * widening a type along a fixed list (a longer varchar, varchar to text, int
33
+ * to bigint, a wider enum column), giving an int key the identity it lacks, and
34
+ * adding enum values. Anything else is refused on this screen, by name.
35
+ *
36
+ * Pure, like the planner it extends: no I/O. The server gathers the context.
37
+ */
38
+ import type { InstallPlan, PlanContext, SchemaModelView } from './plan-model.js';
39
+ import type { Manifest } from './schema.js';
40
+ export type { ContextTableAction as TableAction, InstallTablePlan, PlanContext, PlanEdit, TableChoice, TableClass, TableOffer, } from './plan-model.js';
41
+ /** The longest identifier each engine accepts, in bytes. SQLite has none; the portable 63 holds. */
42
+ export declare const IDENTIFIER_LIMIT: Readonly<Record<PlanContext['dialect'], number>>;
43
+ /** `adminium_roles.slug` is 40 characters. */
44
+ export declare const ROLE_SLUG_LIMIT = 40;
45
+ /**
46
+ * The context half of `planInstall`. Called by it when a context is given;
47
+ * the returned plan keeps every field older callers read (`create`, `reuse`,
48
+ * `references`, `problems`) and adds `tables` and `names`.
49
+ */
50
+ export declare function planWithContext(manifest: Manifest, model: SchemaModelView, context: PlanContext): InstallPlan;
51
+ //# sourceMappingURL=plan-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-context.d.ts","sourceRoot":"","sources":["../src/plan-context.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAEV,WAAW,EAEX,WAAW,EAEX,eAAe,EAEhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,QAAQ,EAAiC,MAAM,aAAa,CAAC;AAE3E,YAAY,EACV,kBAAkB,IAAI,WAAW,EACjC,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,EACV,UAAU,GACX,MAAM,iBAAiB,CAAC;AAGzB,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAI7E,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,eAAe,KAAK,CAAC;AAuDlC;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,WAAW,GACnB,WAAW,CA0Qb"}
@@ -0,0 +1,356 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ /**
3
+ * Planning an APP install with what the server knows about this connection:
4
+ * the app's prefix, the tables it already recorded here, what other apps
5
+ * record here, and the operator's answers for the tables whose names are taken.
6
+ *
7
+ * ─── Why a context at all ───────────────────────────────────────────────────
8
+ *
9
+ * Without one, a table either exists (reuse) or does not (create), and that
10
+ * was the whole plan. It could not tell the app's own table from an earlier
11
+ * install apart from another app's table of the same name, could not offer
12
+ * to rename a stranger's table out of the way, and could not give an app its
13
+ * own prefix. Each table is now CLASSIFIED first, then given an ACTION:
14
+ *
15
+ * new the real name is free → create
16
+ * own-leftover this app recorded it (an earlier install) → reuse (default)
17
+ * shared another app recorded it under the SAME shape (`menu@1`)
18
+ * → share (default)
19
+ * taken it exists and nothing records it as this app's
20
+ * → the operator chooses
21
+ *
22
+ * For a taken table the operator chooses: REUSE it (offered only when it is
23
+ * not another app's in disguise and every change it needs is safe), RENAME the
24
+ * existing table out of the way (only when no other install records it), or
25
+ * give the whole app a DIFFERENT PREFIX (always offered, and it applies to
26
+ * every table at once). Until each taken table has an answer, the plan is not
27
+ * installable and says which table is waiting.
28
+ *
29
+ * ─── Edits ─────────────────────────────────────────────────────────────────
30
+ *
31
+ * A reused table may need changes before the app can write to it. Only changes
32
+ * that cannot lose data are ever offered: adding a missing column (nullable),
33
+ * widening a type along a fixed list (a longer varchar, varchar to text, int
34
+ * to bigint, a wider enum column), giving an int key the identity it lacks, and
35
+ * adding enum values. Anything else is refused on this screen, by name.
36
+ *
37
+ * Pure, like the planner it extends: no I/O. The server gathers the context.
38
+ */
39
+ import { typeConflict } from './plan-types.js';
40
+ /** The longest identifier each engine accepts, in bytes. SQLite has none; the portable 63 holds. */
41
+ export const IDENTIFIER_LIMIT = {
42
+ postgres: 63,
43
+ mysql: 64,
44
+ sqlite: 63,
45
+ };
46
+ /** `adminium_roles.slug` is 40 characters. */
47
+ export const ROLE_SLUG_LIMIT = 40;
48
+ const IDENTIFIER = /^[a-z][a-z0-9_]*$/;
49
+ function byteLength(text) {
50
+ return new TextEncoder().encode(text).length;
51
+ }
52
+ /** The type a declared column is created with, for an edit's `to` — the installer's own vocabulary. */
53
+ function declaredShape(column) {
54
+ if (column.type === 'text' && column.maxLength !== undefined)
55
+ return `varchar(${String(column.maxLength)})`;
56
+ if (column.type === 'enum') {
57
+ const width = (column.enum ?? []).every((value) => value.length <= 32) ? 32 : 64;
58
+ return `varchar(${String(width)})`;
59
+ }
60
+ return column.type;
61
+ }
62
+ /**
63
+ * The widening that would let an existing column hold what the manifest
64
+ * stores, or null when there is no such safe change.
65
+ */
66
+ function wideningFor(declared, have, dialect) {
67
+ const type = have.logicalType;
68
+ const width = typeof have.maxLength === 'number' ? have.maxLength : null;
69
+ if (declared.type === 'text' && type === 'varchar' && width !== null) {
70
+ return { from: `varchar(${String(width)})`, to: declaredShape(declared) };
71
+ }
72
+ if (declared.type === 'enum' && type === 'varchar' && width !== null) {
73
+ return { from: `varchar(${String(width)})`, to: declaredShape(declared) };
74
+ }
75
+ if (declared.type === 'bigint' && type === 'integer') {
76
+ // MySQL cannot change the type of a key another table's foreign key points
77
+ // at; a primary key is where that is all but certain.
78
+ if (dialect === 'mysql' && have.isPrimaryKey === true)
79
+ return null;
80
+ return { from: 'integer', to: 'bigint' };
81
+ }
82
+ return null;
83
+ }
84
+ /**
85
+ * A column an update can add to a table that exists. A link (`fk`) can, when
86
+ * it is nullable: every existing row starts unlinked, and the schema editor
87
+ * adds the foreign key beside it. A required link cannot — the rows already
88
+ * there would have nothing to point at.
89
+ */
90
+ function isOfferable(column) {
91
+ if (column.type === 'fk')
92
+ return column.nullable === true;
93
+ return column.type !== 'id' && column.type !== 'blob';
94
+ }
95
+ /**
96
+ * The context half of `planInstall`. Called by it when a context is given;
97
+ * the returned plan keeps every field older callers read (`create`, `reuse`,
98
+ * `references`, `problems`) and adds `tables` and `names`.
99
+ */
100
+ export function planWithContext(manifest, model, context) {
101
+ const noun = manifest.kind === 'app' ? 'app' : 'add-on';
102
+ const required = manifest.requiredSchema?.tables ?? [];
103
+ const live = new Map(model.tables.map((t) => [t.ref, t]));
104
+ const limit = IDENTIFIER_LIMIT[context.dialect];
105
+ const problems = [];
106
+ const prefix = context.prefix === null ? null : (context.altPrefix ?? context.prefix);
107
+ if (context.altPrefix !== undefined && !/^[a-z][a-z0-9_]*_$/.test(context.altPrefix)) {
108
+ problems.push({
109
+ code: 'IDENTIFIER_TOO_LONG',
110
+ table: context.altPrefix,
111
+ message: `"${context.altPrefix}" is not a usable prefix: lower-case letters, digits and "_", ending in "_".`,
112
+ });
113
+ }
114
+ // 1. Real names. A record wins (it is what this app already uses here); an
115
+ // alternative prefix re-names everything that is not recorded.
116
+ const names = {};
117
+ for (const table of required) {
118
+ const record = context.records[table.ref];
119
+ const usable = record !== undefined && record.state !== 'dropped';
120
+ names[table.ref] = usable && context.altPrefix === undefined ? record.table : prefix === null ? table.ref : `${prefix}${table.ref}`;
121
+ }
122
+ const realNames = new Set(Object.values(names));
123
+ const tables = [];
124
+ for (const table of required) {
125
+ const real = names[table.ref];
126
+ const record = context.records[table.ref];
127
+ const existing = live.get(real);
128
+ const holders = context.others.filter((o) => o.table === real && o.state !== 'dropped');
129
+ const choice = context.choices?.[table.ref];
130
+ if (byteLength(real) > limit) {
131
+ problems.push({
132
+ code: 'IDENTIFIER_TOO_LONG',
133
+ table: table.ref,
134
+ message: `"${real}" is longer than this database allows (${String(limit)} bytes). Choose a shorter prefix.`,
135
+ });
136
+ }
137
+ for (const column of table.columns) {
138
+ if (column.type !== 'fk')
139
+ continue;
140
+ const fk = `fk_${real}_${column.ref}`;
141
+ if (byteLength(fk) > limit) {
142
+ problems.push({
143
+ code: 'IDENTIFIER_TOO_LONG',
144
+ table: table.ref,
145
+ column: column.ref,
146
+ message: `The foreign key "${fk}" would be longer than this database allows (${String(limit)} bytes). Choose a shorter prefix.`,
147
+ });
148
+ }
149
+ }
150
+ // 2. Classify.
151
+ const ownRecord = record !== undefined && record.state !== 'dropped' && context.altPrefix === undefined;
152
+ const sharer = table.shape === undefined ? undefined : holders.find((o) => o.shape === table.shape && o.state !== 'released');
153
+ const klass = existing === undefined ? 'new' : ownRecord ? 'own-leftover' : sharer !== undefined ? 'shared' : 'taken';
154
+ // Two apps whose prefixed names meet. A declared shape both share is the
155
+ // one way two apps may use one table.
156
+ if (holders.length > 0 && sharer === undefined && !ownRecord) {
157
+ problems.push({
158
+ code: 'PREFIX_COLLISION',
159
+ table: table.ref,
160
+ message: `"${real}" is already "${holders[0].appKey}"'s table, so this ${noun} cannot use that name. ` +
161
+ `Give this ${noun} a different prefix.`,
162
+ });
163
+ }
164
+ // Why reuse is not safe for a stranger's table.
165
+ const declaredColumns = new Set(table.columns.map((c) => c.ref));
166
+ const foreign = existing === undefined
167
+ ? []
168
+ : existing.columns.filter((c) => !declaredColumns.has(c.ref) &&
169
+ c.nullable === false &&
170
+ c.hasDefault !== true &&
171
+ c.isPrimaryKey !== true &&
172
+ c.isGenerated !== true);
173
+ const plan = {
174
+ ref: table.ref,
175
+ table: real,
176
+ class: klass,
177
+ action: 'create',
178
+ offers: [],
179
+ edits: [],
180
+ blocked: [],
181
+ };
182
+ if (klass === 'new') {
183
+ plan.action = 'create';
184
+ }
185
+ else if (klass === 'own-leftover') {
186
+ plan.offers = ['reuse', 'rename-existing', 'alt-prefix'];
187
+ if (record?.owned === false)
188
+ plan.adopted = true;
189
+ plan.action = choice?.action === 'rename-existing' ? 'rename-existing' : 'reuse';
190
+ }
191
+ else if (klass === 'shared') {
192
+ plan.offers = ['share', 'alt-prefix'];
193
+ plan.sharedWith = sharer.appKey;
194
+ plan.action = 'share';
195
+ }
196
+ else {
197
+ plan.offers = ['alt-prefix'];
198
+ if (foreign.length === 0)
199
+ plan.offers.unshift('reuse');
200
+ else {
201
+ plan.reuseRefusal =
202
+ `It requires ${foreign.map((c) => `"${c.ref}"`).join(', ')}, which this ${noun} never fills, ` +
203
+ `so every row the ${noun} saves there would be refused.`;
204
+ }
205
+ if (holders.length === 0)
206
+ plan.offers.splice(plan.offers.length - 1, 0, 'rename-existing');
207
+ if (choice === undefined)
208
+ plan.action = 'undecided';
209
+ else if (choice.action === 'reuse' && plan.offers.includes('reuse'))
210
+ plan.action = 'reuse';
211
+ else if (choice.action === 'rename-existing' && plan.offers.includes('rename-existing'))
212
+ plan.action = 'rename-existing';
213
+ else
214
+ plan.action = 'undecided';
215
+ }
216
+ if (plan.action === 'rename-existing') {
217
+ const to = choice?.action === 'rename-existing' ? choice.to : `${real}_old`;
218
+ plan.renameExistingTo = to;
219
+ if (!IDENTIFIER.test(to) || byteLength(to) > limit || live.has(to) || realNames.has(to)) {
220
+ problems.push({
221
+ code: 'TABLE_TAKEN',
222
+ table: table.ref,
223
+ message: `"${to}" cannot be the existing table's new name: it must be a free, lower-case name of at most ${String(limit)} bytes.`,
224
+ });
225
+ }
226
+ }
227
+ if (plan.action === 'undecided') {
228
+ problems.push({
229
+ code: 'TABLE_TAKEN',
230
+ table: table.ref,
231
+ message: `"${real}" already exists and was made by hand. Pick what to do with it before you install.`,
232
+ });
233
+ }
234
+ // 3. Edits, for a table the app will use as it is.
235
+ if ((plan.action === 'reuse' || plan.action === 'share') && existing !== undefined) {
236
+ for (const column of table.columns) {
237
+ const have = existing.columns.find((c) => c.ref === column.ref);
238
+ if (have === undefined) {
239
+ if (isOfferable(column))
240
+ plan.edits.push({ kind: 'add-column', column: column.ref });
241
+ else {
242
+ plan.blocked.push({
243
+ column: column.ref,
244
+ reason: column.type === 'id' ? 'primary-key' : column.type === 'fk' ? 'foreign-key' : 'unsupported-type',
245
+ });
246
+ }
247
+ continue;
248
+ }
249
+ const conflict = typeConflict(column, have, context.dialect);
250
+ if (conflict !== null) {
251
+ const widen = wideningFor(column, have, context.dialect);
252
+ if (widen !== null)
253
+ plan.edits.push({ kind: 'widen', column: column.ref, ...widen });
254
+ else {
255
+ problems.push({
256
+ code: 'COLUMN_TYPE_CONFLICT',
257
+ table: table.ref,
258
+ column: column.ref,
259
+ message: `"${real}.${column.ref}" already exists as ${conflict}, which cannot hold the ${column.type} values this ${noun} stores in it.`,
260
+ });
261
+ }
262
+ continue;
263
+ }
264
+ if (column.role === 'pk' && (column.type === 'int' || column.type === 'bigint') && have.isIdentity === false) {
265
+ plan.edits.push({ kind: 'set-identity', column: column.ref });
266
+ }
267
+ if (column.type === 'enum' && have.enumValues !== undefined) {
268
+ const missing = (column.enum ?? []).filter((value) => !have.enumValues.includes(value));
269
+ if (missing.length > 0)
270
+ plan.edits.push({ kind: 'enum-values', column: column.ref, values: missing });
271
+ }
272
+ }
273
+ if (plan.blocked.length > 0) {
274
+ problems.push({
275
+ code: 'COLUMNS_REQUIRED',
276
+ table: table.ref,
277
+ column: plan.blocked[0].column,
278
+ message: `"${real}" is missing ${plan.blocked.map((b) => `"${b.column}"`).join(', ')}, which cannot be added ` +
279
+ `to a table that already exists. Rename that table out of the way, or use a different prefix.`,
280
+ });
281
+ }
282
+ }
283
+ tables.push(plan);
284
+ }
285
+ // 4. References, against real names.
286
+ const references = [];
287
+ const declared = new Set(required.map((t) => t.ref));
288
+ for (const table of required) {
289
+ for (const column of table.columns) {
290
+ if (column.type !== 'fk' || column.references === undefined)
291
+ continue;
292
+ const target = column.references;
293
+ const resolution = declared.has(target) ? 'internal' : live.has(target) ? 'host' : 'unresolved';
294
+ references.push({ fromTable: table.ref, fromColumn: column.ref, to: target, resolution });
295
+ if (resolution === 'unresolved') {
296
+ problems.push({
297
+ code: 'UNRESOLVED_REFERENCE',
298
+ table: table.ref,
299
+ column: column.ref,
300
+ message: `"${table.ref}.${column.ref}" points at a table called "${target}", which this ` +
301
+ `${noun} does not create and this database does not have. Connect a database that ` +
302
+ `already has it, or create it first.`,
303
+ });
304
+ }
305
+ }
306
+ }
307
+ // 5. Role slugs fit their column.
308
+ if (manifest.kind === 'app') {
309
+ for (const role of manifest.roles ?? []) {
310
+ const slug = `${manifest.key}-${role.key}`;
311
+ if (slug.length > ROLE_SLUG_LIMIT) {
312
+ problems.push({
313
+ code: 'IDENTIFIER_TOO_LONG',
314
+ table: role.key,
315
+ message: `The role "${slug}" is longer than ${String(ROLE_SLUG_LIMIT)} characters.`,
316
+ });
317
+ }
318
+ }
319
+ }
320
+ for (const table of required) {
321
+ if (table.ref.startsWith('adminium_') || names[table.ref].startsWith('adminium_')) {
322
+ problems.push({
323
+ code: 'RESERVED_TABLE',
324
+ table: table.ref,
325
+ message: `"${names[table.ref]}" is in Adminium's own namespace.`,
326
+ });
327
+ }
328
+ }
329
+ const planned = (plan) => {
330
+ const spec = required.find((t) => t.ref === plan.ref);
331
+ const have = live.get(plan.table);
332
+ const missing = plan.action === 'reuse' || plan.action === 'share'
333
+ ? spec.columns.filter((c) => have !== undefined && !have.columns.some((x) => x.ref === c.ref)).map((c) => c.ref)
334
+ : [];
335
+ return {
336
+ ref: plan.ref,
337
+ table: plan.table,
338
+ action: plan.action === 'reuse' || plan.action === 'share' ? 'reuse' : 'create',
339
+ columns: spec.columns.map((c) => ({ ref: c.ref, type: c.type, missing: missing.includes(c.ref) })),
340
+ missingColumns: missing,
341
+ };
342
+ };
343
+ return {
344
+ addOnKey: manifest.key,
345
+ version: manifest.version,
346
+ create: tables.filter((t) => t.action === 'create' || t.action === 'rename-existing').map(planned),
347
+ reuse: tables.filter((t) => t.action === 'reuse' || t.action === 'share').map(planned),
348
+ references,
349
+ problems,
350
+ installable: problems.length === 0,
351
+ touchesData: required.length > 0,
352
+ tables,
353
+ names,
354
+ };
355
+ }
356
+ //# sourceMappingURL=plan-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-context.js","sourceRoot":"","sources":["../src/plan-context.ts"],"names":[],"mappings":"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"}