@playcademy/sandbox 0.6.1-beta.6 → 0.6.1-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -311,7 +311,7 @@ var init_timeback2 = __esm(() => {
311
311
  });
312
312
 
313
313
  // ../constants/src/cloudflare.ts
314
- var WORKER_NAMING, MAX_WORKER_NAME_LENGTH = 63, SECRETS_PREFIX = "secrets_", CLOUDFLARE_COMPATIBILITY_DATE = "2025-10-11";
314
+ var WORKER_NAMING, MAX_WORKER_NAME_LENGTH = 63, SECRETS_PREFIX = "secrets_", CLOUDFLARE_COMPATIBILITY_DATE = "2025-10-11", D1_TIME_TRAVEL_RETENTION_DAYS = 30;
315
315
  var init_cloudflare = __esm(() => {
316
316
  WORKER_NAMING = {
317
317
  STAGING_PREFIX: "staging-",
@@ -1084,7 +1084,7 @@ var package_default;
1084
1084
  var init_package = __esm(() => {
1085
1085
  package_default = {
1086
1086
  name: "@playcademy/sandbox",
1087
- version: "0.6.1-beta.6",
1087
+ version: "0.6.1-beta.8",
1088
1088
  description: "Local development server for Playcademy game development",
1089
1089
  type: "module",
1090
1090
  exports: {
@@ -1153,6 +1153,16 @@ var init_package = __esm(() => {
1153
1153
  });
1154
1154
 
1155
1155
  // ../api-core/src/errors/domain.error.ts
1156
+ function deployErrorCode(error) {
1157
+ if (!(error instanceof DomainError)) {
1158
+ return null;
1159
+ }
1160
+ const details = error.details;
1161
+ if (typeof details !== "object" || details === null || !("code" in details)) {
1162
+ return null;
1163
+ }
1164
+ return typeof details.code === "string" ? details.code : null;
1165
+ }
1156
1166
  var DomainError, BadRequestError, UnauthorizedError, AccessDeniedError, NotFoundError, ConflictError, AlreadyExistsError, ValidationError, RateLimitError, InternalError, ServiceUnavailableError, TimeoutError;
1157
1167
  var init_domain_error = __esm(() => {
1158
1168
  DomainError = class DomainError extends Error {
@@ -1235,6 +1245,158 @@ var init_domain_error = __esm(() => {
1235
1245
  };
1236
1246
  });
1237
1247
 
1248
+ // ../types/src/game.ts
1249
+ var DEPLOY_ERROR_CODES, REFUSAL_CODES, DEPLOY_REFUSAL_CODES, DELETED_ACCOUNT_LABEL = "(deleted account)";
1250
+ var init_game2 = __esm(() => {
1251
+ DEPLOY_ERROR_CODES = {
1252
+ deployIdPayloadMismatch: "deploy-id-payload-mismatch",
1253
+ stateConflict: "deployment-state-conflict",
1254
+ stateDrift: "deployment-state-drift",
1255
+ destructiveSchema: "destructive-schema-changes",
1256
+ upgradeRequired: "deploy-upgrade-required",
1257
+ checksumMismatch: "migration-checksum-mismatch",
1258
+ journalDivergence: "migration-journal-divergence",
1259
+ outOfOrder: "migration-out-of-order",
1260
+ migrationFailed: "migration-failed",
1261
+ strategyMismatch: "strategy-mismatch",
1262
+ pushFailed: "push-failed",
1263
+ pruneUnmanagedSecrets: "secrets-prune-unmanaged",
1264
+ baselineLedgerNotEmpty: "baseline-ledger-not-empty",
1265
+ baselineDatabaseEmpty: "baseline-database-empty",
1266
+ baselineAlreadyAdopted: "baseline-already-adopted",
1267
+ baselineClaimRejected: "baseline-claim-rejected",
1268
+ restoreUnsupported: "restore-unsupported",
1269
+ restoreIncomplete: "restore-incomplete",
1270
+ restoreBlockedByDeploy: "restore-blocked-by-deploy",
1271
+ restoreExpired: "restore-expired"
1272
+ };
1273
+ REFUSAL_CODES = [
1274
+ DEPLOY_ERROR_CODES.deployIdPayloadMismatch,
1275
+ DEPLOY_ERROR_CODES.stateConflict,
1276
+ DEPLOY_ERROR_CODES.stateDrift,
1277
+ DEPLOY_ERROR_CODES.destructiveSchema,
1278
+ DEPLOY_ERROR_CODES.upgradeRequired,
1279
+ DEPLOY_ERROR_CODES.checksumMismatch,
1280
+ DEPLOY_ERROR_CODES.journalDivergence,
1281
+ DEPLOY_ERROR_CODES.outOfOrder,
1282
+ DEPLOY_ERROR_CODES.strategyMismatch,
1283
+ DEPLOY_ERROR_CODES.pruneUnmanagedSecrets,
1284
+ DEPLOY_ERROR_CODES.baselineLedgerNotEmpty,
1285
+ DEPLOY_ERROR_CODES.baselineDatabaseEmpty,
1286
+ DEPLOY_ERROR_CODES.baselineAlreadyAdopted,
1287
+ DEPLOY_ERROR_CODES.baselineClaimRejected
1288
+ ];
1289
+ DEPLOY_REFUSAL_CODES = new Set(REFUSAL_CODES);
1290
+ });
1291
+
1292
+ // ../api-core/src/errors/deploy.error.ts
1293
+ var DeployIdConflictError, DeploymentStateConflictError, DeploymentStateDriftError, LegacySchemaUpgradeRequiredError, DestructiveSchemaError, MigrationChecksumMismatchError, MigrationJournalDivergenceError, MigrationOrderError, SecretsPruneUnmanagedError, BaselineLedgerNotEmptyError, BaselineDatabaseEmptyError, BaselineAlreadyAdoptedError, BaselineClaimRejectedError, MigrationExecutionError, PushExecutionError;
1294
+ var init_deploy_error = __esm(() => {
1295
+ init_game2();
1296
+ init_domain_error();
1297
+ DeployIdConflictError = class DeployIdConflictError extends ConflictError {
1298
+ constructor(deployId, existingJobId) {
1299
+ super(`Deploy '${deployId}' was already created with a different payload — ` + "generate a fresh deployId for a new deploy", { code: DEPLOY_ERROR_CODES.deployIdPayloadMismatch, deployId, existingJobId });
1300
+ this.name = "DeployIdConflictError";
1301
+ }
1302
+ };
1303
+ DeploymentStateConflictError = class DeploymentStateConflictError extends ConflictError {
1304
+ constructor(payload) {
1305
+ super("Deployment state conflict: the schema baseline changed since this deploy was " + "prepared — refetch the deployment state, re-diff, and retry", { code: DEPLOY_ERROR_CODES.stateConflict, ...payload });
1306
+ this.name = "DeploymentStateConflictError";
1307
+ }
1308
+ };
1309
+ DeploymentStateDriftError = class DeploymentStateDriftError extends ConflictError {
1310
+ constructor(payload) {
1311
+ super("Deployment state drift: the live database schema does not match the recorded " + "fingerprint (out-of-band change or partial prior apply) — repair the " + "database state before deploying", { code: DEPLOY_ERROR_CODES.stateDrift, ...payload });
1312
+ this.name = "DeploymentStateDriftError";
1313
+ }
1314
+ };
1315
+ LegacySchemaUpgradeRequiredError = class LegacySchemaUpgradeRequiredError extends ValidationError {
1316
+ constructor() {
1317
+ super("This game's database state is server-managed; the legacy schema payload is no " + "longer accepted — update the Playcademy CLI and redeploy", { code: DEPLOY_ERROR_CODES.upgradeRequired });
1318
+ this.name = "LegacySchemaUpgradeRequiredError";
1319
+ }
1320
+ };
1321
+ DestructiveSchemaError = class DestructiveSchemaError extends ValidationError {
1322
+ constructor(statements) {
1323
+ super(`Push contains ${statements.length} destructive statement(s) that can drop data — ` + "review them and re-run with --accept-data-loss to proceed", { code: DEPLOY_ERROR_CODES.destructiveSchema, statements });
1324
+ this.name = "DestructiveSchemaError";
1325
+ }
1326
+ };
1327
+ MigrationChecksumMismatchError = class MigrationChecksumMismatchError extends ConflictError {
1328
+ constructor(mismatches) {
1329
+ const tags = mismatches.map((mismatch) => mismatch.tag).join(", ");
1330
+ super(`Applied migration(s) ${tags} no longer match their recorded checksums.`, {
1331
+ code: DEPLOY_ERROR_CODES.checksumMismatch,
1332
+ mismatches
1333
+ });
1334
+ this.name = "MigrationChecksumMismatchError";
1335
+ }
1336
+ };
1337
+ MigrationJournalDivergenceError = class MigrationJournalDivergenceError extends ConflictError {
1338
+ constructor(tags) {
1339
+ super(`The database ledger records applied migration(s) missing from the deploy's ` + `journal: ${tags.join(", ")}. Restore the missing migration files (or resolve ` + "the ledger) before deploying", { code: DEPLOY_ERROR_CODES.journalDivergence, tags });
1340
+ this.name = "MigrationJournalDivergenceError";
1341
+ }
1342
+ };
1343
+ MigrationOrderError = class MigrationOrderError extends ValidationError {
1344
+ constructor(tags) {
1345
+ super(`Out-of-order migration(s): ${tags.join(", ")} are ordered before migrations that ` + "already applied. This usually means a branch merged with older-numbered " + "migrations — regenerate them after the applied ones and redeploy", { code: DEPLOY_ERROR_CODES.outOfOrder, tags });
1346
+ this.name = "MigrationOrderError";
1347
+ }
1348
+ };
1349
+ SecretsPruneUnmanagedError = class SecretsPruneUnmanagedError extends ValidationError {
1350
+ constructor(keys) {
1351
+ super(`Cannot prune secret(s) not managed by the platform: ${keys.join(", ")}. ` + "Only keys the platform previously pushed can be pruned", { code: DEPLOY_ERROR_CODES.pruneUnmanagedSecrets, keys });
1352
+ this.name = "SecretsPruneUnmanagedError";
1353
+ }
1354
+ };
1355
+ BaselineLedgerNotEmptyError = class BaselineLedgerNotEmptyError extends ConflictError {
1356
+ constructor(tags) {
1357
+ super(`Cannot baseline: the migration ledger already records ${tags.length} applied ` + "migration(s) — this database is already server-managed. Just deploy", { code: DEPLOY_ERROR_CODES.baselineLedgerNotEmpty, tags });
1358
+ this.name = "BaselineLedgerNotEmptyError";
1359
+ }
1360
+ };
1361
+ BaselineDatabaseEmptyError = class BaselineDatabaseEmptyError extends ValidationError {
1362
+ constructor() {
1363
+ super("Cannot baseline an empty database — there is no applied history to claim. " + "An empty database needs no baseline: deploy directly and the full " + "journal (or schema) applies fresh.", { code: DEPLOY_ERROR_CODES.baselineDatabaseEmpty });
1364
+ this.name = "BaselineDatabaseEmptyError";
1365
+ }
1366
+ };
1367
+ BaselineAlreadyAdoptedError = class BaselineAlreadyAdoptedError extends ConflictError {
1368
+ constructor(baselineSource) {
1369
+ super("Cannot baseline: deployment state already records a schema baseline" + `${baselineSource ? ` (source: ${baselineSource})` : ""} — ` + "use realign/resolve to repair drift instead", { code: DEPLOY_ERROR_CODES.baselineAlreadyAdopted, baselineSource });
1370
+ this.name = "BaselineAlreadyAdoptedError";
1371
+ }
1372
+ };
1373
+ BaselineClaimRejectedError = class BaselineClaimRejectedError extends ConflictError {
1374
+ constructor(details) {
1375
+ const [first] = details.contradictions;
1376
+ super(first ? `Cannot baseline: the claim contradicts the live database — ${first.tag} ${first.detail ?? ""}` : "Cannot baseline: the claim includes migrations that cannot be verified against the live database — " + "pass --allow-unverified to record them anyway", { code: DEPLOY_ERROR_CODES.baselineClaimRejected, ...details });
1377
+ this.name = "BaselineClaimRejectedError";
1378
+ }
1379
+ };
1380
+ MigrationExecutionError = class MigrationExecutionError extends ValidationError {
1381
+ tag;
1382
+ offset;
1383
+ constructor(input) {
1384
+ super(`Migration '${input.tag}' failed and rolled back: ${input.d1Message}. ` + "Fix the migration SQL and redeploy — the deploy resumes from this migration", { code: DEPLOY_ERROR_CODES.migrationFailed, ...input });
1385
+ this.name = "MigrationExecutionError";
1386
+ this.tag = input.tag;
1387
+ this.offset = input.offset;
1388
+ }
1389
+ };
1390
+ PushExecutionError = class PushExecutionError extends ValidationError {
1391
+ offset;
1392
+ constructor(input) {
1393
+ super(`Push schema changes failed and rolled back: ${input.d1Message}. ` + "Fix the schema and redeploy — nothing was applied", { code: DEPLOY_ERROR_CODES.pushFailed, ...input });
1394
+ this.name = "PushExecutionError";
1395
+ this.offset = input.offset;
1396
+ }
1397
+ };
1398
+ });
1399
+
1238
1400
  // ../api-core/src/errors/api.error.ts
1239
1401
  var STATUS_MAP, ApiError;
1240
1402
  var init_api_error = __esm(() => {
@@ -1334,6 +1496,7 @@ var init_api_error = __esm(() => {
1334
1496
  // ../api-core/src/errors/index.ts
1335
1497
  var init_errors = __esm(() => {
1336
1498
  init_domain_error();
1499
+ init_deploy_error();
1337
1500
  init_api_error();
1338
1501
  });
1339
1502
 
@@ -5688,7 +5851,8 @@ var init_schema = __esm(() => {
5688
5851
  ltiTestMode: exports_external.boolean().default(false),
5689
5852
  platformServiceJwt: platformServiceJwtConfigSchema.optional(),
5690
5853
  uploadBucket: exports_external.string().optional(),
5691
- queueIngressSecret: exports_external.string().optional()
5854
+ queueIngressSecret: exports_external.string().optional(),
5855
+ secretsManifestPepper: exports_external.string().optional()
5692
5856
  }).superRefine((config2, ctx) => {
5693
5857
  if (config2.isLocal && !config2.baseUrl) {
5694
5858
  ctx.addIssue({
@@ -11217,7 +11381,7 @@ var init_table4 = __esm(() => {
11217
11381
  });
11218
11382
 
11219
11383
  // ../data/src/domains/game/table.ts
11220
- var gamePlatformEnum, gameTypeEnum, gameVisibilityEnum, games, gameMemberRoleEnum, gameMembers, gameMembersRelations, gameDashboardUserRoleEnum, gameDashboardUsers, gameDashboardUsersRelations, deploymentProviderEnum, deploymentTargetEnum, deployJobStatusEnum, gameDeployments, gameDeployJobs, customHostnameStatusEnum, customHostnameSslStatusEnum, customHostnameEnvironmentEnum, gameCustomHostnames;
11384
+ var gamePlatformEnum, gameTypeEnum, gameVisibilityEnum, games, gameMemberRoleEnum, gameMembers, gameMembersRelations, gameDashboardUserRoleEnum, gameDashboardUsers, gameDashboardUsersRelations, deploymentProviderEnum, deploymentTargetEnum, deployJobStatusEnum, gameDeployments, gameDeployJobs, gameDeployEvents, gameDeploymentState, customHostnameStatusEnum, customHostnameSslStatusEnum, customHostnameEnvironmentEnum, gameCustomHostnames;
11221
11385
  var init_table5 = __esm(() => {
11222
11386
  init_drizzle_orm();
11223
11387
  init_pg_core();
@@ -11306,15 +11470,20 @@ var init_table5 = __esm(() => {
11306
11470
  target: deploymentTargetEnum("target").notNull().default("game"),
11307
11471
  url: text("url").notNull(),
11308
11472
  codeHash: text("code_hash"),
11473
+ schemaHash: text("schema_hash"),
11474
+ schemaFingerprint: text("schema_fingerprint"),
11475
+ timeTravelBookmark: text("time_travel_bookmark"),
11476
+ bookmarkCapturedAt: timestamp("bookmark_captured_at", { withTimezone: true }),
11309
11477
  isActive: boolean("is_active").notNull().default(false),
11310
11478
  resources: jsonb("resources").$type(),
11311
11479
  deployedAt: timestamp("deployed_at", { withTimezone: true }).notNull().defaultNow()
11312
- });
11480
+ }, (table3) => [index("game_deployments_game_target_idx").on(table3.gameId, table3.target)]);
11313
11481
  gameDeployJobs = pgTable("game_deploy_jobs", {
11314
11482
  id: uuid("id").primaryKey().defaultRandom(),
11315
11483
  gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
11316
- userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
11484
+ userId: text("user_id").references(() => users.id, { onDelete: "set null" }),
11317
11485
  status: deployJobStatusEnum("status").notNull().default("pending"),
11486
+ deployId: text("deploy_id"),
11318
11487
  request: jsonb("request").$type().notNull(),
11319
11488
  events: jsonb("events").$type().notNull().default([]),
11320
11489
  error: text("error"),
@@ -11328,6 +11497,27 @@ var init_table5 = __esm(() => {
11328
11497
  createdAt: timestamp("created_at", { mode: "date", withTimezone: true }).notNull().defaultNow(),
11329
11498
  startedAt: timestamp("started_at", { mode: "date", withTimezone: true }),
11330
11499
  completedAt: timestamp("completed_at", { mode: "date", withTimezone: true })
11500
+ }, (table3) => [uniqueIndex("game_deploy_jobs_game_deploy_id_idx").on(table3.gameId, table3.deployId)]);
11501
+ gameDeployEvents = pgTable("game_deploy_events", {
11502
+ id: uuid("id").primaryKey().defaultRandom(),
11503
+ gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
11504
+ userId: text("user_id").references(() => users.id, { onDelete: "set null" }),
11505
+ kind: text("kind").$type().notNull(),
11506
+ payload: jsonb("payload").$type().notNull(),
11507
+ createdAt: timestamp("created_at", { mode: "date", withTimezone: true }).notNull().defaultNow()
11508
+ }, (table3) => [index("game_deploy_events_game_idx").on(table3.gameId, table3.createdAt)]);
11509
+ gameDeploymentState = pgTable("game_deployment_state", {
11510
+ id: uuid("id").primaryKey().defaultRandom(),
11511
+ gameId: uuid("game_id").notNull().unique().references(() => games.id, { onDelete: "cascade" }),
11512
+ schemaHash: text("schema_hash"),
11513
+ schemaSnapshot: jsonb("schema_snapshot"),
11514
+ schemaFingerprint: text("schema_fingerprint"),
11515
+ secretsManifest: jsonb("secrets_manifest").$type(),
11516
+ integrationsHash: text("integrations_hash"),
11517
+ buildHash: text("build_hash"),
11518
+ compatibilityDate: text("compatibility_date"),
11519
+ baselineSource: text("baseline_source").$type(),
11520
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
11331
11521
  });
11332
11522
  customHostnameStatusEnum = pgEnum("custom_hostname_status", [
11333
11523
  "pending",
@@ -11490,7 +11680,9 @@ __export(exports_tables_index, {
11490
11680
  gameMembers: () => gameMembers,
11491
11681
  gameMemberRoleEnum: () => gameMemberRoleEnum,
11492
11682
  gameDeployments: () => gameDeployments,
11683
+ gameDeploymentState: () => gameDeploymentState,
11493
11684
  gameDeployJobs: () => gameDeployJobs,
11685
+ gameDeployEvents: () => gameDeployEvents,
11494
11686
  gameDashboardUsersRelations: () => gameDashboardUsersRelations,
11495
11687
  gameDashboardUsers: () => gameDashboardUsers,
11496
11688
  gameDashboardUserRoleEnum: () => gameDashboardUserRoleEnum,
@@ -22505,7 +22697,112 @@ var init_zip = __esm(() => {
22505
22697
  import_jszip = __toESM(require_lib3(), 1);
22506
22698
  });
22507
22699
 
22700
+ // ../utils/src/stages.ts
22701
+ function isPreviewStage(stage) {
22702
+ return PREVIEW_STAGE_PATTERN.test(stage);
22703
+ }
22704
+ var PREVIEW_STAGE_PATTERN;
22705
+ var init_stages = __esm(() => {
22706
+ PREVIEW_STAGE_PATTERN = /^pr-\d+$/;
22707
+ });
22708
+
22709
+ // ../api-core/src/utils/deployment.util.ts
22710
+ function deployJobInstant() {
22711
+ return sql`COALESCE(${gameDeployJobs.completedAt}, ${gameDeployJobs.createdAt})`;
22712
+ }
22713
+ async function findLastSuccessfulDeploy(db2, gameId) {
22714
+ const job = await db2.query.gameDeployJobs.findFirst({
22715
+ where: and(eq(gameDeployJobs.gameId, gameId), eq(gameDeployJobs.status, "succeeded")),
22716
+ orderBy: desc(deployJobInstant()),
22717
+ columns: { userId: true, createdAt: true, completedAt: true }
22718
+ });
22719
+ if (!job) {
22720
+ return null;
22721
+ }
22722
+ return { userId: job.userId, at: job.completedAt ?? job.createdAt };
22723
+ }
22724
+ async function findLastSuccessfulDeployWithEmail(db2, gameId) {
22725
+ const lastDeploy = await findLastSuccessfulDeploy(db2, gameId);
22726
+ if (!lastDeploy) {
22727
+ return null;
22728
+ }
22729
+ const deployer = lastDeploy.userId ? await db2.query.users.findFirst({
22730
+ where: eq(users.id, lastDeploy.userId),
22731
+ columns: { email: true }
22732
+ }) : null;
22733
+ return { ...lastDeploy, email: deployer?.email ?? null };
22734
+ }
22735
+ function getGameDeploymentId(gameSlug, sstStage) {
22736
+ if (sstStage === "production") {
22737
+ return gameSlug;
22738
+ }
22739
+ if (sstStage === "dev" || isPreviewStage(sstStage)) {
22740
+ return `${WORKER_NAMING.STAGING_PREFIX}${gameSlug}`;
22741
+ }
22742
+ return `${WORKER_NAMING.LOCAL_PREFIX}${sstStage}-${gameSlug}`;
22743
+ }
22744
+ function getDashboardDeploymentId(gameSlug, sstStage) {
22745
+ return `${getGameDeploymentId(gameSlug, sstStage)}${DASHBOARD_WORKER_SUFFIX}`;
22746
+ }
22747
+ function getGameWorkerApiKeyName(slug) {
22748
+ return `${GAME_WORKER_KEY_PREFIX}${slug}`.substring(0, 32);
22749
+ }
22750
+ function getDashboardWorkerApiKeyName(slug) {
22751
+ return `${DASHBOARD_WORKER_KEY_PREFIX}${slug}`;
22752
+ }
22753
+ function toBindingName(queueKey) {
22754
+ return `${queueKey.replace(/-/g, "_").toUpperCase()}_QUEUE`;
22755
+ }
22756
+ function isSchemaAdopted(state) {
22757
+ if (!state) {
22758
+ return false;
22759
+ }
22760
+ return state.schemaHash !== null || state.schemaFingerprint !== null || state.schemaSnapshot !== null;
22761
+ }
22762
+ function isPushAdopted(state) {
22763
+ return Boolean(state?.schemaHash);
22764
+ }
22765
+ function isMigrateManaged(state) {
22766
+ return Boolean(state?.schemaFingerprint) && !state?.schemaHash;
22767
+ }
22768
+ function generateDeploymentHash(code) {
22769
+ return sha256Hex(code);
22770
+ }
22771
+ function computeDeployPayloadFingerprint(payload) {
22772
+ return sha256Hex(canonicalJson(payload));
22773
+ }
22774
+ function canonicalJson(value) {
22775
+ if (value === null || typeof value !== "object") {
22776
+ return JSON.stringify(value) ?? "null";
22777
+ }
22778
+ if (Array.isArray(value)) {
22779
+ return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
22780
+ }
22781
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== undefined).toSorted(([a], [b]) => compareKeys(a, b)).map(([key, entryValue]) => `${JSON.stringify(key)}:${canonicalJson(entryValue)}`);
22782
+ return `{${entries.join(",")}}`;
22783
+ }
22784
+ function compareKeys(a, b) {
22785
+ if (a < b) {
22786
+ return -1;
22787
+ }
22788
+ if (a > b) {
22789
+ return 1;
22790
+ }
22791
+ return 0;
22792
+ }
22793
+ var GAME_WORKER_KEY_PREFIX = "game-worker-", DASHBOARD_WORKER_KEY_PREFIX = "dash-worker-";
22794
+ var init_deployment_util = __esm(() => {
22795
+ init_drizzle_orm();
22796
+ init_src();
22797
+ init_tables_index();
22798
+ init_stages();
22799
+ });
22800
+
22508
22801
  // ../api-core/src/services/deploy-job.service.ts
22802
+ function isEventDetails(value) {
22803
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22804
+ }
22805
+
22509
22806
  class DeployJobService {
22510
22807
  deps;
22511
22808
  constructor(deps) {
@@ -22518,6 +22815,9 @@ class DeployJobService {
22518
22815
  if (leaseLost) {
22519
22816
  return "lease_lost";
22520
22817
  }
22818
+ if (DEPLOY_REFUSAL_CODES.has(deployErrorCode(error) ?? "")) {
22819
+ return "refused";
22820
+ }
22521
22821
  if (error instanceof DomainError) {
22522
22822
  return "domain_error";
22523
22823
  }
@@ -22597,13 +22897,28 @@ class DeployJobService {
22597
22897
  const bucketName = this.getUploadBucket();
22598
22898
  this.deps.storage.deleteObject(bucketName, codeUploadToken).catch(catchAttrs("deploy_job.temp_cleanup"));
22599
22899
  }
22600
- sanitizeRequestForPersistence(request) {
22601
- const sanitized = { ...request };
22900
+ async sanitizeRequestForPersistence(request) {
22901
+ const sanitized = {
22902
+ ...request
22903
+ };
22602
22904
  delete sanitized._headers;
22603
22905
  delete sanitized.code;
22604
22906
  delete sanitized.codeUploadToken;
22907
+ const codeFingerprint = await this.computeCodeFingerprint(request);
22908
+ if (codeFingerprint) {
22909
+ sanitized.codeFingerprint = codeFingerprint;
22910
+ }
22605
22911
  return sanitized;
22606
22912
  }
22913
+ async computeCodeFingerprint(request) {
22914
+ if (request.codeUploadToken) {
22915
+ return `upload:${request.codeUploadToken}`;
22916
+ }
22917
+ if (request.code) {
22918
+ return `sha256:${await generateDeploymentHash(request.code)}`;
22919
+ }
22920
+ return;
22921
+ }
22607
22922
  getLeaseExpiry() {
22608
22923
  return new Date(Date.now() + DEPLOY_JOB_LEASE_MS);
22609
22924
  }
@@ -22636,8 +22951,36 @@ class DeployJobService {
22636
22951
  heartbeatAt: null
22637
22952
  }).where(and(eq(gameDeployJobs.id, jobId), eq(gameDeployJobs.leaseId, leaseId)));
22638
22953
  }
22954
+ async findByDeployId(gameId, deployId) {
22955
+ const job = await this.deps.db.query.gameDeployJobs.findFirst({
22956
+ where: and(eq(gameDeployJobs.gameId, gameId), eq(gameDeployJobs.deployId, deployId))
22957
+ });
22958
+ return job ?? null;
22959
+ }
22960
+ async resolveIdempotentReplay(existing, request) {
22961
+ const [incoming, stored] = await Promise.all([
22962
+ this.sanitizeRequestForPersistence(request).then(computeDeployPayloadFingerprint),
22963
+ computeDeployPayloadFingerprint(existing.request)
22964
+ ]);
22965
+ if (incoming !== stored) {
22966
+ setAttribute("app.deploy_job.idempotency", "payload_mismatch");
22967
+ throw new DeployIdConflictError(request.deployId, existing.id);
22968
+ }
22969
+ setAttributes({
22970
+ "app.deploy_job.idempotency": "replayed",
22971
+ "app.deploy_job.id": existing.id,
22972
+ "app.deploy_job.status": existing.status
22973
+ });
22974
+ return this.toResponse(existing);
22975
+ }
22639
22976
  async create(slug, request, user) {
22640
22977
  const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
22978
+ if (request.deployId) {
22979
+ const existing = await this.findByDeployId(game2.id, request.deployId);
22980
+ if (existing) {
22981
+ return this.resolveIdempotentReplay(existing, request);
22982
+ }
22983
+ }
22641
22984
  const jobId = crypto.randomUUID();
22642
22985
  let codeSource = "none";
22643
22986
  if (request.code) {
@@ -22653,7 +22996,7 @@ class DeployJobService {
22653
22996
  request.code = await this.loadUploadedCode(request.codeUploadToken, game2.id);
22654
22997
  }
22655
22998
  setAttribute("app.deploy_job.code_bundle_size", request.code?.length ?? 0);
22656
- const sanitizedRequest = this.sanitizeRequestForPersistence(request);
22999
+ const sanitizedRequest = await this.sanitizeRequestForPersistence(request);
22657
23000
  if (request.code) {
22658
23001
  await this.storeCodeBundle(jobId, request.code);
22659
23002
  }
@@ -22663,6 +23006,7 @@ class DeployJobService {
22663
23006
  id: jobId,
22664
23007
  gameId: game2.id,
22665
23008
  userId: user.id,
23009
+ deployId: request.deployId ?? null,
22666
23010
  request: sanitizedRequest,
22667
23011
  events: [
22668
23012
  {
@@ -22674,6 +23018,12 @@ class DeployJobService {
22674
23018
  }).returning();
22675
23019
  } catch (error) {
22676
23020
  await this.deleteCodeBundle(jobId);
23021
+ if (request.deployId) {
23022
+ const winner = await this.findByDeployId(game2.id, request.deployId);
23023
+ if (winner) {
23024
+ return this.resolveIdempotentReplay(winner, request);
23025
+ }
23026
+ }
22677
23027
  throw error;
22678
23028
  }
22679
23029
  if (!job) {
@@ -22788,7 +23138,11 @@ class DeployJobService {
22788
23138
  "app.deploy_job.error_status": errorClassification?.errorStatus
22789
23139
  });
22790
23140
  if (!effectiveLeaseLost) {
22791
- await this.addStatusEvent(jobId, "Deployment failed", { error: message });
23141
+ const structuredDetails = error instanceof DomainError && isEventDetails(error.details) ? error.details : undefined;
23142
+ await this.addStatusEvent(jobId, "Deployment failed", {
23143
+ error: message,
23144
+ ...structuredDetails
23145
+ });
22792
23146
  const failed = await this.markFailed(jobId, leaseId, message, errorClassification);
22793
23147
  if (!failed) {
22794
23148
  await this.clearLease(jobId, leaseId);
@@ -22801,18 +23155,21 @@ class DeployJobService {
22801
23155
  displayName: game2.displayName,
22802
23156
  error: message,
22803
23157
  target,
22804
- developer: { id: user.id, email: user.email }
23158
+ developer: { id: user.id, email: user.email },
23159
+ errorCode: deployErrorCode(error)
22805
23160
  });
22806
23161
  }
22807
23162
  await this.deleteCodeBundle(jobId);
22808
23163
  }
22809
23164
  async loadJobActors(job, jobId, leaseId, onMissing) {
22810
- const game2 = await this.deps.db.query.games.findFirst({
22811
- where: eq(games.id, job.gameId)
22812
- });
22813
- const user = await this.deps.db.query.users.findFirst({
22814
- where: eq(users.id, job.userId)
22815
- });
23165
+ const [game2, user] = await Promise.all([
23166
+ this.deps.db.query.games.findFirst({
23167
+ where: eq(games.id, job.gameId)
23168
+ }),
23169
+ job.userId ? this.deps.db.query.users.findFirst({
23170
+ where: eq(users.id, job.userId)
23171
+ }) : undefined
23172
+ ]);
22816
23173
  if (!game2 || !user) {
22817
23174
  const message = !game2 ? "Deploy job game no longer exists" : "Deploy job user no longer exists";
22818
23175
  onMissing();
@@ -22898,7 +23255,8 @@ class DeployJobService {
22898
23255
  for await (const step of this.deps.runDeploy(game2.slug, request, user, uploadDeps, extractZipToDirectory)) {
22899
23256
  assertLease();
22900
23257
  if (step.type === "status" && "message" in step.data && typeof step.data.message === "string") {
22901
- await this.addStatusEvent(jobId, step.data.message);
23258
+ const details = "details" in step.data && isEventDetails(step.data.details) ? step.data.details : undefined;
23259
+ await this.addStatusEvent(jobId, step.data.message, details);
22902
23260
  }
22903
23261
  }
22904
23262
  assertLease();
@@ -22956,8 +23314,10 @@ var init_deploy_job_service = __esm(() => {
22956
23314
  init_helpers_index();
22957
23315
  init_tables_index();
22958
23316
  init_spans();
23317
+ init_game2();
22959
23318
  init_zip();
22960
23319
  init_errors();
23320
+ init_deployment_util();
22961
23321
  STATUS_MAP2 = {
22962
23322
  BAD_REQUEST: 400,
22963
23323
  UNAUTHORIZED: 401,
@@ -22979,8 +23339,153 @@ var init_deploy_job_service = __esm(() => {
22979
23339
  DEPLOY_JOB_LEASE_MS = 2 * 60 * 1000;
22980
23340
  DEPLOY_JOB_HEARTBEAT_MS = 30 * 1000;
22981
23341
  });
23342
+ // ../cloudflare/src/utils/schema.ts
23343
+ function normalizeSqlForChecksum(sql4) {
23344
+ const unified = sql4.replace(/\r\n/g, `
23345
+ `).replace(/\r/g, `
23346
+ `);
23347
+ const stripped = stripSqlComments(unified);
23348
+ return stripped.split(`
23349
+ `).map((line3) => line3.replace(/\s+$/, "")).filter((line3) => line3 !== "").join(`
23350
+ `);
23351
+ }
23352
+ function stripSqlComments(sql4) {
23353
+ let output = "";
23354
+ let i2 = 0;
23355
+ while (i2 < sql4.length) {
23356
+ const char3 = sql4[i2];
23357
+ const next = sql4[i2 + 1];
23358
+ if (char3 === "-" && next === "-") {
23359
+ i2 = skipLineComment(sql4, i2);
23360
+ } else if (char3 === "/" && next === "*") {
23361
+ output += " ";
23362
+ i2 = skipBlockComment(sql4, i2);
23363
+ } else if (char3 === "'" || char3 === '"' || char3 === "`") {
23364
+ const quoted = copyQuoted(sql4, i2, char3);
23365
+ output += quoted.text;
23366
+ i2 = quoted.end;
23367
+ } else if (char3 === "[") {
23368
+ const bracketed = copyBracketed(sql4, i2);
23369
+ output += bracketed.text;
23370
+ i2 = bracketed.end;
23371
+ } else {
23372
+ output += char3;
23373
+ i2++;
23374
+ }
23375
+ }
23376
+ return output;
23377
+ }
23378
+ function skipLineComment(sql4, start2) {
23379
+ let i2 = start2 + 2;
23380
+ while (i2 < sql4.length && sql4[i2] !== `
23381
+ `) {
23382
+ i2++;
23383
+ }
23384
+ return i2;
23385
+ }
23386
+ function skipBlockComment(sql4, start2) {
23387
+ let i2 = start2 + 2;
23388
+ while (i2 < sql4.length && !(sql4[i2] === "*" && sql4[i2 + 1] === "/")) {
23389
+ i2++;
23390
+ }
23391
+ return i2 + 2;
23392
+ }
23393
+ function copyQuoted(sql4, start2, quote) {
23394
+ let text3 = quote;
23395
+ let i2 = start2 + 1;
23396
+ while (i2 < sql4.length) {
23397
+ text3 += sql4[i2];
23398
+ if (sql4[i2] !== quote) {
23399
+ i2++;
23400
+ } else if (sql4[i2 + 1] === quote) {
23401
+ text3 += quote;
23402
+ i2 += 2;
23403
+ } else {
23404
+ i2++;
23405
+ break;
23406
+ }
23407
+ }
23408
+ return { text: text3, end: i2 };
23409
+ }
23410
+ function copyBracketed(sql4, start2) {
23411
+ let text3 = "[";
23412
+ let i2 = start2 + 1;
23413
+ while (i2 < sql4.length) {
23414
+ text3 += sql4[i2];
23415
+ i2++;
23416
+ if (sql4[i2 - 1] === "]") {
23417
+ break;
23418
+ }
23419
+ }
23420
+ return { text: text3, end: i2 };
23421
+ }
23422
+ function findOversizedStatement(statements) {
23423
+ for (const [index2, statement] of statements.entries()) {
23424
+ const byteLength = Buffer.byteLength(statement, "utf8");
23425
+ if (byteLength > D1_MAX_STATEMENT_BYTES) {
23426
+ return { index: index2, byteLength };
23427
+ }
23428
+ }
23429
+ return null;
23430
+ }
23431
+ var MIGRATION_LEDGER_TABLE = "_playcademy_migrations", MIGRATION_CHECKSUM_ALGO = "sha256-v1", D1_MAX_STATEMENT_BYTES;
23432
+ var init_schema3 = __esm(() => {
23433
+ D1_MAX_STATEMENT_BYTES = 100 * 1024;
23434
+ });
23435
+
22982
23436
  // ../cloudflare/src/core/namespaces/d1.ts
22983
- var init_d1 = () => {};
23437
+ function parseD1ErrorOffset(message) {
23438
+ const match = message.match(/at offset (\d+)/);
23439
+ return match ? Number(match[1]) : null;
23440
+ }
23441
+ var MIGRATION_LEDGER_DDL, D1StatementTooLargeError, D1BatchError, D1MigrationError;
23442
+ var init_d1 = __esm(() => {
23443
+ init_schema3();
23444
+ MIGRATION_LEDGER_DDL = `CREATE TABLE IF NOT EXISTS ${MIGRATION_LEDGER_TABLE} (
23445
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
23446
+ tag TEXT NOT NULL UNIQUE,
23447
+ checksum TEXT NOT NULL,
23448
+ checksum_algo TEXT NOT NULL DEFAULT 'sha256-v1',
23449
+ deploy_id TEXT NOT NULL,
23450
+ applied_by TEXT,
23451
+ applied_at TEXT NOT NULL,
23452
+ source TEXT NOT NULL DEFAULT 'deploy',
23453
+ statements_total INTEGER
23454
+ )`;
23455
+ D1StatementTooLargeError = class D1StatementTooLargeError extends Error {
23456
+ name = "D1StatementTooLargeError";
23457
+ statementIndex;
23458
+ byteLength;
23459
+ constructor(tag, statementIndex, byteLength) {
23460
+ super(`Migration '${tag}' statement ${statementIndex} is ${byteLength} bytes — ` + `over D1's ${D1_MAX_STATEMENT_BYTES / 1024} KB per-statement limit. ` + "Split the statement or reduce its size.");
23461
+ this.statementIndex = statementIndex;
23462
+ this.byteLength = byteLength;
23463
+ }
23464
+ };
23465
+ D1BatchError = class D1BatchError extends Error {
23466
+ name = "D1BatchError";
23467
+ d1Message;
23468
+ offset;
23469
+ constructor(d1Message, cause) {
23470
+ super(`Failed to execute batch: ${d1Message}`, { cause });
23471
+ this.d1Message = d1Message;
23472
+ this.offset = parseD1ErrorOffset(d1Message);
23473
+ }
23474
+ };
23475
+ D1MigrationError = class D1MigrationError extends Error {
23476
+ name = "D1MigrationError";
23477
+ tag;
23478
+ d1Message;
23479
+ offset;
23480
+ constructor(tag, d1Message, cause) {
23481
+ super(`Migration '${tag}' failed and rolled back: ${d1Message}`, { cause });
23482
+ this.tag = tag;
23483
+ this.d1Message = d1Message;
23484
+ this.offset = parseD1ErrorOffset(d1Message);
23485
+ }
23486
+ };
23487
+ });
23488
+
22984
23489
  // ../cloudflare/src/core/namespaces/kv.ts
22985
23490
  var init_kv = () => {};
22986
23491
 
@@ -22997,6 +23502,160 @@ var init_assets = __esm(() => {
22997
23502
  init_mime();
22998
23503
  });
22999
23504
 
23505
+ // ../cloudflare/src/utils/journal.ts
23506
+ function findOutOfOrderTags(orderedTags, applied) {
23507
+ let lastAppliedIndex = -1;
23508
+ orderedTags.forEach((tag, index2) => {
23509
+ if (applied.has(tag)) {
23510
+ lastAppliedIndex = index2;
23511
+ }
23512
+ });
23513
+ return orderedTags.filter((tag, index2) => index2 < lastAppliedIndex && !applied.has(tag));
23514
+ }
23515
+
23516
+ // ../cloudflare/src/utils/sql.ts
23517
+ function detectDestructiveStatements(statements) {
23518
+ return statements.filter((statement) => {
23519
+ const scannable = blankStringLiterals(normalizeSqlForChecksum(statement));
23520
+ return DESTRUCTIVE_SQL_PATTERNS.some((pattern) => pattern.test(scannable));
23521
+ });
23522
+ }
23523
+ function splitSqlStatements(sql4) {
23524
+ const statements = [];
23525
+ let current = "";
23526
+ let i2 = 0;
23527
+ while (i2 < sql4.length) {
23528
+ const char3 = sql4[i2];
23529
+ const next = sql4[i2 + 1];
23530
+ if (char3 === ";") {
23531
+ statements.push(current);
23532
+ current = "";
23533
+ i2++;
23534
+ } else if (char3 === "-" && next === "-") {
23535
+ const end = scanLineCommentEnd(sql4, i2);
23536
+ current += sql4.slice(i2, end);
23537
+ i2 = end;
23538
+ } else if (char3 === "/" && next === "*") {
23539
+ const end = scanBlockCommentEnd(sql4, i2);
23540
+ current += sql4.slice(i2, end);
23541
+ i2 = end;
23542
+ } else if (char3 === "'" || char3 === '"' || char3 === "`") {
23543
+ const end = scanQuoteEnd(sql4, i2, char3);
23544
+ current += sql4.slice(i2, end);
23545
+ i2 = end;
23546
+ } else if (char3 === "[") {
23547
+ const end = scanBracketEnd(sql4, i2);
23548
+ current += sql4.slice(i2, end);
23549
+ i2 = end;
23550
+ } else {
23551
+ current += char3;
23552
+ i2++;
23553
+ }
23554
+ }
23555
+ statements.push(current);
23556
+ return statements.map((statement) => statement.trim()).filter((statement) => normalizeSqlForChecksum(statement).trim() !== "");
23557
+ }
23558
+ function blankStringLiterals(sql4) {
23559
+ let output = "";
23560
+ let i2 = 0;
23561
+ while (i2 < sql4.length) {
23562
+ const char3 = sql4[i2];
23563
+ if (char3 === "'") {
23564
+ output += "''";
23565
+ i2 = scanQuoteEnd(sql4, i2, char3);
23566
+ } else if (char3 === '"' || char3 === "`") {
23567
+ const end = scanQuoteEnd(sql4, i2, char3);
23568
+ output += sql4.slice(i2, end);
23569
+ i2 = end;
23570
+ } else if (char3 === "[") {
23571
+ const end = scanBracketEnd(sql4, i2);
23572
+ output += sql4.slice(i2, end);
23573
+ i2 = end;
23574
+ } else {
23575
+ output += char3;
23576
+ i2++;
23577
+ }
23578
+ }
23579
+ return output;
23580
+ }
23581
+ function scanLineCommentEnd(sql4, start2) {
23582
+ let i2 = start2 + 2;
23583
+ while (i2 < sql4.length && sql4[i2] !== `
23584
+ `) {
23585
+ i2++;
23586
+ }
23587
+ return i2;
23588
+ }
23589
+ function scanBlockCommentEnd(sql4, start2) {
23590
+ let i2 = start2 + 2;
23591
+ while (i2 < sql4.length && !(sql4[i2] === "*" && sql4[i2 + 1] === "/")) {
23592
+ i2++;
23593
+ }
23594
+ return Math.min(i2 + 2, sql4.length);
23595
+ }
23596
+ function scanQuoteEnd(sql4, start2, quote) {
23597
+ let i2 = start2 + 1;
23598
+ while (i2 < sql4.length) {
23599
+ if (sql4[i2] !== quote) {
23600
+ i2++;
23601
+ } else if (sql4[i2 + 1] === quote) {
23602
+ i2 += 2;
23603
+ } else {
23604
+ return i2 + 1;
23605
+ }
23606
+ }
23607
+ return i2;
23608
+ }
23609
+ function scanBracketEnd(sql4, start2) {
23610
+ let i2 = start2 + 1;
23611
+ while (i2 < sql4.length) {
23612
+ if (sql4[i2] === "]") {
23613
+ return i2 + 1;
23614
+ }
23615
+ i2++;
23616
+ }
23617
+ return i2;
23618
+ }
23619
+ function isAlreadyExistsSqlError(message) {
23620
+ return /already exists|duplicate column/i.test(message);
23621
+ }
23622
+ function readIdentifier(groups) {
23623
+ return groups.find((group) => group !== undefined) ?? "";
23624
+ }
23625
+ function extractCreatedObjects(statements) {
23626
+ const tables = [];
23627
+ const columns2 = [];
23628
+ for (const statement of statements) {
23629
+ const scannable = blankStringLiterals(normalizeSqlForChecksum(statement));
23630
+ for (const match of scannable.matchAll(CREATE_TABLE_RE)) {
23631
+ const name2 = readIdentifier(match.slice(1, 5));
23632
+ if (name2 && !name2.startsWith("__new_")) {
23633
+ tables.push(name2);
23634
+ }
23635
+ }
23636
+ for (const match of scannable.matchAll(ADD_COLUMN_RE)) {
23637
+ const table8 = readIdentifier(match.slice(1, 5));
23638
+ const column2 = readIdentifier(match.slice(5, 9));
23639
+ if (table8 && column2 && !table8.startsWith("__new_")) {
23640
+ columns2.push({ table: table8, column: column2 });
23641
+ }
23642
+ }
23643
+ }
23644
+ return { tables, columns: columns2 };
23645
+ }
23646
+ var DESTRUCTIVE_SQL_PATTERNS, IDENTIFIER_SOURCE, CREATE_TABLE_RE, ADD_COLUMN_RE;
23647
+ var init_sql3 = __esm(() => {
23648
+ init_schema3();
23649
+ DESTRUCTIVE_SQL_PATTERNS = [
23650
+ /\bDROP\s+TABLE\b/i,
23651
+ /\bALTER\s+TABLE\b[\s\S]*\bDROP\b/i,
23652
+ /\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?["'`[]?__new_/i
23653
+ ];
23654
+ IDENTIFIER_SOURCE = String.raw`(?:"([^"]+)"|\`([^\`]+)\`|\[([^\]]+)\]|([A-Za-z_][\w$]*))`;
23655
+ CREATE_TABLE_RE = new RegExp(String.raw`\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?${IDENTIFIER_SOURCE}`, "gi");
23656
+ ADD_COLUMN_RE = new RegExp(String.raw`\bALTER\s+TABLE\s+${IDENTIFIER_SOURCE}\s+ADD\s+(?:COLUMN\s+)?${IDENTIFIER_SOURCE}`, "gi");
23657
+ });
23658
+
23000
23659
  // ../../node_modules/.bun/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js
23001
23660
  var require_sbmh = __commonJS((exports, module2) => {
23002
23661
  var { EventEmitter } = __require("node:events");
@@ -24926,6 +25585,8 @@ var init_multipart = __esm(() => {
24926
25585
  var init_utils5 = __esm(() => {
24927
25586
  init_hostname();
24928
25587
  init_assets();
25588
+ init_schema3();
25589
+ init_sql3();
24929
25590
  init_multipart();
24930
25591
  });
24931
25592
 
@@ -25080,6 +25741,14 @@ var init_core = __esm(() => {
25080
25741
  init_client();
25081
25742
  });
25082
25743
 
25744
+ // ../cloudflare/src/index.ts
25745
+ var init_src4 = __esm(() => {
25746
+ init_core();
25747
+ init_namespaces();
25748
+ init_utils5();
25749
+ init_utils5();
25750
+ });
25751
+
25083
25752
  // ../cloudflare/src/playcademy/constants.ts
25084
25753
  var CUSTOM_DOMAINS_KV_NAME = "cademy-custom-domains", QUEUE_NAME_PREFIX = "playcademy", GAME_WORKER_DOMAIN_PRODUCTION, GAME_WORKER_DOMAIN_STAGING;
25085
25754
  var init_constants2 = __esm(() => {
@@ -27594,46 +28263,382 @@ var init_tunnel = __esm(() => {
27594
28263
  matchedPorts = new Map;
27595
28264
  });
27596
28265
 
27597
- // ../utils/src/stages.ts
27598
- function isPreviewStage(stage) {
27599
- return PREVIEW_STAGE_PATTERN.test(stage);
28266
+ // ../api-core/src/utils/baseline-validation.util.ts
28267
+ function assertBaselineClaimValid(args2) {
28268
+ const validation = validateBaselineClaim(args2);
28269
+ const blocked = validation.contradictions.length > 0 || validation.unverified.length > 0 && !args2.allowUnverified;
28270
+ if (blocked) {
28271
+ addEvent("deployment_state.baseline_claim_rejected", {
28272
+ "app.game.id": args2.gameId,
28273
+ "app.deployment_state.baseline_claim_source": args2.source,
28274
+ "app.deployment_state.baseline_contradictions": validation.contradictions.length,
28275
+ "app.deployment_state.baseline_unverified": validation.unverified.length,
28276
+ "app.deployment_state.baseline_suggested_tag": validation.suggestedTag ?? "none"
28277
+ });
28278
+ throw new BaselineClaimRejectedError({
28279
+ contradictions: validation.contradictions,
28280
+ unverified: validation.unverified,
28281
+ suggestedTag: validation.suggestedTag,
28282
+ claimedTag: args2.claimedTag
28283
+ });
28284
+ }
28285
+ if (validation.unverified.length > 0) {
28286
+ addEvent("deployment_state.baseline_unverified_overridden", {
28287
+ "app.game.id": args2.gameId,
28288
+ "app.user.id": args2.userId,
28289
+ "app.deployment_state.baseline_overridden_tags": validation.unverified.map((entry) => entry.tag).join(",")
28290
+ });
28291
+ }
28292
+ }
28293
+ function validateBaselineClaim(args2) {
28294
+ const { claimedTag, evidence, tables, indexes: indexes2, views, lastDeployAt } = args2;
28295
+ const claimedIndex = evidence.findIndex((entry) => entry.tag === claimedTag);
28296
+ const expected = replayEvidence(evidence, claimedIndex);
28297
+ const live = { tables, indexes: indexes2, views };
28298
+ const verdicts = [];
28299
+ const unverified = [];
28300
+ evidence.forEach((entry, index2) => {
28301
+ if (claimedIndex === -1 || index2 > claimedIndex) {
28302
+ verdicts.push(judgeBeyond(entry, expected, live));
28303
+ return;
28304
+ }
28305
+ const judged = judgeClaimed(entry, expected, live, lastDeployAt);
28306
+ verdicts.push(judged.verdict);
28307
+ if (judged.unverifiable) {
28308
+ unverified.push(judged.verdict);
28309
+ }
28310
+ });
28311
+ return {
28312
+ verdicts,
28313
+ contradictions: verdicts.filter((verdict) => verdict.verdict === "contradicted"),
28314
+ unverified,
28315
+ suggestedTag: suggestTag(evidence, tables)
28316
+ };
27600
28317
  }
27601
- var PREVIEW_STAGE_PATTERN;
27602
- var init_stages = __esm(() => {
27603
- PREVIEW_STAGE_PATTERN = /^pr-\d+$/;
28318
+ function replayEvidence(evidence, claimedIndex) {
28319
+ const state = { tables: new Map, indexes: new Map, views: new Map };
28320
+ for (let index2 = 0;index2 <= claimedIndex; index2++) {
28321
+ applyEvidenceEntry(state, evidence[index2]);
28322
+ }
28323
+ return state;
28324
+ }
28325
+ function applyEvidenceEntry(state, entry) {
28326
+ for (const table8 of entry.dropsTables) {
28327
+ state.tables.delete(table8);
28328
+ }
28329
+ for (const dropped of entry.dropsColumns) {
28330
+ state.tables.get(dropped.table)?.columns.delete(dropped.column);
28331
+ }
28332
+ for (const droppedIndex of entry.dropsIndexes) {
28333
+ state.indexes.delete(droppedIndex);
28334
+ }
28335
+ for (const view2 of entry.dropsViews) {
28336
+ state.views.delete(view2);
28337
+ }
28338
+ for (const table8 of entry.createsTables) {
28339
+ state.tables.set(table8.name, {
28340
+ creator: entry.tag,
28341
+ columns: new Map(table8.columns.map((column2) => [column2, entry.tag]))
28342
+ });
28343
+ }
28344
+ for (const added of entry.addsColumns) {
28345
+ state.tables.get(added.table)?.columns.set(added.column, entry.tag);
28346
+ }
28347
+ for (const createdIndex of entry.createsIndexes) {
28348
+ state.indexes.set(createdIndex, entry.tag);
28349
+ }
28350
+ for (const view2 of entry.createsViews) {
28351
+ state.views.set(view2, entry.tag);
28352
+ }
28353
+ }
28354
+ function judgeClaimed(entry, expected, live, lastDeployAt) {
28355
+ let surviving = 0;
28356
+ for (const table8 of entry.createsTables) {
28357
+ const expectation = expected.tables.get(table8.name);
28358
+ if (expectation?.creator === entry.tag) {
28359
+ surviving++;
28360
+ const columns2 = live.tables.get(table8.name);
28361
+ if (!columns2) {
28362
+ return {
28363
+ verdict: {
28364
+ tag: entry.tag,
28365
+ verdict: "contradicted",
28366
+ detail: `creates table \`${table8.name}\`, which is not in the live database`
28367
+ },
28368
+ unverifiable: false
28369
+ };
28370
+ }
28371
+ const missing = [...expectation.columns.entries()].filter(([, creator]) => creator === entry.tag).map(([column2]) => column2).filter((column2) => !columns2.includes(column2));
28372
+ if (missing.length > 0) {
28373
+ return {
28374
+ verdict: {
28375
+ tag: entry.tag,
28376
+ verdict: "contradicted",
28377
+ detail: `table \`${table8.name}\` exists but is missing column(s) ${missing.map((column2) => `\`${column2}\``).join(", ")} this migration defines`
28378
+ },
28379
+ unverifiable: false
28380
+ };
28381
+ }
28382
+ }
28383
+ }
28384
+ for (const added of entry.addsColumns) {
28385
+ if (expected.tables.get(added.table)?.columns.get(added.column) === entry.tag) {
28386
+ surviving++;
28387
+ const columns2 = live.tables.get(added.table);
28388
+ if (columns2 && !columns2.includes(added.column)) {
28389
+ return {
28390
+ verdict: {
28391
+ tag: entry.tag,
28392
+ verdict: "contradicted",
28393
+ detail: `adds column \`${added.column}\` to \`${added.table}\`, which the live table does not have`
28394
+ },
28395
+ unverifiable: false
28396
+ };
28397
+ }
28398
+ }
28399
+ }
28400
+ for (const name2 of entry.createsIndexes) {
28401
+ if (expected.indexes.get(name2) === entry.tag && live.indexes.has(name2)) {
28402
+ surviving++;
28403
+ }
28404
+ }
28405
+ for (const name2 of entry.createsViews) {
28406
+ if (expected.views.get(name2) === entry.tag && live.views.has(name2)) {
28407
+ surviving++;
28408
+ }
28409
+ }
28410
+ if (surviving === 0) {
28411
+ const generated = new Date(entry.generatedAt);
28412
+ if (lastDeployAt && generated > lastDeployAt) {
28413
+ return {
28414
+ verdict: {
28415
+ tag: entry.tag,
28416
+ verdict: "no-signal",
28417
+ detail: `no schema footprint to verify, and it was generated after the last deploy (${lastDeployAt.toISOString()})`
28418
+ },
28419
+ unverifiable: true
28420
+ };
28421
+ }
28422
+ return { verdict: { tag: entry.tag, verdict: "no-signal" }, unverifiable: false };
28423
+ }
28424
+ return { verdict: { tag: entry.tag, verdict: "verified" }, unverifiable: false };
28425
+ }
28426
+ function judgeBeyond(entry, expected, live) {
28427
+ for (const table8 of entry.createsTables) {
28428
+ if (live.tables.has(table8.name) && !expected.tables.has(table8.name)) {
28429
+ return {
28430
+ tag: entry.tag,
28431
+ verdict: "contradicted",
28432
+ detail: `is beyond the claim, but the table it creates (\`${table8.name}\`) already exists in the live database — the claim looks too old`
28433
+ };
28434
+ }
28435
+ }
28436
+ for (const added of entry.addsColumns) {
28437
+ const columns2 = live.tables.get(added.table);
28438
+ const explained = expected.tables.get(added.table)?.columns.has(added.column);
28439
+ if (columns2?.includes(added.column) && !explained) {
28440
+ return {
28441
+ tag: entry.tag,
28442
+ verdict: "contradicted",
28443
+ detail: `is beyond the claim, but the column it adds (\`${added.table}.${added.column}\`) already exists — the claim looks too old`
28444
+ };
28445
+ }
28446
+ }
28447
+ for (const index2 of entry.createsIndexes) {
28448
+ if (live.indexes.has(index2) && !expected.indexes.has(index2)) {
28449
+ return {
28450
+ tag: entry.tag,
28451
+ verdict: "contradicted",
28452
+ detail: `is beyond the claim, but the index it creates (\`${index2}\`) already exists — the claim looks too old`
28453
+ };
28454
+ }
28455
+ }
28456
+ for (const view2 of entry.createsViews) {
28457
+ if (live.views.has(view2) && !expected.views.has(view2)) {
28458
+ return {
28459
+ tag: entry.tag,
28460
+ verdict: "contradicted",
28461
+ detail: `is beyond the claim, but the view it creates (\`${view2}\`) already exists — the claim looks too old`
28462
+ };
28463
+ }
28464
+ }
28465
+ return { tag: entry.tag, verdict: "verified" };
28466
+ }
28467
+ function suggestTag(evidence, tables) {
28468
+ const liveCreated = [
28469
+ ...new Set(evidence.flatMap((entry) => entry.createsTables.map((table8) => table8.name)))
28470
+ ].filter((name2) => tables.has(name2));
28471
+ const state = { tables: new Map, indexes: new Map, views: new Map };
28472
+ let best = null;
28473
+ for (const entry of evidence) {
28474
+ applyEvidenceEntry(state, entry);
28475
+ const allPresent = [...state.tables.keys()].every((name2) => tables.has(name2));
28476
+ const noStray = liveCreated.every((name2) => state.tables.has(name2));
28477
+ if (allPresent && noStray) {
28478
+ best = entry.tag;
28479
+ }
28480
+ }
28481
+ return best;
28482
+ }
28483
+ var init_baseline_validation_util = __esm(() => {
28484
+ init_spans();
28485
+ init_errors();
27604
28486
  });
27605
28487
 
27606
- // ../api-core/src/utils/deployment.util.ts
27607
- function getGameDeploymentId(gameSlug, sstStage) {
27608
- if (sstStage === "production") {
27609
- return gameSlug;
28488
+ // ../api-core/src/utils/baseline.util.ts
28489
+ function sliceJournalToTag(journal, lastAppliedMigrationTag) {
28490
+ const index2 = journal.findIndex((entry) => entry.tag === lastAppliedMigrationTag);
28491
+ return index2 === -1 ? null : journal.slice(0, index2 + 1);
28492
+ }
28493
+ function evaluateBaselineGuardrails(input) {
28494
+ if (input.ledgerTags.length > 0) {
28495
+ return "ledger-not-empty";
27610
28496
  }
27611
- if (sstStage === "dev" || isPreviewStage(sstStage)) {
27612
- return `${WORKER_NAMING.STAGING_PREFIX}${gameSlug}`;
28497
+ if (input.liveTables.length === 0) {
28498
+ return "database-empty";
27613
28499
  }
27614
- return `${WORKER_NAMING.LOCAL_PREFIX}${sstStage}-${gameSlug}`;
28500
+ return "ok";
27615
28501
  }
27616
- function getDashboardDeploymentId(gameSlug, sstStage) {
27617
- return `${getGameDeploymentId(gameSlug, sstStage)}${DASHBOARD_WORKER_SUFFIX}`;
28502
+
28503
+ // ../api-core/src/utils/migration.util.ts
28504
+ function planMigrations(journal, ledger) {
28505
+ const ledgerByTag = new Map(ledger.map((row) => [row.tag, row]));
28506
+ const journalTags = new Set(journal.map((entry) => entry.tag));
28507
+ const pendingTags = [];
28508
+ const checksumMismatches = [];
28509
+ for (const entry of journal) {
28510
+ const applied = ledgerByTag.get(entry.tag);
28511
+ if (!applied) {
28512
+ pendingTags.push(entry.tag);
28513
+ } else {
28514
+ const comparable = applied.checksumAlgo === MIGRATION_CHECKSUM_ALGO;
28515
+ if (comparable && applied.checksum !== entry.checksum) {
28516
+ checksumMismatches.push({
28517
+ tag: entry.tag,
28518
+ ledgerChecksum: applied.checksum,
28519
+ journalChecksum: entry.checksum
28520
+ });
28521
+ }
28522
+ }
28523
+ }
28524
+ const outOfOrderTags = findOutOfOrderTags(journal.map((entry) => entry.tag), new Set(ledgerByTag.keys()));
28525
+ const missingFromJournalTags = ledger.filter((row) => !journalTags.has(row.tag)).map((row) => row.tag);
28526
+ return { pendingTags, checksumMismatches, outOfOrderTags, missingFromJournalTags };
27618
28527
  }
27619
- function getGameWorkerApiKeyName(slug) {
27620
- return `${GAME_WORKER_KEY_PREFIX}${slug}`.substring(0, 32);
28528
+ function assessMigrationAlreadyApplied(statements, liveTables) {
28529
+ const created = extractCreatedObjects(statements);
28530
+ const present = [];
28531
+ const missing = [];
28532
+ for (const table8 of created.tables) {
28533
+ (liveTables.has(table8) ? present : missing).push(`table ${table8}`);
28534
+ }
28535
+ for (const added of created.columns) {
28536
+ const live = Boolean(liveTables.get(added.table)?.includes(added.column));
28537
+ (live ? present : missing).push(`column ${added.table}.${added.column}`);
28538
+ }
28539
+ if (present.length === 0) {
28540
+ return { verdict: "no-signal", present, missing };
28541
+ }
28542
+ return {
28543
+ verdict: missing.length === 0 ? "all-present" : "partial",
28544
+ present,
28545
+ missing
28546
+ };
27621
28547
  }
27622
- function getDashboardWorkerApiKeyName(slug) {
27623
- return `${DASHBOARD_WORKER_KEY_PREFIX}${slug}`;
28548
+ function parseMigrationFailure(events) {
28549
+ if (!events) {
28550
+ return null;
28551
+ }
28552
+ for (let i2 = events.length - 1;i2 >= 0; i2--) {
28553
+ const event = events[i2];
28554
+ const failure = event ? parseFailureEvent(event) : null;
28555
+ if (failure) {
28556
+ return failure;
28557
+ }
28558
+ }
28559
+ return null;
27624
28560
  }
27625
- function toBindingName(queueKey) {
27626
- return `${queueKey.replace(/-/g, "_").toUpperCase()}_QUEUE`;
28561
+ function parseFailureEvent(event) {
28562
+ const details = event.details;
28563
+ if (!details) {
28564
+ return null;
28565
+ }
28566
+ const { code, tag, statementIndex, error, d1Message } = details;
28567
+ if (code !== DEPLOY_ERROR_CODES.migrationFailed || typeof tag !== "string") {
28568
+ return null;
28569
+ }
28570
+ return {
28571
+ tag,
28572
+ error: failureMessage(error, d1Message),
28573
+ statementIndex: typeof statementIndex === "number" ? statementIndex : null,
28574
+ at: event.createdAt
28575
+ };
27627
28576
  }
27628
- function generateDeploymentHash(code) {
27629
- return sha256Hex(code);
28577
+ function failureMessage(error, d1Message) {
28578
+ if (typeof error === "string") {
28579
+ return error;
28580
+ }
28581
+ if (typeof d1Message === "string") {
28582
+ return d1Message;
28583
+ }
28584
+ return "Migration failed";
27630
28585
  }
27631
- var GAME_WORKER_KEY_PREFIX = "game-worker-", DASHBOARD_WORKER_KEY_PREFIX = "dash-worker-";
27632
- var init_deployment_util = __esm(() => {
27633
- init_src();
27634
- init_stages();
28586
+ var init_migration_util = __esm(() => {
28587
+ init_src4();
28588
+ init_errors();
27635
28589
  });
27636
28590
 
28591
+ // ../api-core/src/utils/secrets-manifest.util.ts
28592
+ async function deriveSecretsManifestPepper(platformSecret) {
28593
+ const encoder = new TextEncoder;
28594
+ const keyMaterial = await crypto.subtle.importKey("raw", encoder.encode(platformSecret), "HKDF", false, ["deriveBits"]);
28595
+ const bits = await crypto.subtle.deriveBits({
28596
+ name: "HKDF",
28597
+ hash: "SHA-256",
28598
+ salt: new Uint8Array(32),
28599
+ info: encoder.encode(SECRETS_MANIFEST_HKDF_INFO)
28600
+ }, keyMaterial, 256);
28601
+ return new Uint8Array(bits);
28602
+ }
28603
+ async function computeSecretDigest(pepper, input) {
28604
+ const key = await crypto.subtle.importKey("raw", new Uint8Array(pepper), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
28605
+ const message = JSON.stringify([input.gameId, input.key, input.value]);
28606
+ const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(message));
28607
+ return [...new Uint8Array(signature)].map((b) => b.toString(16).padStart(2, "0")).join("");
28608
+ }
28609
+ function computeSecretsDiff(input) {
28610
+ const { localDigests, manifest, remoteKeys } = input;
28611
+ const added = [];
28612
+ const changed = [];
28613
+ const unchanged = [];
28614
+ for (const [key, digest] of Object.entries(localDigests)) {
28615
+ const recorded = manifest[key];
28616
+ if (recorded === undefined) {
28617
+ added.push(key);
28618
+ } else if (recorded === digest) {
28619
+ unchanged.push(key);
28620
+ } else {
28621
+ changed.push(key);
28622
+ }
28623
+ }
28624
+ const localKeys = new Set(Object.keys(localDigests));
28625
+ const managedKeys = new Set(Object.keys(manifest));
28626
+ const remoteOnlyManaged = [...managedKeys].filter((key) => !localKeys.has(key));
28627
+ const remoteOnlyUnmanaged = remoteKeys.filter((key) => !managedKeys.has(key) && !localKeys.has(key));
28628
+ return {
28629
+ added: added.toSorted(),
28630
+ changed: changed.toSorted(),
28631
+ unchanged: unchanged.toSorted(),
28632
+ remoteOnlyManaged: remoteOnlyManaged.toSorted(),
28633
+ remoteOnlyUnmanaged: remoteOnlyUnmanaged.toSorted()
28634
+ };
28635
+ }
28636
+ function findUnmanagedPruneKeys(pruneSecrets, manifest) {
28637
+ const managed = new Set(Object.keys(manifest ?? {}));
28638
+ return pruneSecrets.filter((key) => !managed.has(key));
28639
+ }
28640
+ var SECRETS_MANIFEST_HKDF_INFO = "playcademy:secrets-manifest:v1";
28641
+
27637
28642
  // ../api-core/src/utils/worker-keys.util.ts
27638
28643
  async function sweepDashboardWorkerKeys(deleteApiKeysByName, slug) {
27639
28644
  try {
@@ -27651,6 +28656,9 @@ var init_worker_keys_util = __esm(() => {
27651
28656
  });
27652
28657
 
27653
28658
  // ../api-core/src/services/deploy.service.ts
28659
+ function hasBinding(binding) {
28660
+ return binding === true || Array.isArray(binding) && binding.length > 0;
28661
+ }
27654
28662
  function readDashboardTheme(config2) {
27655
28663
  const theme = config2?.dashboard?.theme;
27656
28664
  return {
@@ -27718,7 +28726,7 @@ class DeployService {
27718
28726
  data: { message: hasBackend ? "Deploying backend code" : "Deploying to platform" }
27719
28727
  };
27720
28728
  const keepAssets = hasBackend && !hasFrontend;
27721
- const deploymentOptions = this.mapGameBindingsToOptions(deploymentId, request.bindings, request.schema);
28729
+ const deploymentOptions = this.mapGameBindingsToOptions(deploymentId, request.bindings);
27722
28730
  const bindings = deploymentOptions?.bindings;
27723
28731
  setAttributes({
27724
28732
  "app.deploy.has_d1": Boolean(bindings?.d1?.length),
@@ -27727,13 +28735,49 @@ class DeployService {
27727
28735
  "app.deploy.queue_count": bindings?.queues?.length ?? 0,
27728
28736
  "app.deploy.dead_letter_queue_count": DeployService.countDeadLetterQueues(bindings)
27729
28737
  });
27730
- const activeDeployment = await db2.query.gameDeployments.findFirst({
27731
- where: activeDeploymentWhere(game2.id, "game"),
27732
- columns: { resources: true }
27733
- });
27734
- if (deploymentOptions?.bindings?.d1?.length) {
28738
+ const [activeDeployment, deploymentState] = await Promise.all([
28739
+ db2.query.gameDeployments.findFirst({
28740
+ where: activeDeploymentWhere(game2.id, "game"),
28741
+ columns: { resources: true }
28742
+ }),
28743
+ db2.query.gameDeploymentState.findFirst({
28744
+ where: eq(gameDeploymentState.gameId, game2.id)
28745
+ })
28746
+ ]);
28747
+ if (request.pruneSecrets?.length) {
28748
+ const unmanaged = findUnmanagedPruneKeys(request.pruneSecrets, deploymentState?.secretsManifest);
28749
+ if (unmanaged.length > 0) {
28750
+ throw new SecretsPruneUnmanagedError(unmanaged);
28751
+ }
28752
+ }
28753
+ let state = deploymentState;
28754
+ if (request.baseline) {
28755
+ if (isSchemaAdopted(state)) {
28756
+ addEvent("deploy.baseline_skipped", {
28757
+ "app.deploy.baseline_source": state?.baselineSource ?? "unknown"
28758
+ });
28759
+ } else {
28760
+ state = yield* this.adoptClientBaseline({
28761
+ game: game2,
28762
+ request,
28763
+ user,
28764
+ deploymentId,
28765
+ baseline: request.baseline,
28766
+ existingResources: activeDeployment?.resources ?? undefined
28767
+ });
28768
+ }
28769
+ }
28770
+ if (deploymentOptions?.bindings?.d1?.length && !isSchemaAdopted(state)) {
27735
28771
  await this.cleanupOrphanD1Databases(cf, deploymentOptions.bindings.d1, slug, game2.id);
27736
28772
  }
28773
+ const databaseOutcome = yield* this.executeDatabaseStep({
28774
+ game: game2,
28775
+ request,
28776
+ user,
28777
+ deploymentId,
28778
+ state,
28779
+ existingResources: activeDeployment?.resources ?? undefined
28780
+ });
27737
28781
  const result = await this.deployToCloudflare({
27738
28782
  deploymentId,
27739
28783
  code: request.code,
@@ -27741,6 +28785,7 @@ class DeployService {
27741
28785
  tempDir,
27742
28786
  options: {
27743
28787
  ...deploymentOptions,
28788
+ ...databaseOutcome.legacySchema && { schema: databaseOutcome.legacySchema },
27744
28789
  compatibilityDate: request.compatibilityDate ?? CLOUDFLARE_COMPATIBILITY_DATE,
27745
28790
  compatibilityFlags: request.compatibilityFlags,
27746
28791
  existingResources: activeDeployment?.resources ?? undefined,
@@ -27756,8 +28801,12 @@ class DeployService {
27756
28801
  result,
27757
28802
  request,
27758
28803
  user,
27759
- flags: flags2
28804
+ flags: flags2,
28805
+ database: databaseOutcome
27760
28806
  });
28807
+ if (request.pruneSecrets?.length) {
28808
+ yield* this.pruneManagedSecretsStep(game2.id, result.deploymentId, request.pruneSecrets);
28809
+ }
27761
28810
  yield { type: "complete", data: updatedGame };
27762
28811
  }
27763
28812
  async* deployDashboard(context2) {
@@ -27884,7 +28933,10 @@ class DeployService {
27884
28933
  "app.deploy.code_size": request.code?.length ?? 0,
27885
28934
  "app.deploy.compatibility_date": request.compatibilityDate ?? CLOUDFLARE_COMPATIBILITY_DATE,
27886
28935
  "app.deploy.compatibility_flag_count": request.compatibilityFlags?.length ?? 0,
27887
- "app.deploy.has_schema": Boolean(request.schema)
28936
+ "app.deploy.has_schema": Boolean(request.schema),
28937
+ "app.deploy.has_database_payload": Boolean(request.database),
28938
+ "app.deploy.has_baseline": Boolean(request.baseline),
28939
+ "app.deploy.prune_secret_count": request.pruneSecrets?.length ?? 0
27888
28940
  });
27889
28941
  if (!hasBackend && !hasFrontend && !hasMetadata) {
27890
28942
  throw new ValidationError("Must provide at least one of: uploadToken (frontend), code (backend), or metadata");
@@ -27921,18 +28973,18 @@ class DeployService {
27921
28973
  }
27922
28974
  return "metadata_only";
27923
28975
  }
27924
- mapGameBindingsToOptions(deploymentId, bindings, schema2) {
27925
- if (!bindings && !schema2) {
28976
+ mapGameBindingsToOptions(deploymentId, bindings) {
28977
+ if (!bindings) {
27926
28978
  return;
27927
28979
  }
27928
28980
  const workerBindings = {};
27929
- if (bindings?.database) {
28981
+ if (hasBinding(bindings.database)) {
27930
28982
  workerBindings.d1 = [deploymentId];
27931
28983
  }
27932
- if (bindings?.keyValue) {
28984
+ if (hasBinding(bindings.keyValue)) {
27933
28985
  workerBindings.kv = [deploymentId];
27934
28986
  }
27935
- if (bindings?.bucket) {
28987
+ if (hasBinding(bindings.bucket)) {
27936
28988
  workerBindings.r2 = [deploymentId];
27937
28989
  }
27938
28990
  if (bindings?.queues) {
@@ -27961,10 +29013,7 @@ class DeployService {
27961
29013
  });
27962
29014
  }
27963
29015
  const hasBindings = workerBindings.d1?.length || workerBindings.kv?.length || workerBindings.r2?.length || workerBindings.queues?.length;
27964
- return {
27965
- ...hasBindings && { bindings: workerBindings },
27966
- ...schema2 && { schema: schema2 }
27967
- };
29016
+ return hasBindings ? { bindings: workerBindings } : undefined;
27968
29017
  }
27969
29018
  static countDeadLetterQueues(bindings) {
27970
29019
  return bindings?.queues?.filter((queue) => Boolean(queue.deadLetterQueue)).length ?? 0;
@@ -27988,6 +29037,473 @@ class DeployService {
27988
29037
  }
27989
29038
  }
27990
29039
  }
29040
+ async* executeDatabaseStep(context2) {
29041
+ const { game: game2, request, user, deploymentId, state } = context2;
29042
+ if (request.schema) {
29043
+ if (isSchemaAdopted(state)) {
29044
+ throw new LegacySchemaUpgradeRequiredError;
29045
+ }
29046
+ const legacyDbId = context2.existingResources?.d1?.find((db2) => db2.name === deploymentId)?.id;
29047
+ if (legacyDbId) {
29048
+ const ledger = await this.getCloudflare().d1.readMigrationLedger(legacyDbId);
29049
+ if (ledger.length > 0) {
29050
+ throw new LegacySchemaUpgradeRequiredError;
29051
+ }
29052
+ }
29053
+ setAttribute("app.deploy.db_mode", "legacy");
29054
+ return { ...NO_DATABASE_WORK, legacySchema: request.schema };
29055
+ }
29056
+ const database = request.database;
29057
+ if (!database) {
29058
+ return NO_DATABASE_WORK;
29059
+ }
29060
+ if (!hasBinding(request.bindings?.database)) {
29061
+ throw new ValidationError("The database payload requires a database binding");
29062
+ }
29063
+ if (!request.deployId) {
29064
+ throw new ValidationError("deployId is required when a database payload is present");
29065
+ }
29066
+ setAttribute("app.deploy.db_mode", database.mode);
29067
+ const cf = this.getCloudflare();
29068
+ const persistedId = context2.existingResources?.d1?.find((db2) => db2.name === deploymentId)?.id;
29069
+ const databaseId = persistedId ?? await cf.d1.create(deploymentId);
29070
+ if (database.mode === "migrate") {
29071
+ return yield* this.runMigrateMode({
29072
+ game: game2,
29073
+ user,
29074
+ deployId: request.deployId,
29075
+ databaseId,
29076
+ migrations: database.migrations,
29077
+ state
29078
+ });
29079
+ }
29080
+ return yield* this.runPushMode({ game: game2, databaseId, payload: database, state });
29081
+ }
29082
+ async* runMigrateMode(args2) {
29083
+ const { game: game2, user, deployId, databaseId, migrations, state } = args2;
29084
+ const cf = this.getCloudflare();
29085
+ yield { type: "status", data: { message: "Preparing database migrations" } };
29086
+ await this.assertNoSchemaDrift(databaseId, state);
29087
+ await cf.d1.ensureMigrationLedger(databaseId);
29088
+ const ledger = await cf.d1.readMigrationLedger(databaseId);
29089
+ const plan = planMigrations(migrations.map((migration) => ({ tag: migration.tag, checksum: migration.checksum })), ledger.map((row) => ({
29090
+ tag: row.tag,
29091
+ checksum: row.checksum,
29092
+ checksumAlgo: row.checksum_algo
29093
+ })));
29094
+ setAttributes({
29095
+ "app.deploy.migrations_total": migrations.length,
29096
+ "app.deploy.migrations_applied_before": ledger.length,
29097
+ "app.deploy.migrations_pending": plan.pendingTags.length
29098
+ });
29099
+ if (plan.checksumMismatches.length > 0) {
29100
+ throw new MigrationChecksumMismatchError(plan.checksumMismatches);
29101
+ }
29102
+ if (plan.missingFromJournalTags.length > 0) {
29103
+ throw new MigrationJournalDivergenceError(plan.missingFromJournalTags);
29104
+ }
29105
+ if (plan.outOfOrderTags.length > 0) {
29106
+ throw new MigrationOrderError(plan.outOfOrderTags);
29107
+ }
29108
+ if (plan.pendingTags.length === 0) {
29109
+ yield { type: "status", data: { message: "Database schema is up to date" } };
29110
+ if (ledger.length > 0 && !state?.schemaFingerprint) {
29111
+ const fingerprint2 = await cf.d1.fingerprintSchema(databaseId);
29112
+ await this.persistDeploymentState(game2.id, {
29113
+ schemaFingerprint: fingerprint2.fingerprint
29114
+ });
29115
+ return {
29116
+ ...NO_DATABASE_WORK,
29117
+ schemaFingerprint: fingerprint2.fingerprint
29118
+ };
29119
+ }
29120
+ return {
29121
+ ...NO_DATABASE_WORK,
29122
+ schemaFingerprint: state?.schemaFingerprint ?? null
29123
+ };
29124
+ }
29125
+ const capture = yield* this.captureBookmarkStep(databaseId);
29126
+ const migrationsByTag = new Map(migrations.map((migration) => [migration.tag, migration]));
29127
+ let appliedCount = 0;
29128
+ for (const tag of plan.pendingTags) {
29129
+ const migration = migrationsByTag.get(tag);
29130
+ const count = migration.statements.length;
29131
+ yield {
29132
+ type: "status",
29133
+ data: { message: `Applying ${tag} (${count} statement${count === 1 ? "" : "s"})` }
29134
+ };
29135
+ const startedAt = Date.now();
29136
+ try {
29137
+ await withSpan("deploy.apply_migration", () => cf.d1.applyMigration(databaseId, {
29138
+ tag,
29139
+ statements: migration.statements,
29140
+ checksum: migration.checksum,
29141
+ deployId,
29142
+ appliedBy: user.id
29143
+ }));
29144
+ } catch (error) {
29145
+ if (appliedCount > 0) {
29146
+ await this.recordAppliedPrefixFingerprint(game2.id, databaseId);
29147
+ }
29148
+ throw await this.toMigrationStepError(databaseId, error, migration);
29149
+ }
29150
+ appliedCount++;
29151
+ const seconds = ((Date.now() - startedAt) / 1000).toFixed(1);
29152
+ yield { type: "status", data: { message: `Applied ${tag} (${seconds}s)` } };
29153
+ }
29154
+ setAttribute("app.deploy.migrations_applied", plan.pendingTags.length);
29155
+ const fingerprint = await cf.d1.fingerprintSchema(databaseId);
29156
+ await this.persistDeploymentState(game2.id, {
29157
+ schemaFingerprint: fingerprint.fingerprint,
29158
+ schemaHash: null,
29159
+ schemaSnapshot: null
29160
+ });
29161
+ return {
29162
+ schemaHash: null,
29163
+ schemaFingerprint: fingerprint.fingerprint,
29164
+ timeTravelBookmark: capture?.bookmark ?? null,
29165
+ bookmarkCapturedAt: capture?.capturedAt ?? null
29166
+ };
29167
+ }
29168
+ async* runPushMode(args2) {
29169
+ const { game: game2, databaseId, payload, state } = args2;
29170
+ const cf = this.getCloudflare();
29171
+ yield { type: "status", data: { message: "Verifying database schema state" } };
29172
+ if (typeof payload.baselineHash !== "string" && payload.baselineHash !== null) {
29173
+ throw new ValidationError("Push deploys require baselineHash (null on first deploy)");
29174
+ }
29175
+ if (isMigrateManaged(state)) {
29176
+ const ledger = await cf.d1.readMigrationLedger(databaseId);
29177
+ throw new ValidationError(`This database is migrate-managed (${ledger.length} applied ` + "migration(s)) and does not accept push-mode SQL.", { code: DEPLOY_ERROR_CODES.strategyMismatch });
29178
+ }
29179
+ const storedHash = state?.schemaHash ?? null;
29180
+ if (payload.baselineHash !== storedHash) {
29181
+ throw await this.buildStateConflictError(game2.id, payload.baselineHash);
29182
+ }
29183
+ const statements = splitSqlStatements(payload.sql);
29184
+ const oversized = findOversizedStatement(statements);
29185
+ if (oversized) {
29186
+ throw new ValidationError(`Push statement ${oversized.index} is ${oversized.byteLength} bytes — over ` + `D1's ${D1_MAX_STATEMENT_BYTES / 1024} KB per-statement limit. Split the ` + "statement or reduce its size.", {
29187
+ code: DEPLOY_ERROR_CODES.pushFailed,
29188
+ statementIndex: oversized.index,
29189
+ offset: null
29190
+ });
29191
+ }
29192
+ const destructive = detectDestructiveStatements(statements);
29193
+ setAttributes({
29194
+ "app.deploy.push_statement_count": statements.length,
29195
+ "app.deploy.push_destructive_count": destructive.length,
29196
+ "app.deploy.push_accept_data_loss": Boolean(payload.acceptDataLoss)
29197
+ });
29198
+ if (destructive.length > 0 && !payload.acceptDataLoss) {
29199
+ throw new DestructiveSchemaError(destructive);
29200
+ }
29201
+ await this.assertNoSchemaDrift(databaseId, state);
29202
+ const reserved = await this.persistPushDeploymentState(game2.id, payload.baselineHash, {
29203
+ schemaFingerprint: PUSH_RESERVATION_FINGERPRINT,
29204
+ schemaHash: payload.nextHash,
29205
+ schemaSnapshot: payload.nextSnapshot
29206
+ });
29207
+ if (!reserved) {
29208
+ throw await this.buildStateConflictError(game2.id, payload.baselineHash);
29209
+ }
29210
+ let capture = null;
29211
+ if (statements.length > 0) {
29212
+ capture = yield* this.captureBookmarkStep(databaseId);
29213
+ yield {
29214
+ type: "status",
29215
+ data: {
29216
+ message: `Applying database schema changes (${statements.length} statements)`
29217
+ }
29218
+ };
29219
+ try {
29220
+ await cf.d1.batch(databaseId, [
29221
+ { sql: "PRAGMA defer_foreign_keys = on" },
29222
+ ...statements.map((statement) => ({ sql: statement })),
29223
+ { sql: "PRAGMA defer_foreign_keys = off" }
29224
+ ]);
29225
+ } catch (error) {
29226
+ await this.persistPushDeploymentState(game2.id, payload.nextHash, {
29227
+ schemaFingerprint: state?.schemaFingerprint ?? null,
29228
+ schemaHash: state?.schemaHash ?? null,
29229
+ schemaSnapshot: state?.schemaSnapshot ?? null
29230
+ });
29231
+ throw this.toPushStepError(error);
29232
+ }
29233
+ }
29234
+ const fingerprint = await cf.d1.fingerprintSchema(databaseId);
29235
+ await this.persistDeploymentState(game2.id, {
29236
+ schemaFingerprint: fingerprint.fingerprint
29237
+ });
29238
+ return {
29239
+ schemaHash: payload.nextHash,
29240
+ schemaFingerprint: fingerprint.fingerprint,
29241
+ timeTravelBookmark: capture?.bookmark ?? null,
29242
+ bookmarkCapturedAt: capture?.capturedAt ?? null
29243
+ };
29244
+ }
29245
+ async* captureBookmarkStep(databaseId) {
29246
+ const cf = this.getCloudflare();
29247
+ const bookmark = await cf.d1.captureBookmark(databaseId);
29248
+ const capturedAt = new Date;
29249
+ setAttribute("app.deploy.db_bookmark_captured", bookmark.captured);
29250
+ if (!bookmark.captured) {
29251
+ yield {
29252
+ type: "status",
29253
+ data: { message: `Time Travel bookmark unavailable (${bookmark.error})` }
29254
+ };
29255
+ return null;
29256
+ }
29257
+ yield {
29258
+ type: "status",
29259
+ data: {
29260
+ message: "Captured Time Travel bookmark",
29261
+ details: { bookmark: bookmark.bookmark }
29262
+ }
29263
+ };
29264
+ return { bookmark: bookmark.bookmark, capturedAt };
29265
+ }
29266
+ async toMigrationStepError(databaseId, error, migration) {
29267
+ if (error instanceof D1StatementTooLargeError) {
29268
+ return new ValidationError(error.message, {
29269
+ code: DEPLOY_ERROR_CODES.migrationFailed,
29270
+ tag: migration.tag,
29271
+ statementIndex: error.statementIndex,
29272
+ offset: null,
29273
+ d1Message: error.message
29274
+ });
29275
+ }
29276
+ if (error instanceof D1MigrationError) {
29277
+ addEvent("deploy.migration_failed", {
29278
+ "app.d1.migration_tag": migration.tag,
29279
+ "app.error.message": error.d1Message,
29280
+ ...error.offset !== null && { "app.d1.error_offset": error.offset }
29281
+ });
29282
+ const alreadyApplied = isAlreadyExistsSqlError(error.d1Message) ? await this.assessAlreadyApplied(databaseId, migration.statements) : null;
29283
+ return new MigrationExecutionError({
29284
+ tag: migration.tag,
29285
+ d1Message: error.d1Message,
29286
+ offset: error.offset,
29287
+ ...alreadyApplied ? { alreadyApplied } : {}
29288
+ });
29289
+ }
29290
+ return error;
29291
+ }
29292
+ async assessAlreadyApplied(databaseId, statements) {
29293
+ try {
29294
+ const cf = this.getCloudflare();
29295
+ const live = await cf.d1.fingerprintSchema(databaseId);
29296
+ const tables = await cf.d1.readTableColumns(databaseId, live.tables);
29297
+ const assessment = assessMigrationAlreadyApplied(statements, tables);
29298
+ addEvent("deploy.already_applied_assessment", {
29299
+ "app.deploy.already_applied_verdict": assessment.verdict,
29300
+ "app.deploy.already_applied_present": assessment.present.length,
29301
+ "app.deploy.already_applied_missing": assessment.missing.length
29302
+ });
29303
+ return assessment.verdict === "no-signal" ? null : assessment;
29304
+ } catch (assessError) {
29305
+ addEvent("deploy.already_applied_check_failed", {
29306
+ "app.error.message": errorMessage(assessError)
29307
+ });
29308
+ return null;
29309
+ }
29310
+ }
29311
+ toPushStepError(error) {
29312
+ if (error instanceof D1BatchError) {
29313
+ addEvent("deploy.push_failed", {
29314
+ "app.error.message": error.d1Message,
29315
+ ...error.offset !== null && { "app.d1.error_offset": error.offset }
29316
+ });
29317
+ return new PushExecutionError({ d1Message: error.d1Message, offset: error.offset });
29318
+ }
29319
+ return error;
29320
+ }
29321
+ async assertNoSchemaDrift(databaseId, state) {
29322
+ if (!state?.schemaFingerprint) {
29323
+ return;
29324
+ }
29325
+ const live = await this.getCloudflare().d1.fingerprintSchema(databaseId);
29326
+ if (live.fingerprint !== state.schemaFingerprint) {
29327
+ addEvent("deploy.state_drift", {
29328
+ "app.deploy.expected_fingerprint": state.schemaFingerprint,
29329
+ "app.deploy.actual_fingerprint": live.fingerprint
29330
+ });
29331
+ throw new DeploymentStateDriftError({
29332
+ expectedFingerprint: state.schemaFingerprint,
29333
+ actualFingerprint: live.fingerprint
29334
+ });
29335
+ }
29336
+ }
29337
+ async buildStateConflictError(gameId, claimedHash) {
29338
+ const [row, lastDeploy] = await Promise.all([
29339
+ this.deps.db.query.gameDeploymentState.findFirst({
29340
+ where: eq(gameDeploymentState.gameId, gameId),
29341
+ columns: { schemaHash: true }
29342
+ }),
29343
+ findLastSuccessfulDeployWithEmail(this.deps.db, gameId)
29344
+ ]);
29345
+ const currentHash = row?.schemaHash ?? null;
29346
+ addEvent("deploy.state_conflict", {
29347
+ "app.deploy.baseline_hash": claimedHash ?? "null",
29348
+ "app.deploy.current_hash": currentHash ?? "null"
29349
+ });
29350
+ return new DeploymentStateConflictError({
29351
+ currentHash,
29352
+ lastDeployAt: lastDeploy?.at.toISOString() ?? null,
29353
+ lastDeployBy: lastDeploy?.email ?? lastDeploy?.userId ?? null
29354
+ });
29355
+ }
29356
+ async recordAppliedPrefixFingerprint(gameId, databaseId) {
29357
+ try {
29358
+ const fingerprint = await this.getCloudflare().d1.fingerprintSchema(databaseId);
29359
+ await this.persistDeploymentState(gameId, {
29360
+ schemaFingerprint: fingerprint.fingerprint
29361
+ });
29362
+ } catch (error) {
29363
+ addEvent("deploy.fingerprint_persist_failed", {
29364
+ "exception.type": errorType(error),
29365
+ "app.error.message": errorMessage(error)
29366
+ });
29367
+ }
29368
+ }
29369
+ async persistDeploymentState(gameId, patch) {
29370
+ const set = {
29371
+ ...patch,
29372
+ updatedAt: new Date
29373
+ };
29374
+ await this.deps.db.insert(gameDeploymentState).values({ gameId, baselineSource: "deploy", ...set }).onConflictDoUpdate({ target: gameDeploymentState.gameId, set });
29375
+ }
29376
+ async persistArtifactHashes(gameId, patch) {
29377
+ const set = {
29378
+ ...patch.buildHash !== undefined && { buildHash: patch.buildHash },
29379
+ ...patch.integrationsHash !== undefined && {
29380
+ integrationsHash: patch.integrationsHash
29381
+ }
29382
+ };
29383
+ if (Object.keys(set).length === 0) {
29384
+ return;
29385
+ }
29386
+ await this.deps.db.insert(gameDeploymentState).values({ gameId, ...set, updatedAt: new Date }).onConflictDoUpdate({
29387
+ target: gameDeploymentState.gameId,
29388
+ set: { ...set, updatedAt: new Date }
29389
+ });
29390
+ }
29391
+ async persistPushDeploymentState(gameId, baselineHash, patch) {
29392
+ const set = { ...patch, updatedAt: new Date };
29393
+ if (baselineHash === null) {
29394
+ const claimed2 = await this.deps.db.insert(gameDeploymentState).values({ gameId, baselineSource: "deploy", ...set }).onConflictDoUpdate({
29395
+ target: gameDeploymentState.gameId,
29396
+ set,
29397
+ setWhere: isNull(gameDeploymentState.schemaHash)
29398
+ }).returning({ gameId: gameDeploymentState.gameId });
29399
+ return claimed2.length > 0;
29400
+ }
29401
+ const claimed = await this.deps.db.update(gameDeploymentState).set(set).where(and(eq(gameDeploymentState.gameId, gameId), eq(gameDeploymentState.schemaHash, baselineHash))).returning({ gameId: gameDeploymentState.gameId });
29402
+ return claimed.length > 0;
29403
+ }
29404
+ async* adoptClientBaseline(context2) {
29405
+ const { game: game2, request, user, deploymentId, baseline } = context2;
29406
+ const cf = this.getCloudflare();
29407
+ const persistedId = context2.existingResources?.d1?.find((db2) => db2.name === deploymentId)?.id;
29408
+ const databaseId = persistedId ?? (hasBinding(request.bindings?.database) ? await cf.d1.create(deploymentId) : null);
29409
+ if (baseline.lastAppliedMigrationTag && !databaseId) {
29410
+ throw new ValidationError("Baseline claims applied migrations, but the deploy has no database binding");
29411
+ }
29412
+ const live = databaseId ? await cf.d1.fingerprintSchema(databaseId) : null;
29413
+ let recordedRows = 0;
29414
+ if (databaseId && baseline.lastAppliedMigrationTag) {
29415
+ if (live.tables.length === 0) {
29416
+ throw new BaselineDatabaseEmptyError;
29417
+ }
29418
+ const slice = sliceJournalToTag(baseline.journal ?? [], baseline.lastAppliedMigrationTag);
29419
+ if (!slice) {
29420
+ throw new ValidationError(`Baseline lastAppliedMigrationTag '${baseline.lastAppliedMigrationTag}' ` + "is not in the submitted journal");
29421
+ }
29422
+ if (baseline.evidence?.length) {
29423
+ const [tables, lastDeploy] = await Promise.all([
29424
+ cf.d1.readTableColumns(databaseId, live.tables),
29425
+ findLastSuccessfulDeploy(this.deps.db, game2.id)
29426
+ ]);
29427
+ assertBaselineClaimValid({
29428
+ claimedTag: baseline.lastAppliedMigrationTag,
29429
+ evidence: baseline.evidence,
29430
+ tables,
29431
+ indexes: new Set(live.indexes),
29432
+ views: new Set(live.views),
29433
+ lastDeployAt: lastDeploy?.at ?? null,
29434
+ allowUnverified: false,
29435
+ source: "seed",
29436
+ gameId: game2.id,
29437
+ userId: user.id
29438
+ });
29439
+ }
29440
+ await cf.d1.ensureMigrationLedger(databaseId);
29441
+ const ledger = await cf.d1.readMigrationLedger(databaseId);
29442
+ const plan = planMigrations(slice, ledger.map((row) => ({
29443
+ tag: row.tag,
29444
+ checksum: row.checksum,
29445
+ checksumAlgo: row.checksum_algo
29446
+ })));
29447
+ if (plan.checksumMismatches.length > 0) {
29448
+ throw new MigrationChecksumMismatchError(plan.checksumMismatches);
29449
+ }
29450
+ if (plan.missingFromJournalTags.length > 0) {
29451
+ throw new MigrationJournalDivergenceError(plan.missingFromJournalTags);
29452
+ }
29453
+ if (plan.outOfOrderTags.length > 0) {
29454
+ throw new MigrationOrderError(plan.outOfOrderTags);
29455
+ }
29456
+ const checksumByTag = new Map(slice.map((entry) => [entry.tag, entry.checksum]));
29457
+ const rows = plan.pendingTags.map((tag) => ({
29458
+ tag,
29459
+ checksum: checksumByTag.get(tag)
29460
+ }));
29461
+ if (rows.length > 0) {
29462
+ await cf.d1.recordLedgerRows(databaseId, {
29463
+ rows,
29464
+ deployId: `baseline:${request.deployId ?? crypto.randomUUID()}`,
29465
+ appliedBy: user.id,
29466
+ source: "baseline"
29467
+ });
29468
+ }
29469
+ recordedRows = rows.length;
29470
+ }
29471
+ const fingerprint = live?.fingerprint ?? null;
29472
+ const set = {
29473
+ ...baseline.schemaHash !== undefined && { schemaHash: baseline.schemaHash },
29474
+ ...baseline.schemaSnapshot !== undefined && {
29475
+ schemaSnapshot: baseline.schemaSnapshot
29476
+ },
29477
+ ...baseline.integrationsHash !== undefined && {
29478
+ integrationsHash: baseline.integrationsHash
29479
+ },
29480
+ ...baseline.buildHash !== undefined && { buildHash: baseline.buildHash },
29481
+ ...fingerprint !== null && { schemaFingerprint: fingerprint },
29482
+ baselineSource: "client-baseline",
29483
+ updatedAt: new Date
29484
+ };
29485
+ await this.deps.db.insert(gameDeploymentState).values({ gameId: game2.id, ...set }).onConflictDoUpdate({ target: gameDeploymentState.gameId, set });
29486
+ setAttributes({
29487
+ "app.deploy.baseline_adopted": true,
29488
+ "app.deploy.baseline_ledger_rows": recordedRows,
29489
+ "app.deploy.baseline_has_snapshot": baseline.schemaSnapshot !== undefined
29490
+ });
29491
+ yield {
29492
+ type: "status",
29493
+ data: {
29494
+ message: "Adopted deployment state from client baseline",
29495
+ details: {
29496
+ ledgerRows: recordedRows,
29497
+ ...baseline.lastAppliedMigrationTag && {
29498
+ lastAppliedMigrationTag: baseline.lastAppliedMigrationTag
29499
+ }
29500
+ }
29501
+ }
29502
+ };
29503
+ return this.deps.db.query.gameDeploymentState.findFirst({
29504
+ where: eq(gameDeploymentState.gameId, game2.id)
29505
+ });
29506
+ }
27991
29507
  async applyGameMetadata(gameId, request, hasFrontend, hasMetadata, deploymentUrl) {
27992
29508
  const updates = { updatedAt: new Date };
27993
29509
  if (hasFrontend) {
@@ -28013,7 +29529,8 @@ class DeployService {
28013
29529
  result,
28014
29530
  request,
28015
29531
  user,
28016
- flags: flags2
29532
+ flags: flags2,
29533
+ database
28017
29534
  }) {
28018
29535
  const { hasBackend, hasFrontend, hasMetadata } = flags2;
28019
29536
  const db2 = this.deps.db;
@@ -28023,9 +29540,17 @@ class DeployService {
28023
29540
  deploymentId: result.deploymentId,
28024
29541
  url: result.url,
28025
29542
  codeHash,
29543
+ schemaHash: database.schemaHash,
29544
+ schemaFingerprint: database.schemaFingerprint,
29545
+ timeTravelBookmark: database.timeTravelBookmark,
29546
+ bookmarkCapturedAt: database.bookmarkCapturedAt,
28026
29547
  resources: result.resources,
28027
29548
  target: "game"
28028
29549
  });
29550
+ await this.persistArtifactHashes(game2.id, {
29551
+ buildHash: hasFrontend ? request.buildHash : undefined,
29552
+ integrationsHash: request.integrationsHash
29553
+ });
28029
29554
  if (hasBackend) {
28030
29555
  await withSpan("deploy.configure_worker_secrets", async () => {
28031
29556
  await this.ensureWorkerApiKeyOnWorker(user, DeployService.gameWorkerKeySpec(slug), result.deploymentId);
@@ -28162,6 +29687,29 @@ class DeployService {
28162
29687
  const cf = this.getCloudflare();
28163
29688
  await cf.setSecrets(deploymentId, { QUEUE_INGRESS_SECRET: secret });
28164
29689
  }
29690
+ async* pruneManagedSecretsStep(gameId, deploymentId, pruneSecrets) {
29691
+ const cf = this.getCloudflare();
29692
+ const keys = [...new Set(pruneSecrets)];
29693
+ yield {
29694
+ type: "status",
29695
+ data: {
29696
+ message: `Pruning ${keys.length} managed secret(s)`,
29697
+ details: { keys }
29698
+ }
29699
+ };
29700
+ await withSpan("deploy.prune_secrets", async () => {
29701
+ const existing = await cf.listSecrets(deploymentId);
29702
+ for (const key of keys) {
29703
+ const prefixedKey = `${SECRETS_PREFIX}${key}`;
29704
+ if (existing.includes(prefixedKey)) {
29705
+ await cf.deleteSecret(deploymentId, prefixedKey);
29706
+ }
29707
+ }
29708
+ const pruned = keys.reduce((expr, key) => sql`${expr} - ${key}::text`, sql`coalesce(${gameDeploymentState.secretsManifest}, '{}'::jsonb)`);
29709
+ await this.deps.db.update(gameDeploymentState).set({ secretsManifest: pruned, updatedAt: new Date }).where(eq(gameDeploymentState.gameId, gameId));
29710
+ });
29711
+ setAttribute("app.deploy.pruned_secret_count", keys.length);
29712
+ }
28165
29713
  async ensureDashboardSessionSecret(deploymentId, existingSecrets, hasPriorDeployment) {
28166
29714
  if (existingSecrets === null && hasPriorDeployment) {
28167
29715
  setAttribute("app.deploy.session_secret_outcome", "check_failed_kept");
@@ -28266,6 +29814,10 @@ class DeployService {
28266
29814
  target: record.target,
28267
29815
  url: record.url,
28268
29816
  codeHash: record.codeHash,
29817
+ schemaHash: record.schemaHash ?? null,
29818
+ schemaFingerprint: record.schemaFingerprint ?? null,
29819
+ timeTravelBookmark: record.timeTravelBookmark ?? null,
29820
+ bookmarkCapturedAt: record.bookmarkCapturedAt ?? null,
28269
29821
  resources: record.resources,
28270
29822
  isActive: true
28271
29823
  });
@@ -28275,8 +29827,10 @@ class DeployService {
28275
29827
  await this.deps.alerts.notifyDeploymentFailure(failure).catch(catchAttrs("alerts.delivery", { "app.alerts.type": "deployment_failure" }));
28276
29828
  }
28277
29829
  }
29830
+ var PUSH_RESERVATION_FINGERPRINT = "reserved:push-in-flight", NO_DATABASE_WORK;
28278
29831
  var init_deploy_service = __esm(() => {
28279
29832
  init_drizzle_orm();
29833
+ init_src4();
28280
29834
  init_playcademy();
28281
29835
  init_src();
28282
29836
  init_helpers_index();
@@ -28284,9 +29838,17 @@ var init_deploy_service = __esm(() => {
28284
29838
  init_spans();
28285
29839
  init_tunnel();
28286
29840
  init_errors();
29841
+ init_baseline_validation_util();
28287
29842
  init_dashboard_util();
28288
29843
  init_deployment_util();
29844
+ init_migration_util();
28289
29845
  init_worker_keys_util();
29846
+ NO_DATABASE_WORK = {
29847
+ schemaHash: null,
29848
+ schemaFingerprint: null,
29849
+ timeTravelBookmark: null,
29850
+ bookmarkCapturedAt: null
29851
+ };
28290
29852
  });
28291
29853
 
28292
29854
  // ../api-core/src/services/developer.service.ts
@@ -29740,7 +31302,7 @@ function createGameServices(deps) {
29740
31302
  }
29741
31303
  };
29742
31304
  }
29743
- var init_game2 = __esm(() => {
31305
+ var init_game3 = __esm(() => {
29744
31306
  init_dashboard_service();
29745
31307
  init_deploy_job_service();
29746
31308
  init_deploy_service();
@@ -29939,16 +31501,37 @@ class AlertsService {
29939
31501
  await this.sendAlert(discord, embed.build());
29940
31502
  }
29941
31503
  async notifyDeploymentFailure(failure) {
29942
- const discord = this.recordAlert("deployment_failure");
31504
+ const refused = DEPLOY_REFUSAL_CODES.has(failure.errorCode ?? "");
31505
+ const discord = this.recordAlert(refused ? "deployment_blocked" : "deployment_failure");
29943
31506
  if (!discord) {
29944
31507
  return;
29945
31508
  }
29946
- const [title, subject] = failure.target === "dashboard" ? ["Dashboard Deployment Failed", "Dashboard deployment"] : ["Deployment Failed", "Deployment"];
29947
- const embed = new DiscordEmbedBuilder().setTitle(title).setDescription(`${subject} failed for **${failure.displayName || failure.slug}** (**${this.getEnvironment()}**).`).setColor(DiscordColors.RED).addField("Slug", failure.slug, true);
31509
+ const [noun, subject] = failure.target === "dashboard" ? ["Dashboard Deployment", "Dashboard deployment"] : ["Deployment", "Deployment"];
31510
+ const title = refused ? `\uD83D\uDEA7 ${noun} Blocked` : `❌ ${noun} Failed`;
31511
+ const verb = refused ? "was blocked" : "failed";
31512
+ const embed = new DiscordEmbedBuilder().setTitle(title).setDescription(`${subject} ${verb} for **${failure.displayName || failure.slug}** (**${this.getEnvironment()}**).`).setColor(refused ? DiscordColors.YELLOW : DiscordColors.RED).addField("Slug", failure.slug, true);
29948
31513
  if (failure.developer) {
29949
31514
  embed.addField("Developer", failure.developer.email || failure.developer.id, true);
29950
31515
  }
29951
- embed.addField("Error", failure.error, false).setFooter("Playcademy Developer Platform").setTimestamp();
31516
+ embed.addField(refused ? "Reason" : "Error", failure.error, false);
31517
+ if (refused) {
31518
+ embed.addField("Next step", "The developer received repair guidance in their terminal", false);
31519
+ }
31520
+ embed.setFooter("Playcademy Developer Platform").setTimestamp();
31521
+ await this.sendAlert(discord, embed.build());
31522
+ }
31523
+ async notifyDeployBlocked(blocked) {
31524
+ const discord = this.recordAlert("deployment_blocked");
31525
+ if (!discord) {
31526
+ return;
31527
+ }
31528
+ const embed = new DiscordEmbedBuilder().setTitle("\uD83D\uDEA7 Deployment Blocked").setDescription(`Deployment was blocked for **${blocked.displayName || blocked.slug}** (**${this.getEnvironment()}**).`).setColor(DiscordColors.YELLOW).addField("Slug", blocked.slug, true);
31529
+ if (blocked.developer) {
31530
+ embed.addField("Developer", blocked.developer.email || blocked.developer.id, true);
31531
+ }
31532
+ embed.addField("Reason", blocked.reason, false);
31533
+ embed.addField("Next step", "The developer received repair guidance in their terminal", false);
31534
+ embed.setFooter("Playcademy Developer Platform").setTimestamp();
29952
31535
  await this.sendAlert(discord, embed.build());
29953
31536
  }
29954
31537
  async notifyGameDeletion(game2) {
@@ -30009,6 +31592,7 @@ var DISCORD_FIELD_LIMIT = 1024;
30009
31592
  var init_alerts_service = __esm(() => {
30010
31593
  init_discord();
30011
31594
  init_spans();
31595
+ init_game2();
30012
31596
  });
30013
31597
 
30014
31598
  // ../api-core/src/services/kv-backup.service.ts
@@ -30441,6 +32025,15 @@ class DatabaseService {
30441
32025
  constructor(deps) {
30442
32026
  this.deps = deps;
30443
32027
  }
32028
+ static remapD1Resource(resources, d1ResourceName, databaseId) {
32029
+ return {
32030
+ resources: {
32031
+ ...resources,
32032
+ d1: resources.d1?.map((dbResource) => dbResource.name === d1ResourceName ? { ...dbResource, id: databaseId } : dbResource)
32033
+ },
32034
+ timeTravelBookmark: null
32035
+ };
32036
+ }
30444
32037
  getD1() {
30445
32038
  const d1 = this.deps.cloudflare?.d1;
30446
32039
  if (!d1) {
@@ -30459,11 +32052,7 @@ class DatabaseService {
30459
32052
  try {
30460
32053
  await this.deps.cloudflare.updateD1Binding(dashboardDeployment.deploymentId, databaseId);
30461
32054
  if (dashboardDeployment.resources?.d1?.length) {
30462
- const updatedResources = {
30463
- ...dashboardDeployment.resources,
30464
- d1: dashboardDeployment.resources.d1.map((dbResource) => dbResource.name === d1ResourceName ? { ...dbResource, id: databaseId } : dbResource)
30465
- };
30466
- await this.deps.db.update(gameDeployments).set({ resources: updatedResources }).where(eq(gameDeployments.id, dashboardDeployment.id));
32055
+ await this.deps.db.update(gameDeployments).set(DatabaseService.remapD1Resource(dashboardDeployment.resources, d1ResourceName, databaseId)).where(eq(gameDeployments.id, dashboardDeployment.id));
30467
32056
  }
30468
32057
  setAttribute("app.database.dashboard_binding", "updated");
30469
32058
  } catch (error) {
@@ -30474,20 +32063,36 @@ class DatabaseService {
30474
32063
  });
30475
32064
  }
30476
32065
  }
30477
- async reset(slug, user, schema2) {
32066
+ async reset(slug, user, request = {}) {
32067
+ const { schema: schema2, database } = request;
30478
32068
  setAttributes({
30479
32069
  "app.database.operation": "reset",
32070
+ "app.database.mode": database?.mode ?? (schema2 ? "legacy" : "none"),
30480
32071
  "app.database.schema_size": schema2?.sql.length,
30481
32072
  "app.database.schema_version": schema2?.hash
30482
32073
  });
30483
32074
  const d1 = this.getD1();
30484
32075
  const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32076
+ const state = await this.deps.db.query.gameDeploymentState.findFirst({
32077
+ where: eq(gameDeploymentState.gameId, game2.id)
32078
+ });
32079
+ if (isSchemaAdopted(state) && !database) {
32080
+ if (schema2) {
32081
+ throw new LegacySchemaUpgradeRequiredError;
32082
+ }
32083
+ throw new ValidationError("This game's database state is server-managed: resetting it requires " + "the mode-aware rebuild payload so the recorded state matches the " + "new database. Run the reset through the Playcademy CLI.");
32084
+ }
30485
32085
  const deploymentId = getGameDeploymentId(slug, this.deps.config.sstStage);
32086
+ let resetDatabaseId = null;
30486
32087
  try {
30487
32088
  const databaseId = await d1.reset(deploymentId);
32089
+ resetDatabaseId = databaseId;
30488
32090
  setAttribute("app.database.id", databaseId);
30489
32091
  let schemaPushed = false;
30490
- if (schema2?.sql) {
32092
+ if (database) {
32093
+ await this.rebuildDatabase(databaseId, database, game2.id, user);
32094
+ schemaPushed = true;
32095
+ } else if (schema2?.sql) {
30491
32096
  await d1.executeSchema(databaseId, schema2);
30492
32097
  schemaPushed = true;
30493
32098
  }
@@ -30503,11 +32108,7 @@ class DatabaseService {
30503
32108
  });
30504
32109
  setAttribute("app.database.active_deployment_found", Boolean(activeDeployment));
30505
32110
  if (activeDeployment?.resources?.d1?.length) {
30506
- const updatedResources = {
30507
- ...activeDeployment.resources,
30508
- d1: activeDeployment.resources.d1.map((dbResource) => dbResource.name === deploymentId ? { ...dbResource, id: databaseId } : dbResource)
30509
- };
30510
- await this.deps.db.update(gameDeployments).set({ resources: updatedResources }).where(eq(gameDeployments.id, activeDeployment.id));
32111
+ await this.deps.db.update(gameDeployments).set(DatabaseService.remapD1Resource(activeDeployment.resources, deploymentId, databaseId)).where(eq(gameDeployments.id, activeDeployment.id));
30511
32112
  }
30512
32113
  await this.syncDashboardD1Binding(game2.id, deploymentId, databaseId);
30513
32114
  setAttributes({
@@ -30521,18 +32122,81 @@ class DatabaseService {
30521
32122
  schemaPushed
30522
32123
  };
30523
32124
  } catch (error) {
32125
+ if (database && resetDatabaseId) {
32126
+ await this.recordLiveFingerprint(game2.id, resetDatabaseId);
32127
+ }
30524
32128
  this.deps.alerts.notifyDatabaseResetFailure({
30525
32129
  slug,
30526
32130
  displayName: game2.displayName,
30527
32131
  error: errorMessage(error),
30528
32132
  developer: { id: user.id, email: user.email }
30529
32133
  }).catch(catchAttrs("alerts.delivery", { "app.alerts.type": "database_reset" }));
32134
+ if (error instanceof DomainError) {
32135
+ throw error;
32136
+ }
30530
32137
  throw new ValidationError(`Database reset failed: ${errorMessage(error)}`);
30531
32138
  }
30532
32139
  }
32140
+ async rebuildDatabase(databaseId, payload, gameId, user) {
32141
+ const d1 = this.getD1();
32142
+ if (payload.mode === "migrate") {
32143
+ const deployId = `reset:${crypto.randomUUID()}`;
32144
+ await d1.ensureMigrationLedger(databaseId);
32145
+ for (const migration of payload.migrations) {
32146
+ await d1.applyMigration(databaseId, {
32147
+ tag: migration.tag,
32148
+ statements: migration.statements,
32149
+ checksum: migration.checksum,
32150
+ deployId,
32151
+ appliedBy: user.id
32152
+ });
32153
+ }
32154
+ setAttribute("app.database.migrations_replayed", payload.migrations.length);
32155
+ const fingerprint2 = await d1.fingerprintSchema(databaseId);
32156
+ await this.persistDeploymentState(gameId, {
32157
+ schemaFingerprint: fingerprint2.fingerprint,
32158
+ schemaHash: null,
32159
+ schemaSnapshot: null
32160
+ });
32161
+ return;
32162
+ }
32163
+ const statements = splitSqlStatements(payload.sql);
32164
+ if (statements.length > 0) {
32165
+ await d1.batch(databaseId, [
32166
+ { sql: "PRAGMA defer_foreign_keys = on" },
32167
+ ...statements.map((statement) => ({ sql: statement })),
32168
+ { sql: "PRAGMA defer_foreign_keys = off" }
32169
+ ]);
32170
+ }
32171
+ setAttribute("app.database.push_statement_count", statements.length);
32172
+ const fingerprint = await d1.fingerprintSchema(databaseId);
32173
+ await this.persistDeploymentState(gameId, {
32174
+ schemaFingerprint: fingerprint.fingerprint,
32175
+ schemaHash: payload.nextHash,
32176
+ schemaSnapshot: payload.nextSnapshot
32177
+ });
32178
+ }
32179
+ async persistDeploymentState(gameId, patch) {
32180
+ const set = { ...patch, updatedAt: new Date };
32181
+ await this.deps.db.insert(gameDeploymentState).values({ gameId, baselineSource: "deploy", ...set }).onConflictDoUpdate({ target: gameDeploymentState.gameId, set });
32182
+ }
32183
+ async recordLiveFingerprint(gameId, databaseId) {
32184
+ try {
32185
+ const fingerprint = await this.getD1().fingerprintSchema(databaseId);
32186
+ await this.persistDeploymentState(gameId, {
32187
+ schemaFingerprint: fingerprint.fingerprint
32188
+ });
32189
+ } catch (error) {
32190
+ addEvent("database.fingerprint_persist_failed", {
32191
+ "exception.type": errorType(error),
32192
+ "app.error.message": errorMessage(error)
32193
+ });
32194
+ }
32195
+ }
30533
32196
  }
30534
32197
  var init_database_service = __esm(() => {
30535
32198
  init_drizzle_orm();
32199
+ init_src4();
30536
32200
  init_helpers_index();
30537
32201
  init_tables_index();
30538
32202
  init_spans();
@@ -30540,6 +32204,527 @@ var init_database_service = __esm(() => {
30540
32204
  init_deployment_util();
30541
32205
  });
30542
32206
 
32207
+ // ../api-core/src/utils/secrets.util.ts
32208
+ async function listUserSecretKeys(cloudflare2, deploymentId) {
32209
+ try {
32210
+ const allKeys = await cloudflare2.listSecrets(deploymentId);
32211
+ return allKeys.filter((key) => key.startsWith(SECRETS_PREFIX)).map((key) => key.slice(SECRETS_PREFIX.length));
32212
+ } catch (error) {
32213
+ const message = errorMessage(error);
32214
+ if (message.includes("not found") || message.includes("10007")) {
32215
+ return null;
32216
+ }
32217
+ throw error;
32218
+ }
32219
+ }
32220
+ var init_secrets_util = __esm(() => {
32221
+ init_src();
32222
+ });
32223
+
32224
+ // ../api-core/src/services/deployment-state.service.ts
32225
+ function historyEventEntry(event) {
32226
+ const base = { at: event.createdAt.toISOString(), by: event.email ?? DELETED_ACCOUNT_LABEL };
32227
+ if (event.kind === "restore" && "restoredTo" in event.payload) {
32228
+ return [{ kind: "restore", ...base, restoredTo: event.payload.restoredTo }];
32229
+ }
32230
+ if (event.kind === "blocked" && "code" in event.payload) {
32231
+ return [
32232
+ { kind: "blocked", ...base, code: event.payload.code, reason: event.payload.reason }
32233
+ ];
32234
+ }
32235
+ return [];
32236
+ }
32237
+ function databaseIdFromResources(resources, deploymentId) {
32238
+ const database = resources?.d1?.find((db2) => db2.name === deploymentId) ?? resources?.d1?.[0];
32239
+ return database?.id ?? null;
32240
+ }
32241
+ function restorePointCapturedAt(row) {
32242
+ return row.bookmarkCapturedAt ?? row.deployedAt;
32243
+ }
32244
+
32245
+ class DeploymentStateService {
32246
+ deps;
32247
+ constructor(deps) {
32248
+ this.deps = deps;
32249
+ }
32250
+ async partitionSecretKeys(slug, manifest) {
32251
+ const managedKeys = Object.keys(manifest ?? {});
32252
+ if (!this.deps.cloudflare) {
32253
+ addEvent("deployment_state.secret_keys_unavailable", {
32254
+ "app.error.message": "Cloudflare provider not configured"
32255
+ });
32256
+ return { managedKeys, unmanagedKeys: null };
32257
+ }
32258
+ const deploymentId = getGameDeploymentId(slug, this.deps.config.sstStage);
32259
+ const remoteKeys = await listUserSecretKeys(this.deps.cloudflare, deploymentId);
32260
+ if (remoteKeys === null) {
32261
+ return { managedKeys, unmanagedKeys: [] };
32262
+ }
32263
+ const managed = new Set(managedKeys);
32264
+ return {
32265
+ managedKeys,
32266
+ unmanagedKeys: remoteKeys.filter((key) => !managed.has(key))
32267
+ };
32268
+ }
32269
+ async readAppliedMigrations(slug, resources) {
32270
+ if (!this.deps.cloudflare || !resources?.d1?.length) {
32271
+ return null;
32272
+ }
32273
+ const deploymentId = getGameDeploymentId(slug, this.deps.config.sstStage);
32274
+ const databaseId = databaseIdFromResources(resources, deploymentId);
32275
+ if (!databaseId) {
32276
+ return null;
32277
+ }
32278
+ const ledger = await this.deps.cloudflare.d1.readMigrationLedger(databaseId);
32279
+ setAttributes({ "app.deployment_state.applied_migrations": ledger.length });
32280
+ return ledger.map((row) => ({
32281
+ tag: row.tag,
32282
+ checksum: row.checksum,
32283
+ checksumAlgo: row.checksum_algo
32284
+ }));
32285
+ }
32286
+ async get(slug, user, options = {}) {
32287
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32288
+ const [state, gameDeployment, dashboardDeployment, lastSucceededJob, lastFailedJob] = await Promise.all([
32289
+ this.deps.db.query.gameDeploymentState.findFirst({
32290
+ where: eq(gameDeploymentState.gameId, game2.id)
32291
+ }),
32292
+ this.deps.db.query.gameDeployments.findFirst({
32293
+ where: activeDeploymentWhere(game2.id, "game"),
32294
+ columns: { codeHash: true, url: true, deployedAt: true, resources: true }
32295
+ }),
32296
+ this.deps.db.query.gameDeployments.findFirst({
32297
+ where: activeDeploymentWhere(game2.id, "dashboard"),
32298
+ columns: { url: true, deployedAt: true }
32299
+ }),
32300
+ findLastSuccessfulDeployWithEmail(this.deps.db, game2.id),
32301
+ this.deps.db.query.gameDeployJobs.findFirst({
32302
+ where: and(eq(gameDeployJobs.gameId, game2.id), eq(gameDeployJobs.status, "failed")),
32303
+ orderBy: desc(deployJobInstant()),
32304
+ columns: { events: true }
32305
+ })
32306
+ ]);
32307
+ const [secrets, appliedMigrations] = await Promise.all([
32308
+ this.partitionSecretKeys(slug, state?.secretsManifest ?? null),
32309
+ this.readAppliedMigrations(slug, gameDeployment?.resources ?? null)
32310
+ ]);
32311
+ setAttributes({
32312
+ "app.deployment_state.seeded": Boolean(state),
32313
+ "app.deployment_state.game_deployed": Boolean(gameDeployment),
32314
+ "app.deployment_state.dashboard_deployed": Boolean(dashboardDeployment)
32315
+ });
32316
+ return {
32317
+ gameId: game2.id,
32318
+ seeded: Boolean(state),
32319
+ game: gameDeployment ? {
32320
+ codeHash: gameDeployment.codeHash,
32321
+ buildHash: state?.buildHash ?? null,
32322
+ url: gameDeployment.url,
32323
+ deployedAt: gameDeployment.deployedAt.toISOString()
32324
+ } : null,
32325
+ dashboard: dashboardDeployment ? {
32326
+ url: dashboardDeployment.url,
32327
+ deployedAt: dashboardDeployment.deployedAt.toISOString()
32328
+ } : null,
32329
+ database: {
32330
+ appliedMigrations,
32331
+ lastFailure: parseMigrationFailure(lastFailedJob?.events ?? null),
32332
+ schemaHash: state?.schemaHash ?? null,
32333
+ schemaFingerprint: state?.schemaFingerprint ?? null,
32334
+ ...options.includeSchemaSnapshot && {
32335
+ schemaSnapshot: state?.schemaSnapshot ?? null
32336
+ }
32337
+ },
32338
+ secrets,
32339
+ integrationsHash: state?.integrationsHash ?? null,
32340
+ compatibilityDate: state?.compatibilityDate ?? null,
32341
+ lastDeploy: lastSucceededJob ? {
32342
+ at: lastSucceededJob.at.toISOString(),
32343
+ by: lastSucceededJob.email ?? DELETED_ACCOUNT_LABEL
32344
+ } : null
32345
+ };
32346
+ }
32347
+ requireCloudflare() {
32348
+ if (!this.deps.cloudflare) {
32349
+ throw new ValidationError("Deployment-state operations are not available in this environment");
32350
+ }
32351
+ return this.deps.cloudflare;
32352
+ }
32353
+ async resolveDatabaseId(slug, gameId) {
32354
+ const databaseId = await this.findDatabaseId(slug, gameId);
32355
+ if (!databaseId) {
32356
+ throw new ValidationError("Game has no deployed database — deploy with a database binding first");
32357
+ }
32358
+ return databaseId;
32359
+ }
32360
+ findSchemaHashState(gameId) {
32361
+ return this.deps.db.query.gameDeploymentState.findFirst({
32362
+ where: eq(gameDeploymentState.gameId, gameId),
32363
+ columns: { schemaHash: true }
32364
+ });
32365
+ }
32366
+ async findDatabaseId(slug, gameId) {
32367
+ const deployment = await this.deps.db.query.gameDeployments.findFirst({
32368
+ where: activeDeploymentWhere(gameId, "game"),
32369
+ columns: { resources: true }
32370
+ });
32371
+ return databaseIdFromResources(deployment?.resources, getGameDeploymentId(slug, this.deps.config.sstStage));
32372
+ }
32373
+ async baseline(slug, input, user) {
32374
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32375
+ const cf = this.requireCloudflare();
32376
+ const state = await this.deps.db.query.gameDeploymentState.findFirst({
32377
+ where: eq(gameDeploymentState.gameId, game2.id)
32378
+ });
32379
+ const schemaAdopted = isSchemaAdopted(state);
32380
+ const migrateOnlyClaim = Boolean(input.lastAppliedMigrationTag) && input.schemaHash === undefined && input.schemaSnapshot === undefined;
32381
+ if (schemaAdopted && !migrateOnlyClaim) {
32382
+ throw new BaselineAlreadyAdoptedError(state?.baselineSource ?? null);
32383
+ }
32384
+ const databaseId = await this.resolveDatabaseId(slug, game2.id);
32385
+ const [ledger, live] = await Promise.all([
32386
+ cf.d1.readMigrationLedger(databaseId),
32387
+ cf.d1.fingerprintSchema(databaseId)
32388
+ ]);
32389
+ const verdict = evaluateBaselineGuardrails({
32390
+ ledgerTags: ledger.map((row) => row.tag),
32391
+ liveTables: live.tables
32392
+ });
32393
+ if (verdict === "ledger-not-empty") {
32394
+ throw new BaselineLedgerNotEmptyError(ledger.map((row) => row.tag));
32395
+ }
32396
+ if (verdict === "database-empty") {
32397
+ throw new BaselineDatabaseEmptyError;
32398
+ }
32399
+ if (schemaAdopted && state?.schemaFingerprint && live.fingerprint !== state.schemaFingerprint) {
32400
+ throw new DeploymentStateDriftError({
32401
+ expectedFingerprint: state.schemaFingerprint,
32402
+ actualFingerprint: live.fingerprint
32403
+ });
32404
+ }
32405
+ if (input.lastAppliedMigrationTag && input.evidence?.length) {
32406
+ const [tables, lastDeploy] = await Promise.all([
32407
+ cf.d1.readTableColumns(databaseId, live.tables),
32408
+ findLastSuccessfulDeploy(this.deps.db, game2.id)
32409
+ ]);
32410
+ assertBaselineClaimValid({
32411
+ claimedTag: input.lastAppliedMigrationTag,
32412
+ evidence: input.evidence,
32413
+ tables,
32414
+ indexes: new Set(live.indexes),
32415
+ views: new Set(live.views),
32416
+ lastDeployAt: lastDeploy?.at ?? null,
32417
+ allowUnverified: Boolean(input.allowUnverified),
32418
+ source: "manual",
32419
+ gameId: game2.id,
32420
+ userId: user.id
32421
+ });
32422
+ }
32423
+ let recordedTags = [];
32424
+ if (input.lastAppliedMigrationTag) {
32425
+ const slice = sliceJournalToTag(input.journal ?? [], input.lastAppliedMigrationTag);
32426
+ if (!slice) {
32427
+ throw new ValidationError(`lastAppliedMigrationTag '${input.lastAppliedMigrationTag}' is not in the ` + "submitted journal");
32428
+ }
32429
+ await cf.d1.ensureMigrationLedger(databaseId);
32430
+ await cf.d1.recordLedgerRows(databaseId, {
32431
+ rows: slice,
32432
+ deployId: `baseline:${crypto.randomUUID()}`,
32433
+ appliedBy: user.id,
32434
+ source: "baseline"
32435
+ });
32436
+ recordedTags = slice.map((entry) => entry.tag);
32437
+ }
32438
+ const graduating = migrateOnlyClaim && isPushAdopted(state);
32439
+ const set = {
32440
+ ...graduating ? { schemaHash: null, schemaSnapshot: null } : {
32441
+ ...input.schemaHash !== undefined && { schemaHash: input.schemaHash },
32442
+ ...input.schemaSnapshot !== undefined && {
32443
+ schemaSnapshot: input.schemaSnapshot
32444
+ }
32445
+ },
32446
+ schemaFingerprint: live.fingerprint,
32447
+ baselineSource: "manual-baseline",
32448
+ updatedAt: new Date
32449
+ };
32450
+ await this.persistDeploymentState(game2.id, set);
32451
+ addEvent("deployment_state.baseline_recorded", {
32452
+ "app.game.id": game2.id,
32453
+ "app.deployment_state.baseline_source": "manual-baseline",
32454
+ "app.deployment_state.baseline_ledger_rows": recordedTags.length,
32455
+ "app.deployment_state.baseline_has_snapshot": input.schemaSnapshot !== undefined,
32456
+ "app.deployment_state.baseline_graduated_from_push": graduating
32457
+ });
32458
+ return this.get(slug, user);
32459
+ }
32460
+ async realignMigration(slug, tag, checksum, user) {
32461
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32462
+ const cf = this.requireCloudflare();
32463
+ const databaseId = await this.resolveDatabaseId(slug, game2.id);
32464
+ const ledger = await cf.d1.readMigrationLedger(databaseId);
32465
+ if (!ledger.some((row) => row.tag === tag)) {
32466
+ throw new NotFoundError("Applied migration", tag);
32467
+ }
32468
+ const updated = await cf.d1.updateLedgerChecksum(databaseId, { tag, checksum });
32469
+ if (!updated) {
32470
+ throw new NotFoundError("Applied migration", tag);
32471
+ }
32472
+ addEvent("deployment_state.migration_realigned", {
32473
+ "app.game.id": game2.id,
32474
+ "app.d1.migration_tag": tag,
32475
+ "app.user.id": user.id
32476
+ });
32477
+ return { tag, checksum, checksumAlgo: MIGRATION_CHECKSUM_ALGO };
32478
+ }
32479
+ async persistDeploymentState(gameId, set) {
32480
+ await this.deps.db.insert(gameDeploymentState).values({ gameId, ...set }).onConflictDoUpdate({ target: gameDeploymentState.gameId, set });
32481
+ }
32482
+ async updateDeploymentState(gameId, set) {
32483
+ const updated = await this.deps.db.update(gameDeploymentState).set(set).where(eq(gameDeploymentState.gameId, gameId)).returning({ gameId: gameDeploymentState.gameId });
32484
+ return updated.length > 0;
32485
+ }
32486
+ async resolveMigration(slug, tag, input, user) {
32487
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32488
+ const cf = this.requireCloudflare();
32489
+ const databaseId = await this.resolveDatabaseId(slug, game2.id);
32490
+ const [ledger, live] = await Promise.all([
32491
+ cf.d1.readMigrationLedger(databaseId),
32492
+ cf.d1.fingerprintSchema(databaseId)
32493
+ ]);
32494
+ const exists2 = ledger.some((row) => row.tag === tag);
32495
+ if (input.resolution === "applied") {
32496
+ if (!input.checksum) {
32497
+ throw new ValidationError("Resolving a migration as 'applied' requires its checksum");
32498
+ }
32499
+ if (exists2) {
32500
+ throw new AlreadyExistsError(`Migration '${tag}' is already recorded as applied`);
32501
+ }
32502
+ await cf.d1.ensureMigrationLedger(databaseId);
32503
+ await cf.d1.recordLedgerRows(databaseId, {
32504
+ rows: [{ tag, checksum: input.checksum }],
32505
+ deployId: `resolve:${crypto.randomUUID()}`,
32506
+ appliedBy: user.id,
32507
+ source: "resolve"
32508
+ });
32509
+ } else {
32510
+ if (!exists2) {
32511
+ throw new NotFoundError("Migration ledger row", tag);
32512
+ }
32513
+ await cf.d1.deleteLedgerRow(databaseId, tag);
32514
+ }
32515
+ const fingerprintRecorded = await this.updateDeploymentState(game2.id, {
32516
+ schemaFingerprint: live.fingerprint,
32517
+ updatedAt: new Date
32518
+ });
32519
+ addEvent("deployment_state.migration_resolved", {
32520
+ "app.game.id": game2.id,
32521
+ "app.d1.migration_tag": tag,
32522
+ "app.deployment_state.resolution": input.resolution,
32523
+ "app.deployment_state.fingerprint_rerecorded": fingerprintRecorded,
32524
+ "app.user.id": user.id
32525
+ });
32526
+ return {
32527
+ tag,
32528
+ resolution: input.resolution,
32529
+ schemaFingerprint: live.fingerprint,
32530
+ fingerprintRecorded
32531
+ };
32532
+ }
32533
+ async history(slug, user, options = {}) {
32534
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32535
+ const limit = options.limit ?? 20;
32536
+ const [jobs, events] = await Promise.all([
32537
+ this.deps.db.select({
32538
+ status: gameDeployJobs.status,
32539
+ createdAt: gameDeployJobs.createdAt,
32540
+ completedAt: gameDeployJobs.completedAt,
32541
+ deployId: gameDeployJobs.deployId,
32542
+ error: gameDeployJobs.error,
32543
+ email: users.email
32544
+ }).from(gameDeployJobs).leftJoin(users, eq(gameDeployJobs.userId, users.id)).where(eq(gameDeployJobs.gameId, game2.id)).orderBy(desc(deployJobInstant())).limit(limit),
32545
+ this.deps.db.select({
32546
+ kind: gameDeployEvents.kind,
32547
+ payload: gameDeployEvents.payload,
32548
+ createdAt: gameDeployEvents.createdAt,
32549
+ email: users.email
32550
+ }).from(gameDeployEvents).leftJoin(users, eq(gameDeployEvents.userId, users.id)).where(eq(gameDeployEvents.gameId, game2.id)).orderBy(desc(gameDeployEvents.createdAt)).limit(limit)
32551
+ ]);
32552
+ setAttributes({
32553
+ "app.deployment_state.history_jobs": jobs.length,
32554
+ "app.deployment_state.history_events": events.length
32555
+ });
32556
+ const deploys = jobs.map((job) => ({
32557
+ kind: "deploy",
32558
+ status: job.status,
32559
+ at: (job.completedAt ?? job.createdAt).toISOString(),
32560
+ completedAt: job.completedAt?.toISOString() ?? null,
32561
+ by: job.email ?? DELETED_ACCOUNT_LABEL,
32562
+ deployId: job.deployId,
32563
+ error: job.error
32564
+ }));
32565
+ const merged = [...deploys, ...events.flatMap(historyEventEntry)].toSorted((a, b) => a.at < b.at ? 1 : -1).slice(0, limit);
32566
+ return { deploys: merged };
32567
+ }
32568
+ async restorePoints(slug, user) {
32569
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32570
+ const retentionCutoff = new Date(Date.now() - D1_TIME_TRAVEL_RETENTION_DAYS * 24 * 60 * 60 * 1000);
32571
+ const [currentDatabaseId, rows, state] = await Promise.all([
32572
+ this.findDatabaseId(slug, game2.id),
32573
+ this.deps.db.query.gameDeployments.findMany({
32574
+ where: and(eq(gameDeployments.gameId, game2.id), eq(gameDeployments.target, "game"), isNotNull(gameDeployments.timeTravelBookmark), gte(gameDeployments.deployedAt, retentionCutoff)),
32575
+ orderBy: desc(gameDeployments.deployedAt),
32576
+ limit: 100,
32577
+ columns: {
32578
+ id: true,
32579
+ deployedAt: true,
32580
+ bookmarkCapturedAt: true,
32581
+ isActive: true,
32582
+ resources: true
32583
+ }
32584
+ }),
32585
+ this.findSchemaHashState(game2.id)
32586
+ ]);
32587
+ if (isPushAdopted(state)) {
32588
+ return { restorePoints: [], restoreUnsupported: true };
32589
+ }
32590
+ if (!currentDatabaseId) {
32591
+ return { restorePoints: [], restoreUnsupported: false };
32592
+ }
32593
+ const deploymentId = getGameDeploymentId(slug, this.deps.config.sstStage);
32594
+ const restorable = rows.filter((row) => databaseIdFromResources(row.resources, deploymentId) === currentDatabaseId && restorePointCapturedAt(row) >= retentionCutoff).slice(0, 20);
32595
+ setAttributes({ "app.deployment_state.restore_points": restorable.length });
32596
+ return {
32597
+ restorePoints: restorable.map((row) => ({
32598
+ id: row.id,
32599
+ capturedAt: restorePointCapturedAt(row).toISOString(),
32600
+ active: row.isActive
32601
+ })),
32602
+ restoreUnsupported: false
32603
+ };
32604
+ }
32605
+ async restoreToBookmark(slug, input, user) {
32606
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32607
+ const cf = this.requireCloudflare();
32608
+ const [row, state, currentDatabaseId, runningJob] = await Promise.all([
32609
+ this.deps.db.query.gameDeployments.findFirst({
32610
+ where: and(eq(gameDeployments.id, input.restorePointId), eq(gameDeployments.gameId, game2.id), eq(gameDeployments.target, "game")),
32611
+ columns: {
32612
+ id: true,
32613
+ timeTravelBookmark: true,
32614
+ deployedAt: true,
32615
+ bookmarkCapturedAt: true,
32616
+ resources: true
32617
+ }
32618
+ }),
32619
+ this.findSchemaHashState(game2.id),
32620
+ this.findDatabaseId(slug, game2.id),
32621
+ this.deps.db.query.gameDeployJobs.findFirst({
32622
+ where: and(eq(gameDeployJobs.gameId, game2.id), or(eq(gameDeployJobs.status, "pending"), and(eq(gameDeployJobs.status, "running"), gt(gameDeployJobs.leaseExpiresAt, new Date)))),
32623
+ columns: { id: true }
32624
+ })
32625
+ ]);
32626
+ if (!row?.timeTravelBookmark) {
32627
+ throw new NotFoundError("Bookmark", input.restorePointId);
32628
+ }
32629
+ if (isPushAdopted(state)) {
32630
+ throw new ValidationError("Restore is not supported for push-mode projects: rewinding the " + "database would leave future push deploys diffing against the " + "wrong schema.", { code: DEPLOY_ERROR_CODES.restoreUnsupported });
32631
+ }
32632
+ if (!currentDatabaseId) {
32633
+ throw new ValidationError("Game has no deployed database — deploy with a database binding first");
32634
+ }
32635
+ const databaseId = currentDatabaseId;
32636
+ const deploymentId = getGameDeploymentId(slug, this.deps.config.sstStage);
32637
+ if (databaseIdFromResources(row.resources, deploymentId) !== databaseId) {
32638
+ throw new ValidationError("This bookmark was captured on a previous database (a reset replaced " + "it since) and can no longer be restored");
32639
+ }
32640
+ const retentionCutoff = new Date(Date.now() - D1_TIME_TRAVEL_RETENTION_DAYS * 24 * 60 * 60 * 1000);
32641
+ if (restorePointCapturedAt(row) < retentionCutoff) {
32642
+ throw new ValidationError(`This bookmark is older than Time Travel's ${D1_TIME_TRAVEL_RETENTION_DAYS}-day ` + "retention window and can no longer be restored.", { code: DEPLOY_ERROR_CODES.restoreExpired });
32643
+ }
32644
+ if (runningJob) {
32645
+ throw new ValidationError("A deploy is currently running for this game. Wait for it to finish, " + "then restore.", { code: DEPLOY_ERROR_CODES.restoreBlockedByDeploy });
32646
+ }
32647
+ const restored = await cf.d1.restoreBookmark(databaseId, row.timeTravelBookmark);
32648
+ const restoredTo = restorePointCapturedAt(row).toISOString();
32649
+ let live;
32650
+ let fingerprintRecorded;
32651
+ try {
32652
+ live = await cf.d1.fingerprintSchema(databaseId);
32653
+ fingerprintRecorded = await this.updateDeploymentState(game2.id, {
32654
+ schemaFingerprint: live.fingerprint,
32655
+ updatedAt: new Date
32656
+ });
32657
+ await this.deps.db.insert(gameDeployEvents).values({
32658
+ gameId: game2.id,
32659
+ userId: user.id,
32660
+ kind: "restore",
32661
+ payload: { restoredTo, previousBookmark: restored.previousBookmark }
32662
+ });
32663
+ } catch (error) {
32664
+ throw new ValidationError("The database WAS restored, but re-recording its schema " + `fingerprint failed (${errorMessage(error)}). Run the same ` + "restore again to complete it.", { code: DEPLOY_ERROR_CODES.restoreIncomplete });
32665
+ }
32666
+ addEvent("deployment_state.bookmark_restored", {
32667
+ "app.game.id": game2.id,
32668
+ "app.deployment_state.restore_point": row.id,
32669
+ "app.deployment_state.fingerprint_rerecorded": fingerprintRecorded,
32670
+ "app.user.id": user.id
32671
+ });
32672
+ return {
32673
+ restorePointId: row.id,
32674
+ restoredTo,
32675
+ schemaFingerprint: live.fingerprint,
32676
+ fingerprintRecorded,
32677
+ previousBookmark: restored.previousBookmark
32678
+ };
32679
+ }
32680
+ async reportDeployBlocked(slug, user, report) {
32681
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
32682
+ const recent = await this.deps.db.query.gameDeployEvents.findMany({
32683
+ where: and(eq(gameDeployEvents.gameId, game2.id), eq(gameDeployEvents.kind, "blocked"), gt(gameDeployEvents.createdAt, new Date(Date.now() - BLOCKED_ALERT_DEDUP_MS))),
32684
+ orderBy: desc(gameDeployEvents.createdAt),
32685
+ limit: 10,
32686
+ columns: { payload: true }
32687
+ });
32688
+ const duplicate = recent.some((event) => ("code" in event.payload) && event.payload.code === report.code);
32689
+ await this.deps.db.insert(gameDeployEvents).values({
32690
+ gameId: game2.id,
32691
+ userId: user.id,
32692
+ kind: "blocked",
32693
+ payload: { code: report.code, reason: report.reason }
32694
+ });
32695
+ addEvent("deployment_state.deploy_blocked", {
32696
+ "app.game.id": game2.id,
32697
+ "app.deploy.blocked_code": report.code,
32698
+ "app.user.id": user.id,
32699
+ "app.alerts.deduped": duplicate
32700
+ });
32701
+ if (!duplicate) {
32702
+ await this.deps.alerts.notifyDeployBlocked({
32703
+ slug,
32704
+ displayName: game2.displayName,
32705
+ reason: report.reason,
32706
+ developer: { id: user.id, email: user.email ?? null }
32707
+ });
32708
+ }
32709
+ }
32710
+ }
32711
+ var BLOCKED_ALERT_DEDUP_MS;
32712
+ var init_deployment_state_service = __esm(() => {
32713
+ init_drizzle_orm();
32714
+ init_src4();
32715
+ init_src();
32716
+ init_helpers_index();
32717
+ init_tables_index();
32718
+ init_spans();
32719
+ init_game2();
32720
+ init_errors();
32721
+ init_baseline_validation_util();
32722
+ init_deployment_util();
32723
+ init_migration_util();
32724
+ init_secrets_util();
32725
+ BLOCKED_ALERT_DEDUP_MS = 10 * 60 * 1000;
32726
+ });
32727
+
30543
32728
  // ../api-core/src/services/domain.service.ts
30544
32729
  class DomainService {
30545
32730
  deps;
@@ -30906,6 +33091,7 @@ var init_kv_service = __esm(() => {
30906
33091
  // ../api-core/src/services/secrets.service.ts
30907
33092
  class SecretsService {
30908
33093
  deps;
33094
+ pepperPromise = null;
30909
33095
  constructor(deps) {
30910
33096
  this.deps = deps;
30911
33097
  }
@@ -30918,36 +33104,69 @@ class SecretsService {
30918
33104
  getGameDeploymentId(slug) {
30919
33105
  return getGameDeploymentId(slug, this.deps.config.sstStage);
30920
33106
  }
30921
- async listKeys(slug, user) {
30922
- await this.deps.validateDeveloperAccessBySlug(user, slug);
30923
- const cf = this.getCloudflare();
30924
- const deploymentId = this.getGameDeploymentId(slug);
30925
- try {
30926
- const allKeys = await cf.listSecrets(deploymentId);
30927
- const userKeys = allKeys.filter((k) => k.startsWith(SECRETS_PREFIX)).map((k) => k.slice(SECRETS_PREFIX.length));
30928
- setAttributes({
30929
- "app.secrets.operation": "list",
30930
- "app.secrets.count": userKeys.length,
30931
- "app.secrets.game_deployed": true
30932
- });
30933
- return userKeys;
30934
- } catch (error) {
30935
- const message = errorMessage(error);
30936
- if (message.includes("not found") || message.includes("10007")) {
33107
+ getPepper() {
33108
+ const pepperSecret = this.deps.config.secretsManifestPepper;
33109
+ if (!pepperSecret) {
33110
+ throw new ValidationError("Secrets manifest is not configured (missing manifest pepper secret)");
33111
+ }
33112
+ this.pepperPromise ??= deriveSecretsManifestPepper(pepperSecret);
33113
+ return this.pepperPromise;
33114
+ }
33115
+ async computeManifestEntries(gameId, secrets) {
33116
+ const pepper = await this.getPepper();
33117
+ const entries = {};
33118
+ for (const [key, value] of Object.entries(secrets)) {
33119
+ entries[key] = await computeSecretDigest(pepper, { gameId, key, value });
33120
+ }
33121
+ return entries;
33122
+ }
33123
+ async readManifest(gameId) {
33124
+ const state = await this.deps.db.query.gameDeploymentState.findFirst({
33125
+ where: eq(gameDeploymentState.gameId, gameId),
33126
+ columns: { secretsManifest: true }
33127
+ });
33128
+ return state?.secretsManifest ?? {};
33129
+ }
33130
+ async upsertManifestEntries(gameId, entries) {
33131
+ const merged = sql`coalesce(${gameDeploymentState.secretsManifest}, '{}'::jsonb) || ${JSON.stringify(entries)}::jsonb`;
33132
+ await this.deps.db.insert(gameDeploymentState).values({ gameId, secretsManifest: entries, updatedAt: new Date }).onConflictDoUpdate({
33133
+ target: gameDeploymentState.gameId,
33134
+ set: { secretsManifest: merged, updatedAt: new Date }
33135
+ });
33136
+ }
33137
+ async removeManifestKey(gameId, key) {
33138
+ await this.deps.db.update(gameDeploymentState).set({
33139
+ secretsManifest: sql`coalesce(${gameDeploymentState.secretsManifest}, '{}'::jsonb) - ${key}::text`,
33140
+ updatedAt: new Date
33141
+ }).where(eq(gameDeploymentState.gameId, gameId));
33142
+ }
33143
+ assertNoReservedKeys(keys, operation) {
33144
+ for (const key of keys) {
33145
+ if (INTERNAL_SECRET_KEYS.includes(key)) {
30937
33146
  setAttributes({
30938
- "app.secrets.operation": "list",
30939
- "app.secrets.count": 0,
30940
- "app.secrets.game_deployed": false
33147
+ "app.secrets.operation": operation,
33148
+ "app.secrets.reserved_key_rejected": true
30941
33149
  });
30942
- return [];
33150
+ throw new ValidationError(operation === "set" ? `Cannot set reserved secret "${key}"` : `Reserved secret "${key}" cannot be managed — remove it locally`);
30943
33151
  }
30944
- throw error;
30945
33152
  }
30946
33153
  }
30947
- async setSecrets(slug, newSecrets, user) {
33154
+ async listKeys(slug, user) {
30948
33155
  await this.deps.validateDeveloperAccessBySlug(user, slug);
30949
33156
  const cf = this.getCloudflare();
30950
33157
  const deploymentId = this.getGameDeploymentId(slug);
33158
+ const userKeys = await listUserSecretKeys(cf, deploymentId);
33159
+ setAttributes({
33160
+ "app.secrets.operation": "list",
33161
+ "app.secrets.count": userKeys?.length ?? 0,
33162
+ "app.secrets.game_deployed": userKeys !== null
33163
+ });
33164
+ return userKeys ?? [];
33165
+ }
33166
+ async setSecrets(slug, newSecrets, user) {
33167
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
33168
+ const cf = this.getCloudflare();
33169
+ const deploymentId = this.getGameDeploymentId(slug);
30951
33170
  const secretKeys = Object.keys(newSecrets);
30952
33171
  if (secretKeys.length === 0) {
30953
33172
  throw new ValidationError("At least one secret must be provided");
@@ -30956,14 +33175,9 @@ class SecretsService {
30956
33175
  if (typeof value !== "string") {
30957
33176
  throw new ValidationError(`Secret value for "${key}" must be a string`);
30958
33177
  }
30959
- if (INTERNAL_SECRET_KEYS.includes(key)) {
30960
- setAttributes({
30961
- "app.secrets.operation": "set",
30962
- "app.secrets.reserved_key_rejected": true
30963
- });
30964
- throw new ValidationError(`Cannot set reserved secret "${key}"`);
30965
- }
30966
33178
  }
33179
+ this.assertNoReservedKeys(secretKeys, "set");
33180
+ const manifestEntries = await this.computeManifestEntries(game2.id, newSecrets);
30967
33181
  try {
30968
33182
  const prefixedSecrets = {};
30969
33183
  for (const [key, value] of Object.entries(newSecrets)) {
@@ -30976,8 +33190,6 @@ class SecretsService {
30976
33190
  "app.secrets.game_deployed": true,
30977
33191
  "app.secrets.reserved_key_rejected": false
30978
33192
  });
30979
- const allKeys = await cf.listSecrets(deploymentId);
30980
- return allKeys.filter((k) => k.startsWith(SECRETS_PREFIX)).map((k) => k.slice(SECRETS_PREFIX.length));
30981
33193
  } catch (error) {
30982
33194
  const message = errorMessage(error);
30983
33195
  if (message.includes("not found") || message.includes("10007")) {
@@ -30989,6 +33201,9 @@ class SecretsService {
30989
33201
  }
30990
33202
  throw error;
30991
33203
  }
33204
+ await this.upsertManifestEntries(game2.id, manifestEntries);
33205
+ const allKeys = await cf.listSecrets(deploymentId);
33206
+ return allKeys.filter((k) => k.startsWith(SECRETS_PREFIX)).map((k) => k.slice(SECRETS_PREFIX.length));
30992
33207
  }
30993
33208
  async deleteSecret(slug, key, user) {
30994
33209
  if (INTERNAL_SECRET_KEYS.includes(key)) {
@@ -30998,19 +33213,25 @@ class SecretsService {
30998
33213
  });
30999
33214
  throw new ValidationError(`Cannot delete reserved secret "${key}"`);
31000
33215
  }
31001
- await this.deps.validateDeveloperAccessBySlug(user, slug);
33216
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
31002
33217
  const cf = this.getCloudflare();
31003
33218
  const deploymentId = this.getGameDeploymentId(slug);
33219
+ const manifest = await this.readManifest(game2.id);
33220
+ const managed = key in manifest;
31004
33221
  try {
31005
33222
  const prefixedKey = `${SECRETS_PREFIX}${key}`;
31006
33223
  const existingKeys = await cf.listSecrets(deploymentId);
31007
- if (!existingKeys.includes(prefixedKey)) {
33224
+ const onWorker = existingKeys.includes(prefixedKey);
33225
+ if (!onWorker && !managed) {
31008
33226
  throw new NotFoundError("Secret", key);
31009
33227
  }
31010
- await cf.deleteSecret(deploymentId, prefixedKey);
33228
+ if (onWorker) {
33229
+ await cf.deleteSecret(deploymentId, prefixedKey);
33230
+ }
31011
33231
  setAttributes({
31012
33232
  "app.secrets.operation": "delete",
31013
33233
  "app.secrets.game_deployed": true,
33234
+ "app.secrets.managed": managed,
31014
33235
  "app.secrets.reserved_key_rejected": false
31015
33236
  });
31016
33237
  } catch (error) {
@@ -31027,14 +33248,45 @@ class SecretsService {
31027
33248
  }
31028
33249
  throw error;
31029
33250
  }
33251
+ if (managed) {
33252
+ await this.removeManifestKey(game2.id, key);
33253
+ }
33254
+ }
33255
+ async diff(slug, localSecrets, user) {
33256
+ const game2 = await this.deps.validateDeveloperAccessBySlug(user, slug);
33257
+ const deploymentId = this.getGameDeploymentId(slug);
33258
+ this.assertNoReservedKeys(Object.keys(localSecrets), "diff");
33259
+ const [manifest, remoteKeys, localDigests] = await Promise.all([
33260
+ this.readManifest(game2.id),
33261
+ this.deps.cloudflare ? listUserSecretKeys(this.deps.cloudflare, deploymentId) : null,
33262
+ this.computeManifestEntries(game2.id, localSecrets)
33263
+ ]);
33264
+ const verdicts = computeSecretsDiff({
33265
+ localDigests,
33266
+ manifest,
33267
+ remoteKeys: remoteKeys ?? []
33268
+ });
33269
+ setAttributes({
33270
+ "app.secrets.operation": "diff",
33271
+ "app.secrets.game_deployed": remoteKeys !== null,
33272
+ "app.secrets.diff_added": verdicts.added.length,
33273
+ "app.secrets.diff_changed": verdicts.changed.length,
33274
+ "app.secrets.diff_unchanged": verdicts.unchanged.length,
33275
+ "app.secrets.diff_remote_only_managed": verdicts.remoteOnlyManaged.length,
33276
+ "app.secrets.diff_remote_only_unmanaged": verdicts.remoteOnlyUnmanaged.length
33277
+ });
33278
+ return verdicts;
31030
33279
  }
31031
33280
  }
31032
33281
  var INTERNAL_SECRET_KEYS;
31033
33282
  var init_secrets_service = __esm(() => {
33283
+ init_drizzle_orm();
31034
33284
  init_src();
33285
+ init_tables_index();
31035
33286
  init_spans();
31036
33287
  init_errors();
31037
33288
  init_deployment_util();
33289
+ init_secrets_util();
31038
33290
  INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY", "GAME_ID", "PLAYCADEMY_BASE_URL"];
31039
33291
  });
31040
33292
  // ../edge-play/src/game/setup.ts
@@ -31572,7 +33824,10 @@ var init_emoji = __esm(() => {
31572
33824
  });
31573
33825
 
31574
33826
  // ../data/src/domains/game/schemas.ts
31575
- var HttpUrlSchema, GameEmojiSchema, GameMetadataRecordSchema, InsertGameSchema, UpdateGameSchema, InsertGameDeploymentSchema, InsertGameDeployJobSchema, UpsertGameMetadataSchema, PatchGameMetadataSchema, AddGameMemberSchema, UpdateGameMemberRoleSchema, AddGameDashboardUserSchema, VerifyGameDashboardLoginSchema, AcceptGameDashboardInviteSchema, AcceptGameDashboardResetSchema, ALLOWED_UPLOAD_EXTENSIONS, InitiateUploadSchema, AddCustomHostnameSchema, SetSecretsRequestSchema, SeedRequestSchema, SchemaInfoSchema, DatabaseResetRequestSchema, VerifyTokenSchema, KVSeedRequestSchema, DeployRequestSchema;
33827
+ function requestsBinding(binding) {
33828
+ return binding === true || Array.isArray(binding) && binding.length > 0;
33829
+ }
33830
+ var HttpUrlSchema, GameEmojiSchema, GameMetadataRecordSchema, InsertGameSchema, UpdateGameSchema, InsertGameDeploymentSchema, InsertGameDeployJobSchema, InsertGameDeploymentStateSchema, UpsertGameMetadataSchema, PatchGameMetadataSchema, AddGameMemberSchema, UpdateGameMemberRoleSchema, AddGameDashboardUserSchema, VerifyGameDashboardLoginSchema, AcceptGameDashboardInviteSchema, AcceptGameDashboardResetSchema, ALLOWED_UPLOAD_EXTENSIONS, InitiateUploadSchema, AddCustomHostnameSchema, SetSecretsRequestSchema, SecretsDiffRequestSchema, SeedRequestSchema, SchemaInfoSchema, VerifyTokenSchema, KVSeedRequestSchema, DeployMigrationSchema, DeployDatabaseSchema, DatabaseResetDatabaseSchema, DatabaseResetRequestSchema, BaselineEvidenceSchema, DeployBaselineSchema, DeploymentStateBaselineSchema, MigrationRealignSchema, MigrationResolveSchema, DatabaseRestoreSchema, DeployBlockedReportSchema, DeployRequestSchema;
31576
33831
  var init_schemas2 = __esm(() => {
31577
33832
  init_drizzle_zod();
31578
33833
  init_esm();
@@ -31651,6 +33906,9 @@ var init_schemas2 = __esm(() => {
31651
33906
  InsertGameDeployJobSchema = createInsertSchema(gameDeployJobs, {
31652
33907
  status: exports_external.enum(deployJobStatusEnum.enumValues)
31653
33908
  });
33909
+ InsertGameDeploymentStateSchema = createInsertSchema(gameDeploymentState, {
33910
+ secretsManifest: exports_external.record(exports_external.string(), exports_external.string()).nullable().optional()
33911
+ });
31654
33912
  UpsertGameMetadataSchema = exports_external.object({
31655
33913
  displayName: exports_external.string().min(1),
31656
33914
  platform: exports_external.enum(gamePlatformEnum.enumValues),
@@ -31708,6 +33966,9 @@ var init_schemas2 = __esm(() => {
31708
33966
  hostname: exports_external.string().min(1).max(255)
31709
33967
  });
31710
33968
  SetSecretsRequestSchema = exports_external.record(exports_external.string().min(1), exports_external.string());
33969
+ SecretsDiffRequestSchema = exports_external.object({
33970
+ secrets: exports_external.record(exports_external.string().min(1), exports_external.string())
33971
+ });
31711
33972
  SeedRequestSchema = exports_external.object({
31712
33973
  code: exports_external.string().min(1, "Seed code is required"),
31713
33974
  secrets: exports_external.record(exports_external.string(), exports_external.string()).optional()
@@ -31716,9 +33977,6 @@ var init_schemas2 = __esm(() => {
31716
33977
  sql: exports_external.string(),
31717
33978
  hash: exports_external.string()
31718
33979
  });
31719
- DatabaseResetRequestSchema = exports_external.object({
31720
- schema: SchemaInfoSchema.optional()
31721
- });
31722
33980
  VerifyTokenSchema = exports_external.object({
31723
33981
  token: exports_external.string().min(1, "Token is required")
31724
33982
  });
@@ -31730,8 +33988,126 @@ var init_schemas2 = __esm(() => {
31730
33988
  metadata: exports_external.record(exports_external.unknown()).optional()
31731
33989
  }))
31732
33990
  });
33991
+ DeployMigrationSchema = exports_external.object({
33992
+ tag: exports_external.string().min(1),
33993
+ statements: exports_external.array(exports_external.string().min(1)).min(1),
33994
+ checksum: exports_external.string().min(1)
33995
+ });
33996
+ DeployDatabaseSchema = exports_external.discriminatedUnion("mode", [
33997
+ exports_external.object({
33998
+ mode: exports_external.literal("push"),
33999
+ sql: exports_external.string(),
34000
+ baselineHash: exports_external.string().nullable(),
34001
+ nextSnapshot: exports_external.record(exports_external.string(), exports_external.unknown()),
34002
+ nextHash: exports_external.string().min(1),
34003
+ acceptDataLoss: exports_external.boolean().optional()
34004
+ }),
34005
+ exports_external.object({
34006
+ mode: exports_external.literal("migrate"),
34007
+ migrations: exports_external.array(DeployMigrationSchema)
34008
+ })
34009
+ ]);
34010
+ DatabaseResetDatabaseSchema = exports_external.discriminatedUnion("mode", [
34011
+ exports_external.object({
34012
+ mode: exports_external.literal("push"),
34013
+ sql: exports_external.string(),
34014
+ nextSnapshot: exports_external.record(exports_external.string(), exports_external.unknown()),
34015
+ nextHash: exports_external.string().min(1)
34016
+ }),
34017
+ exports_external.object({
34018
+ mode: exports_external.literal("migrate"),
34019
+ migrations: exports_external.array(DeployMigrationSchema)
34020
+ })
34021
+ ]);
34022
+ DatabaseResetRequestSchema = exports_external.object({
34023
+ schema: SchemaInfoSchema.optional(),
34024
+ database: DatabaseResetDatabaseSchema.optional()
34025
+ }).refine((data) => !(data.schema && data.database), {
34026
+ message: "Send either the database payload or the legacy schema field, not both",
34027
+ path: ["database"]
34028
+ });
34029
+ BaselineEvidenceSchema = exports_external.array(exports_external.object({
34030
+ tag: exports_external.string().min(1),
34031
+ generatedAt: exports_external.string().min(1),
34032
+ createsTables: exports_external.array(exports_external.object({
34033
+ name: exports_external.string().min(1),
34034
+ columns: exports_external.array(exports_external.string())
34035
+ })),
34036
+ addsColumns: exports_external.array(exports_external.object({
34037
+ table: exports_external.string().min(1),
34038
+ column: exports_external.string().min(1)
34039
+ })),
34040
+ createsIndexes: exports_external.array(exports_external.string()),
34041
+ createsViews: exports_external.array(exports_external.string()),
34042
+ dropsTables: exports_external.array(exports_external.string()),
34043
+ dropsColumns: exports_external.array(exports_external.object({
34044
+ table: exports_external.string().min(1),
34045
+ column: exports_external.string().min(1)
34046
+ })),
34047
+ dropsIndexes: exports_external.array(exports_external.string()),
34048
+ dropsViews: exports_external.array(exports_external.string())
34049
+ })).optional();
34050
+ DeployBaselineSchema = exports_external.object({
34051
+ lastAppliedMigrationTag: exports_external.string().min(1).optional(),
34052
+ journal: exports_external.array(exports_external.object({
34053
+ tag: exports_external.string().min(1),
34054
+ checksum: exports_external.string().min(1)
34055
+ })).optional(),
34056
+ evidence: BaselineEvidenceSchema,
34057
+ schemaSnapshot: exports_external.unknown().optional(),
34058
+ schemaHash: exports_external.string().min(1).optional(),
34059
+ integrationsHash: exports_external.string().min(1).optional(),
34060
+ buildHash: exports_external.string().min(1).optional()
34061
+ }).refine((data) => !data.lastAppliedMigrationTag === !data.journal, {
34062
+ message: "lastAppliedMigrationTag and journal must be provided together",
34063
+ path: ["journal"]
34064
+ }).refine((data) => data.schemaSnapshot === undefined === !data.schemaHash, {
34065
+ message: "schemaSnapshot and schemaHash must be provided together",
34066
+ path: ["schemaHash"]
34067
+ }).refine((data) => Boolean(data.lastAppliedMigrationTag || data.schemaHash || data.integrationsHash || data.buildHash), {
34068
+ message: "A baseline must claim something — migration history, a schema snapshot, or artifact hashes",
34069
+ path: ["lastAppliedMigrationTag"]
34070
+ });
34071
+ DeploymentStateBaselineSchema = exports_external.object({
34072
+ lastAppliedMigrationTag: exports_external.string().min(1).optional(),
34073
+ journal: exports_external.array(exports_external.object({
34074
+ tag: exports_external.string().min(1),
34075
+ checksum: exports_external.string().min(1)
34076
+ })).optional(),
34077
+ schemaSnapshot: exports_external.unknown().optional(),
34078
+ schemaHash: exports_external.string().min(1).optional(),
34079
+ evidence: BaselineEvidenceSchema,
34080
+ allowUnverified: exports_external.boolean().optional()
34081
+ }).refine((data) => !data.lastAppliedMigrationTag === !data.journal, {
34082
+ message: "lastAppliedMigrationTag and journal must be provided together",
34083
+ path: ["journal"]
34084
+ }).refine((data) => data.schemaSnapshot === undefined === !data.schemaHash, {
34085
+ message: "schemaSnapshot and schemaHash must be provided together",
34086
+ path: ["schemaHash"]
34087
+ }).refine((data) => Boolean(data.lastAppliedMigrationTag) || Boolean(data.schemaHash), {
34088
+ message: "A baseline needs a migration claim, a schema snapshot, or both",
34089
+ path: ["lastAppliedMigrationTag"]
34090
+ });
34091
+ MigrationRealignSchema = exports_external.object({
34092
+ checksum: exports_external.string().min(1)
34093
+ });
34094
+ MigrationResolveSchema = exports_external.object({
34095
+ resolution: exports_external.enum(["applied", "rolled-back"]),
34096
+ checksum: exports_external.string().min(1).optional()
34097
+ }).refine((data) => data.resolution !== "applied" || Boolean(data.checksum), {
34098
+ message: "Resolving a migration as 'applied' requires its checksum",
34099
+ path: ["checksum"]
34100
+ });
34101
+ DatabaseRestoreSchema = exports_external.object({
34102
+ restorePointId: exports_external.string().uuid()
34103
+ });
34104
+ DeployBlockedReportSchema = exports_external.object({
34105
+ code: exports_external.string().regex(/^blocked:[a-z-]+$/).max(64),
34106
+ reason: exports_external.string().min(1).max(2000)
34107
+ });
31733
34108
  DeployRequestSchema = exports_external.object({
31734
34109
  target: exports_external.enum(deploymentTargetEnum.enumValues).optional().default("game"),
34110
+ deployId: exports_external.string().min(1).optional(),
31735
34111
  uploadToken: exports_external.string().optional(),
31736
34112
  code: exports_external.string().optional(),
31737
34113
  codeUploadToken: exports_external.string().optional(),
@@ -31758,6 +34134,11 @@ var init_schemas2 = __esm(() => {
31758
34134
  sql: exports_external.string(),
31759
34135
  hash: exports_external.string()
31760
34136
  }).optional(),
34137
+ database: DeployDatabaseSchema.optional(),
34138
+ baseline: DeployBaselineSchema.optional(),
34139
+ buildHash: exports_external.string().min(1).optional(),
34140
+ integrationsHash: exports_external.string().min(1).optional(),
34141
+ pruneSecrets: exports_external.array(exports_external.string().min(1)).optional(),
31761
34142
  metadata: exports_external.object({
31762
34143
  displayName: exports_external.string().optional(),
31763
34144
  description: exports_external.string().optional(),
@@ -31767,9 +34148,24 @@ var init_schemas2 = __esm(() => {
31767
34148
  }).refine((data) => !(data.code && data.codeUploadToken), {
31768
34149
  message: "Specify either code or codeUploadToken, not both",
31769
34150
  path: ["codeUploadToken"]
31770
- }).refine((data) => !(data.target === "dashboard" && (data.schema || data.bindings)), {
31771
- message: "Dashboard deployments cannot include schema or bindings — they attach to the game deployment’s existing resources",
34151
+ }).refine((data) => !(data.target === "dashboard" && (data.schema || data.bindings || data.database)), {
34152
+ message: "Dashboard deployments cannot include schema, database, or bindings — they attach to the game deployment’s existing resources",
31772
34153
  path: ["target"]
34154
+ }).refine((data) => !(data.target === "dashboard" && (data.baseline || data.pruneSecrets)), {
34155
+ message: "Dashboard deployments cannot adopt a baseline or prune secrets",
34156
+ path: ["target"]
34157
+ }).refine((data) => !(data.database && !data.deployId), {
34158
+ message: "deployId is required when a database payload is present",
34159
+ path: ["deployId"]
34160
+ }).refine((data) => !(data.database && data.schema), {
34161
+ message: "Send either the database payload or the legacy schema field, not both",
34162
+ path: ["database"]
34163
+ }).refine((data) => !(data.baseline && data.schema), {
34164
+ message: "The legacy schema field cannot ride a baseline-adopting deploy",
34165
+ path: ["baseline"]
34166
+ }).refine((data) => !(data.database && !requestsBinding(data.bindings?.database)), {
34167
+ message: "The database payload requires a database binding",
34168
+ path: ["database"]
31773
34169
  });
31774
34170
  });
31775
34171
 
@@ -75507,7 +77903,7 @@ var init_pure = __esm(() => {
75507
77903
  });
75508
77904
 
75509
77905
  // ../utils/src/index.ts
75510
- var init_src4 = __esm(() => {
77906
+ var init_src5 = __esm(() => {
75511
77907
  init_pure();
75512
77908
  });
75513
77909
 
@@ -77464,7 +79860,7 @@ var init_dist5 = __esm(async () => {
77464
79860
  init_spans();
77465
79861
  init_src();
77466
79862
  init_spans();
77467
- init_src4();
79863
+ init_src5();
77468
79864
  init_src();
77469
79865
  init_spans();
77470
79866
  init_spans();
@@ -78043,7 +80439,7 @@ function selectTimebackMetricDiscrepancyQueueItems(candidates, options) {
78043
80439
  }
78044
80440
  var DATE_INPUT_RE;
78045
80441
  var init_timeback_discrepancy_queue_util = __esm(() => {
78046
- init_src4();
80442
+ init_src5();
78047
80443
  init_timeback_util();
78048
80444
  DATE_INPUT_RE = /^\d{4}-\d{2}-\d{2}$/;
78049
80445
  });
@@ -80562,7 +82958,7 @@ var init_timeback_admin_service = __esm(async () => {
80562
82958
  init_constants3();
80563
82959
  init_types2();
80564
82960
  init_utils6();
80565
- init_src4();
82961
+ init_src5();
80566
82962
  init_timeback3();
80567
82963
  init_errors();
80568
82964
  init_timeback_admin_metrics_util();
@@ -83018,8 +85414,15 @@ function createPlatformServices(deps) {
83018
85414
  validateDeveloperAccess
83019
85415
  });
83020
85416
  const kv = new KVService({ db: db2, cloudflare: cloudflare2, validateDeveloperAccessBySlug });
83021
- const secrets = new SecretsService({ config: config4, cloudflare: cloudflare2, validateDeveloperAccessBySlug });
85417
+ const secrets = new SecretsService({ db: db2, config: config4, cloudflare: cloudflare2, validateDeveloperAccessBySlug });
83022
85418
  const domain3 = new DomainService({ db: db2, cloudflare: cloudflare2, corsKvs, validateDeveloperAccessBySlug });
85419
+ const deploymentState = new DeploymentStateService({
85420
+ db: db2,
85421
+ config: config4,
85422
+ cloudflare: cloudflare2,
85423
+ alerts,
85424
+ validateDeveloperAccessBySlug
85425
+ });
83023
85426
  const database = new DatabaseService({
83024
85427
  db: db2,
83025
85428
  config: config4,
@@ -83058,6 +85461,7 @@ function createPlatformServices(deps) {
83058
85461
  kv,
83059
85462
  secrets,
83060
85463
  domain: domain3,
85464
+ deploymentState,
83061
85465
  database,
83062
85466
  seed,
83063
85467
  timeback: timeback2,
@@ -83068,6 +85472,7 @@ function createPlatformServices(deps) {
83068
85472
  var init_platform2 = __esm(async () => {
83069
85473
  init_bucket_service();
83070
85474
  init_database_service();
85475
+ init_deployment_state_service();
83071
85476
  init_domain_service();
83072
85477
  init_kv_service();
83073
85478
  init_secrets_service();
@@ -83800,7 +86205,7 @@ function createServices(ctx) {
83800
86205
  };
83801
86206
  }
83802
86207
  var init_factory = __esm(async () => {
83803
- init_game2();
86208
+ init_game3();
83804
86209
  init_infra2();
83805
86210
  init_player();
83806
86211
  init_standalone();
@@ -84107,6 +86512,7 @@ function buildConfig(options) {
84107
86512
  gameDomain: "localhost",
84108
86513
  uploadBucket: "sandbox-uploads",
84109
86514
  ltiTestMode: true,
86515
+ secretsManifestPepper: "sandbox-secrets-manifest-pepper",
84110
86516
  ...options.config
84111
86517
  });
84112
86518
  }
@@ -101048,7 +103454,7 @@ var __create2, __defProp2, __getOwnPropDesc, __getOwnPropNames2, __getProtoOf2,
101048
103454
  __defProp2(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
101049
103455
  }
101050
103456
  return to;
101051
- }, __toESM5 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target, mod)), __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value), ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles2, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default, init_ansi_styles, env, flagForceColor, supportsColor, supports_color_default, init_supports_color, init_utilities, stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles22, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default, init_source, require_old, require_fs, require_path, require_balanced_match, require_brace_expansion, require_minimatch, require_inherits_browser2, require_inherits2, require_common3, require_sync, require_wrappy, require_once, require_inflight, require_glob, require_readline, require_src3, require_utils4, require_lodash, require_hanji, originUUID, snapshotVersion, mapValues, mapKeys, mapEntries, customMapEntries, init_global2, util3, objectUtil2, ZodParsedType2, getParsedType4, init_util4, ZodIssueCode4, ZodError5, init_ZodError2, errorMap2, en_default4, init_en4, overrideErrorMap2, init_errors9, makeIssue2, ParseStatus2, INVALID3, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, init_parseUtil2, init_typeAliases2, errorUtil2, init_errorUtil2, ParseInputLazyPath2, handleResult2, ZodType4, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString4, ZodNumber4, ZodBigInt4, ZodBoolean4, ZodDate4, ZodSymbol4, ZodUndefined4, ZodNull4, ZodAny4, ZodUnknown4, ZodNever4, ZodVoid4, ZodArray4, ZodObject4, ZodUnion4, getDiscriminator2, ZodDiscriminatedUnion4, ZodIntersection4, ZodTuple4, ZodRecord4, ZodMap4, ZodSet4, ZodFunction3, ZodLazy4, ZodLiteral4, ZodEnum4, ZodNativeEnum2, ZodPromise4, ZodEffects2, ZodOptional4, ZodNullable4, ZodDefault4, ZodCatch4, ZodNaN4, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly4, late2, ZodFirstPartyTypeKind3, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, coerce2, init_types5, init_external4, init_v32, init_esm2, enumSchema, enumSchemaV1, indexColumn, index2, fk, sequenceSchema, roleSchema, sequenceSquashed, column2, checkConstraint, columnSquashed, compositePK, uniqueConstraint, policy, policySquashed, viewWithOption, matViewWithOption, mergedViewWithOption, view2, table8, schemaHash, kitInternals, gelSchemaExternal, gelSchemaInternal, tableSquashed, gelSchemaSquashed, gelSchema, dryGel, init_gelSchema, index22, fk2, column22, tableV3, compositePK2, uniqueConstraint2, checkConstraint2, tableV4, table22, viewMeta, view22, kitInternals2, dialect2, schemaHash2, schemaInternalV3, schemaInternalV4, schemaInternalV5, schemaInternal, schemaV3, schemaV4, schemaV5, schema2, tableSquashedV4, tableSquashed2, viewSquashed, schemaSquashed, schemaSquashedV4, MySqlSquasher, squashMysqlScheme, mysqlSchema, mysqlSchemaV5, mysqlSchemaSquashed, backwardCompatibleMysqlSchema, dryMySql, init_mysqlSchema, indexV2, columnV2, tableV2, enumSchemaV12, enumSchema2, pgSchemaV2, references, columnV1, tableV1, pgSchemaV1, indexColumn2, index3, indexV4, indexV5, indexV6, fk3, sequenceSchema2, roleSchema2, sequenceSquashed2, columnV7, column3, checkConstraint3, columnSquashed2, tableV32, compositePK3, uniqueConstraint3, policy2, policySquashed2, viewWithOption2, matViewWithOption2, mergedViewWithOption2, view3, tableV42, tableV5, tableV6, tableV7, table32, schemaHash3, kitInternals3, pgSchemaInternalV3, pgSchemaInternalV4, pgSchemaInternalV5, pgSchemaInternalV6, pgSchemaExternal, pgSchemaInternalV7, pgSchemaInternal, tableSquashed3, tableSquashedV42, pgSchemaSquashedV4, pgSchemaSquashedV6, pgSchemaSquashed, pgSchemaV3, pgSchemaV4, pgSchemaV5, pgSchemaV6, pgSchemaV7, pgSchema, backwardCompatiblePgSchema, PgSquasher, squashPgScheme, dryPg, init_pgSchema, index4, column4, compositePK4, uniqueConstraint4, table42, viewMeta2, kitInternals4, dialect22, schemaHash4, schemaInternal2, schema22, tableSquashed4, schemaSquashed2, SingleStoreSquasher, squashSingleStoreScheme, singlestoreSchema, singlestoreSchemaSquashed, backwardCompatibleSingleStoreSchema, drySingleStore, init_singlestoreSchema, index5, fk4, compositePK5, column5, tableV33, uniqueConstraint5, checkConstraint4, table52, view4, dialect3, schemaHash5, schemaInternalV32, schemaInternalV42, schemaInternalV52, kitInternals5, latestVersion, schemaInternal3, schemaV32, schemaV42, schemaV52, schema3, tableSquashed5, schemaSquashed3, SQLiteSquasher, squashSqliteScheme, drySQLite, sqliteSchemaV5, sqliteSchema, SQLiteSchemaSquashed, backwardCompatibleSqliteSchema, init_sqliteSchema, copy, prepareMigrationMeta, schemaRenameKey, tableRenameKey, columnRenameKey, init_utils7, import_hanji, warning, error88, isRenamePromptItem, ResolveColumnSelect, tableKey, ResolveSelectNamed, ResolveSelect, ResolveSchemasSelect, Spinner2, ProgressView, init_views, glob, init_serializer, fillPgSnapshot, init_migrationPreparator, require_heap, require_heap2, require_difflib, require_difflib2, require_util2, require_styles, require_has_flag2, require_supports_colors, require_trap, require_zalgo, require_america, require_zebra, require_rainbow, require_random, require_colors, require_safe, require_colorize, require_lib4, import_json_diff, mapArraysDiff, findAlternationsInTable, alternationsInColumn, init_jsonDiffer, parseType, Convertor, PgCreateRoleConvertor, PgDropRoleConvertor, PgRenameRoleConvertor, PgAlterRoleConvertor, PgCreatePolicyConvertor, PgDropPolicyConvertor, PgRenamePolicyConvertor, PgAlterPolicyConvertor, PgCreateIndPolicyConvertor, PgDropIndPolicyConvertor, PgRenameIndPolicyConvertor, PgAlterIndPolicyConvertor, PgEnableRlsConvertor, PgDisableRlsConvertor, PgCreateTableConvertor, MySqlCreateTableConvertor, SingleStoreCreateTableConvertor, SQLiteCreateTableConvertor, PgCreateViewConvertor, MySqlCreateViewConvertor, SqliteCreateViewConvertor, PgDropViewConvertor, MySqlDropViewConvertor, SqliteDropViewConvertor, MySqlAlterViewConvertor, PgRenameViewConvertor, MySqlRenameViewConvertor, PgAlterViewSchemaConvertor, PgAlterViewAddWithOptionConvertor, PgAlterViewDropWithOptionConvertor, PgAlterViewAlterTablespaceConvertor, PgAlterViewAlterUsingConvertor, PgAlterTableAlterColumnSetGenerated, PgAlterTableAlterColumnDropGenerated, PgAlterTableAlterColumnAlterGenerated, PgAlterTableAddUniqueConstraintConvertor, PgAlterTableDropUniqueConstraintConvertor, PgAlterTableAddCheckConstraintConvertor, PgAlterTableDeleteCheckConstraintConvertor, MySQLAlterTableAddUniqueConstraintConvertor, MySQLAlterTableDropUniqueConstraintConvertor, MySqlAlterTableAddCheckConstraintConvertor, SingleStoreAlterTableAddUniqueConstraintConvertor, SingleStoreAlterTableDropUniqueConstraintConvertor, MySqlAlterTableDeleteCheckConstraintConvertor, CreatePgSequenceConvertor, DropPgSequenceConvertor, RenamePgSequenceConvertor, MovePgSequenceConvertor, AlterPgSequenceConvertor, CreateTypeEnumConvertor, DropTypeEnumConvertor, AlterTypeAddValueConvertor, AlterTypeSetSchemaConvertor, AlterRenameTypeConvertor, AlterTypeDropValueConvertor, PgDropTableConvertor, MySQLDropTableConvertor, SingleStoreDropTableConvertor, SQLiteDropTableConvertor, PgRenameTableConvertor, SqliteRenameTableConvertor, MySqlRenameTableConvertor, SingleStoreRenameTableConvertor, PgAlterTableRenameColumnConvertor, MySqlAlterTableRenameColumnConvertor, SingleStoreAlterTableRenameColumnConvertor, SQLiteAlterTableRenameColumnConvertor, PgAlterTableDropColumnConvertor, MySqlAlterTableDropColumnConvertor, SingleStoreAlterTableDropColumnConvertor, SQLiteAlterTableDropColumnConvertor, PgAlterTableAddColumnConvertor, MySqlAlterTableAddColumnConvertor, SingleStoreAlterTableAddColumnConvertor, SQLiteAlterTableAddColumnConvertor, PgAlterTableAlterColumnSetTypeConvertor, PgAlterTableAlterColumnSetDefaultConvertor, PgAlterTableAlterColumnDropDefaultConvertor, PgAlterTableAlterColumnDropGeneratedConvertor, PgAlterTableAlterColumnSetExpressionConvertor, PgAlterTableAlterColumnAlterrGeneratedConvertor, SqliteAlterTableAlterColumnDropGeneratedConvertor, SqliteAlterTableAlterColumnSetExpressionConvertor, SqliteAlterTableAlterColumnAlterGeneratedConvertor, MySqlAlterTableAlterColumnAlterrGeneratedConvertor, MySqlAlterTableAddPk, MySqlAlterTableDropPk, LibSQLModifyColumn, MySqlModifyColumn, SingleStoreAlterTableAlterColumnAlterrGeneratedConvertor, SingleStoreAlterTableAddPk, SingleStoreAlterTableDropPk, SingleStoreModifyColumn, PgAlterTableCreateCompositePrimaryKeyConvertor, PgAlterTableDeleteCompositePrimaryKeyConvertor, PgAlterTableAlterCompositePrimaryKeyConvertor, MySqlAlterTableCreateCompositePrimaryKeyConvertor, MySqlAlterTableDeleteCompositePrimaryKeyConvertor, MySqlAlterTableAlterCompositePrimaryKeyConvertor, PgAlterTableAlterColumnSetPrimaryKeyConvertor, PgAlterTableAlterColumnDropPrimaryKeyConvertor, PgAlterTableAlterColumnSetNotNullConvertor, PgAlterTableAlterColumnDropNotNullConvertor, PgCreateForeignKeyConvertor, LibSQLCreateForeignKeyConvertor, MySqlCreateForeignKeyConvertor, PgAlterForeignKeyConvertor, PgDeleteForeignKeyConvertor, MySqlDeleteForeignKeyConvertor, CreatePgIndexConvertor, CreateMySqlIndexConvertor, CreateSingleStoreIndexConvertor, CreateSqliteIndexConvertor, PgDropIndexConvertor, PgCreateSchemaConvertor, PgRenameSchemaConvertor, PgDropSchemaConvertor, PgAlterTableSetSchemaConvertor, PgAlterTableSetNewSchemaConvertor, PgAlterTableRemoveFromSchemaConvertor, SqliteDropIndexConvertor, MySqlDropIndexConvertor, SingleStoreDropIndexConvertor, SQLiteRecreateTableConvertor, LibSQLRecreateTableConvertor, SingleStoreRecreateTableConvertor, convertors, init_sqlgenerator, _moveDataStatements, getOldTableName, getNewTableName, logSuggestionsAndReturn, init_sqlitePushUtils, preparePgCreateTableJson, prepareMySqlCreateTableJson, prepareSingleStoreCreateTableJson, prepareSQLiteCreateTable, prepareDropTableJson, prepareRenameTableJson, prepareCreateEnumJson, prepareAddValuesToEnumJson, prepareDropEnumValues, prepareDropEnumJson, prepareMoveEnumJson, prepareRenameEnumJson, prepareCreateSequenceJson, prepareAlterSequenceJson, prepareDropSequenceJson, prepareMoveSequenceJson, prepareRenameSequenceJson, prepareCreateRoleJson, prepareAlterRoleJson, prepareDropRoleJson, prepareRenameRoleJson, prepareCreateSchemasJson, prepareRenameSchemasJson, prepareDeleteSchemasJson, prepareRenameColumns, _prepareDropColumns, _prepareAddColumns, _prepareSqliteAddColumns, prepareAlterColumnsMysql, preparePgAlterColumns, prepareSqliteAlterColumns, prepareRenamePolicyJsons, prepareRenameIndPolicyJsons, prepareCreatePolicyJsons, prepareCreateIndPolicyJsons, prepareDropPolicyJsons, prepareDropIndPolicyJsons, prepareAlterPolicyJson, prepareAlterIndPolicyJson, preparePgCreateIndexesJson, prepareCreateIndexesJson, prepareCreateReferencesJson, prepareLibSQLCreateReferencesJson, prepareDropReferencesJson, prepareLibSQLDropReferencesJson, prepareAlterReferencesJson, prepareDropIndexesJson, prepareAddCompositePrimaryKeySqlite, prepareDeleteCompositePrimaryKeySqlite, prepareAlterCompositePrimaryKeySqlite, prepareAddCompositePrimaryKeyPg, prepareDeleteCompositePrimaryKeyPg, prepareAlterCompositePrimaryKeyPg, prepareAddUniqueConstraintPg, prepareDeleteUniqueConstraintPg, prepareAddCheckConstraint, prepareDeleteCheckConstraint, prepareAddCompositePrimaryKeyMySql, prepareDeleteCompositePrimaryKeyMySql, prepareAlterCompositePrimaryKeyMySql, preparePgCreateViewJson, prepareMySqlCreateViewJson, prepareSqliteCreateViewJson, prepareDropViewJson, prepareRenameViewJson, preparePgAlterViewAlterSchemaJson, preparePgAlterViewAddWithOptionJson, preparePgAlterViewDropWithOptionJson, preparePgAlterViewAlterTablespaceJson, preparePgAlterViewAlterUsingJson, prepareMySqlAlterView, init_jsonStatements, prepareLibSQLRecreateTable, prepareSQLiteRecreateTable, libSQLCombineStatements, sqliteCombineStatements, prepareSingleStoreRecreateTable, singleStoreCombineStatements, init_statementCombiner, snapshotsDiffer_exports, makeChanged, makeSelfOrChanged, makePatched, makeSelfOrPatched, columnSchema, alteredColumnSchema, enumSchema3, changedEnumSchema, tableScheme, alteredTableScheme, alteredViewCommon, alteredPgViewSchema, alteredMySqlViewSchema, diffResultScheme, diffResultSchemeMysql, diffResultSchemeSingleStore, diffResultSchemeSQLite, schemaChangeFor, nameChangeFor, nameSchemaChangeFor, columnChangeFor, applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, applySingleStoreSnapshotsDiff, applySqliteSnapshotsDiff, applyLibSQLSnapshotsDiff, init_snapshotsDiffer, init_words, dialects, dialect4, commonSquashedSchema, commonSchema, init_schemaValidator, sqliteDriversLiterals, postgresqlDriversLiterals, prefixes, prefix, casingTypes, casingType, sqliteDriver, postgresDriver, driver2, configMigrations, configCommonSchema, casing, introspectParams, configIntrospectCliSchema, configGenerateSchema, configPushSchema, init_common2, withStyle, init_outputs, import_hanji2, schemasResolver, tablesResolver, viewsResolver, mySqlViewsResolver, sqliteViewsResolver, sequencesResolver, roleResolver, policyResolver, indPolicyResolver, enumsResolver, columnsResolver, promptColumnsConflicts, promptNamedConflict, promptNamedWithSchemasConflict, promptSchemasConflict, BREAKPOINT, init_migrate, posixClasses, braceEscape, regexpEscape, rangesToString, parseClass, init_brace_expressions, escape, init_escape, unescape, init_unescape, import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path, sep2, GLOBSTAR, plTypes, qmark, star, twoStarDot, twoStarNoDot, charSet, reSpecials, addPatternStartSet, filter, ext, defaults, braceExpand, MAX_PATTERN_LENGTH, assertValidPattern, makeRe, match2, globUnescape, globMagic, regExpEscape, Minimatch, init_mjs, entityKind2, hasOwnEntityKind2, init_entity2, _a3, Column2, init_column2, _a22, ColumnBuilder2, init_column_builder2, TableName2, init_table_utils2, _a32, ForeignKeyBuilder2, _a4, ForeignKey2, init_foreign_keys2, init_tracing_utils2, _a5, UniqueConstraintBuilder, _a6, UniqueOnConstraintBuilder, _a7, UniqueConstraint, init_unique_constraint2, init_array2, _a8, _b, PgColumnBuilder2, _a9, _b2, PgColumn2, _a10, _b3, ExtraConfigColumn2, _a11, IndexedColumn2, _a12, _b4, PgArrayBuilder2, _a13, _b5, _PgArray, PgArray2, init_common22, _a14, _b6, PgEnumObjectColumnBuilder2, _a15, _b7, PgEnumObjectColumn2, isPgEnumSym2, _a16, _b8, PgEnumColumnBuilder2, _a17, _b9, PgEnumColumn2, init_enum2, _a18, Subquery2, _a19, _b10, WithSubquery2, init_subquery2, version4, init_version2, otel2, rawTracer2, tracer2, init_tracing2, ViewBaseConfig2, init_view_common3, Schema2, Columns2, ExtraConfigColumns2, OriginalName2, BaseName2, IsAlias2, ExtraConfigBuilder2, IsDrizzleTable2, _a20, _b11, _c, _d, _e3, _f, _g, _h, _i, _j, Table2, init_table8, _a21, FakePrimitiveParam, _a222, StringChunk2, _a23, _SQL, SQL2, _a24, Name2, noopDecoder2, noopEncoder2, noopMapper2, _a25, Param2, _a26, Placeholder2, IsDrizzleView2, _a27, _b12, _c2, View3, init_sql3, _a28, ColumnAliasProxyHandler2, _a29, TableAliasProxyHandler2, _a30, RelationTableAliasProxyHandler, init_alias3, _a31, _b13, DrizzleError2, DrizzleQueryError, _a322, _b14, TransactionRollbackError2, init_errors22, _a33, ConsoleLogWriter2, _a34, DefaultLogger2, _a35, NoopLogger2, init_logger3, init_operations, _a36, _b15, QueryPromise2, init_query_promise2, textDecoder, init_utils22, _a37, _b16, PgIntColumnBaseBuilder2, init_int_common2, _a38, _b17, PgBigInt53Builder2, _a39, _b18, PgBigInt532, _a40, _b19, PgBigInt64Builder2, _a41, _b20, PgBigInt642, init_bigint2, _a42, _b21, PgBigSerial53Builder2, _a43, _b22, PgBigSerial532, _a44, _b23, PgBigSerial64Builder2, _a45, _b24, PgBigSerial642, init_bigserial2, _a46, _b25, PgBooleanBuilder2, _a47, _b26, PgBoolean2, init_boolean2, _a48, _b27, PgCharBuilder2, _a49, _b28, PgChar2, init_char2, _a50, _b29, PgCidrBuilder2, _a51, _b30, PgCidr2, init_cidr2, _a52, _b31, PgCustomColumnBuilder2, _a53, _b32, PgCustomColumn2, init_custom2, _a54, _b33, PgDateColumnBaseBuilder2, init_date_common2, _a55, _b34, PgDateBuilder2, _a56, _b35, PgDate2, _a57, _b36, PgDateStringBuilder2, _a58, _b37, PgDateString2, init_date2, _a59, _b38, PgDoublePrecisionBuilder2, _a60, _b39, PgDoublePrecision2, init_double_precision2, _a61, _b40, PgInetBuilder2, _a62, _b41, PgInet2, init_inet2, _a63, _b42, PgIntegerBuilder2, _a64, _b43, PgInteger2, init_integer2, _a65, _b44, PgIntervalBuilder2, _a66, _b45, PgInterval2, init_interval2, _a67, _b46, PgJsonBuilder2, _a68, _b47, PgJson2, init_json2, _a69, _b48, PgJsonbBuilder2, _a70, _b49, PgJsonb2, init_jsonb2, _a71, _b50, PgLineBuilder2, _a72, _b51, PgLineTuple2, _a73, _b52, PgLineABCBuilder2, _a74, _b53, PgLineABC2, init_line2, _a75, _b54, PgMacaddrBuilder2, _a76, _b55, PgMacaddr2, init_macaddr2, _a77, _b56, PgMacaddr8Builder2, _a78, _b57, PgMacaddr82, init_macaddr82, _a79, _b58, PgNumericBuilder2, _a80, _b59, PgNumeric2, _a81, _b60, PgNumericNumberBuilder2, _a82, _b61, PgNumericNumber2, _a83, _b62, PgNumericBigIntBuilder2, _a84, _b63, PgNumericBigInt2, init_numeric2, _a85, _b64, PgPointTupleBuilder2, _a86, _b65, PgPointTuple2, _a87, _b66, PgPointObjectBuilder2, _a88, _b67, PgPointObject2, init_point2, init_utils32, _a89, _b68, PgGeometryBuilder2, _a90, _b69, PgGeometry2, _a91, _b70, PgGeometryObjectBuilder2, _a92, _b71, PgGeometryObject2, init_geometry2, _a93, _b72, PgRealBuilder2, _a94, _b73, PgReal2, init_real2, _a95, _b74, PgSerialBuilder2, _a96, _b75, PgSerial2, init_serial2, _a97, _b76, PgSmallIntBuilder2, _a98, _b77, PgSmallInt2, init_smallint2, _a99, _b78, PgSmallSerialBuilder2, _a100, _b79, PgSmallSerial2, init_smallserial2, _a101, _b80, PgTextBuilder2, _a102, _b81, PgText2, init_text2, _a103, _b82, PgTimeBuilder2, _a104, _b83, PgTime2, init_time2, _a105, _b84, PgTimestampBuilder2, _a106, _b85, PgTimestamp2, _a107, _b86, PgTimestampStringBuilder2, _a108, _b87, PgTimestampString2, init_timestamp2, _a109, _b88, PgUUIDBuilder2, _a110, _b89, PgUUID2, init_uuid3, _a111, _b90, PgVarcharBuilder2, _a112, _b91, PgVarchar2, init_varchar2, _a113, _b92, PgBinaryVectorBuilder2, _a114, _b93, PgBinaryVector2, init_bit2, _a115, _b94, PgHalfVectorBuilder2, _a116, _b95, PgHalfVector2, init_halfvec2, _a117, _b96, PgSparseVectorBuilder2, _a118, _b97, PgSparseVector2, init_sparsevec2, _a119, _b98, PgVectorBuilder2, _a120, _b99, PgVector2, init_vector3, init_all2, InlineForeignKeys2, EnableRLS2, _a121, _b100, _c3, _d2, _e22, _f2, PgTable2, pgTable2, init_table22, _a122, PrimaryKeyBuilder2, _a123, PrimaryKey2, init_primary_keys2, eq2, ne4, gt3, gte2, lt4, lte2, init_conditions2, init_select3, init_expressions2, _a124, Relation2, _a125, Relations2, _a126, _b101, _One, One2, _a127, _b102, _Many, Many2, init_relations2, init_aggregate2, init_vector22, init_functions2, init_sql22, dist_exports, init_dist9, init_alias22, _a128, CheckBuilder, _a129, Check, init_checks6, init_columns2, _a130, _SelectionProxyHandler, SelectionProxyHandler2, init_selection_proxy2, _a131, IndexBuilderOn2, _a132, IndexBuilder2, _a133, Index2, init_indexes2, _a134, PgPolicy, init_policies2, PgViewConfig2, init_view_common22, _a135, CasingCache2, init_casing2, _a136, _b103, PgViewBase2, init_view_base2, _a137, PgDialect2, init_dialect2, _a138, TypedQueryBuilder2, init_query_builder3, _a139, PgSelectBuilder2, _a140, _b104, PgSelectQueryBuilderBase2, _a141, _b105, PgSelectBase2, getPgSetOperators2, union22, unionAll2, intersect2, intersectAll2, except2, exceptAll2, init_select22, _a142, QueryBuilder2, init_query_builder22, _a143, DefaultViewBuilderCore, _a144, _b106, ViewBuilder, _a145, _b107, ManualViewBuilder, _a146, MaterializedViewBuilderCore, _a147, _b108, MaterializedViewBuilder, _a148, _b109, ManualMaterializedViewBuilder, _a149, _b110, _c4, PgView2, PgMaterializedViewConfig2, _a150, _b111, _c5, PgMaterializedView, init_view2, init_utils42, _a151, _b112, PgDeleteBase2, init_delete2, _a152, PgInsertBuilder2, _a153, _b113, PgInsertBase2, init_insert2, _a154, _b114, PgRefreshMaterializedView2, init_refresh_materialized_view2, init_select_types, _a155, PgUpdateBuilder2, _a156, _b115, PgUpdateBase2, init_update2, init_query_builders2, _a157, _b116, _c6, _PgCountBuilder, PgCountBuilder2, init_count2, _a158, RelationalQueryBuilder2, _a159, _b117, PgRelationalQuery2, init_query2, _a160, _b118, PgRaw2, init_raw2, _a161, PgDatabase2, init_db2, _a162, PgRole, init_roles2, _a163, PgSequence, init_sequence2, _a164, PgSchema5, init_schema3, _a165, Cache, _a166, _b119, NoopCache, init_cache, _a167, PgPreparedQuery2, _a168, PgSession2, _a169, _b120, PgTransaction2, init_session3, init_subquery22, init_utils52, init_pg_core2, vectorOps, init_vector32, sqlToStr, init_utils62, indexName, generatePgSnapshot, trimChar, fromDatabase, defaultForColumn, getColumnsInfoQuery, init_pgSerializer, import_hanji4, Select, init_selector_ui, init_alias32, _a170, CheckBuilder2, _a171, Check2, init_checks22, _a172, ForeignKeyBuilder22, _a173, ForeignKey22, init_foreign_keys22, _a174, UniqueConstraintBuilder2, _a175, UniqueOnConstraintBuilder2, _a176, UniqueConstraint2, init_unique_constraint22, _a177, _b121, SQLiteColumnBuilder, _a178, _b122, SQLiteColumn, init_common3, _a179, _b123, SQLiteBigIntBuilder, _a180, _b124, SQLiteBigInt, _a181, _b125, SQLiteBlobJsonBuilder, _a182, _b126, SQLiteBlobJson, _a183, _b127, SQLiteBlobBufferBuilder, _a184, _b128, SQLiteBlobBuffer, init_blob, _a185, _b129, SQLiteCustomColumnBuilder, _a186, _b130, SQLiteCustomColumn, init_custom22, _a187, _b131, SQLiteBaseIntegerBuilder, _a188, _b132, SQLiteBaseInteger, _a189, _b133, SQLiteIntegerBuilder, _a190, _b134, SQLiteInteger, _a191, _b135, SQLiteTimestampBuilder, _a192, _b136, SQLiteTimestamp, _a193, _b137, SQLiteBooleanBuilder, _a194, _b138, SQLiteBoolean, init_integer22, _a195, _b139, SQLiteNumericBuilder, _a196, _b140, SQLiteNumeric, _a197, _b141, SQLiteNumericNumberBuilder, _a198, _b142, SQLiteNumericNumber, _a199, _b143, SQLiteNumericBigIntBuilder, _a200, _b144, SQLiteNumericBigInt, init_numeric22, _a201, _b145, SQLiteRealBuilder, _a202, _b146, SQLiteReal, init_real22, _a203, _b147, SQLiteTextBuilder, _a204, _b148, SQLiteText, _a205, _b149, SQLiteTextJsonBuilder, _a206, _b150, SQLiteTextJson, init_text22, init_columns22, init_all22, InlineForeignKeys22, _a207, _b151, _c7, _d3, _e32, SQLiteTable, sqliteTable, init_table32, _a208, IndexBuilderOn22, _a209, IndexBuilder22, _a210, Index4, init_indexes22, _a211, PrimaryKeyBuilder22, _a212, PrimaryKey22, init_primary_keys22, init_utils72, _a213, _b152, SQLiteDeleteBase, init_delete22, _a214, _b153, SQLiteViewBase, init_view_base22, _a215, SQLiteDialect, _a216, _b154, SQLiteSyncDialect, _a217, _b155, SQLiteAsyncDialect, init_dialect22, _a218, SQLiteSelectBuilder, _a219, _b156, SQLiteSelectQueryBuilderBase, _a220, _b157, SQLiteSelectBase, getSQLiteSetOperators, union32, unionAll22, intersect22, except22, init_select32, _a221, QueryBuilder22, init_query_builder32, _a2222, SQLiteInsertBuilder, _a223, _b158, SQLiteInsertBase, init_insert22, init_select_types2, _a224, SQLiteUpdateBuilder, _a225, _b159, SQLiteUpdateBase, init_update22, init_query_builders22, _a226, _b160, _c8, _SQLiteCountBuilder, SQLiteCountBuilder, init_count22, _a227, RelationalQueryBuilder22, _a228, _b161, SQLiteRelationalQuery, _a229, _b162, SQLiteSyncRelationalQuery, init_query22, _a230, _b163, SQLiteRaw, init_raw22, _a231, BaseSQLiteDatabase, init_db22, _a232, _b164, ExecuteResultSync, _a233, SQLitePreparedQuery, _a234, SQLiteSession, _a235, _b165, SQLiteTransaction, init_session22, init_subquery3, _a236, ViewBuilderCore, _a237, _b166, ViewBuilder2, _a238, _b167, ManualViewBuilder2, _a239, _b168, SQLiteView2, init_view22, init_sqlite_core, generateSqliteSnapshot, fromDatabase2, init_sqliteSerializer, getTablesFilterByExtensions, init_getTablesFilterByExtensions, init_alias4, _a240, CheckBuilder3, _a241, Check3, init_checks32, _a242, ForeignKeyBuilder3, _a243, ForeignKey3, init_foreign_keys3, _a244, UniqueConstraintBuilder3, _a245, UniqueOnConstraintBuilder3, _a246, UniqueConstraint3, init_unique_constraint3, _a247, _b169, MySqlColumnBuilder, _a248, _b170, MySqlColumn, _a249, _b171, MySqlColumnBuilderWithAutoIncrement, _a250, _b172, MySqlColumnWithAutoIncrement, init_common4, _a251, _b173, MySqlBigInt53Builder, _a252, _b174, MySqlBigInt53, _a253, _b175, MySqlBigInt64Builder, _a254, _b176, MySqlBigInt64, init_bigint22, _a255, _b177, MySqlBinaryBuilder, _a256, _b178, MySqlBinary, init_binary, _a257, _b179, MySqlBooleanBuilder, _a258, _b180, MySqlBoolean, init_boolean22, _a259, _b181, MySqlCharBuilder, _a260, _b182, MySqlChar, init_char22, _a261, _b183, MySqlCustomColumnBuilder, _a262, _b184, MySqlCustomColumn, init_custom3, _a263, _b185, MySqlDateBuilder, _a264, _b186, MySqlDate, _a265, _b187, MySqlDateStringBuilder, _a266, _b188, MySqlDateString, init_date22, _a267, _b189, MySqlDateTimeBuilder, _a268, _b190, MySqlDateTime, _a269, _b191, MySqlDateTimeStringBuilder, _a270, _b192, MySqlDateTimeString, init_datetime, _a271, _b193, MySqlDecimalBuilder, _a272, _b194, MySqlDecimal, _a273, _b195, MySqlDecimalNumberBuilder, _a274, _b196, MySqlDecimalNumber, _a275, _b197, MySqlDecimalBigIntBuilder, _a276, _b198, MySqlDecimalBigInt, init_decimal, _a277, _b199, MySqlDoubleBuilder, _a278, _b200, MySqlDouble, init_double, _a279, _b201, MySqlEnumColumnBuilder, _a280, _b202, MySqlEnumColumn, _a281, _b203, MySqlEnumObjectColumnBuilder, _a282, _b204, MySqlEnumObjectColumn, init_enum22, _a283, _b205, MySqlFloatBuilder, _a284, _b206, MySqlFloat, init_float, _a285, _b207, MySqlIntBuilder, _a286, _b208, MySqlInt, init_int, _a287, _b209, MySqlJsonBuilder, _a288, _b210, MySqlJson, init_json22, _a289, _b211, MySqlMediumIntBuilder, _a290, _b212, MySqlMediumInt, init_mediumint, _a291, _b213, MySqlRealBuilder, _a292, _b214, MySqlReal, init_real3, _a293, _b215, MySqlSerialBuilder, _a294, _b216, MySqlSerial, init_serial22, _a295, _b217, MySqlSmallIntBuilder, _a296, _b218, MySqlSmallInt, init_smallint22, _a297, _b219, MySqlTextBuilder, _a298, _b220, MySqlText, init_text3, _a299, _b221, MySqlTimeBuilder, _a300, _b222, MySqlTime, init_time22, _a301, _b223, MySqlDateColumnBaseBuilder, _a302, _b224, MySqlDateBaseColumn, init_date_common22, _a303, _b225, MySqlTimestampBuilder, _a304, _b226, MySqlTimestamp, _a305, _b227, MySqlTimestampStringBuilder, _a306, _b228, MySqlTimestampString, init_timestamp22, _a307, _b229, MySqlTinyIntBuilder, _a308, _b230, MySqlTinyInt, init_tinyint, _a309, _b231, MySqlVarBinaryBuilder, _a310, _b232, MySqlVarBinary, init_varbinary, _a311, _b233, MySqlVarCharBuilder, _a312, _b234, MySqlVarChar, init_varchar22, _a313, _b235, MySqlYearBuilder, _a314, _b236, MySqlYear, init_year, init_columns3, _a315, _b237, _c9, _MySqlCountBuilder, MySqlCountBuilder, init_count3, _a316, IndexBuilderOn3, _a317, IndexBuilder3, _a318, Index5, init_indexes3, init_all3, InlineForeignKeys3, _a319, _b238, _c10, _d4, _e4, MySqlTable, mysqlTable, init_table42, _a320, PrimaryKeyBuilder3, _a321, PrimaryKey3, init_primary_keys3, MySqlViewConfig, init_view_common32, init_utils8, _a3222, _b239, MySqlDeleteBase, init_delete3, _a323, _b240, MySqlViewBase, init_view_base3, _a324, MySqlDialect, init_dialect3, _a325, MySqlSelectBuilder, _a326, _b241, MySqlSelectQueryBuilderBase, _a327, _b242, MySqlSelectBase, getMySqlSetOperators, union4, unionAll3, intersect3, intersectAll22, except3, exceptAll22, init_select4, _a328, QueryBuilder3, init_query_builder4, _a329, MySqlInsertBuilder, _a330, _b243, MySqlInsertBase, init_insert3, init_select_types3, _a331, MySqlUpdateBuilder, _a332, _b244, MySqlUpdateBase, init_update3, init_query_builders3, _a333, RelationalQueryBuilder3, _a334, _b245, MySqlRelationalQuery, init_query3, _a335, MySqlDatabase, init_db3, _a336, ViewBuilderCore2, _a337, _b246, ViewBuilder3, _a338, _b247, ManualViewBuilder3, _a339, _b248, _c11, MySqlView2, init_view3, _a340, MySqlSchema5, init_schema22, _a341, MySqlPreparedQuery, _a342, MySqlSession, _a343, _b249, MySqlTransaction, init_session32, init_subquery4, init_mysql_core, handleEnumType, generateMySqlSnapshot, fromDatabase3, init_mysqlSerializer, cliConfigGenerate, pushParams, pullParams, configCheck, cliConfigCheck, init_cli, gelCredentials, init_gel, libSQLCredentials, init_libsql, mysqlCredentials, init_mysql, postgresCredentials, init_postgres, singlestoreCredentials, init_singlestore, sqliteCredentials, init_sqlite, credentials, studioCliParams, studioConfig, init_studio, es5_exports, _3, es5_default, init_es5, import_hanji7, assertES5, safeRegister, migrateConfig, init_utils9, prepareFromExports, init_pgImports, init_alias5, _a344, UniqueConstraintBuilder4, _a345, UniqueOnConstraintBuilder4, _a346, UniqueConstraint4, init_unique_constraint4, _a347, _b250, SingleStoreColumnBuilder, _a348, _b251, SingleStoreColumn, _a349, _b252, SingleStoreColumnBuilderWithAutoIncrement, _a350, _b253, SingleStoreColumnWithAutoIncrement, init_common5, _a351, _b254, SingleStoreBigInt53Builder, _a352, _b255, SingleStoreBigInt53, _a353, _b256, SingleStoreBigInt64Builder, _a354, _b257, SingleStoreBigInt64, init_bigint3, _a355, _b258, SingleStoreBinaryBuilder, _a356, _b259, SingleStoreBinary, init_binary2, _a357, _b260, SingleStoreBooleanBuilder, _a358, _b261, SingleStoreBoolean, init_boolean3, _a359, _b262, SingleStoreCharBuilder, _a360, _b263, SingleStoreChar, init_char3, _a361, _b264, SingleStoreCustomColumnBuilder, _a362, _b265, SingleStoreCustomColumn, init_custom4, _a363, _b266, SingleStoreDateBuilder, _a364, _b267, SingleStoreDate, _a365, _b268, SingleStoreDateStringBuilder, _a366, _b269, SingleStoreDateString, init_date3, _a367, _b270, SingleStoreDateTimeBuilder, _a368, _b271, SingleStoreDateTime, _a369, _b272, SingleStoreDateTimeStringBuilder, _a370, _b273, SingleStoreDateTimeString, init_datetime2, _a371, _b274, SingleStoreDecimalBuilder, _a372, _b275, SingleStoreDecimal, _a373, _b276, SingleStoreDecimalNumberBuilder, _a374, _b277, SingleStoreDecimalNumber, _a375, _b278, SingleStoreDecimalBigIntBuilder, _a376, _b279, SingleStoreDecimalBigInt, init_decimal2, _a377, _b280, SingleStoreDoubleBuilder, _a378, _b281, SingleStoreDouble, init_double2, _a379, _b282, SingleStoreEnumColumnBuilder, _a380, _b283, SingleStoreEnumColumn, init_enum3, _a381, _b284, SingleStoreFloatBuilder, _a382, _b285, SingleStoreFloat, init_float2, _a383, _b286, SingleStoreIntBuilder, _a384, _b287, SingleStoreInt, init_int2, _a385, _b288, SingleStoreJsonBuilder, _a386, _b289, SingleStoreJson, init_json3, _a387, _b290, SingleStoreMediumIntBuilder, _a388, _b291, SingleStoreMediumInt, init_mediumint2, _a389, _b292, SingleStoreRealBuilder, _a390, _b293, SingleStoreReal, init_real4, _a391, _b294, SingleStoreSerialBuilder, _a392, _b295, SingleStoreSerial, init_serial3, _a393, _b296, SingleStoreSmallIntBuilder, _a394, _b297, SingleStoreSmallInt, init_smallint3, _a395, _b298, SingleStoreTextBuilder, _a396, _b299, SingleStoreText, init_text4, _a397, _b300, SingleStoreTimeBuilder, _a398, _b301, SingleStoreTime, init_time3, _a399, _b302, SingleStoreDateColumnBaseBuilder, _a400, _b303, SingleStoreDateBaseColumn, init_date_common3, _a401, _b304, SingleStoreTimestampBuilder, _a402, _b305, SingleStoreTimestamp, _a403, _b306, SingleStoreTimestampStringBuilder, _a404, _b307, SingleStoreTimestampString, init_timestamp3, _a405, _b308, SingleStoreTinyIntBuilder, _a406, _b309, SingleStoreTinyInt, init_tinyint2, _a407, _b310, SingleStoreVarBinaryBuilder, _a408, _b311, SingleStoreVarBinary, init_varbinary2, _a409, _b312, SingleStoreVarCharBuilder, _a410, _b313, SingleStoreVarChar, init_varchar3, _a411, _b314, SingleStoreVectorBuilder, _a412, _b315, SingleStoreVector, init_vector4, _a413, _b316, SingleStoreYearBuilder, _a414, _b317, SingleStoreYear, init_year2, init_columns4, _a415, _b318, _c12, _SingleStoreCountBuilder, SingleStoreCountBuilder, init_count4, _a416, IndexBuilderOn4, _a417, IndexBuilder4, _a418, Index6, init_indexes4, init_all4, _a419, _b319, _c13, _d5, SingleStoreTable, init_table52, _a420, PrimaryKeyBuilder4, _a421, PrimaryKey4, init_primary_keys4, init_utils10, _a422, _b320, SingleStoreDeleteBase, init_delete4, _a423, SingleStoreInsertBuilder, _a424, _b321, SingleStoreInsertBase, init_insert4, _a425, SingleStoreDialect, init_dialect4, _a426, SingleStoreSelectBuilder, _a427, _b322, SingleStoreSelectQueryBuilderBase, _a428, _b323, SingleStoreSelectBase, getSingleStoreSetOperators, union5, unionAll4, intersect4, except4, minus, init_select5, _a429, QueryBuilder4, init_query_builder5, init_select_types4, _a430, SingleStoreUpdateBuilder, _a431, _b324, SingleStoreUpdateBase, init_update4, init_query_builders4, _a432, SingleStoreDatabase, init_db4, _a433, SingleStoreSchema5, init_schema32, _a434, SingleStorePreparedQuery, _a435, SingleStoreSession, _a436, _b325, SingleStoreTransaction, init_session4, init_subquery5, init_singlestore_core, dialect5, generateSingleStoreSnapshot, fromDatabase4, init_singlestoreSerializer, sqliteImports_exports, prepareFromExports2, prepareFromSqliteImports, init_sqliteImports, mysqlImports_exports, prepareFromExports3, prepareFromMySqlImports, init_mysqlImports, mysqlPushUtils_exports, import_hanji8, filterStatements, logSuggestionsAndReturn2, init_mysqlPushUtils, mysqlIntrospect_exports, import_hanji9, mysqlPushIntrospect, init_mysqlIntrospect, singlestoreImports_exports, prepareFromExports4, prepareFromSingleStoreImports, init_singlestoreImports, singlestorePushUtils_exports, import_hanji10, filterStatements2, logSuggestionsAndReturn3, init_singlestorePushUtils, singlestoreIntrospect_exports, import_hanji11, singlestorePushIntrospect, init_singlestoreIntrospect, import_hanji3, pgPushIntrospect = async (db2, filters, schemaFilters, entities, tsSchema) => {
103457
+ }, __toESM5 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target, mod)), __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value), ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles2, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default, init_ansi_styles, env, flagForceColor, supportsColor, supports_color_default, init_supports_color, init_utilities, stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles22, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default, init_source, require_old, require_fs, require_path, require_balanced_match, require_brace_expansion, require_minimatch, require_inherits_browser2, require_inherits2, require_common3, require_sync, require_wrappy, require_once, require_inflight, require_glob, require_readline, require_src3, require_utils4, require_lodash, require_hanji, originUUID, snapshotVersion, mapValues, mapKeys, mapEntries, customMapEntries, init_global2, util3, objectUtil2, ZodParsedType2, getParsedType4, init_util4, ZodIssueCode4, ZodError5, init_ZodError2, errorMap2, en_default4, init_en4, overrideErrorMap2, init_errors9, makeIssue2, ParseStatus2, INVALID3, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, init_parseUtil2, init_typeAliases2, errorUtil2, init_errorUtil2, ParseInputLazyPath2, handleResult2, ZodType4, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString4, ZodNumber4, ZodBigInt4, ZodBoolean4, ZodDate4, ZodSymbol4, ZodUndefined4, ZodNull4, ZodAny4, ZodUnknown4, ZodNever4, ZodVoid4, ZodArray4, ZodObject4, ZodUnion4, getDiscriminator2, ZodDiscriminatedUnion4, ZodIntersection4, ZodTuple4, ZodRecord4, ZodMap4, ZodSet4, ZodFunction3, ZodLazy4, ZodLiteral4, ZodEnum4, ZodNativeEnum2, ZodPromise4, ZodEffects2, ZodOptional4, ZodNullable4, ZodDefault4, ZodCatch4, ZodNaN4, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly4, late2, ZodFirstPartyTypeKind3, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, coerce2, init_types5, init_external4, init_v32, init_esm2, enumSchema, enumSchemaV1, indexColumn, index2, fk, sequenceSchema, roleSchema, sequenceSquashed, column2, checkConstraint, columnSquashed, compositePK, uniqueConstraint, policy, policySquashed, viewWithOption, matViewWithOption, mergedViewWithOption, view2, table8, schemaHash, kitInternals, gelSchemaExternal, gelSchemaInternal, tableSquashed, gelSchemaSquashed, gelSchema, dryGel, init_gelSchema, index22, fk2, column22, tableV3, compositePK2, uniqueConstraint2, checkConstraint2, tableV4, table22, viewMeta, view22, kitInternals2, dialect2, schemaHash2, schemaInternalV3, schemaInternalV4, schemaInternalV5, schemaInternal, schemaV3, schemaV4, schemaV5, schema2, tableSquashedV4, tableSquashed2, viewSquashed, schemaSquashed, schemaSquashedV4, MySqlSquasher, squashMysqlScheme, mysqlSchema, mysqlSchemaV5, mysqlSchemaSquashed, backwardCompatibleMysqlSchema, dryMySql, init_mysqlSchema, indexV2, columnV2, tableV2, enumSchemaV12, enumSchema2, pgSchemaV2, references, columnV1, tableV1, pgSchemaV1, indexColumn2, index3, indexV4, indexV5, indexV6, fk3, sequenceSchema2, roleSchema2, sequenceSquashed2, columnV7, column3, checkConstraint3, columnSquashed2, tableV32, compositePK3, uniqueConstraint3, policy2, policySquashed2, viewWithOption2, matViewWithOption2, mergedViewWithOption2, view3, tableV42, tableV5, tableV6, tableV7, table32, schemaHash3, kitInternals3, pgSchemaInternalV3, pgSchemaInternalV4, pgSchemaInternalV5, pgSchemaInternalV6, pgSchemaExternal, pgSchemaInternalV7, pgSchemaInternal, tableSquashed3, tableSquashedV42, pgSchemaSquashedV4, pgSchemaSquashedV6, pgSchemaSquashed, pgSchemaV3, pgSchemaV4, pgSchemaV5, pgSchemaV6, pgSchemaV7, pgSchema, backwardCompatiblePgSchema, PgSquasher, squashPgScheme, dryPg, init_pgSchema, index4, column4, compositePK4, uniqueConstraint4, table42, viewMeta2, kitInternals4, dialect22, schemaHash4, schemaInternal2, schema22, tableSquashed4, schemaSquashed2, SingleStoreSquasher, squashSingleStoreScheme, singlestoreSchema, singlestoreSchemaSquashed, backwardCompatibleSingleStoreSchema, drySingleStore, init_singlestoreSchema, index5, fk4, compositePK5, column5, tableV33, uniqueConstraint5, checkConstraint4, table52, view4, dialect3, schemaHash5, schemaInternalV32, schemaInternalV42, schemaInternalV52, kitInternals5, latestVersion, schemaInternal3, schemaV32, schemaV42, schemaV52, schema3, tableSquashed5, schemaSquashed3, SQLiteSquasher, squashSqliteScheme, drySQLite, sqliteSchemaV5, sqliteSchema, SQLiteSchemaSquashed, backwardCompatibleSqliteSchema, init_sqliteSchema, copy, prepareMigrationMeta, schemaRenameKey, tableRenameKey, columnRenameKey, init_utils7, import_hanji, warning, error88, isRenamePromptItem, ResolveColumnSelect, tableKey, ResolveSelectNamed, ResolveSelect, ResolveSchemasSelect, Spinner2, ProgressView, init_views, glob, init_serializer, fillPgSnapshot, init_migrationPreparator, require_heap, require_heap2, require_difflib, require_difflib2, require_util2, require_styles, require_has_flag2, require_supports_colors, require_trap, require_zalgo, require_america, require_zebra, require_rainbow, require_random, require_colors, require_safe, require_colorize, require_lib4, import_json_diff, mapArraysDiff, findAlternationsInTable, alternationsInColumn, init_jsonDiffer, parseType, Convertor, PgCreateRoleConvertor, PgDropRoleConvertor, PgRenameRoleConvertor, PgAlterRoleConvertor, PgCreatePolicyConvertor, PgDropPolicyConvertor, PgRenamePolicyConvertor, PgAlterPolicyConvertor, PgCreateIndPolicyConvertor, PgDropIndPolicyConvertor, PgRenameIndPolicyConvertor, PgAlterIndPolicyConvertor, PgEnableRlsConvertor, PgDisableRlsConvertor, PgCreateTableConvertor, MySqlCreateTableConvertor, SingleStoreCreateTableConvertor, SQLiteCreateTableConvertor, PgCreateViewConvertor, MySqlCreateViewConvertor, SqliteCreateViewConvertor, PgDropViewConvertor, MySqlDropViewConvertor, SqliteDropViewConvertor, MySqlAlterViewConvertor, PgRenameViewConvertor, MySqlRenameViewConvertor, PgAlterViewSchemaConvertor, PgAlterViewAddWithOptionConvertor, PgAlterViewDropWithOptionConvertor, PgAlterViewAlterTablespaceConvertor, PgAlterViewAlterUsingConvertor, PgAlterTableAlterColumnSetGenerated, PgAlterTableAlterColumnDropGenerated, PgAlterTableAlterColumnAlterGenerated, PgAlterTableAddUniqueConstraintConvertor, PgAlterTableDropUniqueConstraintConvertor, PgAlterTableAddCheckConstraintConvertor, PgAlterTableDeleteCheckConstraintConvertor, MySQLAlterTableAddUniqueConstraintConvertor, MySQLAlterTableDropUniqueConstraintConvertor, MySqlAlterTableAddCheckConstraintConvertor, SingleStoreAlterTableAddUniqueConstraintConvertor, SingleStoreAlterTableDropUniqueConstraintConvertor, MySqlAlterTableDeleteCheckConstraintConvertor, CreatePgSequenceConvertor, DropPgSequenceConvertor, RenamePgSequenceConvertor, MovePgSequenceConvertor, AlterPgSequenceConvertor, CreateTypeEnumConvertor, DropTypeEnumConvertor, AlterTypeAddValueConvertor, AlterTypeSetSchemaConvertor, AlterRenameTypeConvertor, AlterTypeDropValueConvertor, PgDropTableConvertor, MySQLDropTableConvertor, SingleStoreDropTableConvertor, SQLiteDropTableConvertor, PgRenameTableConvertor, SqliteRenameTableConvertor, MySqlRenameTableConvertor, SingleStoreRenameTableConvertor, PgAlterTableRenameColumnConvertor, MySqlAlterTableRenameColumnConvertor, SingleStoreAlterTableRenameColumnConvertor, SQLiteAlterTableRenameColumnConvertor, PgAlterTableDropColumnConvertor, MySqlAlterTableDropColumnConvertor, SingleStoreAlterTableDropColumnConvertor, SQLiteAlterTableDropColumnConvertor, PgAlterTableAddColumnConvertor, MySqlAlterTableAddColumnConvertor, SingleStoreAlterTableAddColumnConvertor, SQLiteAlterTableAddColumnConvertor, PgAlterTableAlterColumnSetTypeConvertor, PgAlterTableAlterColumnSetDefaultConvertor, PgAlterTableAlterColumnDropDefaultConvertor, PgAlterTableAlterColumnDropGeneratedConvertor, PgAlterTableAlterColumnSetExpressionConvertor, PgAlterTableAlterColumnAlterrGeneratedConvertor, SqliteAlterTableAlterColumnDropGeneratedConvertor, SqliteAlterTableAlterColumnSetExpressionConvertor, SqliteAlterTableAlterColumnAlterGeneratedConvertor, MySqlAlterTableAlterColumnAlterrGeneratedConvertor, MySqlAlterTableAddPk, MySqlAlterTableDropPk, LibSQLModifyColumn, MySqlModifyColumn, SingleStoreAlterTableAlterColumnAlterrGeneratedConvertor, SingleStoreAlterTableAddPk, SingleStoreAlterTableDropPk, SingleStoreModifyColumn, PgAlterTableCreateCompositePrimaryKeyConvertor, PgAlterTableDeleteCompositePrimaryKeyConvertor, PgAlterTableAlterCompositePrimaryKeyConvertor, MySqlAlterTableCreateCompositePrimaryKeyConvertor, MySqlAlterTableDeleteCompositePrimaryKeyConvertor, MySqlAlterTableAlterCompositePrimaryKeyConvertor, PgAlterTableAlterColumnSetPrimaryKeyConvertor, PgAlterTableAlterColumnDropPrimaryKeyConvertor, PgAlterTableAlterColumnSetNotNullConvertor, PgAlterTableAlterColumnDropNotNullConvertor, PgCreateForeignKeyConvertor, LibSQLCreateForeignKeyConvertor, MySqlCreateForeignKeyConvertor, PgAlterForeignKeyConvertor, PgDeleteForeignKeyConvertor, MySqlDeleteForeignKeyConvertor, CreatePgIndexConvertor, CreateMySqlIndexConvertor, CreateSingleStoreIndexConvertor, CreateSqliteIndexConvertor, PgDropIndexConvertor, PgCreateSchemaConvertor, PgRenameSchemaConvertor, PgDropSchemaConvertor, PgAlterTableSetSchemaConvertor, PgAlterTableSetNewSchemaConvertor, PgAlterTableRemoveFromSchemaConvertor, SqliteDropIndexConvertor, MySqlDropIndexConvertor, SingleStoreDropIndexConvertor, SQLiteRecreateTableConvertor, LibSQLRecreateTableConvertor, SingleStoreRecreateTableConvertor, convertors, init_sqlgenerator, _moveDataStatements, getOldTableName, getNewTableName, logSuggestionsAndReturn, init_sqlitePushUtils, preparePgCreateTableJson, prepareMySqlCreateTableJson, prepareSingleStoreCreateTableJson, prepareSQLiteCreateTable, prepareDropTableJson, prepareRenameTableJson, prepareCreateEnumJson, prepareAddValuesToEnumJson, prepareDropEnumValues, prepareDropEnumJson, prepareMoveEnumJson, prepareRenameEnumJson, prepareCreateSequenceJson, prepareAlterSequenceJson, prepareDropSequenceJson, prepareMoveSequenceJson, prepareRenameSequenceJson, prepareCreateRoleJson, prepareAlterRoleJson, prepareDropRoleJson, prepareRenameRoleJson, prepareCreateSchemasJson, prepareRenameSchemasJson, prepareDeleteSchemasJson, prepareRenameColumns, _prepareDropColumns, _prepareAddColumns, _prepareSqliteAddColumns, prepareAlterColumnsMysql, preparePgAlterColumns, prepareSqliteAlterColumns, prepareRenamePolicyJsons, prepareRenameIndPolicyJsons, prepareCreatePolicyJsons, prepareCreateIndPolicyJsons, prepareDropPolicyJsons, prepareDropIndPolicyJsons, prepareAlterPolicyJson, prepareAlterIndPolicyJson, preparePgCreateIndexesJson, prepareCreateIndexesJson, prepareCreateReferencesJson, prepareLibSQLCreateReferencesJson, prepareDropReferencesJson, prepareLibSQLDropReferencesJson, prepareAlterReferencesJson, prepareDropIndexesJson, prepareAddCompositePrimaryKeySqlite, prepareDeleteCompositePrimaryKeySqlite, prepareAlterCompositePrimaryKeySqlite, prepareAddCompositePrimaryKeyPg, prepareDeleteCompositePrimaryKeyPg, prepareAlterCompositePrimaryKeyPg, prepareAddUniqueConstraintPg, prepareDeleteUniqueConstraintPg, prepareAddCheckConstraint, prepareDeleteCheckConstraint, prepareAddCompositePrimaryKeyMySql, prepareDeleteCompositePrimaryKeyMySql, prepareAlterCompositePrimaryKeyMySql, preparePgCreateViewJson, prepareMySqlCreateViewJson, prepareSqliteCreateViewJson, prepareDropViewJson, prepareRenameViewJson, preparePgAlterViewAlterSchemaJson, preparePgAlterViewAddWithOptionJson, preparePgAlterViewDropWithOptionJson, preparePgAlterViewAlterTablespaceJson, preparePgAlterViewAlterUsingJson, prepareMySqlAlterView, init_jsonStatements, prepareLibSQLRecreateTable, prepareSQLiteRecreateTable, libSQLCombineStatements, sqliteCombineStatements, prepareSingleStoreRecreateTable, singleStoreCombineStatements, init_statementCombiner, snapshotsDiffer_exports, makeChanged, makeSelfOrChanged, makePatched, makeSelfOrPatched, columnSchema, alteredColumnSchema, enumSchema3, changedEnumSchema, tableScheme, alteredTableScheme, alteredViewCommon, alteredPgViewSchema, alteredMySqlViewSchema, diffResultScheme, diffResultSchemeMysql, diffResultSchemeSingleStore, diffResultSchemeSQLite, schemaChangeFor, nameChangeFor, nameSchemaChangeFor, columnChangeFor, applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, applySingleStoreSnapshotsDiff, applySqliteSnapshotsDiff, applyLibSQLSnapshotsDiff, init_snapshotsDiffer, init_words, dialects, dialect4, commonSquashedSchema, commonSchema, init_schemaValidator, sqliteDriversLiterals, postgresqlDriversLiterals, prefixes, prefix, casingTypes, casingType, sqliteDriver, postgresDriver, driver2, configMigrations, configCommonSchema, casing, introspectParams, configIntrospectCliSchema, configGenerateSchema, configPushSchema, init_common2, withStyle, init_outputs, import_hanji2, schemasResolver, tablesResolver, viewsResolver, mySqlViewsResolver, sqliteViewsResolver, sequencesResolver, roleResolver, policyResolver, indPolicyResolver, enumsResolver, columnsResolver, promptColumnsConflicts, promptNamedConflict, promptNamedWithSchemasConflict, promptSchemasConflict, BREAKPOINT, init_migrate, posixClasses, braceEscape, regexpEscape, rangesToString, parseClass, init_brace_expressions, escape, init_escape, unescape, init_unescape, import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path, sep2, GLOBSTAR, plTypes, qmark, star, twoStarDot, twoStarNoDot, charSet, reSpecials, addPatternStartSet, filter, ext, defaults, braceExpand, MAX_PATTERN_LENGTH, assertValidPattern, makeRe, match2, globUnescape, globMagic, regExpEscape, Minimatch, init_mjs, entityKind2, hasOwnEntityKind2, init_entity2, _a3, Column2, init_column2, _a22, ColumnBuilder2, init_column_builder2, TableName2, init_table_utils2, _a32, ForeignKeyBuilder2, _a4, ForeignKey2, init_foreign_keys2, init_tracing_utils2, _a5, UniqueConstraintBuilder, _a6, UniqueOnConstraintBuilder, _a7, UniqueConstraint, init_unique_constraint2, init_array2, _a8, _b, PgColumnBuilder2, _a9, _b2, PgColumn2, _a10, _b3, ExtraConfigColumn2, _a11, IndexedColumn2, _a12, _b4, PgArrayBuilder2, _a13, _b5, _PgArray, PgArray2, init_common22, _a14, _b6, PgEnumObjectColumnBuilder2, _a15, _b7, PgEnumObjectColumn2, isPgEnumSym2, _a16, _b8, PgEnumColumnBuilder2, _a17, _b9, PgEnumColumn2, init_enum2, _a18, Subquery2, _a19, _b10, WithSubquery2, init_subquery2, version4, init_version2, otel2, rawTracer2, tracer2, init_tracing2, ViewBaseConfig2, init_view_common3, Schema2, Columns2, ExtraConfigColumns2, OriginalName2, BaseName2, IsAlias2, ExtraConfigBuilder2, IsDrizzleTable2, _a20, _b11, _c, _d, _e3, _f, _g, _h, _i, _j, Table2, init_table8, _a21, FakePrimitiveParam, _a222, StringChunk2, _a23, _SQL, SQL2, _a24, Name2, noopDecoder2, noopEncoder2, noopMapper2, _a25, Param2, _a26, Placeholder2, IsDrizzleView2, _a27, _b12, _c2, View3, init_sql4, _a28, ColumnAliasProxyHandler2, _a29, TableAliasProxyHandler2, _a30, RelationTableAliasProxyHandler, init_alias3, _a31, _b13, DrizzleError2, DrizzleQueryError, _a322, _b14, TransactionRollbackError2, init_errors22, _a33, ConsoleLogWriter2, _a34, DefaultLogger2, _a35, NoopLogger2, init_logger3, init_operations, _a36, _b15, QueryPromise2, init_query_promise2, textDecoder, init_utils22, _a37, _b16, PgIntColumnBaseBuilder2, init_int_common2, _a38, _b17, PgBigInt53Builder2, _a39, _b18, PgBigInt532, _a40, _b19, PgBigInt64Builder2, _a41, _b20, PgBigInt642, init_bigint2, _a42, _b21, PgBigSerial53Builder2, _a43, _b22, PgBigSerial532, _a44, _b23, PgBigSerial64Builder2, _a45, _b24, PgBigSerial642, init_bigserial2, _a46, _b25, PgBooleanBuilder2, _a47, _b26, PgBoolean2, init_boolean2, _a48, _b27, PgCharBuilder2, _a49, _b28, PgChar2, init_char2, _a50, _b29, PgCidrBuilder2, _a51, _b30, PgCidr2, init_cidr2, _a52, _b31, PgCustomColumnBuilder2, _a53, _b32, PgCustomColumn2, init_custom2, _a54, _b33, PgDateColumnBaseBuilder2, init_date_common2, _a55, _b34, PgDateBuilder2, _a56, _b35, PgDate2, _a57, _b36, PgDateStringBuilder2, _a58, _b37, PgDateString2, init_date2, _a59, _b38, PgDoublePrecisionBuilder2, _a60, _b39, PgDoublePrecision2, init_double_precision2, _a61, _b40, PgInetBuilder2, _a62, _b41, PgInet2, init_inet2, _a63, _b42, PgIntegerBuilder2, _a64, _b43, PgInteger2, init_integer2, _a65, _b44, PgIntervalBuilder2, _a66, _b45, PgInterval2, init_interval2, _a67, _b46, PgJsonBuilder2, _a68, _b47, PgJson2, init_json2, _a69, _b48, PgJsonbBuilder2, _a70, _b49, PgJsonb2, init_jsonb2, _a71, _b50, PgLineBuilder2, _a72, _b51, PgLineTuple2, _a73, _b52, PgLineABCBuilder2, _a74, _b53, PgLineABC2, init_line2, _a75, _b54, PgMacaddrBuilder2, _a76, _b55, PgMacaddr2, init_macaddr2, _a77, _b56, PgMacaddr8Builder2, _a78, _b57, PgMacaddr82, init_macaddr82, _a79, _b58, PgNumericBuilder2, _a80, _b59, PgNumeric2, _a81, _b60, PgNumericNumberBuilder2, _a82, _b61, PgNumericNumber2, _a83, _b62, PgNumericBigIntBuilder2, _a84, _b63, PgNumericBigInt2, init_numeric2, _a85, _b64, PgPointTupleBuilder2, _a86, _b65, PgPointTuple2, _a87, _b66, PgPointObjectBuilder2, _a88, _b67, PgPointObject2, init_point2, init_utils32, _a89, _b68, PgGeometryBuilder2, _a90, _b69, PgGeometry2, _a91, _b70, PgGeometryObjectBuilder2, _a92, _b71, PgGeometryObject2, init_geometry2, _a93, _b72, PgRealBuilder2, _a94, _b73, PgReal2, init_real2, _a95, _b74, PgSerialBuilder2, _a96, _b75, PgSerial2, init_serial2, _a97, _b76, PgSmallIntBuilder2, _a98, _b77, PgSmallInt2, init_smallint2, _a99, _b78, PgSmallSerialBuilder2, _a100, _b79, PgSmallSerial2, init_smallserial2, _a101, _b80, PgTextBuilder2, _a102, _b81, PgText2, init_text2, _a103, _b82, PgTimeBuilder2, _a104, _b83, PgTime2, init_time2, _a105, _b84, PgTimestampBuilder2, _a106, _b85, PgTimestamp2, _a107, _b86, PgTimestampStringBuilder2, _a108, _b87, PgTimestampString2, init_timestamp2, _a109, _b88, PgUUIDBuilder2, _a110, _b89, PgUUID2, init_uuid3, _a111, _b90, PgVarcharBuilder2, _a112, _b91, PgVarchar2, init_varchar2, _a113, _b92, PgBinaryVectorBuilder2, _a114, _b93, PgBinaryVector2, init_bit2, _a115, _b94, PgHalfVectorBuilder2, _a116, _b95, PgHalfVector2, init_halfvec2, _a117, _b96, PgSparseVectorBuilder2, _a118, _b97, PgSparseVector2, init_sparsevec2, _a119, _b98, PgVectorBuilder2, _a120, _b99, PgVector2, init_vector3, init_all2, InlineForeignKeys2, EnableRLS2, _a121, _b100, _c3, _d2, _e22, _f2, PgTable2, pgTable2, init_table22, _a122, PrimaryKeyBuilder2, _a123, PrimaryKey2, init_primary_keys2, eq2, ne4, gt3, gte2, lt4, lte2, init_conditions2, init_select3, init_expressions2, _a124, Relation2, _a125, Relations2, _a126, _b101, _One, One2, _a127, _b102, _Many, Many2, init_relations2, init_aggregate2, init_vector22, init_functions2, init_sql22, dist_exports, init_dist9, init_alias22, _a128, CheckBuilder, _a129, Check, init_checks6, init_columns2, _a130, _SelectionProxyHandler, SelectionProxyHandler2, init_selection_proxy2, _a131, IndexBuilderOn2, _a132, IndexBuilder2, _a133, Index2, init_indexes2, _a134, PgPolicy, init_policies2, PgViewConfig2, init_view_common22, _a135, CasingCache2, init_casing2, _a136, _b103, PgViewBase2, init_view_base2, _a137, PgDialect2, init_dialect2, _a138, TypedQueryBuilder2, init_query_builder3, _a139, PgSelectBuilder2, _a140, _b104, PgSelectQueryBuilderBase2, _a141, _b105, PgSelectBase2, getPgSetOperators2, union22, unionAll2, intersect2, intersectAll2, except2, exceptAll2, init_select22, _a142, QueryBuilder2, init_query_builder22, _a143, DefaultViewBuilderCore, _a144, _b106, ViewBuilder, _a145, _b107, ManualViewBuilder, _a146, MaterializedViewBuilderCore, _a147, _b108, MaterializedViewBuilder, _a148, _b109, ManualMaterializedViewBuilder, _a149, _b110, _c4, PgView2, PgMaterializedViewConfig2, _a150, _b111, _c5, PgMaterializedView, init_view2, init_utils42, _a151, _b112, PgDeleteBase2, init_delete2, _a152, PgInsertBuilder2, _a153, _b113, PgInsertBase2, init_insert2, _a154, _b114, PgRefreshMaterializedView2, init_refresh_materialized_view2, init_select_types, _a155, PgUpdateBuilder2, _a156, _b115, PgUpdateBase2, init_update2, init_query_builders2, _a157, _b116, _c6, _PgCountBuilder, PgCountBuilder2, init_count2, _a158, RelationalQueryBuilder2, _a159, _b117, PgRelationalQuery2, init_query2, _a160, _b118, PgRaw2, init_raw2, _a161, PgDatabase2, init_db2, _a162, PgRole, init_roles2, _a163, PgSequence, init_sequence2, _a164, PgSchema5, init_schema4, _a165, Cache, _a166, _b119, NoopCache, init_cache, _a167, PgPreparedQuery2, _a168, PgSession2, _a169, _b120, PgTransaction2, init_session3, init_subquery22, init_utils52, init_pg_core2, vectorOps, init_vector32, sqlToStr, init_utils62, indexName, generatePgSnapshot, trimChar, fromDatabase, defaultForColumn, getColumnsInfoQuery, init_pgSerializer, import_hanji4, Select, init_selector_ui, init_alias32, _a170, CheckBuilder2, _a171, Check2, init_checks22, _a172, ForeignKeyBuilder22, _a173, ForeignKey22, init_foreign_keys22, _a174, UniqueConstraintBuilder2, _a175, UniqueOnConstraintBuilder2, _a176, UniqueConstraint2, init_unique_constraint22, _a177, _b121, SQLiteColumnBuilder, _a178, _b122, SQLiteColumn, init_common3, _a179, _b123, SQLiteBigIntBuilder, _a180, _b124, SQLiteBigInt, _a181, _b125, SQLiteBlobJsonBuilder, _a182, _b126, SQLiteBlobJson, _a183, _b127, SQLiteBlobBufferBuilder, _a184, _b128, SQLiteBlobBuffer, init_blob, _a185, _b129, SQLiteCustomColumnBuilder, _a186, _b130, SQLiteCustomColumn, init_custom22, _a187, _b131, SQLiteBaseIntegerBuilder, _a188, _b132, SQLiteBaseInteger, _a189, _b133, SQLiteIntegerBuilder, _a190, _b134, SQLiteInteger, _a191, _b135, SQLiteTimestampBuilder, _a192, _b136, SQLiteTimestamp, _a193, _b137, SQLiteBooleanBuilder, _a194, _b138, SQLiteBoolean, init_integer22, _a195, _b139, SQLiteNumericBuilder, _a196, _b140, SQLiteNumeric, _a197, _b141, SQLiteNumericNumberBuilder, _a198, _b142, SQLiteNumericNumber, _a199, _b143, SQLiteNumericBigIntBuilder, _a200, _b144, SQLiteNumericBigInt, init_numeric22, _a201, _b145, SQLiteRealBuilder, _a202, _b146, SQLiteReal, init_real22, _a203, _b147, SQLiteTextBuilder, _a204, _b148, SQLiteText, _a205, _b149, SQLiteTextJsonBuilder, _a206, _b150, SQLiteTextJson, init_text22, init_columns22, init_all22, InlineForeignKeys22, _a207, _b151, _c7, _d3, _e32, SQLiteTable, sqliteTable, init_table32, _a208, IndexBuilderOn22, _a209, IndexBuilder22, _a210, Index4, init_indexes22, _a211, PrimaryKeyBuilder22, _a212, PrimaryKey22, init_primary_keys22, init_utils72, _a213, _b152, SQLiteDeleteBase, init_delete22, _a214, _b153, SQLiteViewBase, init_view_base22, _a215, SQLiteDialect, _a216, _b154, SQLiteSyncDialect, _a217, _b155, SQLiteAsyncDialect, init_dialect22, _a218, SQLiteSelectBuilder, _a219, _b156, SQLiteSelectQueryBuilderBase, _a220, _b157, SQLiteSelectBase, getSQLiteSetOperators, union32, unionAll22, intersect22, except22, init_select32, _a221, QueryBuilder22, init_query_builder32, _a2222, SQLiteInsertBuilder, _a223, _b158, SQLiteInsertBase, init_insert22, init_select_types2, _a224, SQLiteUpdateBuilder, _a225, _b159, SQLiteUpdateBase, init_update22, init_query_builders22, _a226, _b160, _c8, _SQLiteCountBuilder, SQLiteCountBuilder, init_count22, _a227, RelationalQueryBuilder22, _a228, _b161, SQLiteRelationalQuery, _a229, _b162, SQLiteSyncRelationalQuery, init_query22, _a230, _b163, SQLiteRaw, init_raw22, _a231, BaseSQLiteDatabase, init_db22, _a232, _b164, ExecuteResultSync, _a233, SQLitePreparedQuery, _a234, SQLiteSession, _a235, _b165, SQLiteTransaction, init_session22, init_subquery3, _a236, ViewBuilderCore, _a237, _b166, ViewBuilder2, _a238, _b167, ManualViewBuilder2, _a239, _b168, SQLiteView2, init_view22, init_sqlite_core, generateSqliteSnapshot, fromDatabase2, init_sqliteSerializer, getTablesFilterByExtensions, init_getTablesFilterByExtensions, init_alias4, _a240, CheckBuilder3, _a241, Check3, init_checks32, _a242, ForeignKeyBuilder3, _a243, ForeignKey3, init_foreign_keys3, _a244, UniqueConstraintBuilder3, _a245, UniqueOnConstraintBuilder3, _a246, UniqueConstraint3, init_unique_constraint3, _a247, _b169, MySqlColumnBuilder, _a248, _b170, MySqlColumn, _a249, _b171, MySqlColumnBuilderWithAutoIncrement, _a250, _b172, MySqlColumnWithAutoIncrement, init_common4, _a251, _b173, MySqlBigInt53Builder, _a252, _b174, MySqlBigInt53, _a253, _b175, MySqlBigInt64Builder, _a254, _b176, MySqlBigInt64, init_bigint22, _a255, _b177, MySqlBinaryBuilder, _a256, _b178, MySqlBinary, init_binary, _a257, _b179, MySqlBooleanBuilder, _a258, _b180, MySqlBoolean, init_boolean22, _a259, _b181, MySqlCharBuilder, _a260, _b182, MySqlChar, init_char22, _a261, _b183, MySqlCustomColumnBuilder, _a262, _b184, MySqlCustomColumn, init_custom3, _a263, _b185, MySqlDateBuilder, _a264, _b186, MySqlDate, _a265, _b187, MySqlDateStringBuilder, _a266, _b188, MySqlDateString, init_date22, _a267, _b189, MySqlDateTimeBuilder, _a268, _b190, MySqlDateTime, _a269, _b191, MySqlDateTimeStringBuilder, _a270, _b192, MySqlDateTimeString, init_datetime, _a271, _b193, MySqlDecimalBuilder, _a272, _b194, MySqlDecimal, _a273, _b195, MySqlDecimalNumberBuilder, _a274, _b196, MySqlDecimalNumber, _a275, _b197, MySqlDecimalBigIntBuilder, _a276, _b198, MySqlDecimalBigInt, init_decimal, _a277, _b199, MySqlDoubleBuilder, _a278, _b200, MySqlDouble, init_double, _a279, _b201, MySqlEnumColumnBuilder, _a280, _b202, MySqlEnumColumn, _a281, _b203, MySqlEnumObjectColumnBuilder, _a282, _b204, MySqlEnumObjectColumn, init_enum22, _a283, _b205, MySqlFloatBuilder, _a284, _b206, MySqlFloat, init_float, _a285, _b207, MySqlIntBuilder, _a286, _b208, MySqlInt, init_int, _a287, _b209, MySqlJsonBuilder, _a288, _b210, MySqlJson, init_json22, _a289, _b211, MySqlMediumIntBuilder, _a290, _b212, MySqlMediumInt, init_mediumint, _a291, _b213, MySqlRealBuilder, _a292, _b214, MySqlReal, init_real3, _a293, _b215, MySqlSerialBuilder, _a294, _b216, MySqlSerial, init_serial22, _a295, _b217, MySqlSmallIntBuilder, _a296, _b218, MySqlSmallInt, init_smallint22, _a297, _b219, MySqlTextBuilder, _a298, _b220, MySqlText, init_text3, _a299, _b221, MySqlTimeBuilder, _a300, _b222, MySqlTime, init_time22, _a301, _b223, MySqlDateColumnBaseBuilder, _a302, _b224, MySqlDateBaseColumn, init_date_common22, _a303, _b225, MySqlTimestampBuilder, _a304, _b226, MySqlTimestamp, _a305, _b227, MySqlTimestampStringBuilder, _a306, _b228, MySqlTimestampString, init_timestamp22, _a307, _b229, MySqlTinyIntBuilder, _a308, _b230, MySqlTinyInt, init_tinyint, _a309, _b231, MySqlVarBinaryBuilder, _a310, _b232, MySqlVarBinary, init_varbinary, _a311, _b233, MySqlVarCharBuilder, _a312, _b234, MySqlVarChar, init_varchar22, _a313, _b235, MySqlYearBuilder, _a314, _b236, MySqlYear, init_year, init_columns3, _a315, _b237, _c9, _MySqlCountBuilder, MySqlCountBuilder, init_count3, _a316, IndexBuilderOn3, _a317, IndexBuilder3, _a318, Index5, init_indexes3, init_all3, InlineForeignKeys3, _a319, _b238, _c10, _d4, _e4, MySqlTable, mysqlTable, init_table42, _a320, PrimaryKeyBuilder3, _a321, PrimaryKey3, init_primary_keys3, MySqlViewConfig, init_view_common32, init_utils8, _a3222, _b239, MySqlDeleteBase, init_delete3, _a323, _b240, MySqlViewBase, init_view_base3, _a324, MySqlDialect, init_dialect3, _a325, MySqlSelectBuilder, _a326, _b241, MySqlSelectQueryBuilderBase, _a327, _b242, MySqlSelectBase, getMySqlSetOperators, union4, unionAll3, intersect3, intersectAll22, except3, exceptAll22, init_select4, _a328, QueryBuilder3, init_query_builder4, _a329, MySqlInsertBuilder, _a330, _b243, MySqlInsertBase, init_insert3, init_select_types3, _a331, MySqlUpdateBuilder, _a332, _b244, MySqlUpdateBase, init_update3, init_query_builders3, _a333, RelationalQueryBuilder3, _a334, _b245, MySqlRelationalQuery, init_query3, _a335, MySqlDatabase, init_db3, _a336, ViewBuilderCore2, _a337, _b246, ViewBuilder3, _a338, _b247, ManualViewBuilder3, _a339, _b248, _c11, MySqlView2, init_view3, _a340, MySqlSchema5, init_schema22, _a341, MySqlPreparedQuery, _a342, MySqlSession, _a343, _b249, MySqlTransaction, init_session32, init_subquery4, init_mysql_core, handleEnumType, generateMySqlSnapshot, fromDatabase3, init_mysqlSerializer, cliConfigGenerate, pushParams, pullParams, configCheck, cliConfigCheck, init_cli, gelCredentials, init_gel, libSQLCredentials, init_libsql, mysqlCredentials, init_mysql, postgresCredentials, init_postgres, singlestoreCredentials, init_singlestore, sqliteCredentials, init_sqlite, credentials, studioCliParams, studioConfig, init_studio, es5_exports, _3, es5_default, init_es5, import_hanji7, assertES5, safeRegister, migrateConfig, init_utils9, prepareFromExports, init_pgImports, init_alias5, _a344, UniqueConstraintBuilder4, _a345, UniqueOnConstraintBuilder4, _a346, UniqueConstraint4, init_unique_constraint4, _a347, _b250, SingleStoreColumnBuilder, _a348, _b251, SingleStoreColumn, _a349, _b252, SingleStoreColumnBuilderWithAutoIncrement, _a350, _b253, SingleStoreColumnWithAutoIncrement, init_common5, _a351, _b254, SingleStoreBigInt53Builder, _a352, _b255, SingleStoreBigInt53, _a353, _b256, SingleStoreBigInt64Builder, _a354, _b257, SingleStoreBigInt64, init_bigint3, _a355, _b258, SingleStoreBinaryBuilder, _a356, _b259, SingleStoreBinary, init_binary2, _a357, _b260, SingleStoreBooleanBuilder, _a358, _b261, SingleStoreBoolean, init_boolean3, _a359, _b262, SingleStoreCharBuilder, _a360, _b263, SingleStoreChar, init_char3, _a361, _b264, SingleStoreCustomColumnBuilder, _a362, _b265, SingleStoreCustomColumn, init_custom4, _a363, _b266, SingleStoreDateBuilder, _a364, _b267, SingleStoreDate, _a365, _b268, SingleStoreDateStringBuilder, _a366, _b269, SingleStoreDateString, init_date3, _a367, _b270, SingleStoreDateTimeBuilder, _a368, _b271, SingleStoreDateTime, _a369, _b272, SingleStoreDateTimeStringBuilder, _a370, _b273, SingleStoreDateTimeString, init_datetime2, _a371, _b274, SingleStoreDecimalBuilder, _a372, _b275, SingleStoreDecimal, _a373, _b276, SingleStoreDecimalNumberBuilder, _a374, _b277, SingleStoreDecimalNumber, _a375, _b278, SingleStoreDecimalBigIntBuilder, _a376, _b279, SingleStoreDecimalBigInt, init_decimal2, _a377, _b280, SingleStoreDoubleBuilder, _a378, _b281, SingleStoreDouble, init_double2, _a379, _b282, SingleStoreEnumColumnBuilder, _a380, _b283, SingleStoreEnumColumn, init_enum3, _a381, _b284, SingleStoreFloatBuilder, _a382, _b285, SingleStoreFloat, init_float2, _a383, _b286, SingleStoreIntBuilder, _a384, _b287, SingleStoreInt, init_int2, _a385, _b288, SingleStoreJsonBuilder, _a386, _b289, SingleStoreJson, init_json3, _a387, _b290, SingleStoreMediumIntBuilder, _a388, _b291, SingleStoreMediumInt, init_mediumint2, _a389, _b292, SingleStoreRealBuilder, _a390, _b293, SingleStoreReal, init_real4, _a391, _b294, SingleStoreSerialBuilder, _a392, _b295, SingleStoreSerial, init_serial3, _a393, _b296, SingleStoreSmallIntBuilder, _a394, _b297, SingleStoreSmallInt, init_smallint3, _a395, _b298, SingleStoreTextBuilder, _a396, _b299, SingleStoreText, init_text4, _a397, _b300, SingleStoreTimeBuilder, _a398, _b301, SingleStoreTime, init_time3, _a399, _b302, SingleStoreDateColumnBaseBuilder, _a400, _b303, SingleStoreDateBaseColumn, init_date_common3, _a401, _b304, SingleStoreTimestampBuilder, _a402, _b305, SingleStoreTimestamp, _a403, _b306, SingleStoreTimestampStringBuilder, _a404, _b307, SingleStoreTimestampString, init_timestamp3, _a405, _b308, SingleStoreTinyIntBuilder, _a406, _b309, SingleStoreTinyInt, init_tinyint2, _a407, _b310, SingleStoreVarBinaryBuilder, _a408, _b311, SingleStoreVarBinary, init_varbinary2, _a409, _b312, SingleStoreVarCharBuilder, _a410, _b313, SingleStoreVarChar, init_varchar3, _a411, _b314, SingleStoreVectorBuilder, _a412, _b315, SingleStoreVector, init_vector4, _a413, _b316, SingleStoreYearBuilder, _a414, _b317, SingleStoreYear, init_year2, init_columns4, _a415, _b318, _c12, _SingleStoreCountBuilder, SingleStoreCountBuilder, init_count4, _a416, IndexBuilderOn4, _a417, IndexBuilder4, _a418, Index6, init_indexes4, init_all4, _a419, _b319, _c13, _d5, SingleStoreTable, init_table52, _a420, PrimaryKeyBuilder4, _a421, PrimaryKey4, init_primary_keys4, init_utils10, _a422, _b320, SingleStoreDeleteBase, init_delete4, _a423, SingleStoreInsertBuilder, _a424, _b321, SingleStoreInsertBase, init_insert4, _a425, SingleStoreDialect, init_dialect4, _a426, SingleStoreSelectBuilder, _a427, _b322, SingleStoreSelectQueryBuilderBase, _a428, _b323, SingleStoreSelectBase, getSingleStoreSetOperators, union5, unionAll4, intersect4, except4, minus, init_select5, _a429, QueryBuilder4, init_query_builder5, init_select_types4, _a430, SingleStoreUpdateBuilder, _a431, _b324, SingleStoreUpdateBase, init_update4, init_query_builders4, _a432, SingleStoreDatabase, init_db4, _a433, SingleStoreSchema5, init_schema32, _a434, SingleStorePreparedQuery, _a435, SingleStoreSession, _a436, _b325, SingleStoreTransaction, init_session4, init_subquery5, init_singlestore_core, dialect5, generateSingleStoreSnapshot, fromDatabase4, init_singlestoreSerializer, sqliteImports_exports, prepareFromExports2, prepareFromSqliteImports, init_sqliteImports, mysqlImports_exports, prepareFromExports3, prepareFromMySqlImports, init_mysqlImports, mysqlPushUtils_exports, import_hanji8, filterStatements, logSuggestionsAndReturn2, init_mysqlPushUtils, mysqlIntrospect_exports, import_hanji9, mysqlPushIntrospect, init_mysqlIntrospect, singlestoreImports_exports, prepareFromExports4, prepareFromSingleStoreImports, init_singlestoreImports, singlestorePushUtils_exports, import_hanji10, filterStatements2, logSuggestionsAndReturn3, init_singlestorePushUtils, singlestoreIntrospect_exports, import_hanji11, singlestorePushIntrospect, init_singlestoreIntrospect, import_hanji3, pgPushIntrospect = async (db2, filters, schemaFilters, entities, tsSchema) => {
101052
103458
  const matchers = filters.map((it3) => {
101053
103459
  return new Minimatch(it3);
101054
103460
  });
@@ -121474,7 +123880,7 @@ globstar while`, file3, fr, pattern, pr2, swallowee);
121474
123880
  });
121475
123881
  }
121476
123882
  });
121477
- init_sql3 = __esm2({
123883
+ init_sql4 = __esm2({
121478
123884
  "../drizzle-orm/dist/sql/sql.js"() {
121479
123885
  init_entity2();
121480
123886
  init_enum2();
@@ -121827,7 +124233,7 @@ globstar while`, file3, fr, pattern, pr2, swallowee);
121827
124233
  "../drizzle-orm/dist/alias.js"() {
121828
124234
  init_column2();
121829
124235
  init_entity2();
121830
- init_sql3();
124236
+ init_sql4();
121831
124237
  init_table8();
121832
124238
  init_view_common3();
121833
124239
  _a28 = entityKind2;
@@ -122001,7 +124407,7 @@ params: ${params}`);
122001
124407
  "../drizzle-orm/dist/utils.js"() {
122002
124408
  init_column2();
122003
124409
  init_entity2();
122004
- init_sql3();
124410
+ init_sql4();
122005
124411
  init_subquery2();
122006
124412
  init_table8();
122007
124413
  init_view_common3();
@@ -122260,7 +124666,7 @@ params: ${params}`);
122260
124666
  init_date_common2 = __esm2({
122261
124667
  "../drizzle-orm/dist/pg-core/columns/date.common.js"() {
122262
124668
  init_entity2();
122263
- init_sql3();
124669
+ init_sql4();
122264
124670
  init_common22();
122265
124671
  PgDateColumnBaseBuilder2 = class extends (_b33 = PgColumnBuilder2, _a54 = entityKind2, _b33) {
122266
124672
  defaultNow() {
@@ -123045,7 +125451,7 @@ params: ${params}`);
123045
125451
  init_uuid3 = __esm2({
123046
125452
  "../drizzle-orm/dist/pg-core/columns/uuid.js"() {
123047
125453
  init_entity2();
123048
- init_sql3();
125454
+ init_sql4();
123049
125455
  init_common22();
123050
125456
  PgUUIDBuilder2 = class extends (_b88 = PgColumnBuilder2, _a109 = entityKind2, _b88) {
123051
125457
  constructor(name22) {
@@ -123316,7 +125722,7 @@ params: ${params}`);
123316
125722
  init_column2();
123317
125723
  init_entity2();
123318
125724
  init_table8();
123319
- init_sql3();
125725
+ init_sql4();
123320
125726
  eq2 = (left, right) => {
123321
125727
  return sql4`${left} = ${bindIfParam2(right, left)}`;
123322
125728
  };
@@ -123339,7 +125745,7 @@ params: ${params}`);
123339
125745
  });
123340
125746
  init_select3 = __esm2({
123341
125747
  "../drizzle-orm/dist/sql/expressions/select.js"() {
123342
- init_sql3();
125748
+ init_sql4();
123343
125749
  }
123344
125750
  });
123345
125751
  init_expressions2 = __esm2({
@@ -123355,7 +125761,7 @@ params: ${params}`);
123355
125761
  init_entity2();
123356
125762
  init_primary_keys2();
123357
125763
  init_expressions2();
123358
- init_sql3();
125764
+ init_sql4();
123359
125765
  _a124 = entityKind2;
123360
125766
  Relation2 = class {
123361
125767
  constructor(sourceTable, referencedTable, relationName) {
@@ -123409,12 +125815,12 @@ params: ${params}`);
123409
125815
  "../drizzle-orm/dist/sql/functions/aggregate.js"() {
123410
125816
  init_column2();
123411
125817
  init_entity2();
123412
- init_sql3();
125818
+ init_sql4();
123413
125819
  }
123414
125820
  });
123415
125821
  init_vector22 = __esm2({
123416
125822
  "../drizzle-orm/dist/sql/functions/vector.js"() {
123417
- init_sql3();
125823
+ init_sql4();
123418
125824
  }
123419
125825
  });
123420
125826
  init_functions2 = __esm2({
@@ -123427,7 +125833,7 @@ params: ${params}`);
123427
125833
  "../drizzle-orm/dist/sql/index.js"() {
123428
125834
  init_expressions2();
123429
125835
  init_functions2();
123430
- init_sql3();
125836
+ init_sql4();
123431
125837
  }
123432
125838
  });
123433
125839
  dist_exports = {};
@@ -123644,7 +126050,7 @@ params: ${params}`);
123644
126050
  init_alias3();
123645
126051
  init_column2();
123646
126052
  init_entity2();
123647
- init_sql3();
126053
+ init_sql4();
123648
126054
  init_subquery2();
123649
126055
  init_view_common3();
123650
126056
  _a130 = entityKind2;
@@ -123703,7 +126109,7 @@ params: ${params}`);
123703
126109
  });
123704
126110
  init_indexes2 = __esm2({
123705
126111
  "../drizzle-orm/dist/pg-core/indexes.js"() {
123706
- init_sql3();
126112
+ init_sql4();
123707
126113
  init_entity2();
123708
126114
  init_columns2();
123709
126115
  _a131 = entityKind2;
@@ -123866,7 +126272,7 @@ params: ${params}`);
123866
126272
  init_view_base2 = __esm2({
123867
126273
  "../drizzle-orm/dist/pg-core/view-base.js"() {
123868
126274
  init_entity2();
123869
- init_sql3();
126275
+ init_sql4();
123870
126276
  PgViewBase2 = class extends (_b103 = View3, _a136 = entityKind2, _b103) {
123871
126277
  };
123872
126278
  __publicField(PgViewBase2, _a136, "PgViewBase");
@@ -123883,7 +126289,7 @@ params: ${params}`);
123883
126289
  init_table22();
123884
126290
  init_relations2();
123885
126291
  init_sql22();
123886
- init_sql3();
126292
+ init_sql4();
123887
126293
  init_subquery2();
123888
126294
  init_table8();
123889
126295
  init_utils22();
@@ -124467,7 +126873,7 @@ params: ${params}`);
124467
126873
  init_query_builder3();
124468
126874
  init_query_promise2();
124469
126875
  init_selection_proxy2();
124470
- init_sql3();
126876
+ init_sql4();
124471
126877
  init_subquery2();
124472
126878
  init_table8();
124473
126879
  init_tracing2();
@@ -125088,7 +127494,7 @@ params: ${params}`);
125088
127494
  "../drizzle-orm/dist/pg-core/utils.js"() {
125089
127495
  init_entity2();
125090
127496
  init_table22();
125091
- init_sql3();
127497
+ init_sql4();
125092
127498
  init_subquery2();
125093
127499
  init_table8();
125094
127500
  init_view_common3();
@@ -125176,7 +127582,7 @@ params: ${params}`);
125176
127582
  init_entity2();
125177
127583
  init_query_promise2();
125178
127584
  init_selection_proxy2();
125179
- init_sql3();
127585
+ init_sql4();
125180
127586
  init_table8();
125181
127587
  init_tracing2();
125182
127588
  init_utils22();
@@ -125370,7 +127776,7 @@ params: ${params}`);
125370
127776
  init_table22();
125371
127777
  init_query_promise2();
125372
127778
  init_selection_proxy2();
125373
- init_sql3();
127779
+ init_sql4();
125374
127780
  init_subquery2();
125375
127781
  init_table8();
125376
127782
  init_utils22();
@@ -125544,7 +127950,7 @@ params: ${params}`);
125544
127950
  init_count2 = __esm2({
125545
127951
  "../drizzle-orm/dist/pg-core/query-builders/count.js"() {
125546
127952
  init_entity2();
125547
- init_sql3();
127953
+ init_sql4();
125548
127954
  _PgCountBuilder = class _PgCountBuilder2 extends (_c6 = SQL2, _b116 = entityKind2, _a157 = Symbol.toStringTag, _c6) {
125549
127955
  constructor(params) {
125550
127956
  super(_PgCountBuilder2.buildEmbeddedCount(params.source, params.filters).queryChunks);
@@ -125712,7 +128118,7 @@ params: ${params}`);
125712
128118
  init_entity2();
125713
128119
  init_query_builders2();
125714
128120
  init_selection_proxy2();
125715
- init_sql3();
128121
+ init_sql4();
125716
128122
  init_subquery2();
125717
128123
  init_count2();
125718
128124
  init_query2();
@@ -125884,10 +128290,10 @@ params: ${params}`);
125884
128290
  __publicField(PgSequence, _a163, "PgSequence");
125885
128291
  }
125886
128292
  });
125887
- init_schema3 = __esm2({
128293
+ init_schema4 = __esm2({
125888
128294
  "../drizzle-orm/dist/pg-core/schema.js"() {
125889
128295
  init_entity2();
125890
- init_sql3();
128296
+ init_sql4();
125891
128297
  init_enum2();
125892
128298
  init_sequence2();
125893
128299
  init_table22();
@@ -126103,7 +128509,7 @@ params: ${params}`);
126103
128509
  init_primary_keys2();
126104
128510
  init_query_builders2();
126105
128511
  init_roles2();
126106
- init_schema3();
128512
+ init_schema4();
126107
128513
  init_sequence2();
126108
128514
  init_session3();
126109
128515
  init_subquery22();
@@ -127911,7 +130317,7 @@ ORDER BY
127911
130317
  init_integer22 = __esm2({
127912
130318
  "../drizzle-orm/dist/sqlite-core/columns/integer.js"() {
127913
130319
  init_entity2();
127914
- init_sql3();
130320
+ init_sql4();
127915
130321
  init_utils22();
127916
130322
  init_common3();
127917
130323
  SQLiteBaseIntegerBuilder = class extends (_b131 = SQLiteColumnBuilder, _a187 = entityKind2, _b131) {
@@ -128274,7 +130680,7 @@ ORDER BY
128274
130680
  init_utils72 = __esm2({
128275
130681
  "../drizzle-orm/dist/sqlite-core/utils.js"() {
128276
130682
  init_entity2();
128277
- init_sql3();
130683
+ init_sql4();
128278
130684
  init_subquery2();
128279
130685
  init_table8();
128280
130686
  init_view_common3();
@@ -128368,7 +130774,7 @@ ORDER BY
128368
130774
  init_view_base22 = __esm2({
128369
130775
  "../drizzle-orm/dist/sqlite-core/view-base.js"() {
128370
130776
  init_entity2();
128371
- init_sql3();
130777
+ init_sql4();
128372
130778
  SQLiteViewBase = class extends (_b153 = View3, _a214 = entityKind2, _b153) {
128373
130779
  };
128374
130780
  __publicField(SQLiteViewBase, _a214, "SQLiteViewBase");
@@ -128383,7 +130789,7 @@ ORDER BY
128383
130789
  init_errors22();
128384
130790
  init_relations2();
128385
130791
  init_sql22();
128386
- init_sql3();
130792
+ init_sql4();
128387
130793
  init_columns22();
128388
130794
  init_table32();
128389
130795
  init_subquery2();
@@ -128963,7 +131369,7 @@ ORDER BY
128963
131369
  init_query_builder3();
128964
131370
  init_query_promise2();
128965
131371
  init_selection_proxy2();
128966
- init_sql3();
131372
+ init_sql4();
128967
131373
  init_subquery2();
128968
131374
  init_table8();
128969
131375
  init_utils22();
@@ -129326,7 +131732,7 @@ ORDER BY
129326
131732
  "../drizzle-orm/dist/sqlite-core/query-builders/insert.js"() {
129327
131733
  init_entity2();
129328
131734
  init_query_promise2();
129329
- init_sql3();
131735
+ init_sql4();
129330
131736
  init_table32();
129331
131737
  init_table8();
129332
131738
  init_utils22();
@@ -129573,7 +131979,7 @@ ORDER BY
129573
131979
  init_count22 = __esm2({
129574
131980
  "../drizzle-orm/dist/sqlite-core/query-builders/count.js"() {
129575
131981
  init_entity2();
129576
- init_sql3();
131982
+ init_sql4();
129577
131983
  _SQLiteCountBuilder = class _SQLiteCountBuilder2 extends (_c8 = SQL2, _b160 = entityKind2, _a226 = Symbol.toStringTag, _c8) {
129578
131984
  constructor(params) {
129579
131985
  super(_SQLiteCountBuilder2.buildEmbeddedCount(params.source, params.filters).queryChunks);
@@ -129742,7 +132148,7 @@ ORDER BY
129742
132148
  "../drizzle-orm/dist/sqlite-core/db.js"() {
129743
132149
  init_entity2();
129744
132150
  init_selection_proxy2();
129745
- init_sql3();
132151
+ init_sql4();
129746
132152
  init_query_builders22();
129747
132153
  init_subquery2();
129748
132154
  init_count22();
@@ -131713,7 +134119,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
131713
134119
  init_date_common22 = __esm2({
131714
134120
  "../drizzle-orm/dist/mysql-core/columns/date.common.js"() {
131715
134121
  init_entity2();
131716
- init_sql3();
134122
+ init_sql4();
131717
134123
  init_common4();
131718
134124
  MySqlDateColumnBaseBuilder = class extends (_b223 = MySqlColumnBuilder, _a301 = entityKind2, _b223) {
131719
134125
  defaultNow() {
@@ -131939,7 +134345,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
131939
134345
  init_count3 = __esm2({
131940
134346
  "../drizzle-orm/dist/mysql-core/query-builders/count.js"() {
131941
134347
  init_entity2();
131942
- init_sql3();
134348
+ init_sql4();
131943
134349
  _MySqlCountBuilder = class _MySqlCountBuilder2 extends (_c9 = SQL2, _b237 = entityKind2, _a315 = Symbol.toStringTag, _c9) {
131944
134350
  constructor(params) {
131945
134351
  super(_MySqlCountBuilder2.buildEmbeddedCount(params.source, params.filters).queryChunks);
@@ -132201,7 +134607,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
132201
134607
  init_view_base3 = __esm2({
132202
134608
  "../drizzle-orm/dist/mysql-core/view-base.js"() {
132203
134609
  init_entity2();
132204
- init_sql3();
134610
+ init_sql4();
132205
134611
  MySqlViewBase = class extends (_b240 = View3, _a323 = entityKind2, _b240) {
132206
134612
  };
132207
134613
  __publicField(MySqlViewBase, _a323, "MySqlViewBase");
@@ -132216,7 +134622,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
132216
134622
  init_errors22();
132217
134623
  init_relations2();
132218
134624
  init_expressions2();
132219
- init_sql3();
134625
+ init_sql4();
132220
134626
  init_subquery2();
132221
134627
  init_table8();
132222
134628
  init_utils22();
@@ -132982,7 +135388,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
132982
135388
  init_query_builder3();
132983
135389
  init_query_promise2();
132984
135390
  init_selection_proxy2();
132985
- init_sql3();
135391
+ init_sql4();
132986
135392
  init_subquery2();
132987
135393
  init_table8();
132988
135394
  init_utils22();
@@ -133383,7 +135789,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
133383
135789
  "../drizzle-orm/dist/mysql-core/query-builders/insert.js"() {
133384
135790
  init_entity2();
133385
135791
  init_query_promise2();
133386
- init_sql3();
135792
+ init_sql4();
133387
135793
  init_table8();
133388
135794
  init_utils22();
133389
135795
  init_utils8();
@@ -133663,7 +136069,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
133663
136069
  "../drizzle-orm/dist/mysql-core/db.js"() {
133664
136070
  init_entity2();
133665
136071
  init_selection_proxy2();
133666
- init_sql3();
136072
+ init_sql4();
133667
136073
  init_subquery2();
133668
136074
  init_count3();
133669
136075
  init_query_builders3();
@@ -133892,7 +136298,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
133892
136298
  init_cache();
133893
136299
  init_entity2();
133894
136300
  init_errors22();
133895
- init_sql3();
136301
+ init_sql4();
133896
136302
  init_db3();
133897
136303
  _a341 = entityKind2;
133898
136304
  MySqlPreparedQuery = class {
@@ -135915,7 +138321,7 @@ AND
135915
138321
  init_date_common3 = __esm2({
135916
138322
  "../drizzle-orm/dist/singlestore-core/columns/date.common.js"() {
135917
138323
  init_entity2();
135918
- init_sql3();
138324
+ init_sql4();
135919
138325
  init_common5();
135920
138326
  SingleStoreDateColumnBaseBuilder = class extends (_b302 = SingleStoreColumnBuilder, _a399 = entityKind2, _b302) {
135921
138327
  defaultNow() {
@@ -135940,7 +138346,7 @@ AND
135940
138346
  init_timestamp3 = __esm2({
135941
138347
  "../drizzle-orm/dist/singlestore-core/columns/timestamp.js"() {
135942
138348
  init_entity2();
135943
- init_sql3();
138349
+ init_sql4();
135944
138350
  init_utils22();
135945
138351
  init_date_common3();
135946
138352
  SingleStoreTimestampBuilder = class extends (_b304 = SingleStoreDateColumnBaseBuilder, _a401 = entityKind2, _b304) {
@@ -136175,7 +138581,7 @@ AND
136175
138581
  init_count4 = __esm2({
136176
138582
  "../drizzle-orm/dist/singlestore-core/query-builders/count.js"() {
136177
138583
  init_entity2();
136178
- init_sql3();
138584
+ init_sql4();
136179
138585
  _SingleStoreCountBuilder = class _SingleStoreCountBuilder2 extends (_c12 = SQL2, _b318 = entityKind2, _a415 = Symbol.toStringTag, _c12) {
136180
138586
  constructor(params) {
136181
138587
  super(_SingleStoreCountBuilder2.buildEmbeddedCount(params.source, params.filters).queryChunks);
@@ -136345,7 +138751,7 @@ AND
136345
138751
  init_utils10 = __esm2({
136346
138752
  "../drizzle-orm/dist/singlestore-core/utils.js"() {
136347
138753
  init_entity2();
136348
- init_sql3();
138754
+ init_sql4();
136349
138755
  init_subquery2();
136350
138756
  init_table8();
136351
138757
  init_indexes4();
@@ -136423,7 +138829,7 @@ AND
136423
138829
  "../drizzle-orm/dist/singlestore-core/query-builders/insert.js"() {
136424
138830
  init_entity2();
136425
138831
  init_query_promise2();
136426
- init_sql3();
138832
+ init_sql4();
136427
138833
  init_table8();
136428
138834
  init_utils22();
136429
138835
  init_utils10();
@@ -136520,7 +138926,7 @@ AND
136520
138926
  init_errors22();
136521
138927
  init_relations2();
136522
138928
  init_expressions2();
136523
- init_sql3();
138929
+ init_sql4();
136524
138930
  init_subquery2();
136525
138931
  init_table8();
136526
138932
  init_utils22();
@@ -137051,7 +139457,7 @@ AND
137051
139457
  init_query_builder3();
137052
139458
  init_query_promise2();
137053
139459
  init_selection_proxy2();
137054
- init_sql3();
139460
+ init_sql4();
137055
139461
  init_subquery2();
137056
139462
  init_table8();
137057
139463
  init_utils22();
@@ -137509,7 +139915,7 @@ AND
137509
139915
  "../drizzle-orm/dist/singlestore-core/db.js"() {
137510
139916
  init_entity2();
137511
139917
  init_selection_proxy2();
137512
- init_sql3();
139918
+ init_sql4();
137513
139919
  init_subquery2();
137514
139920
  init_count4();
137515
139921
  init_query_builders4();
@@ -137623,7 +140029,7 @@ AND
137623
140029
  init_cache();
137624
140030
  init_entity2();
137625
140031
  init_errors22();
137626
- init_sql3();
140032
+ init_sql4();
137627
140033
  init_db4();
137628
140034
  _a434 = entityKind2;
137629
140035
  SingleStorePreparedQuery = class {
@@ -139898,7 +142304,7 @@ function requireUserId(userId) {
139898
142304
  return userId;
139899
142305
  }
139900
142306
  var init_params_util = __esm(() => {
139901
- init_src4();
142307
+ init_src5();
139902
142308
  init_errors();
139903
142309
  });
139904
142310
 
@@ -139951,6 +142357,7 @@ var init_utils11 = __esm(() => {
139951
142357
  init_lti_util();
139952
142358
  init_lti_provisioning();
139953
142359
  init_params_util();
142360
+ init_secrets_util();
139954
142361
  init_timeback_util();
139955
142362
  init_validation_util();
139956
142363
  });
@@ -140138,7 +142545,7 @@ var init_database_controller = __esm(() => {
140138
142545
  throw ApiError.unprocessableEntity("Validation failed", details);
140139
142546
  }
140140
142547
  }
140141
- return ctx.services.database.reset(slug2, ctx.user, body2.schema);
142548
+ return ctx.services.database.reset(slug2, ctx.user, body2);
140142
142549
  });
140143
142550
  database = defineControllerNames("database", {
140144
142551
  reset
@@ -140191,6 +142598,85 @@ var init_deploy_controller = __esm(() => {
140191
142598
  });
140192
142599
  });
140193
142600
 
142601
+ // ../api-core/src/controllers/deployment-state.controller.ts
142602
+ var get, baseline, realignMigration, resolveMigration, history, restorePoints, restore, reportBlocked, deploymentState;
142603
+ var init_deployment_state_controller = __esm(() => {
142604
+ init_schemas_index();
142605
+ init_errors();
142606
+ init_utils11();
142607
+ get = requireDeveloper(async (ctx) => {
142608
+ const slug2 = requireSlug(ctx.params.slug);
142609
+ const include = ctx.url.searchParams.getAll("include").flatMap((value) => value.split(",")).filter(Boolean);
142610
+ const unsupported = include.filter((value) => value !== "schemaSnapshot");
142611
+ if (unsupported.length > 0) {
142612
+ throw ApiError.badRequest(`Unsupported include value(s): ${unsupported.join(", ")}`);
142613
+ }
142614
+ return ctx.services.deploymentState.get(slug2, ctx.user, {
142615
+ includeSchemaSnapshot: include.includes("schemaSnapshot")
142616
+ });
142617
+ });
142618
+ baseline = requireDeveloper(async (ctx) => {
142619
+ const slug2 = requireSlug(ctx.params.slug);
142620
+ const body2 = await parseRequestBody(ctx.request, DeploymentStateBaselineSchema);
142621
+ return ctx.services.deploymentState.baseline(slug2, body2, ctx.user);
142622
+ });
142623
+ realignMigration = requireDeveloper(async (ctx) => {
142624
+ const slug2 = requireSlug(ctx.params.slug);
142625
+ const tag = ctx.params.tag;
142626
+ if (!tag) {
142627
+ throw ApiError.badRequest("Missing migration tag");
142628
+ }
142629
+ const body2 = await parseRequestBody(ctx.request, MigrationRealignSchema);
142630
+ return ctx.services.deploymentState.realignMigration(slug2, tag, body2.checksum, ctx.user);
142631
+ });
142632
+ resolveMigration = requireDeveloper(async (ctx) => {
142633
+ const slug2 = requireSlug(ctx.params.slug);
142634
+ const tag = ctx.params.tag;
142635
+ if (!tag) {
142636
+ throw ApiError.badRequest("Missing migration tag");
142637
+ }
142638
+ const body2 = await parseRequestBody(ctx.request, MigrationResolveSchema);
142639
+ return ctx.services.deploymentState.resolveMigration(slug2, tag, body2, ctx.user);
142640
+ });
142641
+ history = requireDeveloper(async (ctx) => {
142642
+ const slug2 = requireSlug(ctx.params.slug);
142643
+ const limitParam = ctx.url.searchParams.get("limit");
142644
+ let limit;
142645
+ if (limitParam !== null) {
142646
+ limit = Number(limitParam);
142647
+ if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
142648
+ throw ApiError.badRequest("limit must be an integer between 1 and 100");
142649
+ }
142650
+ }
142651
+ return ctx.services.deploymentState.history(slug2, ctx.user, { limit });
142652
+ });
142653
+ restorePoints = requireDeveloper(async (ctx) => {
142654
+ const slug2 = requireSlug(ctx.params.slug);
142655
+ return ctx.services.deploymentState.restorePoints(slug2, ctx.user);
142656
+ });
142657
+ restore = requireDeveloper(async (ctx) => {
142658
+ const slug2 = requireSlug(ctx.params.slug);
142659
+ const body2 = await parseRequestBody(ctx.request, DatabaseRestoreSchema);
142660
+ return ctx.services.deploymentState.restoreToBookmark(slug2, body2, ctx.user);
142661
+ });
142662
+ reportBlocked = requireDeveloper(async (ctx) => {
142663
+ const slug2 = requireSlug(ctx.params.slug);
142664
+ const body2 = await parseRequestBody(ctx.request, DeployBlockedReportSchema);
142665
+ await ctx.services.deploymentState.reportDeployBlocked(slug2, ctx.user, body2);
142666
+ return { recorded: true };
142667
+ });
142668
+ deploymentState = defineControllerNames("deploymentState", {
142669
+ get,
142670
+ baseline,
142671
+ realignMigration,
142672
+ resolveMigration,
142673
+ history,
142674
+ restorePoints,
142675
+ restore,
142676
+ reportBlocked
142677
+ });
142678
+ });
142679
+
140194
142680
  // ../api-core/src/controllers/developer.controller.ts
140195
142681
  var apply, getStatus, developer;
140196
142682
  var init_developer_controller = __esm(() => {
@@ -140657,7 +143143,7 @@ var init_lti_controller = __esm(() => {
140657
143143
  });
140658
143144
 
140659
143145
  // ../api-core/src/controllers/secrets.controller.ts
140660
- var listKeys2, setSecrets, deleteSecret, secrets;
143146
+ var listKeys2, setSecrets, deleteSecret, diff, secrets;
140661
143147
  var init_secrets_controller = __esm(() => {
140662
143148
  init_esm();
140663
143149
  init_schemas_index();
@@ -140703,10 +143189,19 @@ var init_secrets_controller = __esm(() => {
140703
143189
  await ctx.services.secrets.deleteSecret(slug2, key, ctx.user);
140704
143190
  return { success: true };
140705
143191
  });
143192
+ diff = requireDeveloper(async (ctx) => {
143193
+ const slug2 = ctx.params.slug;
143194
+ if (!slug2) {
143195
+ throw ApiError.badRequest("Missing game slug");
143196
+ }
143197
+ const body2 = await parseRequestBody(ctx.request, SecretsDiffRequestSchema);
143198
+ return ctx.services.secrets.diff(slug2, body2.secrets, ctx.user);
143199
+ });
140706
143200
  secrets = defineControllerNames("secrets", {
140707
143201
  listKeys: listKeys2,
140708
143202
  setSecrets,
140709
- deleteSecret
143203
+ deleteSecret,
143204
+ diff
140710
143205
  });
140711
143206
  });
140712
143207
 
@@ -140781,7 +143276,7 @@ var populateStudent, getUser, getUserEnrollments, getUserById, setupIntegration,
140781
143276
  var init_timeback_controller = __esm(() => {
140782
143277
  init_esm();
140783
143278
  init_schemas_index();
140784
- init_src4();
143279
+ init_src5();
140785
143280
  init_timeback3();
140786
143281
  init_errors();
140787
143282
  init_utils11();
@@ -141548,6 +144043,7 @@ var init_controllers = __esm(() => {
141548
144043
  init_dashboard_controller();
141549
144044
  init_database_controller();
141550
144045
  init_deploy_controller();
144046
+ init_deployment_state_controller();
141551
144047
  init_developer_controller();
141552
144048
  init_domain_controller();
141553
144049
  init_game_member_controller();
@@ -142082,6 +144578,23 @@ var init_deploy = __esm(async () => {
142082
144578
  });
142083
144579
  });
142084
144580
 
144581
+ // src/routes/platform/games/deployment-state.ts
144582
+ var gameDeploymentStateRouter;
144583
+ var init_deployment_state = __esm(async () => {
144584
+ init_dist7();
144585
+ init_controllers();
144586
+ await init_api3();
144587
+ gameDeploymentStateRouter = new Hono2;
144588
+ gameDeploymentStateRouter.get("/:slug/deployment-state", handle2(deploymentState.get));
144589
+ gameDeploymentStateRouter.post("/:slug/deployment-state/baseline", handle2(deploymentState.baseline));
144590
+ gameDeploymentStateRouter.post("/:slug/deployment-state/migrations/:tag/realign", handle2(deploymentState.realignMigration));
144591
+ gameDeploymentStateRouter.post("/:slug/deployment-state/migrations/:tag/resolve", handle2(deploymentState.resolveMigration));
144592
+ gameDeploymentStateRouter.get("/:slug/deployments", handle2(deploymentState.history));
144593
+ gameDeploymentStateRouter.post("/:slug/deployments/blocked", handle2(deploymentState.reportBlocked));
144594
+ gameDeploymentStateRouter.get("/:slug/database/restore-points", handle2(deploymentState.restorePoints));
144595
+ gameDeploymentStateRouter.post("/:slug/database/restore", handle2(deploymentState.restore));
144596
+ });
144597
+
142085
144598
  // src/routes/platform/games/domains.ts
142086
144599
  var gameDomainsRouter;
142087
144600
  var init_domains2 = __esm(async () => {
@@ -142127,6 +144640,7 @@ var init_secrets = __esm(async () => {
142127
144640
  gameSecretsRouter = new Hono2;
142128
144641
  gameSecretsRouter.get("/:slug/secrets", handle2(secrets.listKeys));
142129
144642
  gameSecretsRouter.post("/:slug/secrets", handle2(secrets.setSecrets));
144643
+ gameSecretsRouter.post("/:slug/secrets/diff", handle2(secrets.diff));
142130
144644
  gameSecretsRouter.delete("/:slug/secrets/:key", handle2(secrets.deleteSecret));
142131
144645
  });
142132
144646
 
@@ -142329,6 +144843,7 @@ var init_games2 = __esm(async () => {
142329
144843
  await __promiseAll([
142330
144844
  init_crud(),
142331
144845
  init_deploy(),
144846
+ init_deployment_state(),
142332
144847
  init_domains2(),
142333
144848
  init_logs(),
142334
144849
  init_scores(),
@@ -142343,6 +144858,7 @@ var init_games2 = __esm(async () => {
142343
144858
  gamesRouter.route("/", gameVerifyRouter);
142344
144859
  gamesRouter.route("/", gameUploadsRouter);
142345
144860
  gamesRouter.route("/", gameDeployRouter);
144861
+ gamesRouter.route("/", gameDeploymentStateRouter);
142346
144862
  gamesRouter.route("/", gameDomainsRouter);
142347
144863
  gamesRouter.route("/", gameLogsRouter);
142348
144864
  gamesRouter.route("/", gameScoresRouter);
@@ -144689,7 +147205,7 @@ function printBanner(options) {
144689
147205
  }
144690
147206
 
144691
147207
  // src/cli/options.ts
144692
- init_src4();
147208
+ init_src5();
144693
147209
  import { resolve as resolve3 } from "node:path";
144694
147210
 
144695
147211
  // ../utils/src/file-loader.ts