@amerged/ohmyhost-cli 0.1.44 → 0.1.46
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/README.md +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-VJWPDFZ5.js → chunk-A4ZYW4XW.js} +870 -62
- package/dist/index.js +3 -1
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +137 -2
- package/src/apps/product-cli/src/command.ts +186 -2
- package/src/apps/product-cli/src/product-api.ts +202 -2
- package/src/packages/contracts/package.json +5 -0
- package/src/packages/contracts/src/database-events.ts +208 -11
- package/src/packages/contracts/src/database-migration-admission.ts +22 -0
- package/src/packages/contracts/src/database-migration-capture.ts +177 -0
- package/src/packages/contracts/src/database-migration-lexical.ts +1 -0
- package/src/packages/contracts/src/database-tables.ts +317 -0
- package/src/packages/contracts/src/problem-policy.ts +50 -1
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +37 -0
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +204 -0
- package/src/packages/sdk-ts/src/generated/types.gen.ts +407 -4
|
@@ -26645,7 +26645,7 @@ var require_discriminator = __commonJS({
|
|
|
26645
26645
|
error,
|
|
26646
26646
|
code(cxt) {
|
|
26647
26647
|
const { gen, data, schema, parentSchema, it } = cxt;
|
|
26648
|
-
const { oneOf:
|
|
26648
|
+
const { oneOf: oneOf3 } = parentSchema;
|
|
26649
26649
|
if (!it.opts.discriminator) {
|
|
26650
26650
|
throw new Error("discriminator: requires discriminator option");
|
|
26651
26651
|
}
|
|
@@ -26654,7 +26654,7 @@ var require_discriminator = __commonJS({
|
|
|
26654
26654
|
throw new Error("discriminator: requires propertyName");
|
|
26655
26655
|
if (schema.mapping)
|
|
26656
26656
|
throw new Error("discriminator: mapping is not supported");
|
|
26657
|
-
if (!
|
|
26657
|
+
if (!oneOf3)
|
|
26658
26658
|
throw new Error("discriminator: requires oneOf keyword");
|
|
26659
26659
|
const valid = gen.let("valid", false);
|
|
26660
26660
|
const tag = gen.const("tag", (0, codegen_1._)`${data}${(0, codegen_1.getProperty)(tagName)}`);
|
|
@@ -26682,8 +26682,8 @@ var require_discriminator = __commonJS({
|
|
|
26682
26682
|
const oneOfMapping = {};
|
|
26683
26683
|
const topRequired = hasRequired(parentSchema);
|
|
26684
26684
|
let tagRequired = true;
|
|
26685
|
-
for (let i = 0; i <
|
|
26686
|
-
let sch =
|
|
26685
|
+
for (let i = 0; i < oneOf3.length; i++) {
|
|
26686
|
+
let sch = oneOf3[i];
|
|
26687
26687
|
if ((sch === null || sch === void 0 ? void 0 : sch.$ref) && !(0, util_1.schemaHasRulesButRef)(sch, it.self.RULES)) {
|
|
26688
26688
|
const ref = sch.$ref;
|
|
26689
26689
|
sch = compile_1.resolveRef.call(it.self, it.schemaEnv.root, it.baseId, ref);
|
|
@@ -38776,14 +38776,14 @@ function isFrameworkConversionDiagnosticCode(value) {
|
|
|
38776
38776
|
function parseFrameworkConversionDiagnostic(value) {
|
|
38777
38777
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
38778
38778
|
return null;
|
|
38779
|
-
const
|
|
38780
|
-
const code = Object.hasOwn(
|
|
38781
|
-
const path2 = Object.hasOwn(
|
|
38779
|
+
const record8 = value;
|
|
38780
|
+
const code = Object.hasOwn(record8, "code") ? record8["code"] : void 0;
|
|
38781
|
+
const path2 = Object.hasOwn(record8, "path") ? record8["path"] : void 0;
|
|
38782
38782
|
if (!isFrameworkConversionDiagnosticCode(code) || typeof path2 !== "string")
|
|
38783
38783
|
return null;
|
|
38784
38784
|
const definition = DETAIL_DEFINITIONS[code];
|
|
38785
|
-
const fields = Object.entries(definition.fields ?? {}).map(([name, grammar]) => [name, grammar, Object.hasOwn(
|
|
38786
|
-
if (Object.keys(
|
|
38785
|
+
const fields = Object.entries(definition.fields ?? {}).map(([name, grammar]) => [name, grammar, Object.hasOwn(record8, name) ? record8[name] : void 0]);
|
|
38786
|
+
if (Object.keys(record8).length !== fields.length + 2 || pathClassOf(definition, path2) === null || fields.some(([, grammar, field]) => !fieldMatches(grammar, field)))
|
|
38787
38787
|
return null;
|
|
38788
38788
|
return Object.freeze(Object.fromEntries([
|
|
38789
38789
|
["code", code],
|
|
@@ -40219,6 +40219,48 @@ var PROBLEM_POLICY = {
|
|
|
40219
40219
|
action: "The platform is still retrying this webhook delivery. Read the delivery in the delivery list; replay it only if it ends dead_lettered or the receiver needs the event again.",
|
|
40220
40220
|
title: "Webhook delivery still pending"
|
|
40221
40221
|
},
|
|
40222
|
+
database_watch_limit: {
|
|
40223
|
+
status: 409,
|
|
40224
|
+
retryable: false,
|
|
40225
|
+
action: "List the project's database watches for this environment and delete one you no longer need, then create the watch again.",
|
|
40226
|
+
title: "Database watch limit reached"
|
|
40227
|
+
},
|
|
40228
|
+
database_watch_table_unavailable: {
|
|
40229
|
+
status: 409,
|
|
40230
|
+
retryable: false,
|
|
40231
|
+
action: "The table must exist as an ordinary table owned by the application, created by a deployed migration; views, partitions, temporary tables and the schemas pgcf, ohmyhost, information_schema and pg_* cannot be watched. Fix the name or deploy the migration, then create the watch again.",
|
|
40232
|
+
title: "Table cannot be watched"
|
|
40233
|
+
},
|
|
40234
|
+
database_watch_column_unavailable: {
|
|
40235
|
+
status: 409,
|
|
40236
|
+
retryable: false,
|
|
40237
|
+
action: "List only existing column names exactly as written, names are case-sensitive. Delete the watch before a migration drops a published column, because the write would fail.",
|
|
40238
|
+
title: "Watched column does not exist"
|
|
40239
|
+
},
|
|
40240
|
+
database_watch_events_unavailable: {
|
|
40241
|
+
status: 409,
|
|
40242
|
+
retryable: false,
|
|
40243
|
+
action: "The platform event schema is installed when the database wakes: run any query against that environment, wait for the answer, then create the watch again. If it still fails, report the request_id through feedback.",
|
|
40244
|
+
title: "Database events not installed yet"
|
|
40245
|
+
},
|
|
40246
|
+
database_watch_conflict: {
|
|
40247
|
+
status: 409,
|
|
40248
|
+
retryable: false,
|
|
40249
|
+
action: "A migration already attaches a capture trigger to this table: keep it and skip the watch, or remove it from the migrations, deploy and create the watch again. A table carries one capture trigger.",
|
|
40250
|
+
title: "Table already has a capture trigger"
|
|
40251
|
+
},
|
|
40252
|
+
database_table_conflict: {
|
|
40253
|
+
status: 409,
|
|
40254
|
+
retryable: false,
|
|
40255
|
+
action: "A table with this name already exists with another definition. Choose another table name, or create the table again with the same columns, types, nullability, identity, defaults and primary key it has.",
|
|
40256
|
+
title: "Table already exists with another definition"
|
|
40257
|
+
},
|
|
40258
|
+
database_table_limit: {
|
|
40259
|
+
status: 409,
|
|
40260
|
+
retryable: false,
|
|
40261
|
+
action: "This database already holds the maximum number of tables in its public schema, so no table can be added. Use an existing table, or remove a table you no longer need through a deployed migration, then create the table again.",
|
|
40262
|
+
title: "Database table limit reached"
|
|
40263
|
+
},
|
|
40222
40264
|
project_notes_conflict: {
|
|
40223
40265
|
status: 409,
|
|
40224
40266
|
retryable: false,
|
|
@@ -40483,7 +40525,7 @@ var PROBLEM_POLICY = {
|
|
|
40483
40525
|
api_key_permissions_unavailable: {
|
|
40484
40526
|
status: 503,
|
|
40485
40527
|
retryable: false,
|
|
40486
|
-
action: "Report the platform user-key permission configuration through feedback. Repeated login
|
|
40528
|
+
action: "Report the platform user-key permission configuration through feedback with this request_id; it affects every token the same way, whatever the integration. Repeated login does not fix it. After the platform confirms the fix, repeat the same create with the same name and Idempotency-Key.",
|
|
40487
40529
|
title: "Token permissions unavailable"
|
|
40488
40530
|
},
|
|
40489
40531
|
reconciliation_exhausted: {
|
|
@@ -41354,8 +41396,8 @@ var isPaidValidationRecord = (value) => {
|
|
|
41354
41396
|
if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).sort().join(",") !== "content,name,purpose,type") {
|
|
41355
41397
|
return false;
|
|
41356
41398
|
}
|
|
41357
|
-
const
|
|
41358
|
-
return (
|
|
41399
|
+
const record8 = value;
|
|
41400
|
+
return (record8["type"] === "CNAME" || record8["type"] === "TXT") && boundedString(record8["name"], 1, 253) && boundedString(record8["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record8["purpose"]));
|
|
41359
41401
|
};
|
|
41360
41402
|
var isHttpsUrlValue = (value) => typeof value === "string" && isHttpsUrl(value);
|
|
41361
41403
|
|
|
@@ -41500,7 +41542,7 @@ async function prepareLocalSourcePublication(input) {
|
|
|
41500
41542
|
request = { ...request, expected_commit_sha: link2.source.last_confirmed_commit_sha };
|
|
41501
41543
|
}
|
|
41502
41544
|
parseManagedSourceRequest("upload", request);
|
|
41503
|
-
const
|
|
41545
|
+
const record8 = {
|
|
41504
41546
|
version: 1,
|
|
41505
41547
|
...scope,
|
|
41506
41548
|
operation_id: null,
|
|
@@ -41509,16 +41551,16 @@ async function prepareLocalSourcePublication(input) {
|
|
|
41509
41551
|
request
|
|
41510
41552
|
};
|
|
41511
41553
|
if (original !== null) {
|
|
41512
|
-
assertSameAttempt(original,
|
|
41554
|
+
assertSameAttempt(original, record8);
|
|
41513
41555
|
} else
|
|
41514
|
-
await writePending(
|
|
41556
|
+
await writePending(record8, true);
|
|
41515
41557
|
return {
|
|
41516
41558
|
request,
|
|
41517
41559
|
accepted: async (operation) => {
|
|
41518
41560
|
const current = await readPending(scope, replay);
|
|
41519
41561
|
if (current === null)
|
|
41520
41562
|
throw new LocalSourcePublicationError("source_publication_missing");
|
|
41521
|
-
assertSameAttempt(current,
|
|
41563
|
+
assertSameAttempt(current, record8);
|
|
41522
41564
|
if (current.operation_id !== null && current.operation_id !== operation.id)
|
|
41523
41565
|
throw new ResponseContractError();
|
|
41524
41566
|
if (!replay)
|
|
@@ -41537,7 +41579,7 @@ async function prepareLocalSourcePublication(input) {
|
|
|
41537
41579
|
const current = await readPending(scope);
|
|
41538
41580
|
if (current === null || current.operation_id !== null)
|
|
41539
41581
|
return;
|
|
41540
|
-
assertSameAttempt(current,
|
|
41582
|
+
assertSameAttempt(current, record8);
|
|
41541
41583
|
} catch (error2) {
|
|
41542
41584
|
if (error2 instanceof LocalSourcePublicationError && (error2.code === "source_publication_scope_mismatch" || error2.code === "source_publication_pending"))
|
|
41543
41585
|
return;
|
|
@@ -41740,12 +41782,12 @@ async function readRecord(path2) {
|
|
|
41740
41782
|
await handle?.close();
|
|
41741
41783
|
}
|
|
41742
41784
|
}
|
|
41743
|
-
async function writePending(
|
|
41744
|
-
const parent = join3(
|
|
41785
|
+
async function writePending(record8, create, completed = false) {
|
|
41786
|
+
const parent = join3(record8.directory, ".ohmyhost");
|
|
41745
41787
|
for (const directory of [
|
|
41746
41788
|
parent,
|
|
41747
|
-
|
|
41748
|
-
join3(
|
|
41789
|
+
record8.metadata_directory,
|
|
41790
|
+
join3(record8.metadata_directory, "publications")
|
|
41749
41791
|
]) {
|
|
41750
41792
|
try {
|
|
41751
41793
|
await fs2.mkdir(directory, { mode: 448 });
|
|
@@ -41756,10 +41798,10 @@ async function writePending(record7, create, completed = false) {
|
|
|
41756
41798
|
await checkedDirectory(directory);
|
|
41757
41799
|
await fs2.chmod(directory, 448);
|
|
41758
41800
|
}
|
|
41759
|
-
const target = completed ? completedPath(
|
|
41801
|
+
const target = completed ? completedPath(record8) : pendingPath(record8);
|
|
41760
41802
|
const temporary = create ? target : `${target}.${randomUUID()}.tmp`;
|
|
41761
41803
|
try {
|
|
41762
|
-
await fs2.writeFile(temporary, `${JSON.stringify(
|
|
41804
|
+
await fs2.writeFile(temporary, `${JSON.stringify(record8)}
|
|
41763
41805
|
`, { mode: 384, flag: "wx" });
|
|
41764
41806
|
if (!create)
|
|
41765
41807
|
await fs2.rename(temporary, target);
|
|
@@ -42389,6 +42431,9 @@ var DATABASE_WEBHOOK_EVENT_TYPES = [
|
|
|
42389
42431
|
"database.resized",
|
|
42390
42432
|
"database.deleted"
|
|
42391
42433
|
];
|
|
42434
|
+
var DATABASE_WATCH_OPERATIONS = ["insert", "update", "delete"];
|
|
42435
|
+
var DATABASE_WATCH_MAX_COLUMNS = 32;
|
|
42436
|
+
var DATABASE_WATCH_DEFAULT_SCHEMA = "public";
|
|
42392
42437
|
var DATABASE_WEBHOOK_MAX_EVENT_TYPES = 16;
|
|
42393
42438
|
var DATABASE_WEBHOOK_MAX_HEADERS = 8;
|
|
42394
42439
|
var DATABASE_WEBHOOK_URL_MAX_LENGTH = 2048;
|
|
@@ -42432,7 +42477,22 @@ var USAGE_MAX_RANGE_MS = 31 * 24 * USAGE_HOUR_MS;
|
|
|
42432
42477
|
var WEBHOOK_KEYS = ["id", "environment", "url", "event_types", "header_names", "created_at"];
|
|
42433
42478
|
var WEBHOOK_ID_PATTERN = /^whk_[a-z0-9]{20}$/u;
|
|
42434
42479
|
var DELIVERY_ID_PATTERN = /^dlv_[0-9a-f]{20}$/u;
|
|
42435
|
-
var EVENT_ID_PATTERN = /^evt_[0-9a-f]{20}$/u;
|
|
42480
|
+
var EVENT_ID_PATTERN = /^(?:evt_[0-9a-f]{20}|[a-z][a-z0-9]{19}:[1-9][0-9]{0,15}:[1-9][0-9]{0,15})$/u;
|
|
42481
|
+
var DATA_SUBSCRIPTION_PATTERN = /^data\.(?:\*|[a-z][a-z0-9_]{0,47})$/u;
|
|
42482
|
+
var DATA_EVENT_TYPE_PATTERN = /^data\.[a-z][a-z0-9_]{0,47}$/u;
|
|
42483
|
+
var DATABASE_WATCH_ID_PATTERN = /^pgcf_watch_[0-9a-f]{8}$/u;
|
|
42484
|
+
var DATABASE_WATCH_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]{0,62}$/u;
|
|
42485
|
+
var DATABASE_WATCH_FORBIDDEN_SCHEMAS = ["information_schema", "pgcf", "ohmyhost"];
|
|
42486
|
+
var DATABASE_WATCH_KEYS = [
|
|
42487
|
+
"id",
|
|
42488
|
+
"environment",
|
|
42489
|
+
"schema",
|
|
42490
|
+
"table",
|
|
42491
|
+
"columns",
|
|
42492
|
+
"operations",
|
|
42493
|
+
"topic",
|
|
42494
|
+
"event_type"
|
|
42495
|
+
];
|
|
42436
42496
|
var SCHEDULE_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/u;
|
|
42437
42497
|
var CURSOR_PATTERN = /^[A-Za-z0-9._|:=+/-]{1,200}$/u;
|
|
42438
42498
|
var HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]{0,63}$/u;
|
|
@@ -42454,11 +42514,53 @@ function parseDatabaseWebhookId(value) {
|
|
|
42454
42514
|
throw new TypeError("Invalid database webhook id");
|
|
42455
42515
|
return value;
|
|
42456
42516
|
}
|
|
42517
|
+
function parseDatabaseWatchId(value) {
|
|
42518
|
+
if (!isDatabaseWatchTriggerName(value))
|
|
42519
|
+
throw new TypeError("Invalid database watch id");
|
|
42520
|
+
return value;
|
|
42521
|
+
}
|
|
42457
42522
|
function parseDatabaseDeliveryId(value) {
|
|
42458
42523
|
if (!matches(value, DELIVERY_ID_PATTERN))
|
|
42459
42524
|
throw new TypeError("Invalid database delivery id");
|
|
42460
42525
|
return value;
|
|
42461
42526
|
}
|
|
42527
|
+
function isDatabaseWatchTriggerName(value) {
|
|
42528
|
+
return matches(value, DATABASE_WATCH_ID_PATTERN);
|
|
42529
|
+
}
|
|
42530
|
+
function isDatabaseWatchIdentifier(value) {
|
|
42531
|
+
return matches(value, DATABASE_WATCH_IDENTIFIER_PATTERN);
|
|
42532
|
+
}
|
|
42533
|
+
function isDatabaseWatchSchema(value) {
|
|
42534
|
+
if (!isDatabaseWatchIdentifier(value))
|
|
42535
|
+
return false;
|
|
42536
|
+
const lower = value.toLowerCase();
|
|
42537
|
+
return !lower.startsWith("pg_") && !DATABASE_WATCH_FORBIDDEN_SCHEMAS.includes(lower);
|
|
42538
|
+
}
|
|
42539
|
+
function dataEventTopic(tableName) {
|
|
42540
|
+
const mapped = Array.from(tableName, (character) => {
|
|
42541
|
+
const lower = Array.from(character.toLowerCase())[0] ?? "_";
|
|
42542
|
+
return /^[a-z0-9_]$/u.test(lower) ? lower : "_";
|
|
42543
|
+
}).join("");
|
|
42544
|
+
const topic = /^[a-z]/u.test(mapped) ? mapped : `t_${mapped}`;
|
|
42545
|
+
return topic.slice(0, 48);
|
|
42546
|
+
}
|
|
42547
|
+
function parseDatabaseWatchCreateRequest(value) {
|
|
42548
|
+
if (!record2(value) || !onlyKeys(value, ["schema", "table", "columns", "operations"]) || !isDatabaseWatchIdentifier(value["table"]) || !Array.isArray(value["columns"]) || value["columns"].length < 1 || value["columns"].length > DATABASE_WATCH_MAX_COLUMNS || !value["columns"].every(isDatabaseWatchIdentifier) || new Set(value["columns"]).size !== value["columns"].length)
|
|
42549
|
+
throw new TypeError("Invalid database watch request");
|
|
42550
|
+
return {
|
|
42551
|
+
...parseDatabaseWatchTarget({ schema: value["schema"], table: value["table"] }),
|
|
42552
|
+
columns: value["columns"],
|
|
42553
|
+
operations: parseWatchOperations(value["operations"])
|
|
42554
|
+
};
|
|
42555
|
+
}
|
|
42556
|
+
function parseDatabaseWatchTarget(value) {
|
|
42557
|
+
if (!record2(value) || !onlyKeys(value, ["schema", "table"]) || !isDatabaseWatchIdentifier(value["table"]))
|
|
42558
|
+
throw new TypeError("Invalid database watch target");
|
|
42559
|
+
const schema = value["schema"] === void 0 ? DATABASE_WATCH_DEFAULT_SCHEMA : value["schema"];
|
|
42560
|
+
if (!isDatabaseWatchSchema(schema))
|
|
42561
|
+
throw new TypeError("Invalid database watch target");
|
|
42562
|
+
return { schema, table: value["table"] };
|
|
42563
|
+
}
|
|
42462
42564
|
function parseDatabaseScheduleName(value) {
|
|
42463
42565
|
if (!matches(value, SCHEDULE_NAME_PATTERN))
|
|
42464
42566
|
throw new TypeError("Invalid database schedule name");
|
|
@@ -42515,6 +42617,20 @@ function assertDatabaseWebhook(value) {
|
|
|
42515
42617
|
throw new TypeError("Invalid database webhook");
|
|
42516
42618
|
assertWebhookFields(value);
|
|
42517
42619
|
}
|
|
42620
|
+
function assertDatabaseWatch(value) {
|
|
42621
|
+
if (!record2(value) || !exact2(value, DATABASE_WATCH_KEYS) || !matches(value["id"], DATABASE_WATCH_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isDatabaseWatchSchema(value["schema"]) || !isDatabaseWatchIdentifier(value["table"]) || !Array.isArray(value["columns"]) || value["columns"].length < 1 || value["columns"].length > DATABASE_WATCH_MAX_COLUMNS || !value["columns"].every(isDatabaseWatchIdentifier) || !isCanonicalOperations(value["operations"]) || value["topic"] !== dataEventTopic(value["table"]) || value["event_type"] !== `data.${value["topic"]}`)
|
|
42622
|
+
throw new TypeError("Invalid database watch");
|
|
42623
|
+
}
|
|
42624
|
+
function assertDatabaseWatchPage(value) {
|
|
42625
|
+
if (!record2(value) || !exact2(value, ["items"]) || !pageItems(value["items"]))
|
|
42626
|
+
throw new TypeError("Invalid database watch page");
|
|
42627
|
+
for (const item of value["items"])
|
|
42628
|
+
assertDatabaseWatch(item);
|
|
42629
|
+
}
|
|
42630
|
+
function assertDatabaseWatchDeleted(value) {
|
|
42631
|
+
if (!record2(value) || !exact2(value, ["id", "deleted"]) || !matches(value["id"], DATABASE_WATCH_ID_PATTERN) || value["deleted"] !== true)
|
|
42632
|
+
throw new TypeError("Invalid database watch deletion");
|
|
42633
|
+
}
|
|
42518
42634
|
function assertDatabaseWebhookCreated(value) {
|
|
42519
42635
|
if (!record2(value) || !exact2(value, [...WEBHOOK_KEYS, "secret"]) || typeof value["secret"] !== "string" || value["secret"].length === 0)
|
|
42520
42636
|
throw new TypeError("Invalid database webhook");
|
|
@@ -42543,7 +42659,7 @@ function assertDatabaseWebhookDelivery(value) {
|
|
|
42543
42659
|
"delivered_at",
|
|
42544
42660
|
"last_status",
|
|
42545
42661
|
"last_error"
|
|
42546
|
-
]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !
|
|
42662
|
+
]) || !matches(value["id"], DELIVERY_ID_PATTERN) || !matches(value["event_id"], EVENT_ID_PATTERN) || !isDeliveredEventType(value["event_type"]) || !matches(value["webhook_id"], WEBHOOK_ID_PATTERN) || !oneOf(["pending", "delivered", "dead_lettered"], value["state"]) || !nonNegativeInteger(value["attempts"]) || !timestamp2(value["created_at"]) || !nullable(value["next_attempt_at"], timestamp2) || !nullable(value["delivered_at"], timestamp2) || !nullable(value["last_status"], Number.isSafeInteger) || !nullable(value["last_error"], (error) => oneOf(["timeout", "network", "http", "expired", "permanent"], error)))
|
|
42547
42663
|
throw new TypeError("Invalid database webhook delivery");
|
|
42548
42664
|
}
|
|
42549
42665
|
function assertDatabaseWebhookDeliveryPage(value) {
|
|
@@ -42626,7 +42742,7 @@ function assertUsageRow(value) {
|
|
|
42626
42742
|
throw new TypeError("Invalid database execution usage row");
|
|
42627
42743
|
}
|
|
42628
42744
|
function assertWebhookFields(value) {
|
|
42629
|
-
if (!matches(value["id"], WEBHOOK_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isHttpsUrl2(value["url"]) || !Array.isArray(value["event_types"]) || value["event_types"].length < 1 || value["event_types"].length > DATABASE_WEBHOOK_MAX_EVENT_TYPES || !value["event_types"].every(
|
|
42745
|
+
if (!matches(value["id"], WEBHOOK_ID_PATTERN) || !oneOf(["dev", "prod"], value["environment"]) || !isHttpsUrl2(value["url"]) || !Array.isArray(value["event_types"]) || value["event_types"].length < 1 || value["event_types"].length > DATABASE_WEBHOOK_MAX_EVENT_TYPES || !value["event_types"].every(isDatabaseWebhookEventPattern) || !Array.isArray(value["header_names"]) || value["header_names"].length > DATABASE_WEBHOOK_MAX_HEADERS || !value["header_names"].every((name) => matches(name, HEADER_NAME_PATTERN)) || !timestamp2(value["created_at"]))
|
|
42630
42746
|
throw new TypeError("Invalid database webhook");
|
|
42631
42747
|
}
|
|
42632
42748
|
function parseHttpsUrl(value) {
|
|
@@ -42643,11 +42759,33 @@ function isHttpsUrl2(value) {
|
|
|
42643
42759
|
return false;
|
|
42644
42760
|
}
|
|
42645
42761
|
}
|
|
42762
|
+
function isDatabaseWebhookEventPattern(value) {
|
|
42763
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_SUBSCRIPTION_PATTERN);
|
|
42764
|
+
}
|
|
42765
|
+
function isDeliveredEventType(value) {
|
|
42766
|
+
return oneOf(DATABASE_WEBHOOK_EVENT_TYPES, value) || matches(value, DATA_EVENT_TYPE_PATTERN);
|
|
42767
|
+
}
|
|
42768
|
+
function isDatabaseWebhookEventTypes(value) {
|
|
42769
|
+
return Array.isArray(value) && value.length >= 1 && value.length <= DATABASE_WEBHOOK_MAX_EVENT_TYPES && value.every(isDatabaseWebhookEventPattern) && new Set(value).size === value.length;
|
|
42770
|
+
}
|
|
42646
42771
|
function parseEventTypes(value) {
|
|
42647
|
-
if (!
|
|
42772
|
+
if (!isDatabaseWebhookEventTypes(value))
|
|
42648
42773
|
throw new TypeError("Invalid database webhook event types");
|
|
42649
42774
|
return value;
|
|
42650
42775
|
}
|
|
42776
|
+
function parseWatchOperations(value) {
|
|
42777
|
+
if (value === void 0)
|
|
42778
|
+
return DATABASE_WATCH_OPERATIONS;
|
|
42779
|
+
if (!Array.isArray(value) || value.length < 1 || !value.every((operation) => oneOf(DATABASE_WATCH_OPERATIONS, operation)) || new Set(value).size !== value.length)
|
|
42780
|
+
throw new TypeError("Invalid database watch request");
|
|
42781
|
+
return DATABASE_WATCH_OPERATIONS.filter((operation) => value.includes(operation));
|
|
42782
|
+
}
|
|
42783
|
+
function isCanonicalOperations(value) {
|
|
42784
|
+
if (!Array.isArray(value) || value.length < 1)
|
|
42785
|
+
return false;
|
|
42786
|
+
const canonical = DATABASE_WATCH_OPERATIONS.filter((operation) => value.includes(operation));
|
|
42787
|
+
return canonical.length === value.length && canonical.every((op, index) => op === value[index]);
|
|
42788
|
+
}
|
|
42651
42789
|
function parseHeaders(value) {
|
|
42652
42790
|
if (!record2(value) || Object.keys(value).length > DATABASE_WEBHOOK_MAX_HEADERS || new Set(Object.keys(value).map((name) => name.toLowerCase())).size !== Object.keys(value).length)
|
|
42653
42791
|
throw new TypeError("Invalid database webhook headers");
|
|
@@ -42723,6 +42861,170 @@ function exact2(value, keys) {
|
|
|
42723
42861
|
return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
42724
42862
|
}
|
|
42725
42863
|
|
|
42864
|
+
// packages/contracts/dist/database-tables.js
|
|
42865
|
+
var DATABASE_TABLE_COLUMN_TYPES = [
|
|
42866
|
+
"text",
|
|
42867
|
+
"integer",
|
|
42868
|
+
"bigint",
|
|
42869
|
+
"boolean",
|
|
42870
|
+
"numeric",
|
|
42871
|
+
"double precision",
|
|
42872
|
+
"timestamptz",
|
|
42873
|
+
"date",
|
|
42874
|
+
"uuid",
|
|
42875
|
+
"jsonb"
|
|
42876
|
+
];
|
|
42877
|
+
var DATABASE_TABLE_DEFAULTS = ["now", "uuid"];
|
|
42878
|
+
var DATABASE_TABLE_MAX_COLUMNS = 64;
|
|
42879
|
+
var DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS = 8;
|
|
42880
|
+
var DATABASE_TABLE_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]{0,62}$/u;
|
|
42881
|
+
var RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
42882
|
+
"all",
|
|
42883
|
+
"analyse",
|
|
42884
|
+
"analyze",
|
|
42885
|
+
"and",
|
|
42886
|
+
"any",
|
|
42887
|
+
"array",
|
|
42888
|
+
"as",
|
|
42889
|
+
"asc",
|
|
42890
|
+
"asymmetric",
|
|
42891
|
+
"both",
|
|
42892
|
+
"case",
|
|
42893
|
+
"cast",
|
|
42894
|
+
"check",
|
|
42895
|
+
"collate",
|
|
42896
|
+
"column",
|
|
42897
|
+
"constraint",
|
|
42898
|
+
"create",
|
|
42899
|
+
"current_catalog",
|
|
42900
|
+
"current_date",
|
|
42901
|
+
"current_role",
|
|
42902
|
+
"current_time",
|
|
42903
|
+
"current_timestamp",
|
|
42904
|
+
"current_user",
|
|
42905
|
+
"default",
|
|
42906
|
+
"deferrable",
|
|
42907
|
+
"desc",
|
|
42908
|
+
"distinct",
|
|
42909
|
+
"do",
|
|
42910
|
+
"else",
|
|
42911
|
+
"end",
|
|
42912
|
+
"except",
|
|
42913
|
+
"false",
|
|
42914
|
+
"fetch",
|
|
42915
|
+
"for",
|
|
42916
|
+
"foreign",
|
|
42917
|
+
"from",
|
|
42918
|
+
"grant",
|
|
42919
|
+
"group",
|
|
42920
|
+
"having",
|
|
42921
|
+
"in",
|
|
42922
|
+
"initially",
|
|
42923
|
+
"intersect",
|
|
42924
|
+
"into",
|
|
42925
|
+
"lateral",
|
|
42926
|
+
"leading",
|
|
42927
|
+
"limit",
|
|
42928
|
+
"localtime",
|
|
42929
|
+
"localtimestamp",
|
|
42930
|
+
"not",
|
|
42931
|
+
"null",
|
|
42932
|
+
"offset",
|
|
42933
|
+
"on",
|
|
42934
|
+
"only",
|
|
42935
|
+
"or",
|
|
42936
|
+
"order",
|
|
42937
|
+
"placing",
|
|
42938
|
+
"primary",
|
|
42939
|
+
"references",
|
|
42940
|
+
"returning",
|
|
42941
|
+
"select",
|
|
42942
|
+
"session_user",
|
|
42943
|
+
"some",
|
|
42944
|
+
"symmetric",
|
|
42945
|
+
"table",
|
|
42946
|
+
"then",
|
|
42947
|
+
"to",
|
|
42948
|
+
"trailing",
|
|
42949
|
+
"true",
|
|
42950
|
+
"union",
|
|
42951
|
+
"unique",
|
|
42952
|
+
"user",
|
|
42953
|
+
"using",
|
|
42954
|
+
"variadic",
|
|
42955
|
+
"when",
|
|
42956
|
+
"where",
|
|
42957
|
+
"window",
|
|
42958
|
+
"with"
|
|
42959
|
+
]);
|
|
42960
|
+
function isDatabaseTableIdentifier(value) {
|
|
42961
|
+
return typeof value === "string" && DATABASE_TABLE_IDENTIFIER_PATTERN.test(value) && !value.startsWith("pg_") && !RESERVED_WORDS.has(value);
|
|
42962
|
+
}
|
|
42963
|
+
function parseDatabaseTableCreateRequest(value) {
|
|
42964
|
+
if (!record3(value) || !onlyKeys2(value, ["table", "columns", "primaryKey"]) || !isDatabaseTableIdentifier(value["table"]) || !Array.isArray(value["columns"]) || value["columns"].length < 1 || value["columns"].length > DATABASE_TABLE_MAX_COLUMNS)
|
|
42965
|
+
throw new TypeError("Invalid database table request");
|
|
42966
|
+
const inputs = value["columns"].map(parseColumn);
|
|
42967
|
+
const names = inputs.map((column) => column.name);
|
|
42968
|
+
if (new Set(names).size !== names.length || inputs.filter((column) => column.identity).length > 1)
|
|
42969
|
+
throw new TypeError("Invalid database table request");
|
|
42970
|
+
const primaryKey = parsePrimaryKey(value["primaryKey"], names);
|
|
42971
|
+
return {
|
|
42972
|
+
table: value["table"],
|
|
42973
|
+
columns: inputs.map((column) => completeColumn(column, primaryKey.includes(column.name))),
|
|
42974
|
+
primaryKey
|
|
42975
|
+
};
|
|
42976
|
+
}
|
|
42977
|
+
function parseColumn(value) {
|
|
42978
|
+
if (!record3(value) || !onlyKeys2(value, ["name", "type", "nullable", "identity", "default"]) || !isDatabaseTableIdentifier(value["name"]) || !oneOf2(DATABASE_TABLE_COLUMN_TYPES, value["type"]) || value["nullable"] !== void 0 && typeof value["nullable"] !== "boolean" || value["identity"] !== void 0 && typeof value["identity"] !== "boolean" || value["default"] !== void 0 && !oneOf2(DATABASE_TABLE_DEFAULTS, value["default"]))
|
|
42979
|
+
throw new TypeError("Invalid database table request");
|
|
42980
|
+
const type = value["type"];
|
|
42981
|
+
const identity = value["identity"] === true;
|
|
42982
|
+
const defaultValue = value["default"] ?? null;
|
|
42983
|
+
if (identity && type !== "integer" && type !== "bigint")
|
|
42984
|
+
throw new TypeError("Invalid database table request");
|
|
42985
|
+
if (identity && defaultValue !== null)
|
|
42986
|
+
throw new TypeError("Invalid database table request");
|
|
42987
|
+
if (defaultValue === "now" && type !== "timestamptz")
|
|
42988
|
+
throw new TypeError("Invalid database table request");
|
|
42989
|
+
if (defaultValue === "uuid" && type !== "uuid")
|
|
42990
|
+
throw new TypeError("Invalid database table request");
|
|
42991
|
+
return {
|
|
42992
|
+
name: value["name"],
|
|
42993
|
+
type,
|
|
42994
|
+
nullable: value["nullable"],
|
|
42995
|
+
identity,
|
|
42996
|
+
default: defaultValue
|
|
42997
|
+
};
|
|
42998
|
+
}
|
|
42999
|
+
function parsePrimaryKey(value, names) {
|
|
43000
|
+
if (value === void 0)
|
|
43001
|
+
return [];
|
|
43002
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS || new Set(value).size !== value.length || !value.every((name) => typeof name === "string" && names.includes(name)))
|
|
43003
|
+
throw new TypeError("Invalid database table request");
|
|
43004
|
+
return value;
|
|
43005
|
+
}
|
|
43006
|
+
function completeColumn(column, keyed) {
|
|
43007
|
+
const required = column.identity || keyed;
|
|
43008
|
+
if (required && column.nullable === true)
|
|
43009
|
+
throw new TypeError("Invalid database table request");
|
|
43010
|
+
return {
|
|
43011
|
+
name: column.name,
|
|
43012
|
+
type: column.type,
|
|
43013
|
+
nullable: required ? false : column.nullable ?? true,
|
|
43014
|
+
identity: column.identity,
|
|
43015
|
+
default: column.default
|
|
43016
|
+
};
|
|
43017
|
+
}
|
|
43018
|
+
function oneOf2(allowed, value) {
|
|
43019
|
+
return typeof value === "string" && allowed.includes(value);
|
|
43020
|
+
}
|
|
43021
|
+
function record3(value) {
|
|
43022
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43023
|
+
}
|
|
43024
|
+
function onlyKeys2(value, allowed) {
|
|
43025
|
+
return Object.keys(value).every((key) => allowed.includes(key));
|
|
43026
|
+
}
|
|
43027
|
+
|
|
42726
43028
|
// packages/contracts/dist/database-sizes.js
|
|
42727
43029
|
var DATABASE_SIZES = Object.freeze([
|
|
42728
43030
|
Object.freeze({
|
|
@@ -43083,6 +43385,16 @@ var recognizedCommandLabel = (argv) => {
|
|
|
43083
43385
|
if (values[1] === "revoke")
|
|
43084
43386
|
return "database access revoke";
|
|
43085
43387
|
}
|
|
43388
|
+
if (value === "database" && values[0] === "watch") {
|
|
43389
|
+
if (values[1] === "create")
|
|
43390
|
+
return "database watch create";
|
|
43391
|
+
if (values[1] === "list")
|
|
43392
|
+
return "database watch list";
|
|
43393
|
+
if (values[1] === "delete")
|
|
43394
|
+
return "database watch delete";
|
|
43395
|
+
}
|
|
43396
|
+
if (value === "database" && values[0] === "table" && values[1] === "create")
|
|
43397
|
+
return "database table create";
|
|
43086
43398
|
if (value === "database" && values[0] === "webhook") {
|
|
43087
43399
|
if (values[1] === "create")
|
|
43088
43400
|
return "database webhook create";
|
|
@@ -43932,6 +44244,105 @@ var parseProductCliCommand = (argv) => {
|
|
|
43932
44244
|
}
|
|
43933
44245
|
throw new InvalidCommandError();
|
|
43934
44246
|
}
|
|
44247
|
+
if (first === "database" && values[0] === "watch") {
|
|
44248
|
+
values.shift();
|
|
44249
|
+
const subcommand = values.shift();
|
|
44250
|
+
if (subcommand === "create") {
|
|
44251
|
+
if (!yes || wait || follow || revoke || stdin)
|
|
44252
|
+
throw new InvalidCommandError();
|
|
44253
|
+
const options = parseOptionalOptions(values, [
|
|
44254
|
+
"--project",
|
|
44255
|
+
"--environment",
|
|
44256
|
+
"--table",
|
|
44257
|
+
"--schema",
|
|
44258
|
+
"--columns",
|
|
44259
|
+
"--operations",
|
|
44260
|
+
"--idempotency-key"
|
|
44261
|
+
]);
|
|
44262
|
+
const projectId = options["--project"], environment = options["--environment"], table = options["--table"], schema = options["--schema"], columns = options["--columns"], operations = options["--operations"], idempotencyKey = options["--idempotency-key"];
|
|
44263
|
+
if (!isValue(projectId) || !isValue(idempotencyKey) || !isValue(table) || !isValue(columns) || environment !== "dev" && environment !== "prod")
|
|
44264
|
+
throw new InvalidCommandError();
|
|
44265
|
+
const request = contractValue(() => parseDatabaseWatchCreateRequest({
|
|
44266
|
+
schema,
|
|
44267
|
+
table,
|
|
44268
|
+
columns: columns.split(","),
|
|
44269
|
+
...operations === void 0 ? {} : { operations: operations.split(",") }
|
|
44270
|
+
}));
|
|
44271
|
+
return {
|
|
44272
|
+
kind: "database-watch-create",
|
|
44273
|
+
projectId,
|
|
44274
|
+
environment,
|
|
44275
|
+
request,
|
|
44276
|
+
idempotencyKey,
|
|
44277
|
+
yes: true,
|
|
44278
|
+
credentialStore
|
|
44279
|
+
};
|
|
44280
|
+
}
|
|
44281
|
+
if (subcommand === "list") {
|
|
44282
|
+
if (yes || wait || follow || revoke || stdin)
|
|
44283
|
+
throw new InvalidCommandError();
|
|
44284
|
+
const options = parseOptionalOptions(values, ["--project", "--environment"]);
|
|
44285
|
+
const projectId = options["--project"], environment = options["--environment"] ?? "dev";
|
|
44286
|
+
if (!isValue(projectId) || environment !== "dev" && environment !== "prod")
|
|
44287
|
+
throw new InvalidCommandError();
|
|
44288
|
+
return { kind: "database-watch-list", projectId, environment, credentialStore };
|
|
44289
|
+
}
|
|
44290
|
+
if (subcommand === "delete") {
|
|
44291
|
+
if (!yes || wait || follow || revoke || stdin)
|
|
44292
|
+
throw new InvalidCommandError();
|
|
44293
|
+
const options = parseOptionalOptions(values, [
|
|
44294
|
+
"--project",
|
|
44295
|
+
"--environment",
|
|
44296
|
+
"--watch",
|
|
44297
|
+
"--idempotency-key"
|
|
44298
|
+
]);
|
|
44299
|
+
const projectId = options["--project"], environment = options["--environment"], watchId = options["--watch"], idempotencyKey = options["--idempotency-key"];
|
|
44300
|
+
if (!isValue(projectId) || !isValue(idempotencyKey) || environment !== "dev" && environment !== "prod")
|
|
44301
|
+
throw new InvalidCommandError();
|
|
44302
|
+
return {
|
|
44303
|
+
kind: "database-watch-delete",
|
|
44304
|
+
projectId,
|
|
44305
|
+
environment,
|
|
44306
|
+
watchId: contractValue(() => parseDatabaseWatchId(watchId)),
|
|
44307
|
+
idempotencyKey,
|
|
44308
|
+
yes: true,
|
|
44309
|
+
credentialStore
|
|
44310
|
+
};
|
|
44311
|
+
}
|
|
44312
|
+
throw new InvalidCommandError();
|
|
44313
|
+
}
|
|
44314
|
+
if (first === "database" && values[0] === "table") {
|
|
44315
|
+
values.shift();
|
|
44316
|
+
const subcommand = values.shift();
|
|
44317
|
+
if (subcommand === "create") {
|
|
44318
|
+
if (!yes || wait || follow || revoke || stdin)
|
|
44319
|
+
throw new InvalidCommandError();
|
|
44320
|
+
const options = parseOptionalOptions(values, [
|
|
44321
|
+
"--project",
|
|
44322
|
+
"--environment",
|
|
44323
|
+
"--table",
|
|
44324
|
+
"--columns-file",
|
|
44325
|
+
"--primary-key",
|
|
44326
|
+
"--idempotency-key"
|
|
44327
|
+
]);
|
|
44328
|
+
const projectId = options["--project"], environment = options["--environment"], table = options["--table"], columnsFile = options["--columns-file"], primaryKey = options["--primary-key"], idempotencyKey = options["--idempotency-key"];
|
|
44329
|
+
const keyNames = primaryKey === void 0 ? [] : primaryKey.split(",");
|
|
44330
|
+
if (!isValue(projectId) || !isValue(idempotencyKey) || !isValue(table) || !isValue(columnsFile) || primaryKey !== void 0 && !keyNames.every(isDatabaseTableIdentifier) || keyNames.length > DATABASE_TABLE_MAX_PRIMARY_KEY_COLUMNS || !isDatabaseTableIdentifier(table) || environment !== "dev" && environment !== "prod")
|
|
44331
|
+
throw new InvalidCommandError();
|
|
44332
|
+
return {
|
|
44333
|
+
kind: "database-table-create",
|
|
44334
|
+
projectId,
|
|
44335
|
+
environment,
|
|
44336
|
+
table,
|
|
44337
|
+
columnsFile,
|
|
44338
|
+
primaryKey: keyNames,
|
|
44339
|
+
idempotencyKey,
|
|
44340
|
+
yes: true,
|
|
44341
|
+
credentialStore
|
|
44342
|
+
};
|
|
44343
|
+
}
|
|
44344
|
+
throw new InvalidCommandError();
|
|
44345
|
+
}
|
|
43935
44346
|
if (first === "database" && values[0] === "webhook") {
|
|
43936
44347
|
values.shift();
|
|
43937
44348
|
const subcommand = values.shift();
|
|
@@ -45078,7 +45489,7 @@ import { join as join5, resolve as resolve4 } from "node:path";
|
|
|
45078
45489
|
|
|
45079
45490
|
// packages/contracts/dist/database-access.js
|
|
45080
45491
|
function parseProjectDatabaseWrite(value) {
|
|
45081
|
-
if (!
|
|
45492
|
+
if (!record4(value) || !exact3(value, ["environment", "statement", "parameters"]) || !["dev", "prod"].includes(String(value["environment"])) || typeof value["statement"] !== "string" || !/^\s*(?:insert|update|delete)\b/iu.test(value["statement"]) || new TextEncoder().encode(value["statement"]).byteLength > 65536 || value["statement"].includes("\0") || !Array.isArray(value["parameters"]) || value["parameters"].length > 100)
|
|
45082
45493
|
throw new TypeError("Invalid database write");
|
|
45083
45494
|
const budget = { nodes: 0 };
|
|
45084
45495
|
for (const parameter of value["parameters"])
|
|
@@ -45092,7 +45503,7 @@ function parseProjectDatabaseWrite(value) {
|
|
|
45092
45503
|
};
|
|
45093
45504
|
}
|
|
45094
45505
|
function assertProjectDatabaseWriteReceipt(value) {
|
|
45095
|
-
if (!
|
|
45506
|
+
if (!record4(value) || !exact3(value, ["operation_id", "environment", "state", "command", "affected_rows", "error"]) || typeof value["operation_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value["operation_id"]) || !["dev", "prod"].includes(String(value["environment"])) || !["running", "succeeded", "failed"].includes(String(value["state"])))
|
|
45096
45507
|
throw new TypeError("Invalid database write receipt");
|
|
45097
45508
|
if (value["state"] === "succeeded") {
|
|
45098
45509
|
if (!["INSERT", "UPDATE", "DELETE"].includes(String(value["command"])) || !Number.isSafeInteger(value["affected_rows"]) || Number(value["affected_rows"]) < 0 || Number(value["affected_rows"]) > 1e3 || value["error"] !== null)
|
|
@@ -45105,7 +45516,7 @@ function assertProjectDatabaseWriteReceipt(value) {
|
|
|
45105
45516
|
throw new TypeError("Invalid database write result");
|
|
45106
45517
|
} else {
|
|
45107
45518
|
const error = value["error"];
|
|
45108
|
-
if (!
|
|
45519
|
+
if (!record4(error) || typeof error["code"] !== "string" || !error["code"].startsWith("database_write_") || JSON.stringify(error) !== JSON.stringify(publicOperationFailure(error["code"])))
|
|
45109
45520
|
throw new TypeError("Invalid database write error");
|
|
45110
45521
|
}
|
|
45111
45522
|
}
|
|
@@ -45129,12 +45540,12 @@ var ACCESS_KEYS = [
|
|
|
45129
45540
|
];
|
|
45130
45541
|
var ACCESS_ROLE_PATTERN = /^ohmyho_da_[0-7][0-9a-hjkmnp-tv-z]{25}_[0-9a-z]{8}$/u;
|
|
45131
45542
|
function assertProjectDatabaseAccess(value) {
|
|
45132
|
-
if (!
|
|
45543
|
+
if (!record4(value) || !exact3(value, ACCESS_KEYS))
|
|
45133
45544
|
throw new TypeError("Invalid database access");
|
|
45134
45545
|
assertAccessFields(value);
|
|
45135
45546
|
}
|
|
45136
45547
|
function assertProjectDatabaseAccessCredential(value) {
|
|
45137
|
-
if (!
|
|
45548
|
+
if (!record4(value) || !exact3(value, [...ACCESS_KEYS, "connection_uri", "psql_command"]))
|
|
45138
45549
|
throw new TypeError("Invalid database access credential");
|
|
45139
45550
|
assertAccessFields(value);
|
|
45140
45551
|
const uri = value["connection_uri"];
|
|
@@ -45150,7 +45561,7 @@ function assertProjectDatabaseAccessCredential(value) {
|
|
|
45150
45561
|
throw new TypeError("Invalid database access credential");
|
|
45151
45562
|
}
|
|
45152
45563
|
function assertProjectDatabaseAccessPage(value) {
|
|
45153
|
-
if (!
|
|
45564
|
+
if (!record4(value) || !exact3(value, ["items"]) || !Array.isArray(value["items"]) || value["items"].length > 50)
|
|
45154
45565
|
throw new TypeError("Invalid database access page");
|
|
45155
45566
|
for (const item of value["items"])
|
|
45156
45567
|
assertProjectDatabaseAccess(item);
|
|
@@ -45185,14 +45596,14 @@ function json(value, depth, budget) {
|
|
|
45185
45596
|
json(entry, depth + 1, budget);
|
|
45186
45597
|
return;
|
|
45187
45598
|
}
|
|
45188
|
-
if (
|
|
45599
|
+
if (record4(value)) {
|
|
45189
45600
|
for (const entry of Object.values(value))
|
|
45190
45601
|
json(entry, depth + 1, budget);
|
|
45191
45602
|
return;
|
|
45192
45603
|
}
|
|
45193
45604
|
throw new TypeError("Invalid database parameter");
|
|
45194
45605
|
}
|
|
45195
|
-
function
|
|
45606
|
+
function record4(value) {
|
|
45196
45607
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45197
45608
|
}
|
|
45198
45609
|
function exact3(value, keys) {
|
|
@@ -45201,7 +45612,7 @@ function exact3(value, keys) {
|
|
|
45201
45612
|
|
|
45202
45613
|
// packages/contracts/dist/credit-pricing.js
|
|
45203
45614
|
function assertOrganizationCreditUsage(value) {
|
|
45204
|
-
const
|
|
45615
|
+
const record8 = (input, keys) => {
|
|
45205
45616
|
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
|
|
45206
45617
|
throw new TypeError("Invalid usage fields");
|
|
45207
45618
|
return input;
|
|
@@ -45209,30 +45620,30 @@ function assertOrganizationCreditUsage(value) {
|
|
|
45209
45620
|
const identifier2 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
45210
45621
|
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
45211
45622
|
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
45212
|
-
const report =
|
|
45623
|
+
const report = record8(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
45213
45624
|
if (!identifier2(report["organization_id"]) || !instant2(report["as_of"]) || !instant2(report["from"]) || report["unit"] !== "microcredits" || typeof report["period"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(report["period"]) || !Array.isArray(report["projects"]) || report["projects"].length > 1e3 || !Array.isArray(report["days"]) || report["days"].length > 15)
|
|
45214
45625
|
throw new TypeError("Invalid usage report");
|
|
45215
45626
|
let previous = "";
|
|
45216
45627
|
for (const input of report["projects"]) {
|
|
45217
|
-
const project =
|
|
45628
|
+
const project = record8(input, "project_id,used_micros");
|
|
45218
45629
|
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
45219
45630
|
throw new TypeError("Invalid usage project");
|
|
45220
45631
|
previous = String(project["project_id"]);
|
|
45221
45632
|
}
|
|
45222
45633
|
let previousDay = "";
|
|
45223
45634
|
for (const input of report["days"]) {
|
|
45224
|
-
const day =
|
|
45635
|
+
const day = record8(input, "day,projects");
|
|
45225
45636
|
if (typeof day["day"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/u.test(day["day"]) || day["day"] <= previousDay || !Array.isArray(day["projects"]) || day["projects"].length > 1e3)
|
|
45226
45637
|
throw new TypeError("Invalid usage day");
|
|
45227
45638
|
previousDay = day["day"];
|
|
45228
45639
|
previous = "";
|
|
45229
45640
|
for (const projectInput of day["projects"]) {
|
|
45230
|
-
const project =
|
|
45641
|
+
const project = record8(projectInput, "project_id,meters");
|
|
45231
45642
|
if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
|
|
45232
45643
|
throw new TypeError("Invalid usage project");
|
|
45233
45644
|
previous = String(project["project_id"]);
|
|
45234
45645
|
for (const meterInput of project["meters"]) {
|
|
45235
|
-
const meter =
|
|
45646
|
+
const meter = record8(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
|
|
45236
45647
|
if (meter["environment_id"] !== null && !identifier2(meter["environment_id"]))
|
|
45237
45648
|
throw new TypeError("Invalid usage environment");
|
|
45238
45649
|
for (const key of ["meter", "unit", "rate_card_id"])
|
|
@@ -45267,16 +45678,16 @@ function assertOrganizationAccount(value) {
|
|
|
45267
45678
|
|
|
45268
45679
|
// packages/contracts/dist/database-compute.js
|
|
45269
45680
|
function assertDatabaseCompute(value) {
|
|
45270
|
-
if (!
|
|
45681
|
+
if (!record5(value) || !exact4(value, ["data_mode", "database", "environment", "observed_at", "project_id"]) || typeof value["project_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(value["project_id"]) || !["dev", "prod"].includes(String(value["environment"])) || !["shared", "isolated"].includes(String(value["data_mode"])) || typeof value["observed_at"] !== "string" || !Number.isFinite(Date.parse(value["observed_at"])) || new Date(value["observed_at"]).toISOString() !== value["observed_at"])
|
|
45271
45682
|
throw new TypeError("Invalid database compute report");
|
|
45272
45683
|
const db = value["database"];
|
|
45273
45684
|
if (db === null)
|
|
45274
45685
|
return;
|
|
45275
|
-
if (
|
|
45686
|
+
if (record5(db) && db["provider"] === "pgcf") {
|
|
45276
45687
|
assertPgcfCompute(db);
|
|
45277
45688
|
return;
|
|
45278
45689
|
}
|
|
45279
|
-
if (!
|
|
45690
|
+
if (!record5(db) || !exact4(db, [
|
|
45280
45691
|
"disabled",
|
|
45281
45692
|
"max_cu",
|
|
45282
45693
|
"max_memory_gb",
|
|
@@ -45307,7 +45718,7 @@ function assertPgcfCompute(db) {
|
|
|
45307
45718
|
]) || db["memory_mib"] !== size.memoryMiB || db["cpu_millicores"] !== size.cpuMillicores || db["storage_mib"] !== size.storageMiB || db["max_connections"] !== size.maxConnections || !Number.isSafeInteger(db["suspend_timeout_seconds"]) || Number(db["suspend_timeout_seconds"]) < 60 || Number(db["suspend_timeout_seconds"]) > 900 || !states.includes(String(db["state"])) || db["pending_state"] !== null && !states.includes(String(db["pending_state"])) || typeof db["disabled"] !== "boolean" || !["us", "eu"].includes(String(db["region"])))
|
|
45308
45719
|
throw new TypeError("Invalid fixed database compute configuration");
|
|
45309
45720
|
}
|
|
45310
|
-
function
|
|
45721
|
+
function record5(v) {
|
|
45311
45722
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45312
45723
|
}
|
|
45313
45724
|
function exact4(v, keys) {
|
|
@@ -45317,7 +45728,7 @@ function exact4(v, keys) {
|
|
|
45317
45728
|
// apps/product-cli/package.json
|
|
45318
45729
|
var package_default = {
|
|
45319
45730
|
name: "@ohmyhost/product-cli",
|
|
45320
|
-
version: "0.1.
|
|
45731
|
+
version: "0.1.46",
|
|
45321
45732
|
private: true,
|
|
45322
45733
|
ohmyhost: {
|
|
45323
45734
|
deployment: "production",
|
|
@@ -45364,32 +45775,32 @@ var package_default = {
|
|
|
45364
45775
|
};
|
|
45365
45776
|
|
|
45366
45777
|
// packages/contracts/dist/project-context.js
|
|
45367
|
-
var
|
|
45778
|
+
var record6 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45368
45779
|
var timestamp4 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
|
|
45369
45780
|
var version = (v) => Number.isInteger(v) && Number(v) >= 0 && Number(v) <= 2147483647;
|
|
45370
45781
|
var bounded = (v, lines, bytes) => typeof v === "string" && !/[\r\u2028\u2029]/u.test(v) && !new RegExp("\\p{Cc}", "u").test(v.replace(/[\n\t]/gu, "")) && v.split("\n").length <= lines && new TextEncoder().encode(v).length <= bytes;
|
|
45371
45782
|
function assertProjectNotesReceipt(v) {
|
|
45372
|
-
if (!
|
|
45783
|
+
if (!record6(v) || Object.keys(v).sort().join(",") !== "updated_at,version" || !version(v["version"]) || v["version"] === 0 || !timestamp4(v["updated_at"]))
|
|
45373
45784
|
throw new TypeError("Invalid project notes receipt");
|
|
45374
45785
|
}
|
|
45375
45786
|
function assertProjectContext(v) {
|
|
45376
|
-
if (!
|
|
45787
|
+
if (!record6(v) || Object.keys(v).sort().join(",") !== "credit_access,generated_at,markdown,notes,project_id" || typeof v["project_id"] !== "string" || !/^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(v["project_id"]) || !timestamp4(v["generated_at"]) || !["included", "not_authorized"].includes(String(v["credit_access"])) || !bounded(v["markdown"], 500, 32768))
|
|
45377
45788
|
throw new TypeError("Invalid project context");
|
|
45378
45789
|
const notes = v["notes"];
|
|
45379
|
-
if (!
|
|
45790
|
+
if (!record6(notes) || Object.keys(notes).sort().join(",") !== "markdown,updated_at,version" || !version(notes["version"]) || !bounded(notes["markdown"], 250, 16384) || (notes["version"] === 0 ? notes["updated_at"] !== null || notes["markdown"] !== "" : !timestamp4(notes["updated_at"])))
|
|
45380
45791
|
throw new TypeError("Invalid project notes");
|
|
45381
45792
|
}
|
|
45382
45793
|
|
|
45383
45794
|
// packages/contracts/dist/project-exports.js
|
|
45384
45795
|
function assertProjectExport(value) {
|
|
45385
|
-
if (!
|
|
45796
|
+
if (!record7(value) || Object.keys(value).sort().join(",") !== "archive,error,id,next_poll_after_seconds,next_request_at,project_id,requested_at,state" || typeof value["id"] !== "string" || !id.test(value["id"]) || typeof value["project_id"] !== "string" || !id.test(value["project_id"]) || !["queued", "running", "succeeded", "failed", "cancelled"].includes(String(value["state"])) || !timestamp5(value["requested_at"]) || !timestamp5(value["next_request_at"]))
|
|
45386
45797
|
invalid4();
|
|
45387
45798
|
const active = value["state"] === "queued" || value["state"] === "running";
|
|
45388
45799
|
if (value["next_poll_after_seconds"] !== (active ? 5 : null))
|
|
45389
45800
|
invalid4();
|
|
45390
45801
|
if (value["state"] === "failed") {
|
|
45391
45802
|
const error = value["error"];
|
|
45392
|
-
if (!
|
|
45803
|
+
if (!record7(error) || Object.keys(error).sort().join(",") !== "code,message,retryable,suggested_action" || typeof error["code"] !== "string")
|
|
45393
45804
|
invalid4();
|
|
45394
45805
|
const expected = publicOperationFailure(error["code"]);
|
|
45395
45806
|
for (const key of Object.keys(expected))
|
|
@@ -45403,7 +45814,7 @@ function assertProjectExport(value) {
|
|
|
45403
45814
|
invalid4();
|
|
45404
45815
|
return;
|
|
45405
45816
|
}
|
|
45406
|
-
if (value["state"] !== "succeeded" || !
|
|
45817
|
+
if (value["state"] !== "succeeded" || !record7(archive) || Object.keys(archive).sort().join(",") !== "bytes,captured_at,download_expires_at,download_url,expires_at,sha256,sql_files" || !Number.isSafeInteger(archive["bytes"]) || Number(archive["bytes"]) < 1 || Number(archive["bytes"]) > 536870912 || typeof archive["sha256"] !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(archive["sha256"]) || !['["dev.sql"]', '["prod.sql"]', '["dev.sql","prod.sql"]', '["shared.sql"]'].includes(JSON.stringify(archive["sql_files"])) || !timestamp5(archive["captured_at"]) || !timestamp5(archive["expires_at"]))
|
|
45407
45818
|
invalid4();
|
|
45408
45819
|
if (archive["download_url"] === null) {
|
|
45409
45820
|
if (archive["download_expires_at"] !== null)
|
|
@@ -45422,7 +45833,7 @@ function assertProjectExport(value) {
|
|
|
45422
45833
|
invalid4();
|
|
45423
45834
|
}
|
|
45424
45835
|
var id = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
|
|
45425
|
-
function
|
|
45836
|
+
function record7(value) {
|
|
45426
45837
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45427
45838
|
}
|
|
45428
45839
|
function timestamp5(value) {
|
|
@@ -45662,7 +46073,11 @@ var HELP_USAGE = Object.freeze({
|
|
|
45662
46073
|
"database access create": "ohmyhost database access create --project ULID --environment dev|prod [--mode read|write] [--ttl 5m|1h|24h|SECONDS] [--label TEXT] --yes --json\n The connection URI is shown once. Use it immediately, never store it in files, notes or source, and revoke it when finished.",
|
|
45663
46074
|
"database access list": "ohmyhost database access list --project ULID [--environment dev|prod] --json",
|
|
45664
46075
|
"database access revoke": "ohmyhost database access revoke --project ULID --access ULID --yes --json",
|
|
45665
|
-
"database
|
|
46076
|
+
"database watch create": "ohmyhost database watch create --project ULID --environment dev|prod --table NAME [--schema public] --columns COL[,COL] [--operations insert,update,delete] --idempotency-key KEY --yes --json (publishes only the listed columns, at most 32, of each row change as the event type data.<topic> printed in this answer; the table must exist as an ordinary table of the application; a sleeping database wakes; next, subscribe with 'ohmyhost database webhook create ... --event-types data.<topic>')",
|
|
46077
|
+
"database watch list": "ohmyhost database watch list --project ULID [--environment dev|prod] --json (dev when omitted; a sleeping database wakes)",
|
|
46078
|
+
"database watch delete": "ohmyhost database watch delete --project ULID --environment dev|prod --watch ID --idempotency-key KEY --yes --json",
|
|
46079
|
+
"database table create": "ohmyhost database table create --project ULID --environment dev|prod --table NAME --columns-file PATH [--primary-key COL[,COL]] --idempotency-key KEY --yes --json (the table is created in the public schema as the migration role, with the same access as migration tables, so a database watch can attach later; the columns file is a UTF-8 JSON array of 1 to 64 column objects, at most 64 KiB, each with name, type and optional nullable, identity and default; types: text, integer, bigint, boolean, numeric, double precision, timestamptz, date, uuid, jsonb; identity needs integer or bigint; default now needs timestamptz and default uuid needs uuid; identical repeats answer created false; at most 100 tables, 64 columns per table)",
|
|
46080
|
+
"database webhook create": "ohmyhost database webhook create --project ULID --environment dev|prod --url HTTPS_URL --event-types TYPE[,TYPE] [--headers-file PATH] --idempotency-key KEY --yes --json (the signing secret is shown once in this answer; types: database.created, database.ready, database.woke, database.slept, database.suspended, database.resized, database.deleted, data.<topic> for the rows of one watched table printed by database watch create, or data.* for every watched table; a bare * is not accepted and does not include data events; the headers file is a UTF-8 JSON object of at most 8 KiB)",
|
|
45666
46081
|
"database webhook list": "ohmyhost database webhook list --project ULID [--environment dev|prod] --json (dev when omitted; the secret is never listed)",
|
|
45667
46082
|
"database webhook get": "ohmyhost database webhook get --project ULID [--environment dev|prod] --webhook ID --json",
|
|
45668
46083
|
"database webhook delete": "ohmyhost database webhook delete --project ULID --environment dev|prod --webhook ID --yes --json",
|
|
@@ -45787,6 +46202,7 @@ var LOGOUT_UNCONFIRMED_ACTION = "The saved login was removed from this computer,
|
|
|
45787
46202
|
var HEADERS_FILE_INVALID_ACTION = "Put one JSON object of header names and values in the file named by --headers-file: UTF-8, at most 8 KiB, unique names, values of visible ASCII characters. Names such as content-type, host, content-length, connection, transfer-encoding, user-agent, te, upgrade and expect, and names starting with pgcf-, cf- or x-forwarded-, are refused. Nothing was sent; fix the file and run the command again.";
|
|
45788
46203
|
var SCHEDULE_STATEMENTS_FILE_INVALID_ACTION = "Put one JSON array of 1 to 20 non-empty SQL strings in the file named by --statements-file: UTF-8, at most 64 KiB in total and 16 KiB per statement, without NUL characters. Nothing was saved; fix the file and run the command again.";
|
|
45789
46204
|
var SCHEDULE_INVALID_ACTION = "Check the schedule request: --cron takes five fields in UTC (9 to 120 characters), or --every-seconds takes 60 to 2678400, never both; --timeout-ms takes 1000 to 30000; the statements file must hold 1 to 20 non-blank SQL strings of at most 16 KiB each and 64 KiB in total. Nothing was saved; fix it and run the command again.";
|
|
46205
|
+
var COLUMNS_FILE_INVALID_ACTION = "Put one JSON array of 1 to 64 column objects in the file named by --columns-file: UTF-8, at most 64 KiB, each with a lower-case name, a type (text, integer, bigint, boolean, numeric, double precision, timestamptz, date, uuid or jsonb) and optional nullable, identity (integer or bigint only) and default (now for timestamptz, uuid for uuid). Each --primary-key column must be one of them, at most 8 names. Nothing was created; fix the file or the flags and run the command again.";
|
|
45790
46206
|
var STATEMENT_FILE_INVALID_ACTION = "Put one INSERT, UPDATE or DELETE statement that starts with that keyword (no leading comment or WITH), UTF-8, at most 64 KiB, in the file named by --statement-file, then rerun with the same --idempotency-key.";
|
|
45791
46207
|
var signInCommand = (commandPrefix, profile) => profile === void 0 ? `${commandPrefix} login --json` : `${commandPrefix} login${profile.organizationId === null ? "" : ` --organization ${profile.organizationId}`} --user ${profile.userId} --profile-name ${profile.name} --json`;
|
|
45792
46208
|
var endedLoginAction = (commandPrefix, profile) => `The sign-in of ${profile === void 0 ? "this computer's saved login" : `saved login ${profile.name} (user ${profile.userId}${profile.organizationId === null ? "" : `, organization ${profile.organizationId}`})`} ended and it was removed. Run '${signInCommand(commandPrefix, profile)}' to sign it in again.`;
|
|
@@ -46153,6 +46569,14 @@ var ProductCli = class {
|
|
|
46153
46569
|
return await this.listDatabaseAccess(command, signal);
|
|
46154
46570
|
if (command.kind === "database-access-revoke")
|
|
46155
46571
|
return await this.revokeDatabaseAccess(command, signal);
|
|
46572
|
+
if (command.kind === "database-watch-create")
|
|
46573
|
+
return await this.createDatabaseWatch(command, signal);
|
|
46574
|
+
if (command.kind === "database-watch-list")
|
|
46575
|
+
return await this.listDatabaseWatches(command, signal);
|
|
46576
|
+
if (command.kind === "database-watch-delete")
|
|
46577
|
+
return await this.deleteDatabaseWatch(command, signal);
|
|
46578
|
+
if (command.kind === "database-table-create")
|
|
46579
|
+
return await this.createDatabaseTable(command, signal);
|
|
46156
46580
|
if (command.kind === "database-webhook-create")
|
|
46157
46581
|
return await this.createDatabaseWebhook(command, signal);
|
|
46158
46582
|
if (command.kind === "database-webhook-list")
|
|
@@ -46684,6 +47108,51 @@ var ProductCli = class {
|
|
|
46684
47108
|
assertProjectDatabaseAccess(access);
|
|
46685
47109
|
return success("database access revoke", { status: "succeeded", access });
|
|
46686
47110
|
}
|
|
47111
|
+
/** The answer names the event type to subscribe to; the watch already carries the columns and the topic. */
|
|
47112
|
+
async createDatabaseWatch(command, signal) {
|
|
47113
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
47114
|
+
const watch = await api.createProjectDatabaseWatch({
|
|
47115
|
+
projectId: command.projectId,
|
|
47116
|
+
environment: command.environment,
|
|
47117
|
+
idempotencyKey: command.idempotencyKey,
|
|
47118
|
+
request: command.request
|
|
47119
|
+
});
|
|
47120
|
+
return success("database watch create", {
|
|
47121
|
+
status: "succeeded",
|
|
47122
|
+
watch,
|
|
47123
|
+
next_action: `Run '${this.dependencies.commandPrefix} database webhook create --project ${command.projectId} --environment ${command.environment} --url HTTPS_URL --event-types ${watch.event_type} --idempotency-key KEY --yes --json' to receive ${watch.event_type} events at an HTTPS receiver.`
|
|
47124
|
+
});
|
|
47125
|
+
}
|
|
47126
|
+
async listDatabaseWatches(command, signal) {
|
|
47127
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
47128
|
+
const page = await api.listProjectDatabaseWatches({
|
|
47129
|
+
projectId: command.projectId,
|
|
47130
|
+
environment: command.environment
|
|
47131
|
+
});
|
|
47132
|
+
return success("database watch list", { status: "succeeded", watch: page.items });
|
|
47133
|
+
}
|
|
47134
|
+
async deleteDatabaseWatch(command, signal) {
|
|
47135
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
47136
|
+
const deleted = await api.deleteProjectDatabaseWatch({
|
|
47137
|
+
projectId: command.projectId,
|
|
47138
|
+
environment: command.environment,
|
|
47139
|
+
idempotencyKey: command.idempotencyKey,
|
|
47140
|
+
watchId: command.watchId
|
|
47141
|
+
});
|
|
47142
|
+
return success("database watch delete", { status: "succeeded", deleted });
|
|
47143
|
+
}
|
|
47144
|
+
/** The columns file and the key are checked before any request; a repeat answers the same table with created false. */
|
|
47145
|
+
async createDatabaseTable(command, signal) {
|
|
47146
|
+
const request = await tableCreateRequest(command);
|
|
47147
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
47148
|
+
const answer = await api.createProjectDatabaseTable({
|
|
47149
|
+
projectId: command.projectId,
|
|
47150
|
+
environment: command.environment,
|
|
47151
|
+
idempotencyKey: command.idempotencyKey,
|
|
47152
|
+
request
|
|
47153
|
+
});
|
|
47154
|
+
return success("database table create", { status: "succeeded", table: answer.table });
|
|
47155
|
+
}
|
|
46687
47156
|
/** The signing secret is returned by create only; every other answer carries no secret. */
|
|
46688
47157
|
async createDatabaseWebhook(command, signal) {
|
|
46689
47158
|
const request = await webhookCreateRequest(command);
|
|
@@ -47575,6 +48044,37 @@ var scheduleSetRequest = async (command) => {
|
|
|
47575
48044
|
throw new ProductCliFailure(2, "schedule_invalid", false, SCHEDULE_INVALID_ACTION);
|
|
47576
48045
|
}
|
|
47577
48046
|
};
|
|
48047
|
+
var tableCreateRequest = async (command) => {
|
|
48048
|
+
const columnsFailure = () => new ProductCliFailure(2, "columns_file_invalid", false, COLUMNS_FILE_INVALID_ACTION);
|
|
48049
|
+
const columns = await readBoundedUtf8File(command.columnsFile, 65536, columnsFailure).then((text) => {
|
|
48050
|
+
try {
|
|
48051
|
+
return JSON.parse(text);
|
|
48052
|
+
} catch {
|
|
48053
|
+
throw columnsFailure();
|
|
48054
|
+
}
|
|
48055
|
+
});
|
|
48056
|
+
try {
|
|
48057
|
+
const parsed = parseDatabaseTableCreateRequest({
|
|
48058
|
+
table: command.table,
|
|
48059
|
+
columns,
|
|
48060
|
+
...command.primaryKey.length === 0 ? {} : { primaryKey: command.primaryKey }
|
|
48061
|
+
});
|
|
48062
|
+
return {
|
|
48063
|
+
table: parsed.table,
|
|
48064
|
+
columns: parsed.columns.map(tableColumnInput),
|
|
48065
|
+
primaryKey: parsed.primaryKey
|
|
48066
|
+
};
|
|
48067
|
+
} catch {
|
|
48068
|
+
throw columnsFailure();
|
|
48069
|
+
}
|
|
48070
|
+
};
|
|
48071
|
+
var tableColumnInput = (column) => ({
|
|
48072
|
+
name: column.name,
|
|
48073
|
+
type: column.type,
|
|
48074
|
+
nullable: column.nullable,
|
|
48075
|
+
identity: column.identity,
|
|
48076
|
+
...column.default === null ? {} : { default: column.default }
|
|
48077
|
+
});
|
|
47578
48078
|
var psqlUnavailable = () => failure("database psql", 9, "psql_unavailable", false, "Install the PostgreSQL client (psql) and make it available on PATH, or run 'ohmyhost database access create' and connect with your own SQL client.");
|
|
47579
48079
|
var success = (command, body) => ({
|
|
47580
48080
|
exitCode: 0,
|
|
@@ -47714,6 +48214,14 @@ var parsedCommandName = (command) => {
|
|
|
47714
48214
|
return "database access revoke";
|
|
47715
48215
|
if (command.kind === "database-psql")
|
|
47716
48216
|
return "database psql";
|
|
48217
|
+
if (command.kind === "database-watch-create")
|
|
48218
|
+
return "database watch create";
|
|
48219
|
+
if (command.kind === "database-watch-list")
|
|
48220
|
+
return "database watch list";
|
|
48221
|
+
if (command.kind === "database-watch-delete")
|
|
48222
|
+
return "database watch delete";
|
|
48223
|
+
if (command.kind === "database-table-create")
|
|
48224
|
+
return "database table create";
|
|
47717
48225
|
if (command.kind === "database-webhook-create")
|
|
47718
48226
|
return "database webhook create";
|
|
47719
48227
|
if (command.kind === "database-webhook-list")
|
|
@@ -47936,12 +48444,12 @@ function buildClientParams(args, fields) {
|
|
|
47936
48444
|
};
|
|
47937
48445
|
const map = buildKeyMap(fields);
|
|
47938
48446
|
function writeSlot(slot, key, value) {
|
|
47939
|
-
let
|
|
47940
|
-
if (
|
|
47941
|
-
|
|
47942
|
-
params[slot] =
|
|
48447
|
+
let record8 = params[slot];
|
|
48448
|
+
if (record8 === void 0) {
|
|
48449
|
+
record8 = /* @__PURE__ */ Object.create(null);
|
|
48450
|
+
params[slot] = record8;
|
|
47943
48451
|
}
|
|
47944
|
-
|
|
48452
|
+
record8[key] = value;
|
|
47945
48453
|
}
|
|
47946
48454
|
let config;
|
|
47947
48455
|
for (const [index, arg] of args.entries()) {
|
|
@@ -50586,6 +51094,92 @@ var revokeProjectDatabaseAccess = (parameters, options) => {
|
|
|
50586
51094
|
...params
|
|
50587
51095
|
});
|
|
50588
51096
|
};
|
|
51097
|
+
var createProjectDatabaseTable = (parameters, options) => {
|
|
51098
|
+
const params = buildClientParams([parameters], [
|
|
51099
|
+
{
|
|
51100
|
+
args: [
|
|
51101
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
51102
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
51103
|
+
{ in: "path", key: "project_id" },
|
|
51104
|
+
{ key: "databaseTableCreateRequest", map: "body" }
|
|
51105
|
+
]
|
|
51106
|
+
}
|
|
51107
|
+
]);
|
|
51108
|
+
return (options?.client ?? client).post({
|
|
51109
|
+
responseStyle: "data",
|
|
51110
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
51111
|
+
url: "/v1/projects/{project_id}/database/tables",
|
|
51112
|
+
...options,
|
|
51113
|
+
...params,
|
|
51114
|
+
headers: {
|
|
51115
|
+
"Content-Type": "application/json",
|
|
51116
|
+
...options?.headers,
|
|
51117
|
+
...params.headers
|
|
51118
|
+
}
|
|
51119
|
+
});
|
|
51120
|
+
};
|
|
51121
|
+
var listProjectDatabaseWatches = (parameters, options) => {
|
|
51122
|
+
const params = buildClientParams([parameters], [
|
|
51123
|
+
{
|
|
51124
|
+
args: [
|
|
51125
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
51126
|
+
{ in: "path", key: "project_id" },
|
|
51127
|
+
{ in: "query", key: "environment" }
|
|
51128
|
+
]
|
|
51129
|
+
}
|
|
51130
|
+
]);
|
|
51131
|
+
return (options?.client ?? client).get({
|
|
51132
|
+
responseStyle: "data",
|
|
51133
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
51134
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
51135
|
+
...options,
|
|
51136
|
+
...params
|
|
51137
|
+
});
|
|
51138
|
+
};
|
|
51139
|
+
var createProjectDatabaseWatch = (parameters, options) => {
|
|
51140
|
+
const params = buildClientParams([parameters], [
|
|
51141
|
+
{
|
|
51142
|
+
args: [
|
|
51143
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
51144
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
51145
|
+
{ in: "path", key: "project_id" },
|
|
51146
|
+
{ key: "databaseWatchCreateRequest", map: "body" }
|
|
51147
|
+
]
|
|
51148
|
+
}
|
|
51149
|
+
]);
|
|
51150
|
+
return (options?.client ?? client).post({
|
|
51151
|
+
responseStyle: "data",
|
|
51152
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
51153
|
+
url: "/v1/projects/{project_id}/database/watches",
|
|
51154
|
+
...options,
|
|
51155
|
+
...params,
|
|
51156
|
+
headers: {
|
|
51157
|
+
"Content-Type": "application/json",
|
|
51158
|
+
...options?.headers,
|
|
51159
|
+
...params.headers
|
|
51160
|
+
}
|
|
51161
|
+
});
|
|
51162
|
+
};
|
|
51163
|
+
var deleteProjectDatabaseWatch = (parameters, options) => {
|
|
51164
|
+
const params = buildClientParams([parameters], [
|
|
51165
|
+
{
|
|
51166
|
+
args: [
|
|
51167
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
51168
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
51169
|
+
{ in: "path", key: "project_id" },
|
|
51170
|
+
{ in: "path", key: "watch_id" },
|
|
51171
|
+
{ in: "query", key: "environment" }
|
|
51172
|
+
]
|
|
51173
|
+
}
|
|
51174
|
+
]);
|
|
51175
|
+
return (options?.client ?? client).delete({
|
|
51176
|
+
responseStyle: "data",
|
|
51177
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
51178
|
+
url: "/v1/projects/{project_id}/database/watches/{watch_id}",
|
|
51179
|
+
...options,
|
|
51180
|
+
...params
|
|
51181
|
+
});
|
|
51182
|
+
};
|
|
50589
51183
|
var listProjectDatabaseWebhooks = (parameters, options) => {
|
|
50590
51184
|
const params = buildClientParams([parameters], [
|
|
50591
51185
|
{
|
|
@@ -51959,7 +52553,25 @@ function checkedResponse(kind, value) {
|
|
|
51959
52553
|
|
|
51960
52554
|
// apps/product-cli/dist/product-api.js
|
|
51961
52555
|
var WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
|
|
52556
|
+
var WATCH_SCOPE_MISMATCH = "Watch response scope mismatch";
|
|
52557
|
+
var TABLE_SCOPE_MISMATCH = "Table response scope mismatch";
|
|
51962
52558
|
var SCHEDULE_SCOPE_MISMATCH = "Schedule response scope mismatch";
|
|
52559
|
+
function assertDatabaseTableAnswer(value) {
|
|
52560
|
+
const table = isRecordValue(value) ? value["table"] : void 0;
|
|
52561
|
+
const columns = isRecordValue(table) ? table["columns"] : void 0;
|
|
52562
|
+
const primaryKey = isRecordValue(table) ? table["primary_key"] : void 0;
|
|
52563
|
+
if (!isRecordValue(table) || !hasExactKeys(table, ["environment", "schema", "table", "columns", "primary_key", "created"]) || table["environment"] !== "dev" && table["environment"] !== "prod" || table["schema"] !== "public" || !isDatabaseTableIdentifier(table["table"]) || typeof table["created"] !== "boolean" || !Array.isArray(columns) || columns.length < 1 || !columns.every(isDatabaseTableAnswerColumn) || !Array.isArray(primaryKey) || !primaryKey.every((name) => columns.some((column) => column["name"] === name)))
|
|
52564
|
+
throw new TypeError("Invalid database table answer");
|
|
52565
|
+
}
|
|
52566
|
+
function isDatabaseTableAnswerColumn(value) {
|
|
52567
|
+
return isRecordValue(value) && hasExactKeys(value, ["name", "type", "nullable", "identity", "default"]) && isDatabaseTableIdentifier(value["name"]) && DATABASE_TABLE_COLUMN_TYPES.includes(value["type"]) && typeof value["nullable"] === "boolean" && typeof value["identity"] === "boolean" && (value["default"] === null || DATABASE_TABLE_DEFAULTS.includes(value["default"]));
|
|
52568
|
+
}
|
|
52569
|
+
function isRecordValue(value) {
|
|
52570
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
52571
|
+
}
|
|
52572
|
+
function hasExactKeys(value, keys) {
|
|
52573
|
+
return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
52574
|
+
}
|
|
51963
52575
|
var GeneratedSdkProductApi = class {
|
|
51964
52576
|
#client;
|
|
51965
52577
|
managedSource;
|
|
@@ -52156,6 +52768,58 @@ var GeneratedSdkProductApi = class {
|
|
|
52156
52768
|
assertProjectDatabaseAccess(value);
|
|
52157
52769
|
return value;
|
|
52158
52770
|
}
|
|
52771
|
+
async createProjectDatabaseWatch(input) {
|
|
52772
|
+
const value = await createProjectDatabaseWatch({
|
|
52773
|
+
project_id: input.projectId,
|
|
52774
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
52775
|
+
databaseWatchCreateRequest: {
|
|
52776
|
+
environment: input.environment,
|
|
52777
|
+
schema: input.request.schema,
|
|
52778
|
+
table: input.request.table,
|
|
52779
|
+
columns: [...input.request.columns],
|
|
52780
|
+
operations: [...input.request.operations]
|
|
52781
|
+
}
|
|
52782
|
+
}, { client: this.#client });
|
|
52783
|
+
assertDatabaseWatch(value);
|
|
52784
|
+
if (value.environment !== input.environment || value.schema !== input.request.schema || value.table !== input.request.table)
|
|
52785
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
52786
|
+
return value;
|
|
52787
|
+
}
|
|
52788
|
+
async listProjectDatabaseWatches(input) {
|
|
52789
|
+
const value = await listProjectDatabaseWatches({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
|
|
52790
|
+
assertDatabaseWatchPage(value);
|
|
52791
|
+
if (value.items.some((item) => item.environment !== input.environment))
|
|
52792
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
52793
|
+
return value;
|
|
52794
|
+
}
|
|
52795
|
+
async deleteProjectDatabaseWatch(input) {
|
|
52796
|
+
const value = await deleteProjectDatabaseWatch({
|
|
52797
|
+
project_id: input.projectId,
|
|
52798
|
+
environment: input.environment,
|
|
52799
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
52800
|
+
watch_id: input.watchId
|
|
52801
|
+
}, { client: this.#client });
|
|
52802
|
+
assertDatabaseWatchDeleted(value);
|
|
52803
|
+
if (value.id !== input.watchId)
|
|
52804
|
+
throw new TypeError(WATCH_SCOPE_MISMATCH);
|
|
52805
|
+
return value;
|
|
52806
|
+
}
|
|
52807
|
+
async createProjectDatabaseTable(input) {
|
|
52808
|
+
const value = await createProjectDatabaseTable({
|
|
52809
|
+
project_id: input.projectId,
|
|
52810
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
52811
|
+
databaseTableCreateRequest: {
|
|
52812
|
+
environment: input.environment,
|
|
52813
|
+
table: input.request.table,
|
|
52814
|
+
columns: [...input.request.columns],
|
|
52815
|
+
...input.request.primaryKey.length === 0 ? {} : { primary_key: [...input.request.primaryKey] }
|
|
52816
|
+
}
|
|
52817
|
+
}, { client: this.#client });
|
|
52818
|
+
assertDatabaseTableAnswer(value);
|
|
52819
|
+
if (value.table.environment !== input.environment || value.table.table !== input.request.table)
|
|
52820
|
+
throw new TypeError(TABLE_SCOPE_MISMATCH);
|
|
52821
|
+
return value;
|
|
52822
|
+
}
|
|
52159
52823
|
/** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
|
|
52160
52824
|
async createProjectDatabaseWebhook(input) {
|
|
52161
52825
|
const value = await createProjectDatabaseWebhook({
|
|
@@ -53762,8 +54426,8 @@ function pnpmLockedVersion(document2, packageName) {
|
|
|
53762
54426
|
}
|
|
53763
54427
|
return null;
|
|
53764
54428
|
}
|
|
53765
|
-
function ownValue(
|
|
53766
|
-
return isRecord4(
|
|
54429
|
+
function ownValue(record8, key) {
|
|
54430
|
+
return isRecord4(record8) && Object.hasOwn(record8, key) ? record8[key] : void 0;
|
|
53767
54431
|
}
|
|
53768
54432
|
function isRecord4(value) {
|
|
53769
54433
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -54123,6 +54787,8 @@ function rejectMigrationSqlReferences(tokens, allowIdentityHelpers = false) {
|
|
|
54123
54787
|
if (token?.kind !== "word" && token?.kind !== "identifier")
|
|
54124
54788
|
continue;
|
|
54125
54789
|
const value = token.value.toLowerCase();
|
|
54790
|
+
if (value === "pgcf")
|
|
54791
|
+
throw new DatabaseMigrationAdmissionError("unsupported");
|
|
54126
54792
|
if (value === "ohmyhost") {
|
|
54127
54793
|
if (allowIdentityHelpers && token.value === "ohmyhost" && tokens[index + 1]?.kind === "symbol" && tokens[index + 1]?.value === "." && ["user_id", "claims"].includes(tokens[index + 2]?.value ?? "") && ["word", "identifier"].includes(tokens[index + 2]?.kind ?? "") && tokens[index + 3]?.kind === "symbol" && tokens[index + 3]?.value === "(" && tokens[index + 4]?.kind === "symbol" && tokens[index + 4]?.value === ")")
|
|
54128
54794
|
continue;
|
|
@@ -54134,6 +54800,139 @@ function rejectMigrationSqlReferences(tokens, allowIdentityHelpers = false) {
|
|
|
54134
54800
|
}
|
|
54135
54801
|
}
|
|
54136
54802
|
|
|
54803
|
+
// packages/contracts/dist/database-migration-capture.js
|
|
54804
|
+
var MAX_NAME_BYTES = 63;
|
|
54805
|
+
function readMigrationCaptureTrigger(tokens) {
|
|
54806
|
+
if (!isSqlKeyword(tokens[0], "create") || !isSqlKeyword(tokens[1], "trigger"))
|
|
54807
|
+
return void 0;
|
|
54808
|
+
if (!tokens.some((token) => isNamedPgcf(token, true)))
|
|
54809
|
+
return void 0;
|
|
54810
|
+
return new CaptureReader(tokens).read();
|
|
54811
|
+
}
|
|
54812
|
+
var CaptureReader = class {
|
|
54813
|
+
tokens;
|
|
54814
|
+
position = 2;
|
|
54815
|
+
constructor(tokens) {
|
|
54816
|
+
this.tokens = tokens;
|
|
54817
|
+
}
|
|
54818
|
+
read() {
|
|
54819
|
+
const trigger = this.triggerName();
|
|
54820
|
+
this.expectKeyword("after");
|
|
54821
|
+
const operations = this.operations();
|
|
54822
|
+
this.expectKeyword("on");
|
|
54823
|
+
const schema = this.name();
|
|
54824
|
+
this.expectSymbol(".");
|
|
54825
|
+
const table = this.name();
|
|
54826
|
+
if (!isDatabaseWatchSchema(schema))
|
|
54827
|
+
throw unsupported();
|
|
54828
|
+
for (const keyword of ["for", "each", "row", "execute", "function"]) {
|
|
54829
|
+
this.expectKeyword(keyword);
|
|
54830
|
+
}
|
|
54831
|
+
const header = this.tokens.slice(0, this.position);
|
|
54832
|
+
if (!isNamedPgcf(this.token(), false))
|
|
54833
|
+
throw unsupported();
|
|
54834
|
+
this.position += 1;
|
|
54835
|
+
this.expectSymbol(".");
|
|
54836
|
+
this.expectCapture();
|
|
54837
|
+
this.expectSymbol("(");
|
|
54838
|
+
const columns = this.columns();
|
|
54839
|
+
this.expectSymbol(")");
|
|
54840
|
+
if (this.position !== this.tokens.length)
|
|
54841
|
+
throw unsupported();
|
|
54842
|
+
return Object.freeze({
|
|
54843
|
+
target: Object.freeze({ trigger, schema, table, operations, columns }),
|
|
54844
|
+
header
|
|
54845
|
+
});
|
|
54846
|
+
}
|
|
54847
|
+
triggerName() {
|
|
54848
|
+
const token = this.token();
|
|
54849
|
+
if (token.kind !== "word" && token.kind !== "identifier" || !isDatabaseWatchIdentifier(token.value)) {
|
|
54850
|
+
throw unsupported();
|
|
54851
|
+
}
|
|
54852
|
+
this.position += 1;
|
|
54853
|
+
return token.value;
|
|
54854
|
+
}
|
|
54855
|
+
/** Table and schema names may be quoted identifiers; the executor checks the catalog for the exact name. */
|
|
54856
|
+
name() {
|
|
54857
|
+
const token = this.token();
|
|
54858
|
+
const valid = token.kind === "word" ? isDatabaseWatchIdentifier(token.value) : token.kind === "identifier" && isQuotedName(token.value);
|
|
54859
|
+
if (!valid)
|
|
54860
|
+
throw unsupported();
|
|
54861
|
+
this.position += 1;
|
|
54862
|
+
return token.value;
|
|
54863
|
+
}
|
|
54864
|
+
operations() {
|
|
54865
|
+
const events = [];
|
|
54866
|
+
do {
|
|
54867
|
+
const token = this.token();
|
|
54868
|
+
const operation = DATABASE_WATCH_OPERATIONS.find((name) => isSqlKeyword(token, name));
|
|
54869
|
+
if (operation === void 0 || events.includes(operation))
|
|
54870
|
+
throw unsupported();
|
|
54871
|
+
this.position += 1;
|
|
54872
|
+
events.push(operation);
|
|
54873
|
+
} while (this.takeKeyword("or"));
|
|
54874
|
+
return DATABASE_WATCH_OPERATIONS.filter((operation) => events.includes(operation));
|
|
54875
|
+
}
|
|
54876
|
+
expectCapture() {
|
|
54877
|
+
const token = this.token();
|
|
54878
|
+
if (token.kind !== "word" && token.kind !== "identifier" || token.value !== "capture") {
|
|
54879
|
+
throw unsupported();
|
|
54880
|
+
}
|
|
54881
|
+
this.position += 1;
|
|
54882
|
+
}
|
|
54883
|
+
columns() {
|
|
54884
|
+
const columns = [];
|
|
54885
|
+
do {
|
|
54886
|
+
const token = this.token();
|
|
54887
|
+
if (columns.length >= DATABASE_WATCH_MAX_COLUMNS || token.kind !== "string" || token.text !== `'${token.value}'` || !isDatabaseWatchIdentifier(token.value) || columns.includes(token.value)) {
|
|
54888
|
+
throw unsupported();
|
|
54889
|
+
}
|
|
54890
|
+
this.position += 1;
|
|
54891
|
+
columns.push(token.value);
|
|
54892
|
+
} while (this.takeSymbol(","));
|
|
54893
|
+
return columns;
|
|
54894
|
+
}
|
|
54895
|
+
token() {
|
|
54896
|
+
const token = this.tokens[this.position];
|
|
54897
|
+
if (token === void 0)
|
|
54898
|
+
throw unsupported();
|
|
54899
|
+
return token;
|
|
54900
|
+
}
|
|
54901
|
+
takeKeyword(keyword) {
|
|
54902
|
+
if (!isSqlKeyword(this.tokens[this.position], keyword))
|
|
54903
|
+
return false;
|
|
54904
|
+
this.position += 1;
|
|
54905
|
+
return true;
|
|
54906
|
+
}
|
|
54907
|
+
expectKeyword(keyword) {
|
|
54908
|
+
if (!this.takeKeyword(keyword))
|
|
54909
|
+
throw unsupported();
|
|
54910
|
+
}
|
|
54911
|
+
takeSymbol(symbol) {
|
|
54912
|
+
const token = this.tokens[this.position];
|
|
54913
|
+
if (token?.kind !== "symbol" || token.value !== symbol)
|
|
54914
|
+
return false;
|
|
54915
|
+
this.position += 1;
|
|
54916
|
+
return true;
|
|
54917
|
+
}
|
|
54918
|
+
expectSymbol(symbol) {
|
|
54919
|
+
if (!this.takeSymbol(symbol))
|
|
54920
|
+
throw unsupported();
|
|
54921
|
+
}
|
|
54922
|
+
};
|
|
54923
|
+
function isNamedPgcf(token, ignoreCase) {
|
|
54924
|
+
if (token.kind !== "word" && token.kind !== "identifier")
|
|
54925
|
+
return false;
|
|
54926
|
+
return ignoreCase ? token.value.toLowerCase() === "pgcf" : token.value === "pgcf";
|
|
54927
|
+
}
|
|
54928
|
+
function isQuotedName(value) {
|
|
54929
|
+
const bytes = new TextEncoder().encode(value).byteLength;
|
|
54930
|
+
return bytes >= 1 && bytes <= MAX_NAME_BYTES;
|
|
54931
|
+
}
|
|
54932
|
+
function unsupported() {
|
|
54933
|
+
return new DatabaseMigrationAdmissionError("unsupported");
|
|
54934
|
+
}
|
|
54935
|
+
|
|
54137
54936
|
// packages/contracts/dist/database-migration-policies.js
|
|
54138
54937
|
var PolicyReader = class {
|
|
54139
54938
|
tokens;
|
|
@@ -54287,6 +55086,9 @@ function admitExpandOnlyMigrations(migrations) {
|
|
|
54287
55086
|
throw new DatabaseMigrationAdmissionError("invalid");
|
|
54288
55087
|
}
|
|
54289
55088
|
const statements = parseDatabaseMigrationStatements(sql);
|
|
55089
|
+
if (statements.some((statement) => statement.captureTrigger !== void 0 && isDatabaseWatchTriggerName(statement.captureTrigger.trigger))) {
|
|
55090
|
+
throw new DatabaseMigrationAdmissionError("unsupported");
|
|
55091
|
+
}
|
|
54290
55092
|
statementCount += statements.length;
|
|
54291
55093
|
return Object.freeze({ path: migration.path, statementCount: statements.length });
|
|
54292
55094
|
});
|
|
@@ -54300,6 +55102,11 @@ function parseDatabaseMigrationStatements(sql) {
|
|
|
54300
55102
|
if (statements.length === 0)
|
|
54301
55103
|
throw new DatabaseMigrationAdmissionError("invalid");
|
|
54302
55104
|
return Object.freeze(statements.map((statement) => {
|
|
55105
|
+
const capture = readMigrationCaptureTrigger(statement.tokens);
|
|
55106
|
+
if (capture !== void 0) {
|
|
55107
|
+
rejectMigrationSqlReferences(capture.header);
|
|
55108
|
+
return Object.freeze({ sql: statement.sql, captureTrigger: capture.target });
|
|
55109
|
+
}
|
|
54303
55110
|
rejectMigrationSqlReferences(statement.tokens, true);
|
|
54304
55111
|
const rlsTarget = readMigrationRlsTarget(statement.tokens);
|
|
54305
55112
|
if (rlsTarget !== void 0)
|
|
@@ -56956,6 +57763,7 @@ export {
|
|
|
56956
57763
|
ACCOUNT_SENSITIVE_PROBLEMS,
|
|
56957
57764
|
classifyCliFailure,
|
|
56958
57765
|
GeneratedSdkManagedSourceApi,
|
|
57766
|
+
assertDatabaseTableAnswer,
|
|
56959
57767
|
GeneratedSdkProductApi,
|
|
56960
57768
|
RepositoryInitError,
|
|
56961
57769
|
RepositoryInitBlockedError,
|