@amerged/ohmyhost-cli 0.1.45 → 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.
@@ -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: oneOf2 } = parentSchema;
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 (!oneOf2)
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 < oneOf2.length; i++) {
26686
- let sch = oneOf2[i];
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 record7 = value;
38780
- const code = Object.hasOwn(record7, "code") ? record7["code"] : void 0;
38781
- const path2 = Object.hasOwn(record7, "path") ? record7["path"] : void 0;
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(record7, name) ? record7[name] : void 0]);
38786
- if (Object.keys(record7).length !== fields.length + 2 || pathClassOf(definition, path2) === null || fields.some(([, grammar, field]) => !fieldMatches(grammar, field)))
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],
@@ -40249,6 +40249,18 @@ var PROBLEM_POLICY = {
40249
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
40250
  title: "Table already has a capture trigger"
40251
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
+ },
40252
40264
  project_notes_conflict: {
40253
40265
  status: 409,
40254
40266
  retryable: false,
@@ -41384,8 +41396,8 @@ var isPaidValidationRecord = (value) => {
41384
41396
  if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).sort().join(",") !== "content,name,purpose,type") {
41385
41397
  return false;
41386
41398
  }
41387
- const record7 = value;
41388
- return (record7["type"] === "CNAME" || record7["type"] === "TXT") && boundedString(record7["name"], 1, 253) && boundedString(record7["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record7["purpose"]));
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"]));
41389
41401
  };
41390
41402
  var isHttpsUrlValue = (value) => typeof value === "string" && isHttpsUrl(value);
41391
41403
 
@@ -41530,7 +41542,7 @@ async function prepareLocalSourcePublication(input) {
41530
41542
  request = { ...request, expected_commit_sha: link2.source.last_confirmed_commit_sha };
41531
41543
  }
41532
41544
  parseManagedSourceRequest("upload", request);
41533
- const record7 = {
41545
+ const record8 = {
41534
41546
  version: 1,
41535
41547
  ...scope,
41536
41548
  operation_id: null,
@@ -41539,16 +41551,16 @@ async function prepareLocalSourcePublication(input) {
41539
41551
  request
41540
41552
  };
41541
41553
  if (original !== null) {
41542
- assertSameAttempt(original, record7);
41554
+ assertSameAttempt(original, record8);
41543
41555
  } else
41544
- await writePending(record7, true);
41556
+ await writePending(record8, true);
41545
41557
  return {
41546
41558
  request,
41547
41559
  accepted: async (operation) => {
41548
41560
  const current = await readPending(scope, replay);
41549
41561
  if (current === null)
41550
41562
  throw new LocalSourcePublicationError("source_publication_missing");
41551
- assertSameAttempt(current, record7);
41563
+ assertSameAttempt(current, record8);
41552
41564
  if (current.operation_id !== null && current.operation_id !== operation.id)
41553
41565
  throw new ResponseContractError();
41554
41566
  if (!replay)
@@ -41567,7 +41579,7 @@ async function prepareLocalSourcePublication(input) {
41567
41579
  const current = await readPending(scope);
41568
41580
  if (current === null || current.operation_id !== null)
41569
41581
  return;
41570
- assertSameAttempt(current, record7);
41582
+ assertSameAttempt(current, record8);
41571
41583
  } catch (error2) {
41572
41584
  if (error2 instanceof LocalSourcePublicationError && (error2.code === "source_publication_scope_mismatch" || error2.code === "source_publication_pending"))
41573
41585
  return;
@@ -41770,12 +41782,12 @@ async function readRecord(path2) {
41770
41782
  await handle?.close();
41771
41783
  }
41772
41784
  }
41773
- async function writePending(record7, create, completed = false) {
41774
- const parent = join3(record7.directory, ".ohmyhost");
41785
+ async function writePending(record8, create, completed = false) {
41786
+ const parent = join3(record8.directory, ".ohmyhost");
41775
41787
  for (const directory of [
41776
41788
  parent,
41777
- record7.metadata_directory,
41778
- join3(record7.metadata_directory, "publications")
41789
+ record8.metadata_directory,
41790
+ join3(record8.metadata_directory, "publications")
41779
41791
  ]) {
41780
41792
  try {
41781
41793
  await fs2.mkdir(directory, { mode: 448 });
@@ -41786,10 +41798,10 @@ async function writePending(record7, create, completed = false) {
41786
41798
  await checkedDirectory(directory);
41787
41799
  await fs2.chmod(directory, 448);
41788
41800
  }
41789
- const target = completed ? completedPath(record7) : pendingPath(record7);
41801
+ const target = completed ? completedPath(record8) : pendingPath(record8);
41790
41802
  const temporary = create ? target : `${target}.${randomUUID()}.tmp`;
41791
41803
  try {
41792
- await fs2.writeFile(temporary, `${JSON.stringify(record7)}
41804
+ await fs2.writeFile(temporary, `${JSON.stringify(record8)}
41793
41805
  `, { mode: 384, flag: "wx" });
41794
41806
  if (!create)
41795
41807
  await fs2.rename(temporary, target);
@@ -42849,6 +42861,170 @@ function exact2(value, keys) {
42849
42861
  return Object.keys(value).sort().join(",") === [...keys].sort().join(",");
42850
42862
  }
42851
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
+
42852
43028
  // packages/contracts/dist/database-sizes.js
42853
43029
  var DATABASE_SIZES = Object.freeze([
42854
43030
  Object.freeze({
@@ -43217,6 +43393,8 @@ var recognizedCommandLabel = (argv) => {
43217
43393
  if (values[1] === "delete")
43218
43394
  return "database watch delete";
43219
43395
  }
43396
+ if (value === "database" && values[0] === "table" && values[1] === "create")
43397
+ return "database table create";
43220
43398
  if (value === "database" && values[0] === "webhook") {
43221
43399
  if (values[1] === "create")
43222
43400
  return "database webhook create";
@@ -44133,6 +44311,38 @@ var parseProductCliCommand = (argv) => {
44133
44311
  }
44134
44312
  throw new InvalidCommandError();
44135
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
+ }
44136
44346
  if (first === "database" && values[0] === "webhook") {
44137
44347
  values.shift();
44138
44348
  const subcommand = values.shift();
@@ -45279,7 +45489,7 @@ import { join as join5, resolve as resolve4 } from "node:path";
45279
45489
 
45280
45490
  // packages/contracts/dist/database-access.js
45281
45491
  function parseProjectDatabaseWrite(value) {
45282
- if (!record3(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)
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)
45283
45493
  throw new TypeError("Invalid database write");
45284
45494
  const budget = { nodes: 0 };
45285
45495
  for (const parameter of value["parameters"])
@@ -45293,7 +45503,7 @@ function parseProjectDatabaseWrite(value) {
45293
45503
  };
45294
45504
  }
45295
45505
  function assertProjectDatabaseWriteReceipt(value) {
45296
- if (!record3(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"])))
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"])))
45297
45507
  throw new TypeError("Invalid database write receipt");
45298
45508
  if (value["state"] === "succeeded") {
45299
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)
@@ -45306,7 +45516,7 @@ function assertProjectDatabaseWriteReceipt(value) {
45306
45516
  throw new TypeError("Invalid database write result");
45307
45517
  } else {
45308
45518
  const error = value["error"];
45309
- if (!record3(error) || typeof error["code"] !== "string" || !error["code"].startsWith("database_write_") || JSON.stringify(error) !== JSON.stringify(publicOperationFailure(error["code"])))
45519
+ if (!record4(error) || typeof error["code"] !== "string" || !error["code"].startsWith("database_write_") || JSON.stringify(error) !== JSON.stringify(publicOperationFailure(error["code"])))
45310
45520
  throw new TypeError("Invalid database write error");
45311
45521
  }
45312
45522
  }
@@ -45330,12 +45540,12 @@ var ACCESS_KEYS = [
45330
45540
  ];
45331
45541
  var ACCESS_ROLE_PATTERN = /^ohmyho_da_[0-7][0-9a-hjkmnp-tv-z]{25}_[0-9a-z]{8}$/u;
45332
45542
  function assertProjectDatabaseAccess(value) {
45333
- if (!record3(value) || !exact3(value, ACCESS_KEYS))
45543
+ if (!record4(value) || !exact3(value, ACCESS_KEYS))
45334
45544
  throw new TypeError("Invalid database access");
45335
45545
  assertAccessFields(value);
45336
45546
  }
45337
45547
  function assertProjectDatabaseAccessCredential(value) {
45338
- if (!record3(value) || !exact3(value, [...ACCESS_KEYS, "connection_uri", "psql_command"]))
45548
+ if (!record4(value) || !exact3(value, [...ACCESS_KEYS, "connection_uri", "psql_command"]))
45339
45549
  throw new TypeError("Invalid database access credential");
45340
45550
  assertAccessFields(value);
45341
45551
  const uri = value["connection_uri"];
@@ -45351,7 +45561,7 @@ function assertProjectDatabaseAccessCredential(value) {
45351
45561
  throw new TypeError("Invalid database access credential");
45352
45562
  }
45353
45563
  function assertProjectDatabaseAccessPage(value) {
45354
- if (!record3(value) || !exact3(value, ["items"]) || !Array.isArray(value["items"]) || value["items"].length > 50)
45564
+ if (!record4(value) || !exact3(value, ["items"]) || !Array.isArray(value["items"]) || value["items"].length > 50)
45355
45565
  throw new TypeError("Invalid database access page");
45356
45566
  for (const item of value["items"])
45357
45567
  assertProjectDatabaseAccess(item);
@@ -45386,14 +45596,14 @@ function json(value, depth, budget) {
45386
45596
  json(entry, depth + 1, budget);
45387
45597
  return;
45388
45598
  }
45389
- if (record3(value)) {
45599
+ if (record4(value)) {
45390
45600
  for (const entry of Object.values(value))
45391
45601
  json(entry, depth + 1, budget);
45392
45602
  return;
45393
45603
  }
45394
45604
  throw new TypeError("Invalid database parameter");
45395
45605
  }
45396
- function record3(value) {
45606
+ function record4(value) {
45397
45607
  return typeof value === "object" && value !== null && !Array.isArray(value);
45398
45608
  }
45399
45609
  function exact3(value, keys) {
@@ -45402,7 +45612,7 @@ function exact3(value, keys) {
45402
45612
 
45403
45613
  // packages/contracts/dist/credit-pricing.js
45404
45614
  function assertOrganizationCreditUsage(value) {
45405
- const record7 = (input, keys) => {
45615
+ const record8 = (input, keys) => {
45406
45616
  if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join() !== keys.split(",").sort().join())
45407
45617
  throw new TypeError("Invalid usage fields");
45408
45618
  return input;
@@ -45410,30 +45620,30 @@ function assertOrganizationCreditUsage(value) {
45410
45620
  const identifier2 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
45411
45621
  const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
45412
45622
  const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
45413
- const report = record7(value, "organization_id,as_of,unit,period,from,projects,days");
45623
+ const report = record8(value, "organization_id,as_of,unit,period,from,projects,days");
45414
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)
45415
45625
  throw new TypeError("Invalid usage report");
45416
45626
  let previous = "";
45417
45627
  for (const input of report["projects"]) {
45418
- const project = record7(input, "project_id,used_micros");
45628
+ const project = record8(input, "project_id,used_micros");
45419
45629
  if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
45420
45630
  throw new TypeError("Invalid usage project");
45421
45631
  previous = String(project["project_id"]);
45422
45632
  }
45423
45633
  let previousDay = "";
45424
45634
  for (const input of report["days"]) {
45425
- const day = record7(input, "day,projects");
45635
+ const day = record8(input, "day,projects");
45426
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)
45427
45637
  throw new TypeError("Invalid usage day");
45428
45638
  previousDay = day["day"];
45429
45639
  previous = "";
45430
45640
  for (const projectInput of day["projects"]) {
45431
- const project = record7(projectInput, "project_id,meters");
45641
+ const project = record8(projectInput, "project_id,meters");
45432
45642
  if (!identifier2(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
45433
45643
  throw new TypeError("Invalid usage project");
45434
45644
  previous = String(project["project_id"]);
45435
45645
  for (const meterInput of project["meters"]) {
45436
- const meter = record7(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
45646
+ const meter = record8(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
45437
45647
  if (meter["environment_id"] !== null && !identifier2(meter["environment_id"]))
45438
45648
  throw new TypeError("Invalid usage environment");
45439
45649
  for (const key of ["meter", "unit", "rate_card_id"])
@@ -45468,16 +45678,16 @@ function assertOrganizationAccount(value) {
45468
45678
 
45469
45679
  // packages/contracts/dist/database-compute.js
45470
45680
  function assertDatabaseCompute(value) {
45471
- if (!record4(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"])
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"])
45472
45682
  throw new TypeError("Invalid database compute report");
45473
45683
  const db = value["database"];
45474
45684
  if (db === null)
45475
45685
  return;
45476
- if (record4(db) && db["provider"] === "pgcf") {
45686
+ if (record5(db) && db["provider"] === "pgcf") {
45477
45687
  assertPgcfCompute(db);
45478
45688
  return;
45479
45689
  }
45480
- if (!record4(db) || !exact4(db, [
45690
+ if (!record5(db) || !exact4(db, [
45481
45691
  "disabled",
45482
45692
  "max_cu",
45483
45693
  "max_memory_gb",
@@ -45508,7 +45718,7 @@ function assertPgcfCompute(db) {
45508
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"])))
45509
45719
  throw new TypeError("Invalid fixed database compute configuration");
45510
45720
  }
45511
- function record4(v) {
45721
+ function record5(v) {
45512
45722
  return typeof v === "object" && v !== null && !Array.isArray(v);
45513
45723
  }
45514
45724
  function exact4(v, keys) {
@@ -45518,7 +45728,7 @@ function exact4(v, keys) {
45518
45728
  // apps/product-cli/package.json
45519
45729
  var package_default = {
45520
45730
  name: "@ohmyhost/product-cli",
45521
- version: "0.1.45",
45731
+ version: "0.1.46",
45522
45732
  private: true,
45523
45733
  ohmyhost: {
45524
45734
  deployment: "production",
@@ -45565,32 +45775,32 @@ var package_default = {
45565
45775
  };
45566
45776
 
45567
45777
  // packages/contracts/dist/project-context.js
45568
- var record5 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
45778
+ var record6 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
45569
45779
  var timestamp4 = (v) => typeof v === "string" && Number.isFinite(Date.parse(v)) && new Date(v).toISOString() === v;
45570
45780
  var version = (v) => Number.isInteger(v) && Number(v) >= 0 && Number(v) <= 2147483647;
45571
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;
45572
45782
  function assertProjectNotesReceipt(v) {
45573
- if (!record5(v) || Object.keys(v).sort().join(",") !== "updated_at,version" || !version(v["version"]) || v["version"] === 0 || !timestamp4(v["updated_at"]))
45783
+ if (!record6(v) || Object.keys(v).sort().join(",") !== "updated_at,version" || !version(v["version"]) || v["version"] === 0 || !timestamp4(v["updated_at"]))
45574
45784
  throw new TypeError("Invalid project notes receipt");
45575
45785
  }
45576
45786
  function assertProjectContext(v) {
45577
- if (!record5(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))
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))
45578
45788
  throw new TypeError("Invalid project context");
45579
45789
  const notes = v["notes"];
45580
- if (!record5(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"])))
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"])))
45581
45791
  throw new TypeError("Invalid project notes");
45582
45792
  }
45583
45793
 
45584
45794
  // packages/contracts/dist/project-exports.js
45585
45795
  function assertProjectExport(value) {
45586
- if (!record6(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"]))
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"]))
45587
45797
  invalid4();
45588
45798
  const active = value["state"] === "queued" || value["state"] === "running";
45589
45799
  if (value["next_poll_after_seconds"] !== (active ? 5 : null))
45590
45800
  invalid4();
45591
45801
  if (value["state"] === "failed") {
45592
45802
  const error = value["error"];
45593
- if (!record6(error) || Object.keys(error).sort().join(",") !== "code,message,retryable,suggested_action" || typeof error["code"] !== "string")
45803
+ if (!record7(error) || Object.keys(error).sort().join(",") !== "code,message,retryable,suggested_action" || typeof error["code"] !== "string")
45594
45804
  invalid4();
45595
45805
  const expected = publicOperationFailure(error["code"]);
45596
45806
  for (const key of Object.keys(expected))
@@ -45604,7 +45814,7 @@ function assertProjectExport(value) {
45604
45814
  invalid4();
45605
45815
  return;
45606
45816
  }
45607
- if (value["state"] !== "succeeded" || !record6(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"]))
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"]))
45608
45818
  invalid4();
45609
45819
  if (archive["download_url"] === null) {
45610
45820
  if (archive["download_expires_at"] !== null)
@@ -45623,7 +45833,7 @@ function assertProjectExport(value) {
45623
45833
  invalid4();
45624
45834
  }
45625
45835
  var id = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
45626
- function record6(value) {
45836
+ function record7(value) {
45627
45837
  return typeof value === "object" && value !== null && !Array.isArray(value);
45628
45838
  }
45629
45839
  function timestamp5(value) {
@@ -45866,6 +46076,7 @@ var HELP_USAGE = Object.freeze({
45866
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>')",
45867
46077
  "database watch list": "ohmyhost database watch list --project ULID [--environment dev|prod] --json (dev when omitted; a sleeping database wakes)",
45868
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)",
45869
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)",
45870
46081
  "database webhook list": "ohmyhost database webhook list --project ULID [--environment dev|prod] --json (dev when omitted; the secret is never listed)",
45871
46082
  "database webhook get": "ohmyhost database webhook get --project ULID [--environment dev|prod] --webhook ID --json",
@@ -45991,6 +46202,7 @@ var LOGOUT_UNCONFIRMED_ACTION = "The saved login was removed from this computer,
45991
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.";
45992
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.";
45993
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.";
45994
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.";
45995
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`;
45996
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.`;
@@ -46363,6 +46575,8 @@ var ProductCli = class {
46363
46575
  return await this.listDatabaseWatches(command, signal);
46364
46576
  if (command.kind === "database-watch-delete")
46365
46577
  return await this.deleteDatabaseWatch(command, signal);
46578
+ if (command.kind === "database-table-create")
46579
+ return await this.createDatabaseTable(command, signal);
46366
46580
  if (command.kind === "database-webhook-create")
46367
46581
  return await this.createDatabaseWebhook(command, signal);
46368
46582
  if (command.kind === "database-webhook-list")
@@ -46927,6 +47141,18 @@ var ProductCli = class {
46927
47141
  });
46928
47142
  return success("database watch delete", { status: "succeeded", deleted });
46929
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
+ }
46930
47156
  /** The signing secret is returned by create only; every other answer carries no secret. */
46931
47157
  async createDatabaseWebhook(command, signal) {
46932
47158
  const request = await webhookCreateRequest(command);
@@ -47818,6 +48044,37 @@ var scheduleSetRequest = async (command) => {
47818
48044
  throw new ProductCliFailure(2, "schedule_invalid", false, SCHEDULE_INVALID_ACTION);
47819
48045
  }
47820
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
+ });
47821
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.");
47822
48079
  var success = (command, body) => ({
47823
48080
  exitCode: 0,
@@ -47963,6 +48220,8 @@ var parsedCommandName = (command) => {
47963
48220
  return "database watch list";
47964
48221
  if (command.kind === "database-watch-delete")
47965
48222
  return "database watch delete";
48223
+ if (command.kind === "database-table-create")
48224
+ return "database table create";
47966
48225
  if (command.kind === "database-webhook-create")
47967
48226
  return "database webhook create";
47968
48227
  if (command.kind === "database-webhook-list")
@@ -48185,12 +48444,12 @@ function buildClientParams(args, fields) {
48185
48444
  };
48186
48445
  const map = buildKeyMap(fields);
48187
48446
  function writeSlot(slot, key, value) {
48188
- let record7 = params[slot];
48189
- if (record7 === void 0) {
48190
- record7 = /* @__PURE__ */ Object.create(null);
48191
- params[slot] = record7;
48447
+ let record8 = params[slot];
48448
+ if (record8 === void 0) {
48449
+ record8 = /* @__PURE__ */ Object.create(null);
48450
+ params[slot] = record8;
48192
48451
  }
48193
- record7[key] = value;
48452
+ record8[key] = value;
48194
48453
  }
48195
48454
  let config;
48196
48455
  for (const [index, arg] of args.entries()) {
@@ -50835,6 +51094,30 @@ var revokeProjectDatabaseAccess = (parameters, options) => {
50835
51094
  ...params
50836
51095
  });
50837
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
+ };
50838
51121
  var listProjectDatabaseWatches = (parameters, options) => {
50839
51122
  const params = buildClientParams([parameters], [
50840
51123
  {
@@ -52271,7 +52554,24 @@ function checkedResponse(kind, value) {
52271
52554
  // apps/product-cli/dist/product-api.js
52272
52555
  var WEBHOOK_SCOPE_MISMATCH = "Webhook response scope mismatch";
52273
52556
  var WATCH_SCOPE_MISMATCH = "Watch response scope mismatch";
52557
+ var TABLE_SCOPE_MISMATCH = "Table response scope mismatch";
52274
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
+ }
52275
52575
  var GeneratedSdkProductApi = class {
52276
52576
  #client;
52277
52577
  managedSource;
@@ -52504,6 +52804,22 @@ var GeneratedSdkProductApi = class {
52504
52804
  throw new TypeError(WATCH_SCOPE_MISMATCH);
52505
52805
  return value;
52506
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
+ }
52507
52823
  /** The signing secret exists only in this answer; the CLI prints it once and stores nothing. */
52508
52824
  async createProjectDatabaseWebhook(input) {
52509
52825
  const value = await createProjectDatabaseWebhook({
@@ -54110,8 +54426,8 @@ function pnpmLockedVersion(document2, packageName) {
54110
54426
  }
54111
54427
  return null;
54112
54428
  }
54113
- function ownValue(record7, key) {
54114
- return isRecord4(record7) && Object.hasOwn(record7, key) ? record7[key] : void 0;
54429
+ function ownValue(record8, key) {
54430
+ return isRecord4(record8) && Object.hasOwn(record8, key) ? record8[key] : void 0;
54115
54431
  }
54116
54432
  function isRecord4(value) {
54117
54433
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -57447,6 +57763,7 @@ export {
57447
57763
  ACCOUNT_SENSITIVE_PROBLEMS,
57448
57764
  classifyCliFailure,
57449
57765
  GeneratedSdkManagedSourceApi,
57766
+ assertDatabaseTableAnswer,
57450
57767
  GeneratedSdkProductApi,
57451
57768
  RepositoryInitError,
57452
57769
  RepositoryInitBlockedError,