@sequenceholdings/orm 2.8.5 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +2 -2
- package/dist/authoring.d.ts +2 -2
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +72 -72
- package/dist/canonical.d.ts +72 -72
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +122 -68
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +32 -1
- package/dist/cli.d.ts +32 -1
- package/dist/cli.js +117 -69
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +259 -18
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +183 -3
- package/dist/compiler.d.ts +183 -3
- package/dist/compiler.js +254 -19
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-Dou1RkTo.d.cts → constants-D2o0vK6U.d.cts} +8 -1
- package/dist/{constants-Dou1RkTo.d.ts → constants-D2o0vK6U.d.ts} +8 -1
- package/dist/dynamic-input.d.cts +1 -1
- package/dist/dynamic-input.d.ts +1 -1
- package/dist/index.cjs +53 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -60
- package/dist/index.d.ts +61 -60
- package/dist/index.js +51 -32
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +9 -7
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +85 -74
- package/dist/ir.d.ts +85 -74
- package/dist/ir.js +9 -8
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +9 -7
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +3 -1
- package/dist/predicate-v2.d.ts +3 -1
- package/dist/predicate-v2.js +9 -7
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +8 -7
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +1 -1
- package/dist/sdl.d.ts +1 -1
- package/dist/sdl.js +8 -7
- package/dist/sdl.js.map +1 -1
- package/package.json +3 -3
- package/templates/orm-namespace/package.json +2 -1
- package/dist/{definition-DjfC7Lll.d.cts → definition-B99BsOAO.d.cts} +4 -4
- package/dist/{definition-DjfC7Lll.d.ts → definition-B99BsOAO.d.ts} +4 -4
package/dist/cli.d.cts
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
/** Set by the seq-studio delegate; direct users export them. */
|
|
2
2
|
declare const BASE_URL_ENV = "SEQUENCE_ORM_BASE_URL";
|
|
3
3
|
declare const TOKEN_ENV = "SEQUENCE_ORM_TOKEN";
|
|
4
|
+
/** JSON `{repository_id, commit, path, dirty?}` naming the Git Service source of this apply; set by the seq-studio delegate. */
|
|
5
|
+
declare const SOURCE_ENV = "SEQUENCE_ORM_SOURCE";
|
|
6
|
+
/** Namespace-admin override reason for an apply whose source does not verify; set by `seq-studio orm apply --unverified-source`. */
|
|
7
|
+
declare const UNVERIFIED_SOURCE_REASON_ENV = "SEQUENCE_ORM_UNVERIFIED_SOURCE_REASON";
|
|
8
|
+
/**
|
|
9
|
+
* The caller's token for the source claim's `source_environment`; set by `seq-studio orm apply --source-env`.
|
|
10
|
+
* Only the apply request carries it (as `x-sequence-source-authorization`), so Atlas can read the source there.
|
|
11
|
+
*/
|
|
12
|
+
declare const SOURCE_AUTHORIZATION_ENV = "SEQUENCE_ORM_SOURCE_AUTHORIZATION";
|
|
13
|
+
/** The apply request's source environment credential header, when the delegate supplied one. */
|
|
14
|
+
declare function applySourceHeaders(env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
15
|
+
/** The apply body's `source` claim, when the delegate supplied one. Atlas verifies it; it never authorizes anything. */
|
|
16
|
+
declare function applySourceFromEnv(env?: NodeJS.ProcessEnv): {
|
|
17
|
+
source?: Record<string, unknown>;
|
|
18
|
+
unverified_source_reason?: string;
|
|
19
|
+
};
|
|
4
20
|
/**
|
|
5
21
|
* Test/dev hook mirroring `LoadNamespaceOptions.ormModulePath`: when set, bare
|
|
6
22
|
* `'@sequenceholdings/orm'` imports in consumer files resolve to this path
|
|
@@ -12,6 +28,8 @@ type TokenProvider = () => Promise<string | null>;
|
|
|
12
28
|
/** Hand the CLI a refreshing token source (used by the seq-studio delegate). */
|
|
13
29
|
declare function setTokenProvider(provider: TokenProvider): void;
|
|
14
30
|
declare function runCli(argv: readonly string[]): Promise<number>;
|
|
31
|
+
/** Where the live version came from: `live since <time> from <commit> on <branch> at <path> by <actor>`. */
|
|
32
|
+
declare function describeActivation(activation: RegistryActivation): string;
|
|
15
33
|
interface ApplyWait {
|
|
16
34
|
wait: boolean;
|
|
17
35
|
timeoutMs: number;
|
|
@@ -24,5 +42,18 @@ declare function parseApplyWait(rest: readonly string[]): ApplyWait;
|
|
|
24
42
|
* details name the variable, column, constraint, or requirement at fault.
|
|
25
43
|
*/
|
|
26
44
|
declare function errorDetail(payload: unknown): string | null;
|
|
45
|
+
/** One row of the namespace's activation history, as the detail route returns it (absent on older Atlas). */
|
|
46
|
+
interface RegistryActivation {
|
|
47
|
+
id: string;
|
|
48
|
+
provenance_class: string;
|
|
49
|
+
/** Absent on an older Atlas; null for this deployment's own Git Service. */
|
|
50
|
+
source_environment?: string | null;
|
|
51
|
+
source_commit: string | null;
|
|
52
|
+
source_branch: string | null;
|
|
53
|
+
source_path: string | null;
|
|
54
|
+
reported_source: Record<string, unknown> | null;
|
|
55
|
+
actor_sub: string;
|
|
56
|
+
activated_at: string;
|
|
57
|
+
}
|
|
27
58
|
|
|
28
|
-
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, TOKEN_ENV, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
|
59
|
+
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, type RegistryActivation, SOURCE_AUTHORIZATION_ENV, SOURCE_ENV, TOKEN_ENV, UNVERIFIED_SOURCE_REASON_ENV, applySourceFromEnv, applySourceHeaders, describeActivation, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
/** Set by the seq-studio delegate; direct users export them. */
|
|
2
2
|
declare const BASE_URL_ENV = "SEQUENCE_ORM_BASE_URL";
|
|
3
3
|
declare const TOKEN_ENV = "SEQUENCE_ORM_TOKEN";
|
|
4
|
+
/** JSON `{repository_id, commit, path, dirty?}` naming the Git Service source of this apply; set by the seq-studio delegate. */
|
|
5
|
+
declare const SOURCE_ENV = "SEQUENCE_ORM_SOURCE";
|
|
6
|
+
/** Namespace-admin override reason for an apply whose source does not verify; set by `seq-studio orm apply --unverified-source`. */
|
|
7
|
+
declare const UNVERIFIED_SOURCE_REASON_ENV = "SEQUENCE_ORM_UNVERIFIED_SOURCE_REASON";
|
|
8
|
+
/**
|
|
9
|
+
* The caller's token for the source claim's `source_environment`; set by `seq-studio orm apply --source-env`.
|
|
10
|
+
* Only the apply request carries it (as `x-sequence-source-authorization`), so Atlas can read the source there.
|
|
11
|
+
*/
|
|
12
|
+
declare const SOURCE_AUTHORIZATION_ENV = "SEQUENCE_ORM_SOURCE_AUTHORIZATION";
|
|
13
|
+
/** The apply request's source environment credential header, when the delegate supplied one. */
|
|
14
|
+
declare function applySourceHeaders(env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
15
|
+
/** The apply body's `source` claim, when the delegate supplied one. Atlas verifies it; it never authorizes anything. */
|
|
16
|
+
declare function applySourceFromEnv(env?: NodeJS.ProcessEnv): {
|
|
17
|
+
source?: Record<string, unknown>;
|
|
18
|
+
unverified_source_reason?: string;
|
|
19
|
+
};
|
|
4
20
|
/**
|
|
5
21
|
* Test/dev hook mirroring `LoadNamespaceOptions.ormModulePath`: when set, bare
|
|
6
22
|
* `'@sequenceholdings/orm'` imports in consumer files resolve to this path
|
|
@@ -12,6 +28,8 @@ type TokenProvider = () => Promise<string | null>;
|
|
|
12
28
|
/** Hand the CLI a refreshing token source (used by the seq-studio delegate). */
|
|
13
29
|
declare function setTokenProvider(provider: TokenProvider): void;
|
|
14
30
|
declare function runCli(argv: readonly string[]): Promise<number>;
|
|
31
|
+
/** Where the live version came from: `live since <time> from <commit> on <branch> at <path> by <actor>`. */
|
|
32
|
+
declare function describeActivation(activation: RegistryActivation): string;
|
|
15
33
|
interface ApplyWait {
|
|
16
34
|
wait: boolean;
|
|
17
35
|
timeoutMs: number;
|
|
@@ -24,5 +42,18 @@ declare function parseApplyWait(rest: readonly string[]): ApplyWait;
|
|
|
24
42
|
* details name the variable, column, constraint, or requirement at fault.
|
|
25
43
|
*/
|
|
26
44
|
declare function errorDetail(payload: unknown): string | null;
|
|
45
|
+
/** One row of the namespace's activation history, as the detail route returns it (absent on older Atlas). */
|
|
46
|
+
interface RegistryActivation {
|
|
47
|
+
id: string;
|
|
48
|
+
provenance_class: string;
|
|
49
|
+
/** Absent on an older Atlas; null for this deployment's own Git Service. */
|
|
50
|
+
source_environment?: string | null;
|
|
51
|
+
source_commit: string | null;
|
|
52
|
+
source_branch: string | null;
|
|
53
|
+
source_path: string | null;
|
|
54
|
+
reported_source: Record<string, unknown> | null;
|
|
55
|
+
actor_sub: string;
|
|
56
|
+
activated_at: string;
|
|
57
|
+
}
|
|
27
58
|
|
|
28
|
-
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, TOKEN_ENV, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
|
59
|
+
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, type RegistryActivation, SOURCE_AUTHORIZATION_ENV, SOURCE_ENV, TOKEN_ENV, UNVERIFIED_SOURCE_REASON_ENV, applySourceFromEnv, applySourceHeaders, describeActivation, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
package/dist/cli.js
CHANGED
|
@@ -102,6 +102,8 @@ function materializedRefreshFunctionName(table) {
|
|
|
102
102
|
function materializeLockKey(schema, table) {
|
|
103
103
|
return `orm:materialize:${schema}.${table}`;
|
|
104
104
|
}
|
|
105
|
+
var OPERATION_DOCUMENTS_FILE = "operations.documents.json";
|
|
106
|
+
var OPERATION_DOCUMENTS_VERSION = 1;
|
|
105
107
|
|
|
106
108
|
// src/hash.ts
|
|
107
109
|
function stableJson(value) {
|
|
@@ -1811,19 +1813,20 @@ var variableIrSchema = z.object({
|
|
|
1811
1813
|
defaultValue: variableDefaultIrSchema.optional()
|
|
1812
1814
|
});
|
|
1813
1815
|
var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz", "jsonb"]), nullable: z.boolean() });
|
|
1816
|
+
var sqlObjectIrSchema = z.object({
|
|
1817
|
+
ref: z.string(),
|
|
1818
|
+
table: z.string(),
|
|
1819
|
+
columns: z.array(sqlColumnSchema.extend({ type: z.string() })).min(1),
|
|
1820
|
+
scan: z.string().min(1),
|
|
1821
|
+
read: z.array(z.string()).min(1)
|
|
1822
|
+
}).strict();
|
|
1814
1823
|
var compiledOperationSchema = z.object({
|
|
1815
1824
|
language: z.literal("sql").optional(),
|
|
1816
1825
|
/** Server-compiled object catalog and permission ceiling, never caller SQL. */
|
|
1817
1826
|
sqlQuery: z.object({
|
|
1818
1827
|
catalog: z.object({
|
|
1819
1828
|
identity: z.string(),
|
|
1820
|
-
objects: z.array(
|
|
1821
|
-
ref: z.string(),
|
|
1822
|
-
table: z.string(),
|
|
1823
|
-
columns: z.array(sqlColumnSchema.extend({ type: z.string() })).min(1),
|
|
1824
|
-
scan: z.string().min(1),
|
|
1825
|
-
read: z.array(z.string()).min(1)
|
|
1826
|
-
}).strict()).min(1).max(256)
|
|
1829
|
+
objects: z.array(sqlObjectIrSchema).min(1).max(256)
|
|
1827
1830
|
}).strict(),
|
|
1828
1831
|
read: z.array(z.string()).min(1).max(256),
|
|
1829
1832
|
maxRows: z.number().int().min(1).max(1e4)
|
|
@@ -2483,6 +2486,7 @@ var FLIPPED = {
|
|
|
2483
2486
|
">=": "<="
|
|
2484
2487
|
};
|
|
2485
2488
|
function resolveTable(resolver, table) {
|
|
2489
|
+
resolver.onTable?.(table);
|
|
2486
2490
|
const info = resolver.tables[table];
|
|
2487
2491
|
if (!info) {
|
|
2488
2492
|
throw new PolicyCompileError(`unknown table '${table}'`, "unknown-table", Object.keys(resolver.tables));
|
|
@@ -5398,10 +5402,13 @@ function sqlHash(value) {
|
|
|
5398
5402
|
return `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
5399
5403
|
}
|
|
5400
5404
|
function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
|
|
5401
|
-
if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
|
|
5402
5405
|
const { ctx, diagnostics } = buildCompileContext(canonical);
|
|
5403
5406
|
if (diagnostics.some((d) => d.severity === "error")) throw new Error(diagnostics.map((d) => d.message).join("; "));
|
|
5404
|
-
|
|
5407
|
+
return createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx });
|
|
5408
|
+
}
|
|
5409
|
+
function createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx, identity: suppliedIdentity }) {
|
|
5410
|
+
if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
|
|
5411
|
+
const identity = suppliedIdentity ?? sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
|
|
5405
5412
|
const logicalNames = new Map(Object.entries(ctx.tables).map(([key, meta]) => [meta, key]));
|
|
5406
5413
|
const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${logicalNames.get(meta)}`;
|
|
5407
5414
|
const definitions = [canonical, ...canonical.imports ?? []];
|
|
@@ -5512,9 +5519,10 @@ var SqlEmitter = class {
|
|
|
5512
5519
|
only(cte, ["ctename", "ctequery", "ctematerialized", "location"]);
|
|
5513
5520
|
const name2 = str(cte.ctename);
|
|
5514
5521
|
if (scope.ctes.has(name2)) fail3("duplicate CTE");
|
|
5522
|
+
const materialization = cte.ctematerialized === "CTEMaterializeAlways" ? "MATERIALIZED " : cte.ctematerialized === "CTEMaterializeNever" ? "NOT MATERIALIZED " : cte.ctematerialized === "CTEMaterializeDefault" ? "" : fail3("unsupported CTE materialization");
|
|
5515
5523
|
const result2 = this.select(obj(cte.ctequery), { ...parent, ctes: scope.ctes });
|
|
5516
5524
|
scope.ctes.set(name2, result2);
|
|
5517
|
-
ctes.push(`${quoteIdentifier(name2)} AS (${result2.text})`);
|
|
5525
|
+
ctes.push(`${quoteIdentifier(name2)} AS ${materialization}(${result2.text})`);
|
|
5518
5526
|
}
|
|
5519
5527
|
}
|
|
5520
5528
|
const result = node.op === "SETOP_UNION" ? this.union(node, scope) : this.projection(node, scope);
|
|
@@ -10343,6 +10351,42 @@ async function readSnapshot(dir, ordinal) {
|
|
|
10343
10351
|
const path = join(dir, MIGRATIONS_DIRNAME, META_DIRNAME, `${pad(ordinal)}.snapshot.json`);
|
|
10344
10352
|
return parseJson(path, await readSnapshotText(dir, ordinal));
|
|
10345
10353
|
}
|
|
10354
|
+
async function verifyCommittedLedger(dir, entries) {
|
|
10355
|
+
const firstRequiredSnapshot = entries.length - 2;
|
|
10356
|
+
let previousId3;
|
|
10357
|
+
let previousSnapshotPresent = false;
|
|
10358
|
+
let previousHash = null;
|
|
10359
|
+
for (const [index3, entry] of entries.entries()) {
|
|
10360
|
+
const sql4 = await readMigrationSql(dir, entry);
|
|
10361
|
+
if (checksumOf(sql4) !== entry.checksum) {
|
|
10362
|
+
return `${MIGRATIONS_DIRNAME}/${entry.name}.sql does not match its journal checksum \u2014 committed migrations must not be edited`;
|
|
10363
|
+
}
|
|
10364
|
+
const snapshotText = index3 >= firstRequiredSnapshot ? await readSnapshotText(dir, entry.ordinal) : await readPrunableSnapshotText(dir, entry.ordinal);
|
|
10365
|
+
if (snapshotText !== void 0) {
|
|
10366
|
+
if (checksumOf(snapshotText) !== entry.snapshot_checksum) {
|
|
10367
|
+
return `the snapshot for ${entry.name} does not match its journal checksum \u2014 committed snapshots must not be edited (the next diff builds on it)`;
|
|
10368
|
+
}
|
|
10369
|
+
const snapshot = JSON.parse(snapshotText);
|
|
10370
|
+
if (previousSnapshotPresent && snapshot.prevId !== previousId3) {
|
|
10371
|
+
return `snapshot chain broken at ${entry.name} \u2014 regenerate the workspace with \`seq-studio orm diff\``;
|
|
10372
|
+
}
|
|
10373
|
+
previousId3 = snapshot.id;
|
|
10374
|
+
}
|
|
10375
|
+
previousSnapshotPresent = snapshotText !== void 0;
|
|
10376
|
+
if (entry.previous_content_hash !== previousHash) {
|
|
10377
|
+
return `content-hash chain broken at ${entry.name} \u2014 migrations must be appended in order by \`seq-studio orm diff\``;
|
|
10378
|
+
}
|
|
10379
|
+
previousHash = entry.content_hash;
|
|
10380
|
+
}
|
|
10381
|
+
return void 0;
|
|
10382
|
+
}
|
|
10383
|
+
async function readPrunableSnapshotText(dir, ordinal) {
|
|
10384
|
+
const path = join(dir, MIGRATIONS_DIRNAME, META_DIRNAME, `${pad(ordinal)}.snapshot.json`);
|
|
10385
|
+
return readFile(path, "utf8").catch((error) => {
|
|
10386
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
|
|
10387
|
+
throw error;
|
|
10388
|
+
});
|
|
10389
|
+
}
|
|
10346
10390
|
async function readMigrationSql(dir, entry) {
|
|
10347
10391
|
const path = join(dir, MIGRATIONS_DIRNAME, `${entry.name}.sql`);
|
|
10348
10392
|
return readFile(path, "utf8").catch(() => {
|
|
@@ -10503,30 +10547,10 @@ async function checkWorkspace({
|
|
|
10503
10547
|
log(`no committed migrations for '${loaded.definition.namespace}' \u2014 run \`seq-studio orm diff\` and commit the result`);
|
|
10504
10548
|
return 1;
|
|
10505
10549
|
}
|
|
10506
|
-
|
|
10507
|
-
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
if (checksumOf(sql4) !== entry.checksum) {
|
|
10511
|
-
log(`${MIGRATIONS_DIRNAME}/${entry.name}.sql does not match its journal checksum \u2014 committed migrations must not be edited`);
|
|
10512
|
-
return 1;
|
|
10513
|
-
}
|
|
10514
|
-
const snapshotText = await readSnapshotText(dir, entry.ordinal);
|
|
10515
|
-
if (checksumOf(snapshotText) !== entry.snapshot_checksum) {
|
|
10516
|
-
log(`the snapshot for ${entry.name} does not match its journal checksum \u2014 committed snapshots must not be edited (the next diff builds on it)`);
|
|
10517
|
-
return 1;
|
|
10518
|
-
}
|
|
10519
|
-
const snapshot = JSON.parse(snapshotText);
|
|
10520
|
-
if (entry.ordinal > 1 && snapshot.prevId !== previousId3) {
|
|
10521
|
-
log(`snapshot chain broken at ${entry.name} \u2014 regenerate the workspace with \`seq-studio orm diff\``);
|
|
10522
|
-
return 1;
|
|
10523
|
-
}
|
|
10524
|
-
if (entry.previous_content_hash !== previousHash) {
|
|
10525
|
-
log(`content-hash chain broken at ${entry.name} \u2014 migrations must be appended in order by \`seq-studio orm diff\``);
|
|
10526
|
-
return 1;
|
|
10527
|
-
}
|
|
10528
|
-
previousId3 = snapshot.id;
|
|
10529
|
-
previousHash = entry.content_hash;
|
|
10550
|
+
const broken = await verifyCommittedLedger(dir, workspace.journal.entries);
|
|
10551
|
+
if (broken) {
|
|
10552
|
+
log(broken);
|
|
10553
|
+
return 1;
|
|
10530
10554
|
}
|
|
10531
10555
|
if (tip.content_hash !== loaded.contentHash) {
|
|
10532
10556
|
log(`definitions changed since ${tip.name} \u2014 run \`seq-studio orm diff\` and commit the new migration`);
|
|
@@ -11405,6 +11429,27 @@ function parseArgs(argv) {
|
|
|
11405
11429
|
// src/cli.ts
|
|
11406
11430
|
var BASE_URL_ENV = "SEQUENCE_ORM_BASE_URL";
|
|
11407
11431
|
var TOKEN_ENV = "SEQUENCE_ORM_TOKEN";
|
|
11432
|
+
var SOURCE_ENV = "SEQUENCE_ORM_SOURCE";
|
|
11433
|
+
var UNVERIFIED_SOURCE_REASON_ENV = "SEQUENCE_ORM_UNVERIFIED_SOURCE_REASON";
|
|
11434
|
+
var SOURCE_AUTHORIZATION_ENV = "SEQUENCE_ORM_SOURCE_AUTHORIZATION";
|
|
11435
|
+
function applySourceHeaders(env = process.env) {
|
|
11436
|
+
const token = env[SOURCE_AUTHORIZATION_ENV]?.trim();
|
|
11437
|
+
return token ? { "x-sequence-source-authorization": `Bearer ${token}` } : {};
|
|
11438
|
+
}
|
|
11439
|
+
function applySourceFromEnv(env = process.env) {
|
|
11440
|
+
const reason = env[UNVERIFIED_SOURCE_REASON_ENV]?.trim();
|
|
11441
|
+
const override = reason ? { unverified_source_reason: reason } : {};
|
|
11442
|
+
const raw = env[SOURCE_ENV];
|
|
11443
|
+
if (!raw) return override;
|
|
11444
|
+
let parsed;
|
|
11445
|
+
try {
|
|
11446
|
+
parsed = JSON.parse(raw);
|
|
11447
|
+
} catch {
|
|
11448
|
+
throw new Error(`${SOURCE_ENV} is not valid JSON`);
|
|
11449
|
+
}
|
|
11450
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error(`${SOURCE_ENV} must be a JSON object`);
|
|
11451
|
+
return { source: Object.fromEntries(Object.entries(parsed)), ...override };
|
|
11452
|
+
}
|
|
11408
11453
|
var ORM_MODULE_PATH_ENV = "SEQUENCE_ORM_MODULE_PATH";
|
|
11409
11454
|
var USAGE = `usage:
|
|
11410
11455
|
seq-studio orm init <dir> scaffold a namespace package (v2: TypeScript schema + persisted operations)
|
|
@@ -11722,15 +11767,21 @@ async function generateCommand(rest) {
|
|
|
11722
11767
|
await writeGenerateOutputs(dir, compiled.project);
|
|
11723
11768
|
const { loaded, manifest } = compiled.project;
|
|
11724
11769
|
console.log(
|
|
11725
|
-
`wrote ${SCHEMA_GRAPHQL_FILE}, ${OPERATIONS_MANIFEST_FILE}, ${TYPE_POLICIES_FILE}, sql-operations.gen.ts, namespace.contract.json (${loaded.canonical.tables.length} table(s), ${loaded.canonical.views?.length ?? 0} view(s), ${Object.keys(manifest.operations).length} operation(s))`
|
|
11770
|
+
`wrote ${SCHEMA_GRAPHQL_FILE}, ${OPERATIONS_MANIFEST_FILE}, ${OPERATION_DOCUMENTS_FILE}, ${TYPE_POLICIES_FILE}, sql-operations.gen.ts, namespace.contract.json (${loaded.canonical.tables.length} table(s), ${loaded.canonical.views?.length ?? 0} view(s), ${Object.keys(manifest.operations).length} operation(s))`
|
|
11726
11771
|
);
|
|
11727
11772
|
return runConsumerCodegen(dir);
|
|
11728
11773
|
}
|
|
11729
11774
|
async function writeGenerateOutputs(dir, project) {
|
|
11730
|
-
const { loaded, sdl, manifest } = project;
|
|
11775
|
+
const { loaded, sdl, manifest, documents } = project;
|
|
11731
11776
|
await writeFile(join(dir, SCHEMA_GRAPHQL_FILE), sdl);
|
|
11732
11777
|
await writeFile(join(dir, "namespace.contract.json"), `${JSON.stringify(loaded.canonical, null, 2)}
|
|
11733
11778
|
`);
|
|
11779
|
+
const sortedDocuments = [...documents].sort((a, b) => a.path.localeCompare(b.path)).map(({ path, contents }) => ({ path, contents }));
|
|
11780
|
+
await writeFile(
|
|
11781
|
+
join(dir, OPERATION_DOCUMENTS_FILE),
|
|
11782
|
+
`${JSON.stringify({ documentsVersion: OPERATION_DOCUMENTS_VERSION, documents: sortedDocuments }, null, 2)}
|
|
11783
|
+
`
|
|
11784
|
+
);
|
|
11734
11785
|
const operations = Object.entries(manifest.operations).map(([name2, op]) => ({
|
|
11735
11786
|
name: name2,
|
|
11736
11787
|
kind: op.kind,
|
|
@@ -11936,8 +11987,21 @@ function reportRegistryState(registry) {
|
|
|
11936
11987
|
if (match && match.id === registry.activeVersionId) console.log("-- registry: this content is the ACTIVE version");
|
|
11937
11988
|
else if (match) console.log(`-- registry: registered (status ${match.status}), not active`);
|
|
11938
11989
|
else console.log(`-- registry: new content (active is ${active ? active.content_hash.slice(0, 12) : "none"})`);
|
|
11990
|
+
if (registry.activeActivation) console.log(`-- registry: ${describeActivation(registry.activeActivation)}`);
|
|
11939
11991
|
return 0;
|
|
11940
11992
|
}
|
|
11993
|
+
function describeActivation(activation) {
|
|
11994
|
+
const since = `live since ${activation.activated_at.slice(0, 16).replace("T", " ")}Z`;
|
|
11995
|
+
const by = `by ${activation.actor_sub.replace(/^google-apps\|/, "")}`;
|
|
11996
|
+
if (activation.source_commit && activation.source_branch) {
|
|
11997
|
+
const at = activation.source_path ? ` at ${activation.source_path}` : "";
|
|
11998
|
+
const branch = activation.source_environment ? `${activation.source_environment}:${activation.source_branch}` : activation.source_branch;
|
|
11999
|
+
return `${since} from ${activation.source_commit.slice(0, 12)} on ${branch}${at} (${activation.provenance_class}) ${by}`;
|
|
12000
|
+
}
|
|
12001
|
+
const failure = activation.reported_source?.verification_failure;
|
|
12002
|
+
const why = typeof failure === "string" ? `: ${failure}` : "";
|
|
12003
|
+
return `${since} from an untraced source (${activation.provenance_class}${why}) ${by}`;
|
|
12004
|
+
}
|
|
11941
12005
|
var META_DIRNAME2 = "meta";
|
|
11942
12006
|
var JOURNAL_FILENAME2 = "journal.json";
|
|
11943
12007
|
var padOrdinal = (ordinal) => String(ordinal).padStart(4, "0");
|
|
@@ -12025,30 +12089,10 @@ async function checkWorkspaceV2({
|
|
|
12025
12089
|
log(`no committed migrations for '${namespace}' \u2014 run \`seq-studio orm diff\` and commit the result`);
|
|
12026
12090
|
return 1;
|
|
12027
12091
|
}
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
if (checksumOf(sql4) !== entry.checksum) {
|
|
12033
|
-
log(`${MIGRATIONS_DIRNAME}/${entry.name}.sql does not match its journal checksum \u2014 committed migrations must not be edited`);
|
|
12034
|
-
return 1;
|
|
12035
|
-
}
|
|
12036
|
-
const snapshotText = await readSnapshotText(dir, entry.ordinal);
|
|
12037
|
-
if (checksumOf(snapshotText) !== entry.snapshot_checksum) {
|
|
12038
|
-
log(`the snapshot for ${entry.name} does not match its journal checksum \u2014 committed snapshots must not be edited (the next diff builds on it)`);
|
|
12039
|
-
return 1;
|
|
12040
|
-
}
|
|
12041
|
-
const snapshot = JSON.parse(snapshotText);
|
|
12042
|
-
if (entry.ordinal > 1 && snapshot.prevId !== previousId3) {
|
|
12043
|
-
log(`snapshot chain broken at ${entry.name} \u2014 regenerate the workspace with \`seq-studio orm diff\``);
|
|
12044
|
-
return 1;
|
|
12045
|
-
}
|
|
12046
|
-
if (entry.previous_content_hash !== previousHash) {
|
|
12047
|
-
log(`content-hash chain broken at ${entry.name} \u2014 migrations must be appended in order by \`seq-studio orm diff\``);
|
|
12048
|
-
return 1;
|
|
12049
|
-
}
|
|
12050
|
-
previousId3 = snapshot.id;
|
|
12051
|
-
previousHash = entry.content_hash;
|
|
12092
|
+
const broken = await verifyCommittedLedger(dir, workspace.journal.entries);
|
|
12093
|
+
if (broken) {
|
|
12094
|
+
log(broken);
|
|
12095
|
+
return 1;
|
|
12052
12096
|
}
|
|
12053
12097
|
if (tip.content_hash !== loaded.hash) {
|
|
12054
12098
|
log(`definitions changed since ${tip.name} \u2014 run \`seq-studio orm diff\` and commit the new migration`);
|
|
@@ -12162,8 +12206,9 @@ async function applyV2Command(rest, dir) {
|
|
|
12162
12206
|
const applied = await apiRequestStrict("POST", `/api/orm/namespaces/${namespace}/apply`, {
|
|
12163
12207
|
version_id: registered.version_id,
|
|
12164
12208
|
...allowDestructive ? { allow_destructive: true } : {},
|
|
12165
|
-
...schemaAlreadyActive && registered.operation_set_id ? { operation_set_id: registered.operation_set_id } : {}
|
|
12166
|
-
|
|
12209
|
+
...schemaAlreadyActive && registered.operation_set_id ? { operation_set_id: registered.operation_set_id } : {},
|
|
12210
|
+
...applySourceFromEnv()
|
|
12211
|
+
}, applySourceHeaders());
|
|
12167
12212
|
const live = { namespace, contentHash: registered.content_hash };
|
|
12168
12213
|
if ("ops_only" in applied) {
|
|
12169
12214
|
console.log(
|
|
@@ -12619,8 +12664,9 @@ async function applyCommand(rest) {
|
|
|
12619
12664
|
if (dryRun) return dryRunRehearsal({ namespace, versionId: registered.version_id, contentHash: registered.content_hash });
|
|
12620
12665
|
const applied = await apiRequestStrict("POST", `/api/orm/namespaces/${namespace}/apply`, {
|
|
12621
12666
|
version_id: registered.version_id,
|
|
12622
|
-
...allowDestructive ? { allow_destructive: true } : {}
|
|
12623
|
-
|
|
12667
|
+
...allowDestructive ? { allow_destructive: true } : {},
|
|
12668
|
+
...applySourceFromEnv()
|
|
12669
|
+
}, applySourceHeaders());
|
|
12624
12670
|
if ("status" in applied) {
|
|
12625
12671
|
const verdict = await awaitQueuedApply({ dir, namespace, contentHash: registered.content_hash, runId: applied.run_id, applyWait });
|
|
12626
12672
|
return verdict === "live" ? writeGeneratedTypes(dir, loaded) : verdict;
|
|
@@ -12765,7 +12811,7 @@ async function apiRequest(method, path, body, options) {
|
|
|
12765
12811
|
if (!token) throw new Error("not authenticated \u2014 run: seq-studio login");
|
|
12766
12812
|
const response = await fetch(`${baseUrl}${path}`, {
|
|
12767
12813
|
method,
|
|
12768
|
-
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
12814
|
+
headers: { ...options?.headers, Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
12769
12815
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
12770
12816
|
});
|
|
12771
12817
|
if (response.status === 404 && options?.allow404) return null;
|
|
@@ -12792,18 +12838,20 @@ function errorDetail(payload) {
|
|
|
12792
12838
|
const fields = details && typeof details === "object" ? Object.entries(details).filter(([, value]) => typeof value === "string").map(([key, value]) => `${key}: ${String(value)}`) : [];
|
|
12793
12839
|
return `${String(first.message)}${code ? ` (${code})` : ""}${fields.length ? ` [${fields.join(", ")}]` : ""}`;
|
|
12794
12840
|
}
|
|
12795
|
-
async function apiRequestStrict(method, path, body) {
|
|
12796
|
-
const result = await apiRequest(method, path, body);
|
|
12841
|
+
async function apiRequestStrict(method, path, body, headers) {
|
|
12842
|
+
const result = await apiRequest(method, path, body, { headers });
|
|
12797
12843
|
if (result === null) throw new Error(`${method} ${path} returned no payload`);
|
|
12798
12844
|
return result;
|
|
12799
12845
|
}
|
|
12800
12846
|
async function fetchRegistryState(namespace, contentHash) {
|
|
12801
12847
|
if (!process.env[BASE_URL_ENV]?.trim() || !await resolveToken()) return { kind: "offline" };
|
|
12802
|
-
const body = await apiRequest("GET", `/api/orm/namespaces/${namespace}?hash=${encodeURIComponent(contentHash)}`, void 0, { allow404: true });
|
|
12848
|
+
const body = await apiRequest("GET", `/api/orm/namespaces/${namespace}?hash=${encodeURIComponent(contentHash)}&activations_limit=1`, void 0, { allow404: true });
|
|
12803
12849
|
if (!body) return { kind: "missing" };
|
|
12850
|
+
const latest = body.activations?.[0];
|
|
12804
12851
|
return {
|
|
12805
12852
|
kind: "found",
|
|
12806
12853
|
activeVersionId: body.namespace.active_version_id,
|
|
12854
|
+
activeActivation: latest && latest.id === body.namespace.active_activation_id ? latest : null,
|
|
12807
12855
|
versions: body.versions,
|
|
12808
12856
|
hashVersion: body.hash_version ?? null
|
|
12809
12857
|
};
|
|
@@ -12818,6 +12866,6 @@ function positional(rest) {
|
|
|
12818
12866
|
}
|
|
12819
12867
|
var firstLine2 = (sql4) => sql4.split("\n")[0] ?? sql4;
|
|
12820
12868
|
|
|
12821
|
-
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, TOKEN_ENV, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
|
12869
|
+
export { BASE_URL_ENV, ORM_MODULE_PATH_ENV, SOURCE_AUTHORIZATION_ENV, SOURCE_ENV, TOKEN_ENV, UNVERIFIED_SOURCE_REASON_ENV, applySourceFromEnv, applySourceHeaders, describeActivation, errorDetail, parseApplyWait, runCli, setTokenProvider };
|
|
12822
12870
|
//# sourceMappingURL=cli.js.map
|
|
12823
12871
|
//# sourceMappingURL=cli.js.map
|