@zuplo/cli 6.62.17 → 6.63.1
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/__tests__/integration/deploy.integration.test.js +59 -2
- package/dist/__tests__/integration/deploy.integration.test.js.map +1 -1
- package/dist/__tests__/integration/jest-mocks-setup.js +3 -6
- package/dist/__tests__/integration/jest-mocks-setup.js.map +1 -1
- package/dist/__tests__/integration/link.integration.test.js +11 -51
- package/dist/__tests__/integration/link.integration.test.js.map +1 -1
- package/dist/cli.js +1 -5
- package/dist/cli.js.map +1 -1
- package/dist/common/middleware/user-configuration.js +3 -3
- package/dist/common/middleware/user-configuration.js.map +1 -1
- package/dist/common/populate.js +3 -3
- package/dist/common/populate.js.map +1 -1
- package/dist/deploy/archive.d.ts.map +1 -1
- package/dist/deploy/archive.js +11 -6
- package/dist/deploy/archive.js.map +1 -1
- package/dist/deploy/archive.test.d.ts +2 -0
- package/dist/deploy/archive.test.d.ts.map +1 -0
- package/dist/deploy/archive.test.js +245 -0
- package/dist/deploy/archive.test.js.map +1 -0
- package/dist/editor/handler.d.ts.map +1 -1
- package/dist/editor/handler.js +2 -1
- package/dist/editor/handler.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-configuration.js","sourceRoot":"","sources":["../../../src/common/middleware/user-configuration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"user-configuration.js","sourceRoot":"","sources":["../../../src/common/middleware/user-configuration.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { ParseError, parse } from \"jsonc-parser\";\nimport {\n ZUPLO_FALLBACK_JSON_FILE,\n ZUPLO_PREFERRED_JSON_FILE,\n} from \"../constants.js\";\nimport { logger } from \"../logger.js\";\nimport {\n printCriticalFailureToConsoleAndExit,\n printWarningToConsole,\n} from \"../output.js\";\nimport settings from \"../settings.js\";\n\n/**\n * This is the middleware to set the context for the CLI calls.\n *\n * It can be used to set sensible configurations such as account and project that are gotten from the API, zuplo.jsonc, --parameters\n *\n * The order of setting a configuration is\n * 1. API key\n * 2. zuplo.jsonc\n * 3. --parameters from the CLI invocation\n *\n * Note that --parameters objects can also come from .env file because of https://yargs.js.org/docs/#api-reference-envprefix\n *\n * @param argv - The yargs object\n */\nexport async function configure(argv: { [key: string]: unknown }) {\n // Clone the original value (for merging at the end)\n // The original is the most specific since it can only contain things from --parameters\n // It will always be applied last to override anything from zuplo.jsonc or the API key\n const cliParametersConfiguration = { ...argv };\n\n // Make a call to the API key\n const whoAmIResponse = await fetch(\n `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`,\n {\n method: \"GET\",\n headers: {\n // biome-ignore lint/style/useNamingConvention: External API property\n Authorization: `Bearer ${argv.authToken}`,\n },\n }\n );\n\n if (whoAmIResponse.ok) {\n // Note that the algorithms below are based on \"addition\"\n // You cannot unset/remove a value from the configuration by setting it to null/undefined\n // Do be mindful of parameters that might be the same value since things might be overridden\n\n // Merge any non-null values from the API key\n const apiKeyMetadata = await whoAmIResponse.json();\n\n // The API key metadata response contains the account.\n Object.assign(argv, omitNull(apiKeyMetadata));\n\n // Merge any non-null values from zuplo.jsonc\n // For now, only merge project since zuplo.jsonc could have many keys that might conflict\n const { project: zuploJsoncProject } = await processZuploConfigurationFile(\n argv.dir as string | undefined\n );\n if (zuploJsoncProject) {\n printWarningToConsole(\n \"The project name in zuplo.jsonc is deprecated. Please remove the project key from zuplo.jsonc and use the --project flag or ZUPLO_PROJECT environment variable instead.\"\n );\n argv.project = zuploJsoncProject;\n }\n\n // Merge any non-null values from --parameters\n Object.assign(argv, cliParametersConfiguration);\n } else {\n logger.trace(\n { status: whoAmIResponse.status, statusText: whoAmIResponse.statusText },\n \"Failed to determine who-am-i\"\n );\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to validate the API key. Check your API key.\"\n );\n }\n}\n\nasync function processZuploConfigurationFile(sourceDirectory: string = \".\") {\n const normalizedDir = resolve(sourceDirectory);\n const preferredPath = join(normalizedDir, ZUPLO_PREFERRED_JSON_FILE);\n const fallbackPath = join(normalizedDir, ZUPLO_FALLBACK_JSON_FILE);\n let fileContents = \"{}\";\n if (existsSync(preferredPath)) {\n fileContents = await readFile(preferredPath, \"utf-8\");\n } else if (existsSync(fallbackPath)) {\n fileContents = await readFile(fallbackPath, \"utf-8\");\n } else {\n logger.trace(\"No zuplo.jsonc file found\");\n return {};\n }\n\n // If we get here, we have a zuplo.jsonc (or, zuplo.json) file\n // That means we should report any issues with it.\n const errors: ParseError[] = [];\n const data = parse(fileContents, errors, { allowTrailingComma: true });\n if (errors.length > 0) {\n logger.trace(errors[0], \"Failed to parse zuplo.jsonc\");\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to parse the values from zuplo.jsonc. Check your zuplo.jsonc file.\"\n );\n }\n return data;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: Migrated from ESLint\nconst omitNull = (obj: any) => {\n Object.keys(obj)\n .filter((k) => obj[k] === null)\n .forEach((k) => delete obj[k]);\n return obj;\n};\n"]}
|
package/dist/common/populate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import { join,
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
3
|
import { ZUPLO_SYSTEM_ENV_VAR } from "./constants.js";
|
|
4
4
|
import { logger } from "./logger.js";
|
|
5
5
|
import { printCriticalFailureToConsoleAndExit } from "./output.js";
|
|
@@ -15,7 +15,7 @@ function wrapEnvValue(value) {
|
|
|
15
15
|
return `"${escapedValue}"`;
|
|
16
16
|
}
|
|
17
17
|
export async function pullSystemConfig(argv) {
|
|
18
|
-
const normalizedDir =
|
|
18
|
+
const normalizedDir = resolve(argv.dir);
|
|
19
19
|
const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);
|
|
20
20
|
const environmentResponseFromDeveloperAPI = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/configurations`, {
|
|
21
21
|
headers: {
|
|
@@ -48,7 +48,7 @@ ZUPLO_SYSTEM_CONFIGURATIONS=${payload["systemConfigurations"]}
|
|
|
48
48
|
await writeFile(zuploPreferredConfigFile, content);
|
|
49
49
|
}
|
|
50
50
|
export async function pullLocalConfig(argv) {
|
|
51
|
-
const normalizedDir =
|
|
51
|
+
const normalizedDir = resolve(argv.dir);
|
|
52
52
|
const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);
|
|
53
53
|
const environmentResponseFromDeveloperAPI = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/local-configurations`, {
|
|
54
54
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"populate.js","sourceRoot":"","sources":["../../src/common/populate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,QAAQ,MAAM,eAAe,CAAC;AAGrC,MAAM,WAAW,GAAG;IAClB,aAAa;IACb,aAAa;IACb,iBAAiB;IACjB,sBAAsB;CACvB,CAAC;AAUF,SAAS,YAAY,CAAC,KAAa;IAEjC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAEhD,OAAO,IAAI,YAAY,GAAG,CAAC;AAC7B,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA0D;IAE1D,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,wBAAwB,GAAG,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC;IAE3E,MAAM,mCAAmC,GAAG,MAAM,KAAK,CACrD,GAAG,QAAQ,CAAC,4BAA4B,oBAAoB,IAAI,CAAC,WAAW,iBAAiB,EAC7F;QACE,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,IAAI,CAAC,SAAS,EAAE;SAC1C;KACF,CACF,CAAC;IAEF,IAAI,CAAC,mCAAmC,CAAC,EAAE,EAAE,CAAC;QAC5C,IACE,mCAAmC,CAAC,MAAM,KAAK,GAAG;YAClD,mCAAmC,CAAC,MAAM,KAAK,GAAG,EAClD,CAAC;YACD,MAAM,oCAAoC,CACxC,8HAA8H,CAC/H,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CACV;gBACE,MAAM,EAAE,mCAAmC,CAAC,MAAM;gBAClD,UAAU,EAAE,mCAAmC,CAAC,UAAU;aAC3D,EACD,4BAA4B,IAAI,CAAC,WAAW,EAAE,CAC/C,CAAC;YACF,MAAM,oCAAoC,CACxC,0EAA0E,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,mCAAmC,CAAC,IAAI,EAAE,CAAC;IAEjE,MAAM,OAAO,GAAG;;;;qBAIG,OAAO,CAAC,WAAW;qBACnB,OAAO,CAAC,WAAW;yBACf,OAAO,CAAC,eAAe;8BAClB,OAAO,CAAC,sBAAsB,CAAC;CAC5D,CAAC;IAEA,MAAM,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAA0D;IAE1D,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,wBAAwB,GAAG,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC;IAE3E,MAAM,mCAAmC,GAAG,MAAM,KAAK,CACrD,GAAG,QAAQ,CAAC,4BAA4B,oBAAoB,IAAI,CAAC,WAAW,uBAAuB,EACnG;QACE,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,IAAI,CAAC,SAAS,EAAE;SAC1C;KACF,CACF,CAAC;IAEF,IAAI,CAAC,mCAAmC,CAAC,EAAE,EAAE,CAAC;QAC5C,IACE,mCAAmC,CAAC,MAAM,KAAK,GAAG;YAClD,mCAAmC,CAAC,MAAM,KAAK,GAAG,EAClD,CAAC;YACD,MAAM,oCAAoC,CACxC,8HAA8H,CAC/H,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CACV;gBACE,MAAM,EAAE,mCAAmC,CAAC,MAAM;gBAClD,UAAU,EAAE,mCAAmC,CAAC,UAAU;aAC3D,EACD,4BAA4B,IAAI,CAAC,WAAW,EAAE,CAC/C,CAAC;YACF,MAAM,oCAAoC,CACxC,0EAA0E,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,mCAAmC,CAAC,IAAI,EAAE,CAAC;IAIjE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;SACrC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,OAAO,GAAG,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEL,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;SAC5C,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAEd,OAAO,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,OAAO,GAAG,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEL,IAAI,OAAO,GAAG;;;;qBAIK,OAAO,CAAC,WAAW;qBACnB,OAAO,CAAC,WAAW;yBACf,OAAO,CAAC,eAAe;8BAClB,OAAO,CAAC,sBAAsB,CAAC,EAAE,CAAC;IAG9D,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI;;;EAGb,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChC,CAAC;IAGD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI;;;;;EAKb,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACzB,CAAC;IAGD,OAAO,IAAI,IAAI,CAAC;IAEhB,MAAM,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC","sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { ZUPLO_SYSTEM_ENV_VAR } from \"./constants.js\";\nimport { logger } from \"./logger.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"./output.js\";\nimport settings from \"./settings.js\";\nimport { Arguments } from \"../link/handler.js\";\n\nconst SYSTEM_KEYS = [\n \"accountName\",\n \"projectName\",\n \"environmentType\",\n \"systemConfigurations\",\n];\n\n/**\n * Wraps environment variable values in single quotes for dotenv compatibility.\n * Escapes any single quotes within the value by replacing them with \\'.\n * This ensures proper parsing while preserving special characters.\n *\n * @param value The environment variable value to wrap\n * @returns The value wrapped in single quotes with escaped single quotes\n */\nfunction wrapEnvValue(value: string): string {\n // Escape single quotes by replacing them with \\'\n const escapedValue = value.replace(/\"/g, '\\\\\"');\n // Always use single quotes\n return `\"${escapedValue}\"`;\n}\n\n/**\n * Pulls the system configuration from the API and writes it to the .env.zuplo file.\n * All the system environment variables are encoded in base58. Use this wherever\n * we need to *make sure* that the system environment variables are preserved correctly,\n * e.g in deployments.\n * @param argv\n */\nexport async function pullSystemConfig(\n argv: Pick<Arguments, \"dir\" | \"environment\" | \"authToken\">\n) {\n const normalizedDir = join(relative(process.cwd(), argv.dir));\n const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);\n\n const environmentResponseFromDeveloperAPI = await fetch(\n `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/configurations`,\n {\n headers: {\n authorization: `Bearer ${argv.authToken}`,\n },\n }\n );\n\n if (!environmentResponseFromDeveloperAPI.ok) {\n if (\n environmentResponseFromDeveloperAPI.status === 404 ||\n environmentResponseFromDeveloperAPI.status === 401\n ) {\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. The environment you specified doesn't exist or you don't have access to it.\"\n );\n } else {\n logger.error(\n {\n status: environmentResponseFromDeveloperAPI.status,\n statusText: environmentResponseFromDeveloperAPI.statusText,\n },\n `Failed to link data from ${argv.environment}`\n );\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. Please try again later.\"\n );\n }\n }\n\n const payload = await environmentResponseFromDeveloperAPI.json();\n\n const content = `\n# This file is auto-generated from zuplo link. Please do not edit it manually.\n# It will be auto-generated afresh the next time you run zuplo link.\n# If you wish to add your own environment variables, create a separate .env file.\nZUPLO_ACCOUNT_NAME=${payload.accountName}\nZUPLO_PROJECT_NAME=${payload.projectName}\nZUPLO_ENVIRONMENT_TYPE=${payload.environmentType}\nZUPLO_SYSTEM_CONFIGURATIONS=${payload[\"systemConfigurations\"]}\n`;\n\n await writeFile(zuploPreferredConfigFile, content);\n}\n\n/**\n * Pulls the local configuration from dev-api and writes it to the .env.zuplo file.\n * This method differs from pullSystemConfig in that it writes the user defined\n * environment variables, as well as the public variables explicitly to the\n * file instead of getting all variable in the base58 encoded ZUPLO_SYSTEM_CONFIGURATIONS\n * variable.\n * @param argv\n */\nexport async function pullLocalConfig(\n argv: Pick<Arguments, \"dir\" | \"environment\" | \"authToken\">\n) {\n const normalizedDir = join(relative(process.cwd(), argv.dir));\n const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);\n\n const environmentResponseFromDeveloperAPI = await fetch(\n `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/local-configurations`,\n {\n headers: {\n authorization: `Bearer ${argv.authToken}`,\n },\n }\n );\n\n if (!environmentResponseFromDeveloperAPI.ok) {\n if (\n environmentResponseFromDeveloperAPI.status === 404 ||\n environmentResponseFromDeveloperAPI.status === 401\n ) {\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. The environment you specified doesn't exist or you don't have access to it.\"\n );\n } else {\n logger.error(\n {\n status: environmentResponseFromDeveloperAPI.status,\n statusText: environmentResponseFromDeveloperAPI.statusText,\n },\n `Failed to link data from ${argv.environment}`\n );\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. Please try again later.\"\n );\n }\n }\n\n const payload = await environmentResponseFromDeveloperAPI.json();\n\n // We wrap the env vars in appropriate quotes to preserve special characters\n // and handle single quotes properly for dotenv parsing.\n const userEnvVars = Object.keys(payload)\n .filter((key) => {\n return !key.startsWith(\"ZUPLO_PUBLIC_\") && !SYSTEM_KEYS.includes(key);\n })\n .map((key) => {\n return `${key}=${wrapEnvValue(payload[key])}`;\n });\n\n const zuploPublicEnvVars = Object.keys(payload)\n .filter((key) => {\n // These start with ZUPLO_PUBLIC_ and are not system variables\n return key.startsWith(\"ZUPLO_PUBLIC_\");\n })\n .map((key) => {\n return `${key}=${wrapEnvValue(payload[key])}`;\n });\n\n let content = `# This file is auto-generated from zuplo link. Please do not edit it manually.\n# It will be auto-generated afresh the next time you run zuplo link.\n# If you wish to add your own environment variables, create a separate .env file.\n\nZUPLO_ACCOUNT_NAME=${payload.accountName}\nZUPLO_PROJECT_NAME=${payload.projectName}\nZUPLO_ENVIRONMENT_TYPE=${payload.environmentType}\nZUPLO_SYSTEM_CONFIGURATIONS=${payload[\"systemConfigurations\"]}`;\n\n // Only add public environment variables section if there are any\n if (zuploPublicEnvVars.length > 0) {\n content += `\n\n# Public Zuplo environment variables\n${zuploPublicEnvVars.join(\"\\n\")}`;\n }\n\n // Only add user environment variables section if there are any\n if (userEnvVars.length > 0) {\n content += `\n\n# Environment variables defined in the Zuplo UI for the environment\n# Note that \" characters are escaped with a backslash and escaped double quotes\n# will show up as \\\\\" in the value.\n${userEnvVars.join(\"\\n\")}`;\n }\n\n // Add final newline\n content += \"\\n\";\n\n await writeFile(zuploPreferredConfigFile, content);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"populate.js","sourceRoot":"","sources":["../../src/common/populate.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { ZUPLO_SYSTEM_ENV_VAR } from \"./constants.js\";\nimport { logger } from \"./logger.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"./output.js\";\nimport settings from \"./settings.js\";\nimport { Arguments } from \"../link/handler.js\";\n\nconst SYSTEM_KEYS = [\n \"accountName\",\n \"projectName\",\n \"environmentType\",\n \"systemConfigurations\",\n];\n\n/**\n * Wraps environment variable values in single quotes for dotenv compatibility.\n * Escapes any single quotes within the value by replacing them with \\'.\n * This ensures proper parsing while preserving special characters.\n *\n * @param value The environment variable value to wrap\n * @returns The value wrapped in single quotes with escaped single quotes\n */\nfunction wrapEnvValue(value: string): string {\n // Escape single quotes by replacing them with \\'\n const escapedValue = value.replace(/\"/g, '\\\\\"');\n // Always use single quotes\n return `\"${escapedValue}\"`;\n}\n\n/**\n * Pulls the system configuration from the API and writes it to the .env.zuplo file.\n * All the system environment variables are encoded in base58. Use this wherever\n * we need to *make sure* that the system environment variables are preserved correctly,\n * e.g in deployments.\n * @param argv\n */\nexport async function pullSystemConfig(\n argv: Pick<Arguments, \"dir\" | \"environment\" | \"authToken\">\n) {\n const normalizedDir = resolve(argv.dir);\n const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);\n\n const environmentResponseFromDeveloperAPI = await fetch(\n `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/configurations`,\n {\n headers: {\n authorization: `Bearer ${argv.authToken}`,\n },\n }\n );\n\n if (!environmentResponseFromDeveloperAPI.ok) {\n if (\n environmentResponseFromDeveloperAPI.status === 404 ||\n environmentResponseFromDeveloperAPI.status === 401\n ) {\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. The environment you specified doesn't exist or you don't have access to it.\"\n );\n } else {\n logger.error(\n {\n status: environmentResponseFromDeveloperAPI.status,\n statusText: environmentResponseFromDeveloperAPI.statusText,\n },\n `Failed to link data from ${argv.environment}`\n );\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. Please try again later.\"\n );\n }\n }\n\n const payload = await environmentResponseFromDeveloperAPI.json();\n\n const content = `\n# This file is auto-generated from zuplo link. Please do not edit it manually.\n# It will be auto-generated afresh the next time you run zuplo link.\n# If you wish to add your own environment variables, create a separate .env file.\nZUPLO_ACCOUNT_NAME=${payload.accountName}\nZUPLO_PROJECT_NAME=${payload.projectName}\nZUPLO_ENVIRONMENT_TYPE=${payload.environmentType}\nZUPLO_SYSTEM_CONFIGURATIONS=${payload[\"systemConfigurations\"]}\n`;\n\n await writeFile(zuploPreferredConfigFile, content);\n}\n\n/**\n * Pulls the local configuration from dev-api and writes it to the .env.zuplo file.\n * This method differs from pullSystemConfig in that it writes the user defined\n * environment variables, as well as the public variables explicitly to the\n * file instead of getting all variable in the base58 encoded ZUPLO_SYSTEM_CONFIGURATIONS\n * variable.\n * @param argv\n */\nexport async function pullLocalConfig(\n argv: Pick<Arguments, \"dir\" | \"environment\" | \"authToken\">\n) {\n const normalizedDir = resolve(argv.dir);\n const zuploPreferredConfigFile = join(normalizedDir, ZUPLO_SYSTEM_ENV_VAR);\n\n const environmentResponseFromDeveloperAPI = await fetch(\n `${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/environments/${argv.environment}/local-configurations`,\n {\n headers: {\n authorization: `Bearer ${argv.authToken}`,\n },\n }\n );\n\n if (!environmentResponseFromDeveloperAPI.ok) {\n if (\n environmentResponseFromDeveloperAPI.status === 404 ||\n environmentResponseFromDeveloperAPI.status === 401\n ) {\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. The environment you specified doesn't exist or you don't have access to it.\"\n );\n } else {\n logger.error(\n {\n status: environmentResponseFromDeveloperAPI.status,\n statusText: environmentResponseFromDeveloperAPI.statusText,\n },\n `Failed to link data from ${argv.environment}`\n );\n await printCriticalFailureToConsoleAndExit(\n \"Error: Failed to link data from the environment. Please try again later.\"\n );\n }\n }\n\n const payload = await environmentResponseFromDeveloperAPI.json();\n\n // We wrap the env vars in appropriate quotes to preserve special characters\n // and handle single quotes properly for dotenv parsing.\n const userEnvVars = Object.keys(payload)\n .filter((key) => {\n return !key.startsWith(\"ZUPLO_PUBLIC_\") && !SYSTEM_KEYS.includes(key);\n })\n .map((key) => {\n return `${key}=${wrapEnvValue(payload[key])}`;\n });\n\n const zuploPublicEnvVars = Object.keys(payload)\n .filter((key) => {\n // These start with ZUPLO_PUBLIC_ and are not system variables\n return key.startsWith(\"ZUPLO_PUBLIC_\");\n })\n .map((key) => {\n return `${key}=${wrapEnvValue(payload[key])}`;\n });\n\n let content = `# This file is auto-generated from zuplo link. Please do not edit it manually.\n# It will be auto-generated afresh the next time you run zuplo link.\n# If you wish to add your own environment variables, create a separate .env file.\n\nZUPLO_ACCOUNT_NAME=${payload.accountName}\nZUPLO_PROJECT_NAME=${payload.projectName}\nZUPLO_ENVIRONMENT_TYPE=${payload.environmentType}\nZUPLO_SYSTEM_CONFIGURATIONS=${payload[\"systemConfigurations\"]}`;\n\n // Only add public environment variables section if there are any\n if (zuploPublicEnvVars.length > 0) {\n content += `\n\n# Public Zuplo environment variables\n${zuploPublicEnvVars.join(\"\\n\")}`;\n }\n\n // Only add user environment variables section if there are any\n if (userEnvVars.length > 0) {\n content += `\n\n# Environment variables defined in the Zuplo UI for the environment\n# Note that \" characters are escaped with a backslash and escaped double quotes\n# will show up as \\\\\" in the value.\n${userEnvVars.join(\"\\n\")}`;\n }\n\n // Add final newline\n content += \"\\n\";\n\n await writeFile(zuploPreferredConfigFile, content);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/deploy/archive.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAS3C,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS;;;;;;;
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/deploy/archive.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAS3C,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS;;;;;;;GAkE5C;AAID,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,OA2BzD;AAeD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,SAAS;;;;GAmErD"}
|
package/dist/deploy/archive.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join,
|
|
4
|
+
import { join, resolve, sep } from "node:path";
|
|
5
5
|
import ignore from "ignore";
|
|
6
6
|
import { minimatch } from "minimatch";
|
|
7
7
|
import { simpleGit } from "simple-git";
|
|
@@ -16,18 +16,23 @@ function createTempFileWithSuffix(suffix = ARCHIVE_EXTENSION) {
|
|
|
16
16
|
return tempFilePath;
|
|
17
17
|
}
|
|
18
18
|
export async function archive(argv) {
|
|
19
|
-
const tarball = createTempFileWithSuffix();
|
|
20
|
-
const ignoreFn = createIgnoreFunction(argv.dir);
|
|
19
|
+
const tarball = createTempFileWithSuffix(".tar.gz");
|
|
21
20
|
const normalizedDir = resolve(argv.dir);
|
|
21
|
+
const ignoreFn = createIgnoreFunction(normalizedDir);
|
|
22
22
|
const metadata = await prepareDeployerMetadata(argv);
|
|
23
23
|
await tar.create({
|
|
24
24
|
gzip: true,
|
|
25
25
|
file: tarball,
|
|
26
|
+
cwd: normalizedDir,
|
|
26
27
|
filter: (path, stat) => {
|
|
27
28
|
const stats = stat;
|
|
29
|
+
const cleanPath = path.startsWith("./") ? path.slice(2) : path;
|
|
30
|
+
if (cleanPath === "." || cleanPath === "") {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
28
33
|
const normalizedPath = stats.isDirectory()
|
|
29
|
-
? join(
|
|
30
|
-
:
|
|
34
|
+
? join(cleanPath, sep)
|
|
35
|
+
: cleanPath;
|
|
31
36
|
if (minimatch(normalizedPath, "/", { windowsPathsNoEscape: true })) {
|
|
32
37
|
return true;
|
|
33
38
|
}
|
|
@@ -48,7 +53,7 @@ export async function archive(argv) {
|
|
|
48
53
|
logger.trace(`${normalizedPath} ignored: ${result}`);
|
|
49
54
|
return !result;
|
|
50
55
|
},
|
|
51
|
-
}, [
|
|
56
|
+
}, ["."]);
|
|
52
57
|
return {
|
|
53
58
|
tarball,
|
|
54
59
|
metadata,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/deploy/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAEL,UAAU,EACV,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAE3C,SAAS,wBAAwB,CAAC,MAAM,GAAG,iBAAiB;IAC1D,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;IACzB,MAAM,UAAU,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,UAAU,GAAG,MAAM,EAAE,CAAC,CAAC;IAC7D,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAe;IAC3C,MAAM,OAAO,GAAG,wBAAwB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAErD,MAAM,GAAG,CAAC,MAAM,CACd;QACE,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,KAAK,GAAG,IAAwB,CAAC;YACvC,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE;gBACxC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC;gBAC1C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;YAGxC,IAAI,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBACnE,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IACE,SAAS,CAAC,cAAc,EAAE,SAAS,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,EACpE,CAAC;gBAED,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IACE,SAAS,CAAC,cAAc,EAAE,UAAU,sBAAsB,EAAE,EAAE;gBAC5D,oBAAoB,EAAE,IAAI;aAC3B,CAAC,EACF,CAAC;gBAED,OAAO,IAAI,CAAC;YACd,CAAC;YAGD,IAAI,cAAc,KAAK,MAAM,IAAI,cAAc,KAAK,YAAY,EAAE,CAAC;gBACjE,IAAI,IAAI,CAAC,sBAAsB,CAAC,EAAE,CAAC;oBACjC,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CAAC,GAAG,cAAc,aAAa,MAAM,EAAE,CAAC,CAAC;YAKrD,OAAO,CAAC,MAAM,CAAC;QACjB,CAAC;KACF,EACD,CAAC,aAAa,CAAC,CAChB,CAAC;IACF,OAAO;QACL,OAAO;QACP,QAAQ;KACT,CAAC;AACJ,CAAC;AAID,MAAM,UAAU,oBAAoB,CAAC,aAAqB;IAKxD,MAAM,UAAU,GAAI,MAAc,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAElD,IAAI,UAAU,CAAC,GAAG,aAAa,aAAa,CAAC,EAAE,CAAC;QAC9C,MAAM,aAAa,GAAG,GAAG,aAAa,aAAa,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,SAAS,aAAa,sBAAsB,CAAC,CAAC;QAC3D,OAAO,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,UAAU,CAAC,GAAG,aAAa,aAAa,CAAC,EAAE,CAAC;QACrD,MAAM,aAAa,GAAG,GAAG,aAAa,aAAa,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,SAAS,aAAa,sBAAsB,CAAC,CAAC;QAC3D,MAAM,gBAAgB,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;QAEhE,MAAM,+BAA+B,GAAG,gBAAgB,CAAC,OAAO,CAC9D,YAAY,EACZ,EAAE,CACH,CAAC;QACF,OAAO,UAAU,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CACV,4FAA4F,CAC7F,CAAC;QACF,OAAO,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAQD,KAAK,UAAU,uBAAuB,CAAC,IAAe;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,sBAAsB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAe;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,MAAc,CAAC;IACnB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAElB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAI/B,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAEtB,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAE3B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9C,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;gBAClC,IAAI;gBACJ,YAAY;gBACZ,YAAY,CAAC,OAAO;aACrB,CAAC,CAAC;YACH,IAAI,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACvC,MAAM,iBAAiB,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBAChE,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACvB,MAAM,IAAI,KAAK,CACb,qDAAqD,CACtD,CAAC;gBACJ,CAAC;gBACD,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;IACJ,CAAC;IAGD,IAAI,GAAuB,CAAC;IAC5B,IAAI,OAA2B,CAAC;IAChC,IAAI,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAClB,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,KAAK,CACV,yGAAyG,CAC1G,CAAC;YACF,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO;QACP,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,GAAW,EAAE,QAA0B;IAC3E,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAE5B,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,sBAAsB,CAAC,EAC3C,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EACjC;QACE,IAAI,EAAE,GAAG;KACV,CACF,CAAC;AACJ,CAAC","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n Stats,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport ignore from \"ignore\";\nimport { minimatch } from \"minimatch\";\nimport { simpleGit } from \"simple-git\";\nimport * as tar from \"tar\";\nimport { DEPLOYER_METADATA_FILE } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { Arguments } from \"./handler.js\";\n\nexport const ARCHIVE_EXTENSION = \".tar.gz\";\n\nfunction createTempFileWithSuffix(suffix = ARCHIVE_EXTENSION) {\n const tempDir = tmpdir();\n const randomName = randomBytes(16).toString(\"hex\");\n const tempFilePath = join(tempDir, `${randomName}${suffix}`);\n return tempFilePath;\n}\n\nexport async function archive(argv: Arguments) {\n const tarball = createTempFileWithSuffix();\n const ignoreFn = createIgnoreFunction(argv.dir);\n const normalizedDir = resolve(argv.dir);\n\n const metadata = await prepareDeployerMetadata(argv);\n\n await tar.create(\n {\n gzip: true,\n file: tarball,\n filter: (path, stat) => {\n const stats = stat as unknown as Stats;\n const normalizedPath = stats.isDirectory()\n ? join(relative(process.cwd(), path), sep) // add / to help the ignore module determine that this is a folder\n : join(relative(process.cwd(), path));\n\n // special case to allow for processing of the root by tar (./)\n if (minimatch(normalizedPath, \"/\", { windowsPathsNoEscape: true })) {\n return true;\n }\n\n if (\n minimatch(normalizedPath, \".zuplo/\", { windowsPathsNoEscape: true })\n ) {\n // Need to return true to allow this to process the entries of the directory\n return true;\n }\n\n if (\n minimatch(normalizedPath, `.zuplo/${DEPLOYER_METADATA_FILE}`, {\n windowsPathsNoEscape: true,\n })\n ) {\n // Now on the second round when it enters the .zuplo folder, we specifically look for this file\n return true;\n }\n\n // We special case the .env files to allow for the self-hosted endpoint to be passed in\n if (normalizedPath === \".env\" || normalizedPath === \".env.zuplo\") {\n if (argv[\"self-hosted-endpoint\"]) {\n return true;\n }\n }\n\n const result = ignoreFn.ignores(normalizedPath);\n logger.trace(`${normalizedPath} ignored: ${result}`);\n\n // The way `tar` interprets true|false is \"opposite\" from ignore\n // When ignore returns true, it means that the .ignore file doesn't want it.\n // When tar return true, it means that we want it.\n return !result;\n },\n },\n [normalizedDir]\n );\n return {\n tarball,\n metadata,\n };\n}\n\n// Note that we do not recursively create an ignore function for each dir\n// We only create one for the top-level of the directory\nexport function createIgnoreFunction(normalizedDir: string) {\n // Most ignore files forget to ignore the .git directory\n\n // Need to do this conversion because of some weird confusion with the d.ts for ignore package in esm\n // biome-ignore lint/suspicious/noExplicitAny: Migrated from ESLint\n const baseIgnore = (ignore as any)().add(\".git/\");\n\n if (existsSync(`${normalizedDir}/.zupignore`)) {\n const zupignorePath = `${normalizedDir}/.zupignore`;\n logger.debug(`Using ${zupignorePath} to filter out files`);\n return baseIgnore.add(readFileSync(zupignorePath).toString());\n } else if (existsSync(`${normalizedDir}/.gitignore`)) {\n const gitignorePath = `${normalizedDir}/.gitignore`;\n logger.debug(`Using ${gitignorePath} to filter out files`);\n const gitIgnoreContent = readFileSync(gitignorePath).toString();\n // @NOTE - we should always include the .zuplo folder\n const gitIgnoreContentDotZuploRemoved = gitIgnoreContent.replace(\n /\\.zuplo[/]/,\n \"\"\n );\n return baseIgnore.add(gitIgnoreContentDotZuploRemoved);\n } else {\n logger.debug(\n \"Didn't find a .gitignore or .zupignore file. Defaulting to ignoring .git and node_modules.\"\n );\n return baseIgnore.add(\"node_modules/\");\n }\n}\n\ninterface DeployerMetadata {\n branch: string;\n repoUrl: string | undefined;\n sha: string | undefined;\n}\n\nasync function prepareDeployerMetadata(argv: Arguments) {\n const dir = argv.dir;\n const metadata = await generateMetadata(argv);\n await writeGeneratedMetadata(dir, metadata);\n return metadata;\n}\n\nexport async function generateMetadata(argv: Arguments) {\n const dir = argv.dir;\n const git = simpleGit({ baseDir: dir });\n\n const isRepo = await git.checkIsRepo();\n let branch: string;\n if (argv.environment) {\n branch = argv.environment;\n } else if (isRepo) {\n // Get the current branch from Git\n const status = await git.status();\n if (!status.current) {\n throw new Error(\"Invalid state: Directory is in detached head state.\");\n }\n branch = status.current.trim();\n\n // @NOTE - gitlab returns HEAD as the current branch when running git.status()\n // https://forum.gitlab.com/t/why-i-cant-get-the-branch-name/72462/6\n if (branch === \"HEAD\") {\n // Fetch remote branches to ensure the latest information\n await git.fetch([\"--all\"]);\n\n const branchCommit = await git.branch([\"-a\"]);\n const brancheRef = await git.branch([\n \"-r\",\n \"--contains\",\n branchCommit.current,\n ]);\n if (brancheRef?.all?.[0]) {\n const originBranch = brancheRef.all[0];\n const cleanOriginBranch = originBranch.replace(/^origin\\//, \"\");\n if (!cleanOriginBranch) {\n throw new Error(\n \"Invalid state: Directory is in detached head state.\"\n );\n }\n branch = cleanOriginBranch.trim();\n }\n }\n } else {\n throw new Error(\n \"The argument `environment` is required when not in a git repository.\"\n );\n }\n\n // Get the current sha\n let sha: string | undefined;\n let repoUrl: string | undefined;\n if (argv[\"override-repo-url\"]) {\n repoUrl = argv[\"override-repo-url\"];\n } else if (isRepo) {\n sha = (await git.revparse([\"HEAD\"])).trim();\n try {\n repoUrl = (await git.listRemote([\"--get-url\"])).trim();\n } catch {\n logger.debug(\n \"Failed to get the remote URL from the git repository. This can happen if there is no remote configured.\"\n );\n repoUrl = undefined;\n }\n }\n\n return {\n branch,\n repoUrl,\n sha,\n };\n}\n\nasync function writeGeneratedMetadata(dir: string, metadata: DeployerMetadata) {\n try {\n mkdirSync(join(dir, \".zuplo\"));\n } catch (err) {\n if (err.code === \"EEXIST\") {\n // this is fine, which means that we don't create it and move on\n } else {\n throw err;\n }\n }\n writeFileSync(\n join(dir, \".zuplo\", DEPLOYER_METADATA_FILE),\n JSON.stringify(metadata, null, 2),\n {\n flag: \"w\",\n }\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/deploy/archive.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n Stats,\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, resolve, sep } from \"node:path\";\nimport ignore from \"ignore\";\nimport { minimatch } from \"minimatch\";\nimport { simpleGit } from \"simple-git\";\nimport * as tar from \"tar\";\nimport { DEPLOYER_METADATA_FILE } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { Arguments } from \"./handler.js\";\n\nexport const ARCHIVE_EXTENSION = \".tar.gz\";\n\nfunction createTempFileWithSuffix(suffix = ARCHIVE_EXTENSION) {\n const tempDir = tmpdir();\n const randomName = randomBytes(16).toString(\"hex\");\n const tempFilePath = join(tempDir, `${randomName}${suffix}`);\n return tempFilePath;\n}\n\nexport async function archive(argv: Arguments) {\n const tarball = createTempFileWithSuffix(\".tar.gz\");\n const normalizedDir = resolve(argv.dir);\n const ignoreFn = createIgnoreFunction(normalizedDir);\n\n const metadata = await prepareDeployerMetadata(argv);\n\n await tar.create(\n {\n gzip: true,\n file: tarball,\n cwd: normalizedDir,\n filter: (path, stat) => {\n const stats = stat as unknown as Stats;\n const cleanPath = path.startsWith(\"./\") ? path.slice(2) : path;\n if (cleanPath === \".\" || cleanPath === \"\") {\n return true;\n }\n\n const normalizedPath = stats.isDirectory()\n ? join(cleanPath, sep)\n : cleanPath;\n\n // special case to allow for processing of the root by tar (./)\n if (minimatch(normalizedPath, \"/\", { windowsPathsNoEscape: true })) {\n return true;\n }\n\n if (\n minimatch(normalizedPath, \".zuplo/\", { windowsPathsNoEscape: true })\n ) {\n // Need to return true to allow this to process the entries of the directory\n return true;\n }\n\n if (\n minimatch(normalizedPath, `.zuplo/${DEPLOYER_METADATA_FILE}`, {\n windowsPathsNoEscape: true,\n })\n ) {\n // Now on the second round when it enters the .zuplo folder, we specifically look for this file\n return true;\n }\n\n // We special case the .env files to allow for the self-hosted endpoint to be passed in\n if (normalizedPath === \".env\" || normalizedPath === \".env.zuplo\") {\n if (argv[\"self-hosted-endpoint\"]) {\n return true;\n }\n }\n\n const result = ignoreFn.ignores(normalizedPath);\n logger.trace(`${normalizedPath} ignored: ${result}`);\n\n // The way `tar` interprets true|false is \"opposite\" from ignore\n // When ignore returns true, it means that the .ignore file doesn't want it.\n // When tar return true, it means that we want it.\n return !result;\n },\n },\n [\".\"]\n );\n return {\n tarball,\n metadata,\n };\n}\n\n// Note that we do not recursively create an ignore function for each dir\n// We only create one for the top-level of the directory\nexport function createIgnoreFunction(normalizedDir: string) {\n // Most ignore files forget to ignore the .git directory\n\n // Need to do this conversion because of some weird confusion with the d.ts for ignore package in esm\n // biome-ignore lint/suspicious/noExplicitAny: Migrated from ESLint\n const baseIgnore = (ignore as any)().add(\".git/\");\n\n if (existsSync(`${normalizedDir}/.zupignore`)) {\n const zupignorePath = `${normalizedDir}/.zupignore`;\n logger.debug(`Using ${zupignorePath} to filter out files`);\n return baseIgnore.add(readFileSync(zupignorePath).toString());\n } else if (existsSync(`${normalizedDir}/.gitignore`)) {\n const gitignorePath = `${normalizedDir}/.gitignore`;\n logger.debug(`Using ${gitignorePath} to filter out files`);\n const gitIgnoreContent = readFileSync(gitignorePath).toString();\n // @NOTE - we should always include the .zuplo folder\n const gitIgnoreContentDotZuploRemoved = gitIgnoreContent.replace(\n /\\.zuplo[/]/,\n \"\"\n );\n return baseIgnore.add(gitIgnoreContentDotZuploRemoved);\n } else {\n logger.debug(\n \"Didn't find a .gitignore or .zupignore file. Defaulting to ignoring .git and node_modules.\"\n );\n return baseIgnore.add(\"node_modules/\");\n }\n}\n\ninterface DeployerMetadata {\n branch: string;\n repoUrl: string | undefined;\n sha: string | undefined;\n}\n\nasync function prepareDeployerMetadata(argv: Arguments) {\n const dir = argv.dir;\n const metadata = await generateMetadata(argv);\n await writeGeneratedMetadata(dir, metadata);\n return metadata;\n}\n\nexport async function generateMetadata(argv: Arguments) {\n const dir = argv.dir;\n const git = simpleGit({ baseDir: dir });\n\n const isRepo = await git.checkIsRepo();\n let branch: string;\n if (argv.environment) {\n branch = argv.environment;\n } else if (isRepo) {\n // Get the current branch from Git\n const status = await git.status();\n if (!status.current) {\n throw new Error(\"Invalid state: Directory is in detached head state.\");\n }\n branch = status.current.trim();\n\n // @NOTE - gitlab returns HEAD as the current branch when running git.status()\n // https://forum.gitlab.com/t/why-i-cant-get-the-branch-name/72462/6\n if (branch === \"HEAD\") {\n // Fetch remote branches to ensure the latest information\n await git.fetch([\"--all\"]);\n\n const branchCommit = await git.branch([\"-a\"]);\n const brancheRef = await git.branch([\n \"-r\",\n \"--contains\",\n branchCommit.current,\n ]);\n if (brancheRef?.all?.[0]) {\n const originBranch = brancheRef.all[0];\n const cleanOriginBranch = originBranch.replace(/^origin\\//, \"\");\n if (!cleanOriginBranch) {\n throw new Error(\n \"Invalid state: Directory is in detached head state.\"\n );\n }\n branch = cleanOriginBranch.trim();\n }\n }\n } else {\n throw new Error(\n \"The argument `environment` is required when not in a git repository.\"\n );\n }\n\n // Get the current sha\n let sha: string | undefined;\n let repoUrl: string | undefined;\n if (argv[\"override-repo-url\"]) {\n repoUrl = argv[\"override-repo-url\"];\n } else if (isRepo) {\n sha = (await git.revparse([\"HEAD\"])).trim();\n try {\n repoUrl = (await git.listRemote([\"--get-url\"])).trim();\n } catch {\n logger.debug(\n \"Failed to get the remote URL from the git repository. This can happen if there is no remote configured.\"\n );\n repoUrl = undefined;\n }\n }\n\n return {\n branch,\n repoUrl,\n sha,\n };\n}\n\nasync function writeGeneratedMetadata(dir: string, metadata: DeployerMetadata) {\n try {\n mkdirSync(join(dir, \".zuplo\"));\n } catch (err) {\n if (err.code === \"EEXIST\") {\n // this is fine, which means that we don't create it and move on\n } else {\n throw err;\n }\n }\n writeFileSync(\n join(dir, \".zuplo\", DEPLOYER_METADATA_FILE),\n JSON.stringify(metadata, null, 2),\n {\n flag: \"w\",\n }\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.test.d.ts","sourceRoot":"","sources":["../../src/deploy/archive.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import assert from "node:assert";
|
|
7
|
+
import * as tar from "tar";
|
|
8
|
+
import { archive, createIgnoreFunction, generateMetadata } from "./archive.js";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const testTmpPath = path.join(__dirname, "..", "__tests__", "test-tmp", "archive");
|
|
12
|
+
describe("Archive Path Handling", () => {
|
|
13
|
+
let originalCwd;
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
originalCwd = process.cwd();
|
|
16
|
+
await fs.mkdir(testTmpPath, { recursive: true });
|
|
17
|
+
await fs.writeFile(path.join(testTmpPath, "zuplo.jsonc"), JSON.stringify({ name: "test-project" }, null, 2));
|
|
18
|
+
await fs.writeFile(path.join(testTmpPath, ".gitignore"), "node_modules/\n.env\n");
|
|
19
|
+
const { simpleGit } = await import("simple-git");
|
|
20
|
+
const git = simpleGit({ baseDir: testTmpPath });
|
|
21
|
+
await git.init();
|
|
22
|
+
await git.addConfig("user.name", "Test User");
|
|
23
|
+
await git.addConfig("user.email", "test@example.com");
|
|
24
|
+
await git.add(".");
|
|
25
|
+
await git.commit("Initial commit");
|
|
26
|
+
});
|
|
27
|
+
afterEach(async () => {
|
|
28
|
+
process.chdir(originalCwd);
|
|
29
|
+
try {
|
|
30
|
+
await fs.rm(testTmpPath, { recursive: true, force: true });
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
describe("archive with various --dir formats", () => {
|
|
36
|
+
it("should work with --dir=. (current directory)", async () => {
|
|
37
|
+
process.chdir(testTmpPath);
|
|
38
|
+
const result = await archive({
|
|
39
|
+
dir: ".",
|
|
40
|
+
account: "test-account",
|
|
41
|
+
project: "test-project",
|
|
42
|
+
authToken: "test-token",
|
|
43
|
+
});
|
|
44
|
+
assert.ok(result.tarball);
|
|
45
|
+
assert.ok(result.metadata);
|
|
46
|
+
assert.ok(result.metadata.branch === "main" || result.metadata.branch === "master");
|
|
47
|
+
await fs.unlink(result.tarball);
|
|
48
|
+
});
|
|
49
|
+
it("should work with --dir without argument (defaults to .)", async () => {
|
|
50
|
+
process.chdir(testTmpPath);
|
|
51
|
+
const result = await archive({
|
|
52
|
+
dir: ".",
|
|
53
|
+
account: "test-account",
|
|
54
|
+
project: "test-project",
|
|
55
|
+
authToken: "test-token",
|
|
56
|
+
});
|
|
57
|
+
assert.ok(result.tarball);
|
|
58
|
+
assert.ok(result.metadata);
|
|
59
|
+
await fs.unlink(result.tarball);
|
|
60
|
+
});
|
|
61
|
+
it("should work with absolute path", async () => {
|
|
62
|
+
const absolutePath = path.resolve(testTmpPath);
|
|
63
|
+
const result = await archive({
|
|
64
|
+
dir: absolutePath,
|
|
65
|
+
account: "test-account",
|
|
66
|
+
project: "test-project",
|
|
67
|
+
authToken: "test-token",
|
|
68
|
+
});
|
|
69
|
+
assert.ok(result.tarball);
|
|
70
|
+
assert.ok(result.metadata);
|
|
71
|
+
await fs.unlink(result.tarball);
|
|
72
|
+
});
|
|
73
|
+
it("should work with relative path from parent", async () => {
|
|
74
|
+
const parentDir = path.dirname(testTmpPath);
|
|
75
|
+
const relativePath = path.relative(parentDir, testTmpPath);
|
|
76
|
+
process.chdir(parentDir);
|
|
77
|
+
const result = await archive({
|
|
78
|
+
dir: relativePath,
|
|
79
|
+
account: "test-account",
|
|
80
|
+
project: "test-project",
|
|
81
|
+
authToken: "test-token",
|
|
82
|
+
});
|
|
83
|
+
assert.ok(result.tarball);
|
|
84
|
+
assert.ok(result.metadata);
|
|
85
|
+
await fs.unlink(result.tarball);
|
|
86
|
+
});
|
|
87
|
+
it("should work with ./relative/path format", async () => {
|
|
88
|
+
const parentDir = path.dirname(testTmpPath);
|
|
89
|
+
const baseName = path.basename(testTmpPath);
|
|
90
|
+
process.chdir(parentDir);
|
|
91
|
+
const result = await archive({
|
|
92
|
+
dir: `./${baseName}`,
|
|
93
|
+
account: "test-account",
|
|
94
|
+
project: "test-project",
|
|
95
|
+
authToken: "test-token",
|
|
96
|
+
});
|
|
97
|
+
assert.ok(result.tarball);
|
|
98
|
+
assert.ok(result.metadata);
|
|
99
|
+
await fs.unlink(result.tarball);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe("createIgnoreFunction with various path formats", () => {
|
|
103
|
+
it("should read .gitignore with absolute path", async () => {
|
|
104
|
+
const absolutePath = path.resolve(testTmpPath);
|
|
105
|
+
const ignoreFn = createIgnoreFunction(absolutePath);
|
|
106
|
+
assert.strictEqual(ignoreFn.ignores("node_modules/"), true);
|
|
107
|
+
assert.strictEqual(ignoreFn.ignores("src/index.ts"), false);
|
|
108
|
+
});
|
|
109
|
+
it("should read .gitignore with relative path from cwd", async () => {
|
|
110
|
+
const parentDir = path.dirname(testTmpPath);
|
|
111
|
+
const relativePath = path.relative(parentDir, testTmpPath);
|
|
112
|
+
process.chdir(parentDir);
|
|
113
|
+
const absolutePath = path.resolve(relativePath);
|
|
114
|
+
const ignoreFn = createIgnoreFunction(absolutePath);
|
|
115
|
+
assert.strictEqual(ignoreFn.ignores("node_modules/"), true);
|
|
116
|
+
assert.strictEqual(ignoreFn.ignores(".git/"), true);
|
|
117
|
+
});
|
|
118
|
+
it("should read .gitignore with . as directory", async () => {
|
|
119
|
+
process.chdir(testTmpPath);
|
|
120
|
+
const absolutePath = path.resolve(".");
|
|
121
|
+
const ignoreFn = createIgnoreFunction(absolutePath);
|
|
122
|
+
assert.strictEqual(ignoreFn.ignores("node_modules/"), true);
|
|
123
|
+
assert.strictEqual(ignoreFn.ignores(".env"), true);
|
|
124
|
+
});
|
|
125
|
+
it("should prefer .zupignore over .gitignore", async () => {
|
|
126
|
+
await fs.writeFile(path.join(testTmpPath, ".zupignore"), "dist/\n*.log\n");
|
|
127
|
+
const absolutePath = path.resolve(testTmpPath);
|
|
128
|
+
const ignoreFn = createIgnoreFunction(absolutePath);
|
|
129
|
+
assert.strictEqual(ignoreFn.ignores("dist/"), true);
|
|
130
|
+
assert.strictEqual(ignoreFn.ignores("test.log"), true);
|
|
131
|
+
assert.strictEqual(ignoreFn.ignores(".git/"), true);
|
|
132
|
+
});
|
|
133
|
+
it("should always ignore .git directory", async () => {
|
|
134
|
+
await fs.unlink(path.join(testTmpPath, ".gitignore"));
|
|
135
|
+
const absolutePath = path.resolve(testTmpPath);
|
|
136
|
+
const ignoreFn = createIgnoreFunction(absolutePath);
|
|
137
|
+
assert.strictEqual(ignoreFn.ignores(".git/"), true);
|
|
138
|
+
assert.strictEqual(ignoreFn.ignores("node_modules/"), true);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe("generateMetadata with various path formats", () => {
|
|
142
|
+
it("should generate metadata with absolute path", async () => {
|
|
143
|
+
const absolutePath = path.resolve(testTmpPath);
|
|
144
|
+
const metadata = await generateMetadata({
|
|
145
|
+
dir: absolutePath,
|
|
146
|
+
account: "test-account",
|
|
147
|
+
project: "test-project",
|
|
148
|
+
authToken: "test-token",
|
|
149
|
+
});
|
|
150
|
+
assert.ok(metadata.branch);
|
|
151
|
+
assert.ok(metadata.sha);
|
|
152
|
+
assert.ok(metadata.branch === "main" || metadata.branch === "master");
|
|
153
|
+
});
|
|
154
|
+
it("should generate metadata with . as directory", async () => {
|
|
155
|
+
process.chdir(testTmpPath);
|
|
156
|
+
const metadata = await generateMetadata({
|
|
157
|
+
dir: ".",
|
|
158
|
+
account: "test-account",
|
|
159
|
+
project: "test-project",
|
|
160
|
+
authToken: "test-token",
|
|
161
|
+
});
|
|
162
|
+
assert.ok(metadata.branch);
|
|
163
|
+
assert.ok(metadata.sha);
|
|
164
|
+
});
|
|
165
|
+
it("should generate metadata with relative path", async () => {
|
|
166
|
+
const parentDir = path.dirname(testTmpPath);
|
|
167
|
+
const relativePath = path.relative(parentDir, testTmpPath);
|
|
168
|
+
process.chdir(parentDir);
|
|
169
|
+
const metadata = await generateMetadata({
|
|
170
|
+
dir: relativePath,
|
|
171
|
+
account: "test-account",
|
|
172
|
+
project: "test-project",
|
|
173
|
+
authToken: "test-token",
|
|
174
|
+
});
|
|
175
|
+
assert.ok(metadata.branch);
|
|
176
|
+
assert.ok(metadata.sha);
|
|
177
|
+
});
|
|
178
|
+
it("should use --environment flag over git branch", async () => {
|
|
179
|
+
const metadata = await generateMetadata({
|
|
180
|
+
dir: testTmpPath,
|
|
181
|
+
environment: "production",
|
|
182
|
+
account: "test-account",
|
|
183
|
+
project: "test-project",
|
|
184
|
+
authToken: "test-token",
|
|
185
|
+
});
|
|
186
|
+
assert.strictEqual(metadata.branch, "production");
|
|
187
|
+
assert.ok(metadata.sha);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe("archive structure validation", () => {
|
|
191
|
+
it("should create archive with relative paths, not absolute paths", async () => {
|
|
192
|
+
process.chdir(testTmpPath);
|
|
193
|
+
await fs.mkdir(path.join(testTmpPath, "config"), { recursive: true });
|
|
194
|
+
await fs.writeFile(path.join(testTmpPath, "config", "routes.json"), JSON.stringify({ routes: [] }));
|
|
195
|
+
const result = await archive({
|
|
196
|
+
dir: ".",
|
|
197
|
+
account: "test-account",
|
|
198
|
+
project: "test-project",
|
|
199
|
+
authToken: "test-token",
|
|
200
|
+
});
|
|
201
|
+
assert.ok(result.tarball);
|
|
202
|
+
const files = [];
|
|
203
|
+
await tar.list({
|
|
204
|
+
file: result.tarball,
|
|
205
|
+
onentry: (entry) => {
|
|
206
|
+
files.push(entry.path);
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
assert.ok(files.some((f) => f === "config/routes.json" || f === "./config/routes.json"), `Expected to find config/routes.json in archive, but got: ${files.join(", ")}`);
|
|
210
|
+
const hasAbsolutePath = files.some((f) => f.includes(testTmpPath));
|
|
211
|
+
assert.strictEqual(hasAbsolutePath, false, `Archive should not contain absolute paths, but found: ${files.filter((f) => f.includes(testTmpPath)).join(", ")}`);
|
|
212
|
+
await fs.unlink(result.tarball);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe("cross-platform path handling", () => {
|
|
216
|
+
it("should normalize Windows-style paths on Windows", async () => {
|
|
217
|
+
if (os.platform() !== "win32") {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const windowsPath = testTmpPath.replace(/\//g, "\\");
|
|
221
|
+
const result = await archive({
|
|
222
|
+
dir: windowsPath,
|
|
223
|
+
account: "test-account",
|
|
224
|
+
project: "test-project",
|
|
225
|
+
authToken: "test-token",
|
|
226
|
+
});
|
|
227
|
+
assert.ok(result.tarball);
|
|
228
|
+
assert.ok(result.metadata);
|
|
229
|
+
await fs.unlink(result.tarball);
|
|
230
|
+
});
|
|
231
|
+
it("should handle forward slashes on all platforms", async () => {
|
|
232
|
+
const unixStylePath = testTmpPath.replace(/\\/g, "/");
|
|
233
|
+
const result = await archive({
|
|
234
|
+
dir: unixStylePath,
|
|
235
|
+
account: "test-account",
|
|
236
|
+
project: "test-project",
|
|
237
|
+
authToken: "test-token",
|
|
238
|
+
});
|
|
239
|
+
assert.ok(result.tarball);
|
|
240
|
+
assert.ok(result.metadata);
|
|
241
|
+
await fs.unlink(result.tarball);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
//# sourceMappingURL=archive.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.test.js","sourceRoot":"","sources":["../../src/deploy/archive.test.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport assert from \"node:assert\";\nimport * as tar from \"tar\";\nimport { archive, createIgnoreFunction, generateMetadata } from \"./archive.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst testTmpPath = path.join(\n __dirname,\n \"..\",\n \"__tests__\",\n \"test-tmp\",\n \"archive\"\n);\n\ndescribe(\"Archive Path Handling\", () => {\n let originalCwd: string;\n\n beforeEach(async () => {\n // Save original cwd\n originalCwd = process.cwd();\n\n // Ensure test-tmp directory exists\n await fs.mkdir(testTmpPath, { recursive: true });\n\n // Create a minimal zuplo project structure\n await fs.writeFile(\n path.join(testTmpPath, \"zuplo.jsonc\"),\n JSON.stringify({ name: \"test-project\" }, null, 2)\n );\n\n // Create a .gitignore file\n await fs.writeFile(\n path.join(testTmpPath, \".gitignore\"),\n \"node_modules/\\n.env\\n\"\n );\n\n // Initialize a git repo (needed for generateMetadata)\n const { simpleGit } = await import(\"simple-git\");\n const git = simpleGit({ baseDir: testTmpPath });\n await git.init();\n await git.addConfig(\"user.name\", \"Test User\");\n await git.addConfig(\"user.email\", \"test@example.com\");\n await git.add(\".\");\n await git.commit(\"Initial commit\");\n });\n\n afterEach(async () => {\n // Restore original cwd\n process.chdir(originalCwd);\n\n // Clean up test files\n try {\n await fs.rm(testTmpPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n });\n\n describe(\"archive with various --dir formats\", () => {\n it(\"should work with --dir=. (current directory)\", async () => {\n // Change to test directory\n process.chdir(testTmpPath);\n\n const result = await archive({\n dir: \".\",\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n // Branch name can be \"main\" or \"master\" depending on git configuration\n assert.ok(\n result.metadata.branch === \"main\" || result.metadata.branch === \"master\"\n );\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n\n it(\"should work with --dir without argument (defaults to .)\", async () => {\n // Change to test directory\n process.chdir(testTmpPath);\n\n const result = await archive({\n dir: \".\",\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n\n it(\"should work with absolute path\", async () => {\n const absolutePath = path.resolve(testTmpPath);\n\n const result = await archive({\n dir: absolutePath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n\n it(\"should work with relative path from parent\", async () => {\n const parentDir = path.dirname(testTmpPath);\n const relativePath = path.relative(parentDir, testTmpPath);\n\n // Change to parent directory\n process.chdir(parentDir);\n\n const result = await archive({\n dir: relativePath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n\n it(\"should work with ./relative/path format\", async () => {\n const parentDir = path.dirname(testTmpPath);\n const baseName = path.basename(testTmpPath);\n\n // Change to parent directory\n process.chdir(parentDir);\n\n const result = await archive({\n dir: `./${baseName}`,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n });\n\n describe(\"createIgnoreFunction with various path formats\", () => {\n it(\"should read .gitignore with absolute path\", async () => {\n const absolutePath = path.resolve(testTmpPath);\n const ignoreFn = createIgnoreFunction(absolutePath);\n\n assert.strictEqual(ignoreFn.ignores(\"node_modules/\"), true);\n assert.strictEqual(ignoreFn.ignores(\"src/index.ts\"), false);\n });\n\n it(\"should read .gitignore with relative path from cwd\", async () => {\n const parentDir = path.dirname(testTmpPath);\n const relativePath = path.relative(parentDir, testTmpPath);\n\n process.chdir(parentDir);\n\n const absolutePath = path.resolve(relativePath);\n const ignoreFn = createIgnoreFunction(absolutePath);\n\n assert.strictEqual(ignoreFn.ignores(\"node_modules/\"), true);\n assert.strictEqual(ignoreFn.ignores(\".git/\"), true);\n });\n\n it(\"should read .gitignore with . as directory\", async () => {\n process.chdir(testTmpPath);\n\n const absolutePath = path.resolve(\".\");\n const ignoreFn = createIgnoreFunction(absolutePath);\n\n assert.strictEqual(ignoreFn.ignores(\"node_modules/\"), true);\n assert.strictEqual(ignoreFn.ignores(\".env\"), true);\n });\n\n it(\"should prefer .zupignore over .gitignore\", async () => {\n await fs.writeFile(\n path.join(testTmpPath, \".zupignore\"),\n \"dist/\\n*.log\\n\"\n );\n\n const absolutePath = path.resolve(testTmpPath);\n const ignoreFn = createIgnoreFunction(absolutePath);\n\n assert.strictEqual(ignoreFn.ignores(\"dist/\"), true);\n assert.strictEqual(ignoreFn.ignores(\"test.log\"), true);\n // .zupignore doesn't have node_modules, but it should still ignore .git\n assert.strictEqual(ignoreFn.ignores(\".git/\"), true);\n });\n\n it(\"should always ignore .git directory\", async () => {\n // Remove .gitignore to test default behavior\n await fs.unlink(path.join(testTmpPath, \".gitignore\"));\n\n const absolutePath = path.resolve(testTmpPath);\n const ignoreFn = createIgnoreFunction(absolutePath);\n\n assert.strictEqual(ignoreFn.ignores(\".git/\"), true);\n assert.strictEqual(ignoreFn.ignores(\"node_modules/\"), true);\n });\n });\n\n describe(\"generateMetadata with various path formats\", () => {\n it(\"should generate metadata with absolute path\", async () => {\n const absolutePath = path.resolve(testTmpPath);\n\n const metadata = await generateMetadata({\n dir: absolutePath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(metadata.branch);\n assert.ok(metadata.sha);\n // Branch name can be \"main\" or \"master\" depending on git configuration\n assert.ok(metadata.branch === \"main\" || metadata.branch === \"master\");\n });\n\n it(\"should generate metadata with . as directory\", async () => {\n process.chdir(testTmpPath);\n\n const metadata = await generateMetadata({\n dir: \".\",\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(metadata.branch);\n assert.ok(metadata.sha);\n });\n\n it(\"should generate metadata with relative path\", async () => {\n const parentDir = path.dirname(testTmpPath);\n const relativePath = path.relative(parentDir, testTmpPath);\n\n process.chdir(parentDir);\n\n const metadata = await generateMetadata({\n dir: relativePath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(metadata.branch);\n assert.ok(metadata.sha);\n });\n\n it(\"should use --environment flag over git branch\", async () => {\n const metadata = await generateMetadata({\n dir: testTmpPath,\n environment: \"production\",\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.strictEqual(metadata.branch, \"production\");\n assert.ok(metadata.sha);\n });\n });\n\n describe(\"archive structure validation\", () => {\n it(\"should create archive with relative paths, not absolute paths\", async () => {\n process.chdir(testTmpPath);\n\n // Create some test files\n await fs.mkdir(path.join(testTmpPath, \"config\"), { recursive: true });\n await fs.writeFile(\n path.join(testTmpPath, \"config\", \"routes.json\"),\n JSON.stringify({ routes: [] })\n );\n\n const result = await archive({\n dir: \".\",\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n\n // Extract and verify the tar contents\n const files: string[] = [];\n\n await tar.list({\n file: result.tarball,\n onentry: (entry: tar.ReadEntry) => {\n files.push(entry.path);\n },\n });\n\n // Archive should contain relative paths like \"config/routes.json\"\n // NOT absolute paths like \"/Users/ntotten/.../config/routes.json\"\n assert.ok(\n files.some(\n (f) => f === \"config/routes.json\" || f === \"./config/routes.json\"\n ),\n `Expected to find config/routes.json in archive, but got: ${files.join(\", \")}`\n );\n\n // Verify paths don't contain the full testTmpPath\n const hasAbsolutePath = files.some((f) => f.includes(testTmpPath));\n assert.strictEqual(\n hasAbsolutePath,\n false,\n `Archive should not contain absolute paths, but found: ${files.filter((f) => f.includes(testTmpPath)).join(\", \")}`\n );\n\n // Cleanup\n await fs.unlink(result.tarball);\n });\n });\n\n describe(\"cross-platform path handling\", () => {\n it(\"should normalize Windows-style paths on Windows\", async () => {\n // Skip this test if not on Windows\n if (os.platform() !== \"win32\") {\n return;\n }\n\n // Windows path with backslashes\n const windowsPath = testTmpPath.replace(/\\//g, \"\\\\\");\n\n const result = await archive({\n dir: windowsPath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n\n it(\"should handle forward slashes on all platforms\", async () => {\n const unixStylePath = testTmpPath.replace(/\\\\/g, \"/\");\n\n const result = await archive({\n dir: unixStylePath,\n account: \"test-account\",\n project: \"test-project\",\n authToken: \"test-token\",\n });\n\n assert.ok(result.tarball);\n assert.ok(result.metadata);\n\n // Cleanup tarball\n await fs.unlink(result.tarball);\n });\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/editor/handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/editor/handler.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,iBA6B5C"}
|
package/dist/editor/handler.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { logger } from "../common/logger.js";
|
|
2
2
|
import { LocalEditorServer } from "@zuplo/editor";
|
|
3
3
|
import { printDiagnosticsToConsole } from "../common/output.js";
|
|
4
|
+
import { resolve } from "node:path";
|
|
4
5
|
export async function editor(argv) {
|
|
5
|
-
const sourceDirectory = argv.dir
|
|
6
|
+
const sourceDirectory = resolve(argv.dir);
|
|
6
7
|
const server = new LocalEditorServer({
|
|
7
8
|
sourceDirectory,
|
|
8
9
|
deploymentUrl: `http://localhost:9000`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/editor/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/editor/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB;IAC3C,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC;QACnC,eAAe;QACf,aAAa,EAAE,uBAAuB;QACtC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAEjD,yBAAyB,CAAC,wBAAwB,CAAC,CAAC;IACpD,yBAAyB,CAAC,gBAAgB,CAAC,CAAC;IAC5C,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAC9B,yBAAyB,CAAC,uCAAuC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9E,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAC9B,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAE9B,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,KAAK,UAAU,IAAI;YACjB,yBAAyB,CAAC,EAAE,CAAC,CAAC;YAC9B,yBAAyB,CAAC,4BAA4B,CAAC,CAAC;YAExD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { logger } from \"../common/logger.js\";\nimport { LocalEditorServer } from \"@zuplo/editor\";\nimport { printDiagnosticsToConsole } from \"../common/output.js\";\nimport { resolve } from \"node:path\";\n\nexport interface EditorArgs {\n dir: string;\n port: number;\n}\n\nexport async function editor(argv: EditorArgs) {\n const sourceDirectory = resolve(argv.dir);\n const server = new LocalEditorServer({\n sourceDirectory,\n deploymentUrl: `http://localhost:9000`,\n port: argv.port,\n logger,\n });\n\n server.start().catch((err) => logger.error(err));\n\n printDiagnosticsToConsole(\"Started route designer\");\n printDiagnosticsToConsole(\"Ctrl+C to exit\");\n printDiagnosticsToConsole(\"\");\n printDiagnosticsToConsole(`📘 Route Designer: http://localhost:${argv.port}`);\n printDiagnosticsToConsole(\"\");\n printDiagnosticsToConsole(\"\");\n\n return new Promise<void>((resolve) => {\n async function exit() {\n printDiagnosticsToConsole(\"\");\n printDiagnosticsToConsole(\"Stopping route designer...\");\n\n await server.close();\n resolve();\n }\n process.on(\"SIGTERM\", exit);\n process.on(\"SIGINT\", exit);\n });\n}\n"]}
|