@geekmidas/cli 10.0.0-alpha.54 → 10.0.0-alpha.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{HostingerProvider-GF6NAZAK.mjs → HostingerProvider-cL-6oQ5r.mjs} +2 -2
- package/dist/{HostingerProvider-GF6NAZAK.mjs.map → HostingerProvider-cL-6oQ5r.mjs.map} +1 -1
- package/dist/LegacyStateStore-ByRWQ9s1.mjs +89 -0
- package/dist/LegacyStateStore-ByRWQ9s1.mjs.map +1 -0
- package/dist/LegacyStateStore-C_OFs1gN.cjs +89 -0
- package/dist/LegacyStateStore-C_OFs1gN.cjs.map +1 -0
- package/dist/LocalStateStore-BupdV-VN.mjs +163 -0
- package/dist/LocalStateStore-BupdV-VN.mjs.map +1 -0
- package/dist/LocalStateStore-DDDU0HkI.cjs +163 -0
- package/dist/LocalStateStore-DDDU0HkI.cjs.map +1 -0
- package/dist/{OpenApiTsGenerator-BzIGy8KE.mjs → OpenApiTsGenerator-DKmAorGX.mjs} +34 -11
- package/dist/{OpenApiTsGenerator-BzIGy8KE.mjs.map → OpenApiTsGenerator-DKmAorGX.mjs.map} +1 -1
- package/dist/{OpenApiTsGenerator-BN0PIZxd.cjs → OpenApiTsGenerator-WlUHjimW.cjs} +34 -11
- package/dist/{OpenApiTsGenerator-BN0PIZxd.cjs.map → OpenApiTsGenerator-WlUHjimW.cjs.map} +1 -1
- package/dist/S3StateStore-C7eBae0G.cjs +160 -0
- package/dist/S3StateStore-C7eBae0G.cjs.map +1 -0
- package/dist/S3StateStore-FhzyENrN.mjs +161 -0
- package/dist/S3StateStore-FhzyENrN.mjs.map +1 -0
- package/dist/SSMStateStore-DD7jKrCO.cjs +146 -0
- package/dist/SSMStateStore-DD7jKrCO.cjs.map +1 -0
- package/dist/SSMStateStore-oda9xOGc.mjs +147 -0
- package/dist/SSMStateStore-oda9xOGc.mjs.map +1 -0
- package/dist/{backends-Dfeu5Dgc.mjs → backends-BNrMPlJb.mjs} +2 -2
- package/dist/{backends-Dfeu5Dgc.mjs.map → backends-BNrMPlJb.mjs.map} +1 -1
- package/dist/{backends-D5aDWxuA.cjs → backends-nBauiBkt.cjs} +2 -2
- package/dist/{backends-D5aDWxuA.cjs.map → backends-nBauiBkt.cjs.map} +1 -1
- package/dist/{bundler--fyybf1N.mjs → bundler-URImKj-A.mjs} +2 -2
- package/dist/{bundler--fyybf1N.mjs.map → bundler-URImKj-A.mjs.map} +1 -1
- package/dist/{config-Cvr5fCbn.cjs → config-C7NZG2tr.cjs} +2 -2
- package/dist/{config-Cvr5fCbn.cjs.map → config-C7NZG2tr.cjs.map} +1 -1
- package/dist/{config-SOkDH-n1.mjs → config-XEd-dKVX.mjs} +2 -2
- package/dist/{config-SOkDH-n1.mjs.map → config-XEd-dKVX.mjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.cts +2 -2
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +2 -2
- package/dist/{encryption-O-XdeNxe.mjs → encryption-Bc1cMdeY.mjs} +4 -4
- package/dist/{encryption-O-XdeNxe.mjs.map → encryption-Bc1cMdeY.mjs.map} +1 -1
- package/dist/{encryption-tB4LqLKN.cjs → encryption-DSHYN5ap.cjs} +4 -4
- package/dist/{encryption-tB4LqLKN.cjs.map → encryption-DSHYN5ap.cjs.map} +1 -1
- package/dist/{github-BGx4U61b.cjs → github-CWflxaV4.cjs} +3 -3
- package/dist/{github-BGx4U61b.cjs.map → github-CWflxaV4.cjs.map} +1 -1
- package/dist/{github-U_frvZgD.mjs → github-DWHXTcwL.mjs} +3 -3
- package/dist/{github-U_frvZgD.mjs.map → github-DWHXTcwL.mjs.map} +1 -1
- package/dist/{index-fU3qHy7c.d.cts → index-B8nraKvg.d.mts} +2 -2
- package/dist/{index-DYh5TrsZ.d.mts.map → index-B8nraKvg.d.mts.map} +1 -1
- package/dist/{index-DYh5TrsZ.d.mts → index-BvBQS89a.d.cts} +2 -2
- package/dist/{index-fU3qHy7c.d.cts.map → index-BvBQS89a.d.cts.map} +1 -1
- package/dist/index.cjs +993 -215
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +991 -221
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-DN5VM5vy.cjs → migrate-DHMRgnP6.cjs} +4 -4
- package/dist/{migrate-DN5VM5vy.cjs.map → migrate-DHMRgnP6.cjs.map} +1 -1
- package/dist/{migrate-DWDaaBfo.mjs → migrate-PcQg692O.mjs} +4 -4
- package/dist/{migrate-DWDaaBfo.mjs.map → migrate-PcQg692O.mjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +3 -3
- package/dist/{ready-VkNwfJu7.cjs → ready-BefA4mM0.cjs} +2 -2
- package/dist/{ready-VkNwfJu7.cjs.map → ready-BefA4mM0.cjs.map} +1 -1
- package/dist/{ready-C8wG_d0v.mjs → ready-bES_Jk5v.mjs} +2 -2
- package/dist/{ready-C8wG_d0v.mjs.map → ready-bES_Jk5v.mjs.map} +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{types-DYDT4FfE.d.cts → types-Cgj-cq2m.d.mts} +136 -5
- package/dist/types-Cgj-cq2m.d.mts.map +1 -0
- package/dist/{types-CT0ymlBk.d.mts → types-CmxMhLGp.d.cts} +137 -4
- package/dist/types-CmxMhLGp.d.cts.map +1 -0
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-Bwl0728I.mjs → workspace-BE0WHPw9.mjs} +8 -8
- package/dist/{workspace-Bwl0728I.mjs.map → workspace-BE0WHPw9.mjs.map} +1 -1
- package/dist/{workspace-DFYu-iRP.cjs → workspace-CXvYabDJ.cjs} +6 -6
- package/dist/{workspace-DFYu-iRP.cjs.map → workspace-CXvYabDJ.cjs.map} +1 -1
- package/dist/{workspace-bOsks1uk.mjs → workspace-DHK2N1mq.mjs} +22 -3
- package/dist/{workspace-bOsks1uk.mjs.map → workspace-DHK2N1mq.mjs.map} +1 -1
- package/dist/{workspace-BcCiLzTO.cjs → workspace-DL_99LJC.cjs} +22 -3
- package/dist/{workspace-BcCiLzTO.cjs.map → workspace-DL_99LJC.cjs.map} +1 -1
- package/package.json +14 -14
- package/dist/types-CT0ymlBk.d.mts.map +0 -1
- package/dist/types-DYDT4FfE.d.cts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalStateStore-DDDU0HkI.cjs","names":["DocumentStateStore","join","readFile","contentVersion","StateVersionConflict","randomUUID","open","rename","rm","writeFile","StateLocked","mkdir","unlink","StateStoreBusy","stat"],"sources":["../src/deploy/LocalStateStore.ts"],"sourcesContent":["/**\n * Local filesystem state store.\n *\n * `.gkm/deploy-<stage>.json` holds the state, `.gkm/deploy-<stage>.lock` the\n * lock. Every file is mode 0600: state holds database passwords and IAM keys.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport {\n\tmkdir,\n\topen,\n\treadFile,\n\trename,\n\trm,\n\tstat,\n\tunlink,\n\twriteFile,\n} from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n\tcontentVersion,\n\tDocumentStateStore,\n\ttype LockHolder,\n\ttype RawState,\n\tStateLocked,\n\tStateStoreBusy,\n\ttype StateVersion,\n\tStateVersionConflict,\n} from './StateStore';\n\nconst FILE_MODE = 0o600;\n\n/** How long a write waits for another process's write to finish. */\nconst MUTEX_TIMEOUT_MS = 5_000;\n/**\n * A write holds the mutex for milliseconds, so one this old was left by a\n * process that died mid-write and is safe to take over.\n */\nconst MUTEX_STALE_MS = 30_000;\n\nfunction isCode(error: unknown, code: string): boolean {\n\treturn (error as NodeJS.ErrnoException)?.code === code;\n}\n\nexport class LocalStateStore extends DocumentStateStore {\n\tconstructor(readonly workspaceRoot: string) {\n\t\tsuper();\n\t}\n\n\tprivate get dir(): string {\n\t\treturn join(this.workspaceRoot, '.gkm');\n\t}\n\n\tstatePath(stage: string): string {\n\t\treturn join(this.dir, `deploy-${stage}.json`);\n\t}\n\n\tlockPath(stage: string): string {\n\t\treturn join(this.dir, `deploy-${stage}.lock`);\n\t}\n\n\tbackupPath(stage: string): string {\n\t\treturn join(this.dir, `deploy-${stage}.v1.json`);\n\t}\n\n\tprivate mutexPath(stage: string): string {\n\t\treturn join(this.dir, `deploy-${stage}.json.mutex`);\n\t}\n\n\tprotected location(stage: string): string {\n\t\treturn this.statePath(stage);\n\t}\n\n\tprotected async readRaw(stage: string): Promise<RawState | null> {\n\t\ttry {\n\t\t\tconst body = await readFile(this.statePath(stage), 'utf-8');\n\t\t\treturn { body, version: contentVersion(body) };\n\t\t} catch (error) {\n\t\t\tif (isCode(error, 'ENOENT')) return null;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprotected async writeRaw(\n\t\tstage: string,\n\t\tbody: string,\n\t\texpectedVersion: StateVersion | null,\n\t): Promise<StateVersion> {\n\t\tawait this.ensureDir();\n\t\treturn this.withMutex(stage, async () => {\n\t\t\tconst current = await this.readRaw(stage);\n\t\t\tconst actual = current?.version ?? null;\n\t\t\tif (actual !== expectedVersion) {\n\t\t\t\tthrow new StateVersionConflict(stage, expectedVersion, actual);\n\t\t\t}\n\n\t\t\t// Written beside the target and renamed over it: a reader sees the\n\t\t\t// old file or the new one, never half of either.\n\t\t\tconst target = this.statePath(stage);\n\t\t\tconst temp = `${target}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\tconst handle = await open(temp, 'wx', FILE_MODE);\n\t\t\t\ttry {\n\t\t\t\t\tawait handle.writeFile(body);\n\t\t\t\t\tawait handle.sync();\n\t\t\t\t} finally {\n\t\t\t\t\tawait handle.close();\n\t\t\t\t}\n\t\t\t\tawait rename(temp, target);\n\t\t\t} catch (error) {\n\t\t\t\tawait rm(temp, { force: true });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn contentVersion(body);\n\t\t});\n\t}\n\n\tprotected async writeV1Backup(stage: string, body: string): Promise<void> {\n\t\ttry {\n\t\t\tawait writeFile(this.backupPath(stage), body, {\n\t\t\t\tflag: 'wx',\n\t\t\t\tmode: FILE_MODE,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t// The first migration's backup is the one worth keeping.\n\t\t\tif (!isCode(error, 'EEXIST')) throw error;\n\t\t}\n\t}\n\n\tprotected async createLock(stage: string, holder: LockHolder): Promise<void> {\n\t\tawait this.ensureDir();\n\t\tlet handle: Awaited<ReturnType<typeof open>>;\n\t\ttry {\n\t\t\thandle = await open(this.lockPath(stage), 'wx', FILE_MODE);\n\t\t} catch (error) {\n\t\t\tif (isCode(error, 'EEXIST')) {\n\t\t\t\tthrow new StateLocked(\n\t\t\t\t\tstage,\n\t\t\t\t\tawait this.readLock(stage),\n\t\t\t\t\tthis.lockPath(stage),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\ttry {\n\t\t\tawait handle.writeFile(JSON.stringify(holder, null, 2));\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t}\n\n\tprotected async readLock(stage: string): Promise<LockHolder | null> {\n\t\ttry {\n\t\t\treturn JSON.parse(\n\t\t\t\tawait readFile(this.lockPath(stage), 'utf-8'),\n\t\t\t) as LockHolder;\n\t\t} catch {\n\t\t\t// Missing, or created by a process that died before writing to it.\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprotected async removeLock(\n\t\tstage: string,\n\t\tholder: LockHolder | null,\n\t): Promise<void> {\n\t\tif (holder) {\n\t\t\tconst current = await this.readLock(stage);\n\t\t\tif (current?.id !== holder.id) return;\n\t\t}\n\t\tawait rm(this.lockPath(stage), { force: true });\n\t}\n\n\tprivate async ensureDir(): Promise<void> {\n\t\tawait mkdir(this.dir, { recursive: true, mode: 0o700 });\n\t}\n\n\t/**\n\t * Serialises the check-then-rename of a conditional write across\n\t * processes. The stage lock is for whole runs; this is for the instant of\n\t * a single write, so even writers that skip the lock never interleave.\n\t */\n\tprivate async withMutex<T>(stage: string, fn: () => Promise<T>): Promise<T> {\n\t\tconst path = this.mutexPath(stage);\n\t\tconst deadline = Date.now() + MUTEX_TIMEOUT_MS;\n\n\t\tfor (;;) {\n\t\t\ttry {\n\t\t\t\tconst handle = await open(path, 'wx', FILE_MODE);\n\t\t\t\tawait handle.close();\n\t\t\t\tbreak;\n\t\t\t} catch (error) {\n\t\t\t\tif (!isCode(error, 'EEXIST')) throw error;\n\t\t\t\tif (await this.isStale(path)) {\n\t\t\t\t\tawait unlink(path).catch(() => {});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (Date.now() > deadline) throw new StateStoreBusy(stage, path);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 10));\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tawait rm(path, { force: true });\n\t\t}\n\t}\n\n\tprivate async isStale(path: string): Promise<boolean> {\n\t\ttry {\n\t\t\treturn Date.now() - (await stat(path)).mtimeMs > MUTEX_STALE_MS;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -976,11 +976,15 @@ ${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry p
|
|
|
976
976
|
// a provider.
|
|
977
977
|
${context.storageDrivers.setup}
|
|
978
978
|
` : ""}
|
|
979
|
-
|
|
979
|
+
${context.surface ? `// Who this server is to Postgres: application_name on every connection.
|
|
980
|
+
process.env.GKM_APP_NAME ??= ${JSON.stringify(context.surface.id)};
|
|
981
|
+
|
|
982
|
+
` : ""}export interface ServerApp {
|
|
980
983
|
app: HonoType;
|
|
981
984
|
start: (options?: {
|
|
982
985
|
port?: number;
|
|
983
|
-
|
|
986
|
+
/** Returns the server, so a shutdown can stop it taking requests. */
|
|
987
|
+
serve: (app: HonoType, port: number) => unknown;
|
|
984
988
|
}) => Promise<void>;
|
|
985
989
|
}
|
|
986
990
|
|
|
@@ -1148,20 +1152,35 @@ export const handler = adapter.handler;
|
|
|
1148
1152
|
import { setupQueues } from './queues.js';
|
|
1149
1153
|
import { setupCrons } from './crons.js';` : "";
|
|
1150
1154
|
const gracefulShutdownCode = enableGracefulShutdown ? `
|
|
1151
|
-
// Graceful shutdown
|
|
1155
|
+
// Graceful shutdown: stop taking requests, let in-flight ones finish, then
|
|
1156
|
+
// close what constructs opened (database pools) — so a rolling deploy does
|
|
1157
|
+
// not leave the old task holding connections. Bounded by
|
|
1158
|
+
// GKM_SHUTDOWN_TIMEOUT_MS, 8s by default: under Docker's 10s stop timeout,
|
|
1159
|
+
// so the process exits on its own terms rather than being killed mid-drain.
|
|
1152
1160
|
let isShuttingDown = false;
|
|
1153
1161
|
|
|
1154
1162
|
const shutdown = async () => {
|
|
1155
1163
|
if (isShuttingDown) return;
|
|
1156
1164
|
isShuttingDown = true;
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
setTimeout(() =>
|
|
1165
|
+
const deadline = Number(process.env.GKM_SHUTDOWN_TIMEOUT_MS) || 8000;
|
|
1166
|
+
logger.info({ deadline }, 'Graceful shutdown initiated');
|
|
1167
|
+
setTimeout(() => {
|
|
1168
|
+
logger.warn({ deadline }, 'Shutdown deadline reached, exiting');
|
|
1169
|
+
process.exit(1);
|
|
1170
|
+
}, deadline).unref();
|
|
1171
|
+
await new Promise<void>((resolve) => {
|
|
1172
|
+
const close = (server as { close?: (done: () => void) => void } | undefined)?.close;
|
|
1173
|
+
if (typeof close === 'function') close.call(server, () => resolve());
|
|
1174
|
+
else resolve();
|
|
1175
|
+
});
|
|
1176
|
+
await runShutdownHooks((error) => logger.error({ error }, 'Shutdown hook failed'));
|
|
1177
|
+
process.exit(0);
|
|
1160
1178
|
};
|
|
1161
1179
|
|
|
1162
1180
|
process.on('SIGTERM', shutdown);
|
|
1163
1181
|
process.on('SIGINT', shutdown);
|
|
1164
1182
|
` : "";
|
|
1183
|
+
const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
|
|
1165
1184
|
const content = `/**
|
|
1166
1185
|
* Generated production server application
|
|
1167
1186
|
*
|
|
@@ -1173,7 +1192,7 @@ import { setupCrons } from './crons.js';` : "";
|
|
|
1173
1192
|
*/
|
|
1174
1193
|
import { Hono } from 'hono';
|
|
1175
1194
|
import type { Hono as HonoType } from 'hono';
|
|
1176
|
-
import {
|
|
1195
|
+
${enableGracefulShutdown ? "import { runShutdownHooks } from '@geekmidas/constructs';\n" : ""}import { setupEndpoints } from '${endpointsImportPath}';
|
|
1177
1196
|
${subscriberImport}
|
|
1178
1197
|
${runtime.imports}
|
|
1179
1198
|
${runtime.bindings}
|
|
@@ -1184,7 +1203,10 @@ ${context.storageDrivers?.imports ?? ""}
|
|
|
1184
1203
|
${context.storageDrivers?.setup ? `// The entry point registers the drivers its target needs.
|
|
1185
1204
|
${context.storageDrivers.setup}
|
|
1186
1205
|
` : ""}
|
|
1187
|
-
|
|
1206
|
+
${context.surface ? `// Who this server is to Postgres: application_name on every connection.
|
|
1207
|
+
process.env.GKM_APP_NAME ??= ${JSON.stringify(context.surface.id)};
|
|
1208
|
+
|
|
1209
|
+
` : ""}export interface ServerApp {
|
|
1188
1210
|
app: HonoType;
|
|
1189
1211
|
start: (options?: {
|
|
1190
1212
|
port?: number;
|
|
@@ -1217,11 +1239,12 @@ ${afterSetupCall}
|
|
|
1217
1239
|
}
|
|
1218
1240
|
|
|
1219
1241
|
const port = options.port ?? Number(process.env.PORT) ?? 3000;
|
|
1242
|
+
let server: unknown;
|
|
1220
1243
|
${gracefulShutdownCode}${subscriberSetup}
|
|
1221
1244
|
logger.info({ port }, 'Starting production server');
|
|
1222
1245
|
|
|
1223
1246
|
// Start HTTP server using provided serve function
|
|
1224
|
-
await options.serve(honoApp, port);
|
|
1247
|
+
server = await options.serve(honoApp, port);
|
|
1225
1248
|
|
|
1226
1249
|
logger.info({ port }, 'Production server started');
|
|
1227
1250
|
${includeSubscribers ? "\n await subscribeForPush(port);" : ""}
|
|
@@ -1255,7 +1278,7 @@ const { start } = await createApp();
|
|
|
1255
1278
|
|
|
1256
1279
|
await start({
|
|
1257
1280
|
port,
|
|
1258
|
-
serve: (app, port) =>
|
|
1281
|
+
serve: (app, port) => serve({ fetch: app.fetch, port }),
|
|
1259
1282
|
});
|
|
1260
1283
|
`);
|
|
1261
1284
|
}
|
|
@@ -1768,4 +1791,4 @@ function unknownType(name) {
|
|
|
1768
1791
|
//#endregion
|
|
1769
1792
|
export { EndpointGenerator as n, runtimeFor as r, OpenApiTsGenerator as t };
|
|
1770
1793
|
|
|
1771
|
-
//# sourceMappingURL=OpenApiTsGenerator-
|
|
1794
|
+
//# sourceMappingURL=OpenApiTsGenerator-DKmAorGX.mjs.map
|