@open-mercato/cli 0.6.6-develop.6339.1.193c6c7c71 → 0.6.6-develop.6344.1.c4b17c07c4
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.
|
@@ -65,7 +65,7 @@ function computeRailwayVariables(input) {
|
|
|
65
65
|
return variables;
|
|
66
66
|
}
|
|
67
67
|
function formatVariablePlan(variables, railwayToken) {
|
|
68
|
-
return Object.keys(variables).sort().map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? "", railwayToken)}`);
|
|
68
|
+
return Object.keys(variables).sort((a, b) => a < b ? -1 : a > b ? 1 : 0).map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? "", railwayToken)}`);
|
|
69
69
|
}
|
|
70
70
|
function writeGeneratedSecrets(envFile, secrets) {
|
|
71
71
|
const ignoreCheck = spawnSync("git", ["check-ignore", "--quiet", envFile], {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/deploy/railway/env.ts"],
|
|
4
|
-
"sourcesContent": ["import { randomBytes } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { assertSafeVariables, formatVariableValue } from './redaction'\n\nexport type RailwayServiceRole = 'app' | 'worker'\n\nexport function resolveEnvFile(cwd: string, requested?: string): string {\n const candidates = requested ? [requested] : ['.env.production', '.env']\n for (const candidate of candidates) {\n const path = resolve(cwd, candidate)\n if (existsSync(path)) return path\n }\n throw new Error(`Environment file not found. Checked: ${candidates.join(', ')}.`)\n}\n\nexport function parseEnvFile(contents: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const rawLine of contents.split(/\\r?\\n/)) {\n const line = rawLine.trim()\n if (!line || line.startsWith('#')) continue\n const normalized = line.startsWith('export ') ? line.slice(7).trim() : line\n const separator = normalized.indexOf('=')\n if (separator <= 0) continue\n const key = normalized.slice(0, separator).trim()\n let value = normalized.slice(separator + 1).trim()\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1)\n }\n result[key] = value.replace(/\\\\n/g, '\\n')\n }\n return result\n}\n\nexport function generateProtectedSecrets(existing: Record<string, string>): Record<string, string> {\n return {\n AUTH_SECRET: existing.AUTH_SECRET || randomBytes(64).toString('hex'),\n JWT_SECRET: existing.JWT_SECRET || randomBytes(64).toString('hex'),\n TENANT_DATA_ENCRYPTION_FALLBACK_KEY:\n existing.TENANT_DATA_ENCRYPTION_FALLBACK_KEY || randomBytes(32).toString('base64url'),\n }\n}\n\nexport function computeRailwayVariables(input: {\n env: Record<string, string>\n role: RailwayServiceRole\n workerEnabled: boolean\n appUrl?: string\n protectedSecrets: Record<string, string>\n railwayToken?: string\n allowedSecretKeys?: string[]\n}): Record<string, string> {\n const variables: Record<string, string> = {\n ...input.env,\n ...input.protectedSecrets,\n DATABASE_URL: '${{Postgres.DATABASE_URL}}',\n REDIS_URL: '${{Redis.REDIS_URL}}',\n CACHE_STRATEGY: 'redis',\n NODE_ENV: 'production',\n NEXT_TELEMETRY_DISABLED: '1',\n PORT: '3000',\n OM_AI_PROVIDER: input.env.OM_AI_PROVIDER || 'openai',\n OM_AI_MODEL: input.env.OM_AI_MODEL || 'gpt-5-mini',\n QUEUE_STRATEGY: 'async',\n NEXT_PUBLIC_QUEUE_STRATEGY: 'async',\n AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n OM_AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n }\n\n if (input.appUrl) {\n variables.APP_URL = input.appUrl\n variables.NEXT_PUBLIC_APP_URL = input.appUrl\n }\n\n delete variables.RAILWAY_API_TOKEN\n delete variables.RAILWAY_TOKEN\n assertSafeVariables(variables, {\n railwayToken: input.railwayToken,\n allowedKeys: input.allowedSecretKeys,\n })\n return variables\n}\n\nexport function formatVariablePlan(\n variables: Record<string, string>,\n railwayToken?: string,\n): string[] {\n return Object.keys(variables)\n .sort()\n .map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? '', railwayToken)}`)\n}\n\nexport function writeGeneratedSecrets(envFile: string, secrets: Record<string, string>): void {\n const ignoreCheck = spawnSync('git', ['check-ignore', '--quiet', envFile], {\n cwd: dirname(envFile),\n stdio: 'ignore',\n })\n if (ignoreCheck.status !== 0) {\n throw new Error(`Refusing --write-env because ${envFile} is not ignored by Git.`)\n }\n const existing = readFileSync(envFile, 'utf8')\n const missing = Object.entries(secrets).filter(([key]) => !new RegExp(`^${key}=`, 'm').test(existing))\n if (missing.length === 0) return\n const suffix = missing.map(([key, value]) => `${key}=${value}`).join('\\n')\n writeFileSync(envFile, `${existing.trimEnd()}\\n\\n# DO NOT COMMIT: generated for Railway deployment\\n${suffix}\\n`, {\n mode: 0o600,\n })\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB,2BAA2B;AAIlD,SAAS,eAAe,KAAa,WAA4B;AACtE,QAAM,aAAa,YAAY,CAAC,SAAS,IAAI,CAAC,mBAAmB,MAAM;AACvE,aAAW,aAAa,YAAY;AAClC,UAAM,OAAO,QAAQ,KAAK,SAAS;AACnC,QAAI,WAAW,IAAI,EAAG,QAAO;AAAA,EAC/B;AACA,QAAM,IAAI,MAAM,wCAAwC,WAAW,KAAK,IAAI,CAAC,GAAG;AAClF;AAEO,SAAS,aAAa,UAA0C;AACrE,QAAM,SAAiC,CAAC;AACxC,aAAW,WAAW,SAAS,MAAM,OAAO,GAAG;AAC7C,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AACnC,UAAM,aAAa,KAAK,WAAW,SAAS,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,IAAI;AACvE,UAAM,YAAY,WAAW,QAAQ,GAAG;AACxC,QAAI,aAAa,EAAG;AACpB,UAAM,MAAM,WAAW,MAAM,GAAG,SAAS,EAAE,KAAK;AAChD,QAAI,QAAQ,WAAW,MAAM,YAAY,CAAC,EAAE,KAAK;AACjD,QACG,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC5C;AACA,cAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3B;AACA,WAAO,GAAG,IAAI,MAAM,QAAQ,QAAQ,IAAI;AAAA,EAC1C;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,UAA0D;AACjG,SAAO;AAAA,IACL,aAAa,SAAS,eAAe,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IACnE,YAAY,SAAS,cAAc,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IACjE,qCACE,SAAS,uCAAuC,YAAY,EAAE,EAAE,SAAS,WAAW;AAAA,EACxF;AACF;AAEO,SAAS,wBAAwB,OAQb;AACzB,QAAM,YAAoC;AAAA,IACxC,GAAG,MAAM;AAAA,IACT,GAAG,MAAM;AAAA,IACT,cAAc;AAAA,IACd,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,yBAAyB;AAAA,IACzB,MAAM;AAAA,IACN,gBAAgB,MAAM,IAAI,kBAAkB;AAAA,IAC5C,aAAa,MAAM,IAAI,eAAe;AAAA,IACtC,gBAAgB;AAAA,IAChB,4BAA4B;AAAA,IAC5B,oBAAoB,MAAM,SAAS,SAAS,CAAC,MAAM,gBAAgB,SAAS;AAAA,IAC5E,uBAAuB,MAAM,SAAS,SAAS,CAAC,MAAM,gBAAgB,SAAS;AAAA,EACjF;AAEA,MAAI,MAAM,QAAQ;AAChB,cAAU,UAAU,MAAM;AAC1B,cAAU,sBAAsB,MAAM;AAAA,EACxC;AAEA,SAAO,UAAU;AACjB,SAAO,UAAU;AACjB,sBAAoB,WAAW;AAAA,IAC7B,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM;AAAA,EACrB,CAAC;AACD,SAAO;AACT;AAEO,SAAS,mBACd,WACA,cACU;AACV,SAAO,OAAO,KAAK,SAAS,EACzB,KAAK,
|
|
4
|
+
"sourcesContent": ["import { randomBytes } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { assertSafeVariables, formatVariableValue } from './redaction'\n\nexport type RailwayServiceRole = 'app' | 'worker'\n\nexport function resolveEnvFile(cwd: string, requested?: string): string {\n const candidates = requested ? [requested] : ['.env.production', '.env']\n for (const candidate of candidates) {\n const path = resolve(cwd, candidate)\n if (existsSync(path)) return path\n }\n throw new Error(`Environment file not found. Checked: ${candidates.join(', ')}.`)\n}\n\nexport function parseEnvFile(contents: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const rawLine of contents.split(/\\r?\\n/)) {\n const line = rawLine.trim()\n if (!line || line.startsWith('#')) continue\n const normalized = line.startsWith('export ') ? line.slice(7).trim() : line\n const separator = normalized.indexOf('=')\n if (separator <= 0) continue\n const key = normalized.slice(0, separator).trim()\n let value = normalized.slice(separator + 1).trim()\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1)\n }\n result[key] = value.replace(/\\\\n/g, '\\n')\n }\n return result\n}\n\nexport function generateProtectedSecrets(existing: Record<string, string>): Record<string, string> {\n return {\n AUTH_SECRET: existing.AUTH_SECRET || randomBytes(64).toString('hex'),\n JWT_SECRET: existing.JWT_SECRET || randomBytes(64).toString('hex'),\n TENANT_DATA_ENCRYPTION_FALLBACK_KEY:\n existing.TENANT_DATA_ENCRYPTION_FALLBACK_KEY || randomBytes(32).toString('base64url'),\n }\n}\n\nexport function computeRailwayVariables(input: {\n env: Record<string, string>\n role: RailwayServiceRole\n workerEnabled: boolean\n appUrl?: string\n protectedSecrets: Record<string, string>\n railwayToken?: string\n allowedSecretKeys?: string[]\n}): Record<string, string> {\n const variables: Record<string, string> = {\n ...input.env,\n ...input.protectedSecrets,\n DATABASE_URL: '${{Postgres.DATABASE_URL}}',\n REDIS_URL: '${{Redis.REDIS_URL}}',\n CACHE_STRATEGY: 'redis',\n NODE_ENV: 'production',\n NEXT_TELEMETRY_DISABLED: '1',\n PORT: '3000',\n OM_AI_PROVIDER: input.env.OM_AI_PROVIDER || 'openai',\n OM_AI_MODEL: input.env.OM_AI_MODEL || 'gpt-5-mini',\n QUEUE_STRATEGY: 'async',\n NEXT_PUBLIC_QUEUE_STRATEGY: 'async',\n AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n OM_AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n }\n\n if (input.appUrl) {\n variables.APP_URL = input.appUrl\n variables.NEXT_PUBLIC_APP_URL = input.appUrl\n }\n\n delete variables.RAILWAY_API_TOKEN\n delete variables.RAILWAY_TOKEN\n assertSafeVariables(variables, {\n railwayToken: input.railwayToken,\n allowedKeys: input.allowedSecretKeys,\n })\n return variables\n}\n\nexport function formatVariablePlan(\n variables: Record<string, string>,\n railwayToken?: string,\n): string[] {\n return Object.keys(variables)\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n .map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? '', railwayToken)}`)\n}\n\nexport function writeGeneratedSecrets(envFile: string, secrets: Record<string, string>): void {\n const ignoreCheck = spawnSync('git', ['check-ignore', '--quiet', envFile], {\n cwd: dirname(envFile),\n stdio: 'ignore',\n })\n if (ignoreCheck.status !== 0) {\n throw new Error(`Refusing --write-env because ${envFile} is not ignored by Git.`)\n }\n const existing = readFileSync(envFile, 'utf8')\n const missing = Object.entries(secrets).filter(([key]) => !new RegExp(`^${key}=`, 'm').test(existing))\n if (missing.length === 0) return\n const suffix = missing.map(([key, value]) => `${key}=${value}`).join('\\n')\n writeFileSync(envFile, `${existing.trimEnd()}\\n\\n# DO NOT COMMIT: generated for Railway deployment\\n${suffix}\\n`, {\n mode: 0o600,\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.6.6-develop.
|
|
3
|
+
"version": "0.6.6-develop.6344.1.c4b17c07c4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"@mikro-orm/decorators": "^7.1.4",
|
|
61
61
|
"@mikro-orm/migrations": "^7.1.4",
|
|
62
62
|
"@mikro-orm/postgresql": "^7.1.4",
|
|
63
|
-
"@open-mercato/queue": "0.6.6-develop.
|
|
64
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
63
|
+
"@open-mercato/queue": "0.6.6-develop.6344.1.c4b17c07c4",
|
|
64
|
+
"@open-mercato/shared": "0.6.6-develop.6344.1.c4b17c07c4",
|
|
65
65
|
"cross-spawn": "^7.0.6",
|
|
66
66
|
"pg": "8.22.0",
|
|
67
67
|
"semver": "^7.8.5",
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"typescript": "^6.0.3"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
74
|
+
"@open-mercato/shared": "0.6.6-develop.6344.1.c4b17c07c4"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
77
|
+
"@open-mercato/shared": "0.6.6-develop.6344.1.c4b17c07c4",
|
|
78
78
|
"@types/jest": "^30.0.0",
|
|
79
79
|
"jest": "^30.4.2",
|
|
80
80
|
"ts-jest": "^29.4.11"
|
|
@@ -90,7 +90,7 @@ export function formatVariablePlan(
|
|
|
90
90
|
railwayToken?: string,
|
|
91
91
|
): string[] {
|
|
92
92
|
return Object.keys(variables)
|
|
93
|
-
.sort()
|
|
93
|
+
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
|
|
94
94
|
.map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? '', railwayToken)}`)
|
|
95
95
|
}
|
|
96
96
|
|