@zintrust/core 0.4.39 → 0.4.41

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.
Files changed (29) hide show
  1. package/package.json +2 -2
  2. package/src/cli/cloudflare/CloudflareEnvTargetConfig.d.ts +37 -0
  3. package/src/cli/cloudflare/CloudflareEnvTargetConfig.d.ts.map +1 -0
  4. package/src/cli/cloudflare/CloudflareEnvTargetConfig.js +104 -0
  5. package/src/cli/cloudflare/CloudflareSecretSync.d.ts +34 -0
  6. package/src/cli/cloudflare/CloudflareSecretSync.d.ts.map +1 -0
  7. package/src/cli/cloudflare/CloudflareSecretSync.js +147 -0
  8. package/src/cli/commands/DeployCommand.d.ts.map +1 -1
  9. package/src/cli/commands/DeployCommand.js +27 -3
  10. package/src/cli/commands/DeployContainersProxyCommand.d.ts.map +1 -1
  11. package/src/cli/commands/DeployContainersProxyCommand.js +27 -3
  12. package/src/cli/commands/ProxyScaffoldUtils.d.ts.map +1 -1
  13. package/src/cli/commands/ProxyScaffoldUtils.js +2 -3
  14. package/src/cli/commands/PutCommand.d.ts.map +1 -1
  15. package/src/cli/commands/PutCommand.js +14 -117
  16. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  17. package/src/cli/commands/StartCommand.js +68 -25
  18. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  19. package/src/cli/scaffolding/ProjectScaffolder.js +24 -0
  20. package/src/cli/scaffolding/ServiceScaffolder.d.ts.map +1 -1
  21. package/src/cli/scaffolding/ServiceScaffolder.js +32 -2
  22. package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
  23. package/src/cli/utils/EnvFileLoader.js +21 -4
  24. package/src/config/env.d.ts +16 -0
  25. package/src/config/env.d.ts.map +1 -1
  26. package/src/config/env.js +126 -2
  27. package/src/index.js +3 -3
  28. package/src/runtime/RuntimeServices.d.ts.map +1 -1
  29. package/src/runtime/RuntimeServices.js +4 -34
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.39",
3
+ "version": "0.4.41",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@cloudflare/containers": "^0.2.0",
61
- "@zintrust/workers": "^0.4.39",
61
+ "@zintrust/workers": "^0.4.41",
62
62
  "bcryptjs": "^3.0.3",
63
63
  "bullmq": "^5.71.1",
64
64
  "chalk": "^5.6.2",
@@ -0,0 +1,37 @@
1
+ type ZintrustConfig = Record<string, unknown>;
2
+ export interface CloudflareEnvTargetConfig {
3
+ sharedEnv: string[];
4
+ wranglerEnvs: Record<string, string[]>;
5
+ targets: Record<string, string[]>;
6
+ }
7
+ type ResolveTargetArgs = {
8
+ projectRoot: string;
9
+ cwd: string;
10
+ configPath?: string;
11
+ };
12
+ export declare const readZintrustConfig: (cwd: string) => ZintrustConfig;
13
+ export declare const resolveCloudflareEnvTargetConfig: (config: ZintrustConfig) => CloudflareEnvTargetConfig;
14
+ export declare const inferCloudflareTarget: ({ projectRoot, cwd, configPath, }: ResolveTargetArgs) => string;
15
+ export declare const resolveCloudflareEnvKeys: (args: {
16
+ config: ZintrustConfig;
17
+ projectRoot: string;
18
+ cwd: string;
19
+ configPath?: string;
20
+ wranglerEnv?: string;
21
+ target?: string;
22
+ }) => string[];
23
+ declare const _default: Readonly<{
24
+ readZintrustConfig: (cwd: string) => ZintrustConfig;
25
+ resolveCloudflareEnvTargetConfig: (config: ZintrustConfig) => CloudflareEnvTargetConfig;
26
+ inferCloudflareTarget: ({ projectRoot, cwd, configPath, }: ResolveTargetArgs) => string;
27
+ resolveCloudflareEnvKeys: (args: {
28
+ config: ZintrustConfig;
29
+ projectRoot: string;
30
+ cwd: string;
31
+ configPath?: string;
32
+ wranglerEnv?: string;
33
+ target?: string;
34
+ }) => string[];
35
+ }>;
36
+ export default _default;
37
+ //# sourceMappingURL=CloudflareEnvTargetConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareEnvTargetConfig.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloudflare/CloudflareEnvTargetConfig.ts"],"names":[],"mappings":"AAKA,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACnC;AAED,KAAK,iBAAiB,GAAG;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAkCF,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,KAAG,cAahD,CAAC;AAEF,eAAO,MAAM,gCAAgC,GAC3C,QAAQ,cAAc,KACrB,yBAQF,CAAC;AAqBF,eAAO,MAAM,qBAAqB,GAAI,mCAInC,iBAAiB,KAAG,MActB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,MAAM;IAC7C,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,MAAM,EAiBT,CAAC;;8BA1FsC,MAAM,KAAG,cAAc;+CAgBrD,cAAc,KACrB,yBAAyB;+DAiCzB,iBAAiB,KAAG,MAAM;qCAgBkB;QAC7C,MAAM,EAAE,cAAc,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,KAAG,MAAM,EAAE;;AAmBZ,wBAKG"}
@@ -0,0 +1,104 @@
1
+ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
2
+ import { isArray, isNonEmptyString, isObject } from '../../helper/index.js';
3
+ import { existsSync, readFileSync } from '../../node-singletons/fs.js';
4
+ import * as path from '../../node-singletons/path.js';
5
+ const uniq = (items) => {
6
+ const seen = new Set();
7
+ const out = [];
8
+ for (const item of items) {
9
+ const normalized = item.trim();
10
+ if (normalized === '' || seen.has(normalized))
11
+ continue;
12
+ seen.add(normalized);
13
+ out.push(normalized);
14
+ }
15
+ return out;
16
+ };
17
+ const toStringArray = (value) => {
18
+ if (!isArray(value))
19
+ return [];
20
+ return uniq(value.filter(isNonEmptyString).map((item) => item.trim()));
21
+ };
22
+ const toStringArrayRecord = (value) => {
23
+ if (!isObject(value))
24
+ return {};
25
+ return Object.fromEntries(Object.entries(value)
26
+ .filter(([key]) => isNonEmptyString(key))
27
+ .map(([key, entry]) => [key.trim(), toStringArray(entry)]));
28
+ };
29
+ const isAbsolutePath = (value) => value.startsWith('/') || /^[A-Za-z]:[\\/]/.test(value);
30
+ export const readZintrustConfig = (cwd) => {
31
+ const filePath = path.join(cwd, '.zintrust.json');
32
+ if (!existsSync(filePath)) {
33
+ return {};
34
+ }
35
+ try {
36
+ const raw = readFileSync(filePath, 'utf8');
37
+ const parsed = JSON.parse(raw);
38
+ return isObject(parsed) ? parsed : {};
39
+ }
40
+ catch (error) {
41
+ throw ErrorFactory.createCliError('Failed to parse .zintrust.json', error);
42
+ }
43
+ };
44
+ export const resolveCloudflareEnvTargetConfig = (config) => {
45
+ const raw = isObject(config['cloudflare']) ? config['cloudflare'] : {};
46
+ return Object.freeze({
47
+ sharedEnv: toStringArray(raw['shared_env']),
48
+ wranglerEnvs: toStringArrayRecord(raw['wrangler_envs']),
49
+ targets: toStringArrayRecord(raw['targets']),
50
+ });
51
+ };
52
+ const normalizeConfigPath = (cwd, configPath) => {
53
+ if (!isNonEmptyString(configPath))
54
+ return undefined;
55
+ return isAbsolutePath(configPath) ? configPath : path.join(cwd, configPath);
56
+ };
57
+ const inferServiceTarget = (projectRoot, candidateDir) => {
58
+ const servicesRoot = path.join(projectRoot, 'src', 'services');
59
+ const relative = path.relative(servicesRoot, candidateDir);
60
+ if (relative === '' || relative.startsWith('..'))
61
+ return undefined;
62
+ const segments = relative
63
+ .split(path.sep)
64
+ .map((segment) => segment.trim())
65
+ .filter((segment) => segment !== '');
66
+ if (segments.length < 2)
67
+ return undefined;
68
+ return `${segments[0]}/${segments[1]}`;
69
+ };
70
+ export const inferCloudflareTarget = ({ projectRoot, cwd, configPath, }) => {
71
+ const normalizedConfigPath = normalizeConfigPath(cwd, configPath);
72
+ const configBase = normalizedConfigPath === undefined ? '' : path.basename(normalizedConfigPath);
73
+ if (configBase.startsWith('wrangler.containers-proxy.')) {
74
+ return 'containers-proxy';
75
+ }
76
+ const candidateDir = normalizedConfigPath === undefined ? cwd : path.dirname(normalizedConfigPath);
77
+ const serviceTarget = inferServiceTarget(projectRoot, candidateDir);
78
+ if (serviceTarget !== undefined)
79
+ return serviceTarget;
80
+ return 'worker';
81
+ };
82
+ export const resolveCloudflareEnvKeys = (args) => {
83
+ const cloudflare = resolveCloudflareEnvTargetConfig(args.config);
84
+ const target = isNonEmptyString(args.target)
85
+ ? args.target.trim()
86
+ : inferCloudflareTarget({
87
+ projectRoot: args.projectRoot,
88
+ cwd: args.cwd,
89
+ configPath: args.configPath,
90
+ });
91
+ const wranglerEnv = isNonEmptyString(args.wranglerEnv) ? args.wranglerEnv.trim() : undefined;
92
+ return uniq([
93
+ ...cloudflare.sharedEnv,
94
+ ...(cloudflare.targets['default'] ?? []),
95
+ ...(cloudflare.targets[target] ?? []),
96
+ ...(wranglerEnv === undefined ? [] : (cloudflare.wranglerEnvs[wranglerEnv] ?? [])),
97
+ ]);
98
+ };
99
+ export default Object.freeze({
100
+ readZintrustConfig,
101
+ resolveCloudflareEnvTargetConfig,
102
+ inferCloudflareTarget,
103
+ resolveCloudflareEnvKeys,
104
+ });
@@ -0,0 +1,34 @@
1
+ type CloudflareSecretLog = {
2
+ info: (message: string) => void;
3
+ warn: (message: string) => void;
4
+ success?: (message: string) => void;
5
+ };
6
+ export type CloudflareSecretSyncFailure = {
7
+ wranglerEnv: string;
8
+ key: string;
9
+ reason: string;
10
+ };
11
+ type CloudflareSecretSyncArgs = {
12
+ log: CloudflareSecretLog;
13
+ cwd: string;
14
+ wranglerEnvs: string[];
15
+ envPath: string;
16
+ dryRun?: boolean;
17
+ configGroups?: string[];
18
+ configPath?: string;
19
+ target?: string;
20
+ requireSelection?: boolean;
21
+ };
22
+ export type CloudflareSecretSyncResult = {
23
+ pushed: number;
24
+ failures: CloudflareSecretSyncFailure[];
25
+ selectedKeys: string[];
26
+ };
27
+ export declare const reportCloudflareSecretSync: (log: CloudflareSecretLog, result: Pick<CloudflareSecretSyncResult, "pushed" | "failures">) => void;
28
+ export declare const syncCloudflareSecrets: ({ log, cwd, wranglerEnvs, envPath, dryRun, configGroups, configPath, target, requireSelection, }: CloudflareSecretSyncArgs) => Promise<CloudflareSecretSyncResult>;
29
+ declare const _default: Readonly<{
30
+ syncCloudflareSecrets: ({ log, cwd, wranglerEnvs, envPath, dryRun, configGroups, configPath, target, requireSelection, }: CloudflareSecretSyncArgs) => Promise<CloudflareSecretSyncResult>;
31
+ reportCloudflareSecretSync: (log: CloudflareSecretLog, result: Pick<CloudflareSecretSyncResult, "pushed" | "failures">) => void;
32
+ }>;
33
+ export default _default;
34
+ //# sourceMappingURL=CloudflareSecretSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloudflareSecretSync.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloudflare/CloudflareSecretSync.ts"],"names":[],"mappings":"AAYA,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAaF,KAAK,wBAAwB,GAAG;IAC9B,GAAG,EAAE,mBAAmB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,2BAA2B,EAAE,CAAC;IACxC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAiJF,eAAO,MAAM,0BAA0B,GACrC,KAAK,mBAAmB,EACxB,QAAQ,IAAI,CAAC,0BAA0B,EAAE,QAAQ,GAAG,UAAU,CAAC,KAC9D,IAcF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAU,kGAUzC,wBAAwB,KAAG,OAAO,CAAC,0BAA0B,CAqC/D,CAAC;;8HArCC,wBAAwB,KAAG,OAAO,CAAC,0BAA0B,CAAC;sCA5B1D,mBAAmB,UAChB,IAAI,CAAC,0BAA0B,EAAE,QAAQ,GAAG,UAAU,CAAC,KAC9D,IAAI;;AAiEP,wBAGG"}
@@ -0,0 +1,147 @@
1
+ import { readZintrustConfig, resolveCloudflareEnvKeys, } from '../cloudflare/CloudflareEnvTargetConfig.js';
2
+ import { resolveNpmPath } from '../../common/index.js';
3
+ import { appConfig } from '../../config/app.js';
4
+ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
5
+ import { execFileSync } from '../../node-singletons/child-process.js';
6
+ import { existsSync } from '../../node-singletons/fs.js';
7
+ import * as path from '../../node-singletons/path.js';
8
+ import { EnvFile } from '../../toolkit/Secrets/EnvFile.js';
9
+ const uniq = (items) => {
10
+ const seen = new Set();
11
+ const out = [];
12
+ for (const item of items) {
13
+ const normalized = item.trim();
14
+ if (normalized === '' || seen.has(normalized))
15
+ continue;
16
+ seen.add(normalized);
17
+ out.push(normalized);
18
+ }
19
+ return out;
20
+ };
21
+ const getConfigArray = (config, key) => {
22
+ const raw = config[key];
23
+ if (!Array.isArray(raw))
24
+ return [];
25
+ return uniq(raw.filter((item) => typeof item === 'string'));
26
+ };
27
+ const resolveValue = (key, envMap) => {
28
+ const fromFile = envMap[key];
29
+ const fromProcess = process.env[key];
30
+ return fromFile ?? fromProcess ?? '';
31
+ };
32
+ const getPutTimeoutMs = () => {
33
+ const raw = process.env['ZT_PUT_TIMEOUT_MS'];
34
+ if (typeof raw !== 'string')
35
+ return 120000;
36
+ const parsed = Number.parseInt(raw, 10);
37
+ if (!Number.isFinite(parsed) || parsed <= 0)
38
+ return 120000;
39
+ return parsed;
40
+ };
41
+ const putSecret = (wranglerEnv, key, value, configPath) => {
42
+ const npmPath = resolveNpmPath();
43
+ const args = ['exec', '--yes', '--', 'wrangler'];
44
+ if (typeof configPath === 'string' && configPath.trim() !== '') {
45
+ args.push('--config', configPath.trim());
46
+ }
47
+ args.push('secret', 'put', key, '--env', wranglerEnv);
48
+ execFileSync(npmPath, args, {
49
+ stdio: ['pipe', 'inherit', 'inherit'],
50
+ input: value,
51
+ encoding: 'utf8',
52
+ timeout: getPutTimeoutMs(),
53
+ killSignal: 'SIGTERM',
54
+ env: appConfig.getSafeEnv(),
55
+ });
56
+ };
57
+ const getFailureReason = (error) => error instanceof Error ? error.message : String(error);
58
+ const resolveSelectedKeys = ({ log, config, cwd, wranglerEnvs, configGroups = [], configPath, target, requireSelection, }) => {
59
+ const explicitKeys = uniq(configGroups.flatMap((groupKey) => {
60
+ const keys = getConfigArray(config, groupKey);
61
+ if (keys.length === 0) {
62
+ log.warn(`Group \`${groupKey}\` is missing or empty in .zintrust.json`);
63
+ }
64
+ return keys;
65
+ }));
66
+ const manifestKeys = uniq(wranglerEnvs.flatMap((wranglerEnv) => resolveCloudflareEnvKeys({
67
+ config,
68
+ projectRoot: cwd,
69
+ cwd,
70
+ ...(configPath === undefined ? {} : { configPath }),
71
+ wranglerEnv,
72
+ ...(typeof target === 'string' && target.trim() !== '' ? { target: target.trim() } : {}),
73
+ })));
74
+ const selectedKeys = uniq([...explicitKeys, ...manifestKeys]);
75
+ if (selectedKeys.length > 0 || !requireSelection) {
76
+ return selectedKeys;
77
+ }
78
+ throw ErrorFactory.createCliError(configGroups.length === 0
79
+ ? 'No secret keys resolved from .zintrust.json cloudflare.shared_env/cloudflare.targets/cloudflare.wrangler_envs. Use --var <group> or add a Cloudflare env manifest.'
80
+ : 'No secret keys resolved from selected groups.');
81
+ };
82
+ const processSecretSync = (log, wranglerEnvs, selectedKeys, envMap, dryRun, configPath) => {
83
+ let pushed = 0;
84
+ const failures = [];
85
+ for (const wranglerEnv of wranglerEnvs) {
86
+ for (const key of selectedKeys) {
87
+ const value = resolveValue(key, envMap);
88
+ if (value.trim() === '') {
89
+ failures.push({ wranglerEnv, key, reason: 'empty value' });
90
+ continue;
91
+ }
92
+ try {
93
+ if (!dryRun) {
94
+ log.info(`putting ${key} -> ${wranglerEnv}...`);
95
+ putSecret(wranglerEnv, key, value, configPath);
96
+ }
97
+ pushed += 1;
98
+ log.info(`${dryRun ? '[dry-run] ' : ''}put ${key} -> ${wranglerEnv}`);
99
+ }
100
+ catch (error) {
101
+ failures.push({ wranglerEnv, key, reason: getFailureReason(error) });
102
+ }
103
+ }
104
+ }
105
+ return { pushed, failures };
106
+ };
107
+ export const reportCloudflareSecretSync = (log, result) => {
108
+ if (typeof log.success === 'function') {
109
+ log.success(`Cloudflare secrets report: pushed=${result.pushed}, failed=${result.failures.length}`);
110
+ }
111
+ else {
112
+ log.info(`Cloudflare secrets report: pushed=${result.pushed}, failed=${result.failures.length}`);
113
+ }
114
+ for (const item of result.failures) {
115
+ log.warn(`${item.key} -> ${item.wranglerEnv}: ${item.reason}`);
116
+ }
117
+ };
118
+ export const syncCloudflareSecrets = async ({ log, cwd, wranglerEnvs, envPath, dryRun = false, configGroups = [], configPath, target, requireSelection = true, }) => {
119
+ const normalizedConfigPath = typeof configPath === 'string' && configPath.trim() !== '' ? configPath.trim() : undefined;
120
+ if (normalizedConfigPath !== undefined && !existsSync(path.join(cwd, normalizedConfigPath))) {
121
+ throw ErrorFactory.createCliError(`Wrangler config not found: ${normalizedConfigPath}`);
122
+ }
123
+ const config = readZintrustConfig(cwd);
124
+ const selectedKeys = resolveSelectedKeys({
125
+ log,
126
+ config,
127
+ cwd,
128
+ wranglerEnvs,
129
+ configGroups,
130
+ configPath: normalizedConfigPath,
131
+ target,
132
+ requireSelection,
133
+ });
134
+ if (selectedKeys.length === 0) {
135
+ return { pushed: 0, failures: [], selectedKeys: [] };
136
+ }
137
+ const envMap = await EnvFile.read({ cwd, path: envPath });
138
+ const syncResult = processSecretSync(log, wranglerEnvs, selectedKeys, envMap, dryRun, normalizedConfigPath);
139
+ return {
140
+ ...syncResult,
141
+ selectedKeys,
142
+ };
143
+ };
144
+ export default Object.freeze({
145
+ syncCloudflareSecrets,
146
+ reportCloudflareSecretSync,
147
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"DeployCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DeployCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyIrE;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB;;OAEG;cACO,YAAY;EAGtB,CAAC"}
1
+ {"version":3,"file":"DeployCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DeployCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0LrE;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB;;OAEG;cACO,YAAY;EAGtB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { BaseCommand } from '../BaseCommand.js';
2
+ import { reportCloudflareSecretSync, syncCloudflareSecrets, } from '../cloudflare/CloudflareSecretSync.js';
2
3
  import { SpawnUtil } from '../utils/spawn.js';
3
4
  import { Logger } from '../../config/logger.js';
4
5
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
@@ -44,7 +45,25 @@ const deployProxyStack = async (label) => {
44
45
  await runCompose(['compose', '-f', composePath, 'up', '-d', '--build']);
45
46
  Logger.info(`✅ ${label} deployed.`);
46
47
  };
47
- const runDeploy = async (target, options) => {
48
+ const syncWranglerSecrets = async (cmd, cwd, wranglerEnv, options) => {
49
+ if (options.syncSecrets === false)
50
+ return;
51
+ const result = await syncCloudflareSecrets({
52
+ log: cmd,
53
+ cwd,
54
+ wranglerEnvs: [wranglerEnv],
55
+ envPath: typeof options.envPath === 'string' && options.envPath.trim() !== ''
56
+ ? options.envPath
57
+ : '.env',
58
+ configPath: typeof options.config === 'string' ? options.config.trim() : undefined,
59
+ target: typeof options.target === 'string' ? options.target : undefined,
60
+ requireSelection: false,
61
+ });
62
+ if (result.selectedKeys.length === 0)
63
+ return;
64
+ reportCloudflareSecretSync(cmd, result);
65
+ };
66
+ const runDeploy = async (cmd, target, options) => {
48
67
  const normalizedTarget = target.trim().toLowerCase();
49
68
  if (normalizedTarget === 'cw' || normalizedTarget === 'cwr') {
50
69
  const label = normalizedTarget === 'cwr'
@@ -70,6 +89,7 @@ const runDeploy = async (target, options) => {
70
89
  }
71
90
  }
72
91
  Logger.info(`Deploying to Cloudflare environment: ${environment}`);
92
+ await syncWranglerSecrets(cmd, process.cwd(), environment, options);
73
93
  const exitCode = await SpawnUtil.spawnAndWait({
74
94
  command: 'wrangler',
75
95
  args: ['deploy', ...(config.length > 0 ? ['--config', config] : []), '--env', environment],
@@ -79,7 +99,7 @@ const runDeploy = async (target, options) => {
79
99
  }
80
100
  };
81
101
  const createDeployCommand = () => {
82
- return BaseCommand.create({
102
+ const cmd = BaseCommand.create({
83
103
  name: 'deploy',
84
104
  description: 'Deploy ZinTrust to Cloudflare Workers',
85
105
  addOptions: (command) => {
@@ -87,6 +107,9 @@ const createDeployCommand = () => {
87
107
  .argument('[target]', 'Deployment target (worker, d1-proxy, kv-proxy, production, cw, cp)', 'worker')
88
108
  .option('-e, --env <env>', 'Wrangler environment (overrides target)');
89
109
  command.option('-c, --config <path>', 'Wrangler config file (e.g. wrangler.containers-proxy.jsonc)');
110
+ command.option('--env-path <path>', 'Path to env file used when syncing Cloudflare secrets', '.env');
111
+ command.option('--target <id>', 'Cloudflare worker target key from .zintrust.json cloudflare.targets');
112
+ command.option('--no-sync-secrets', 'Skip Cloudflare secret sync before wrangler deploy');
90
113
  },
91
114
  execute: async (options) => {
92
115
  // Note: BaseCommand.create sets up action handler that calls execute(options).
@@ -103,9 +126,10 @@ const createDeployCommand = () => {
103
126
  //
104
127
  // So 'target' will be available in options.args[0]
105
128
  const target = options.args?.[0] ?? 'worker';
106
- await runDeploy(target, options);
129
+ await runDeploy(cmd, target, options);
107
130
  },
108
131
  });
132
+ return cmd;
109
133
  };
110
134
  /**
111
135
  * Deploy Command Factory
@@ -1 +1 @@
1
- {"version":3,"file":"DeployContainersProxyCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DeployContainersProxyCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA2CrE,eAAO,MAAM,4BAA4B;cAC7B,YAAY;EAatB,CAAC"}
1
+ {"version":3,"file":"DeployContainersProxyCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/DeployContainersProxyCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA6ErE,eAAO,MAAM,4BAA4B;cAC7B,YAAY;EAyBtB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { BaseCommand } from '../BaseCommand.js';
2
+ import { reportCloudflareSecretSync, syncCloudflareSecrets, } from '../cloudflare/CloudflareSecretSync.js';
2
3
  import { SpawnUtil } from '../utils/spawn.js';
3
4
  import { Logger } from '../../config/logger.js';
4
5
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
@@ -17,11 +18,30 @@ const resolveEnv = (raw) => {
17
18
  const normalized = typeof raw === 'string' ? raw.trim() : '';
18
19
  return normalized.length > 0 ? normalized : 'production';
19
20
  };
20
- const execute = async (options) => {
21
+ const syncDeploySecrets = async (cmd, cwd, config, env, options) => {
22
+ if (options.syncSecrets === false)
23
+ return;
24
+ const result = await syncCloudflareSecrets({
25
+ log: cmd,
26
+ cwd,
27
+ wranglerEnvs: [env],
28
+ envPath: typeof options.envPath === 'string' && options.envPath.trim() !== ''
29
+ ? options.envPath
30
+ : '.env',
31
+ configPath: config,
32
+ target: typeof options.target === 'string' ? options.target : undefined,
33
+ requireSelection: false,
34
+ });
35
+ if (result.selectedKeys.length === 0)
36
+ return;
37
+ reportCloudflareSecretSync(cmd, result);
38
+ };
39
+ const execute = async (cmd, options) => {
21
40
  const cwd = process.cwd();
22
41
  const config = resolveConfig(cwd, options.config);
23
42
  const env = resolveEnv(options.env);
24
43
  Logger.info(`Deploying Containers proxy via Wrangler (env=${env})...`);
44
+ await syncDeploySecrets(cmd, cwd, config, env, options);
25
45
  const exitCode = await SpawnUtil.spawnAndWait({
26
46
  command: 'wrangler',
27
47
  args: ['deploy', '--config', config, '--env', env],
@@ -31,15 +51,19 @@ const execute = async (options) => {
31
51
  };
32
52
  export const DeployContainersProxyCommand = Object.freeze({
33
53
  create() {
34
- return BaseCommand.create({
54
+ const cmd = BaseCommand.create({
35
55
  name: 'deploy:ccp',
36
56
  aliases: ['deploy:containers-proxy', 'deploy:cf-containers-proxy', 'd:ccp', 'ccp:deploy'],
37
57
  description: 'Deploy Cloudflare Containers proxy Worker (wrangler.containers-proxy.jsonc)',
38
58
  addOptions: (command) => {
39
59
  command.option('-e, --env <name>', 'Wrangler environment name', 'production');
40
60
  command.option('-c, --config <path>', 'Wrangler config file', DEFAULT_CONFIG);
61
+ command.option('--env-path <path>', 'Path to env file used when syncing Cloudflare secrets', '.env');
62
+ command.option('--target <id>', 'Cloudflare worker target key from .zintrust.json cloudflare.targets');
63
+ command.option('--no-sync-secrets', 'Skip Cloudflare secret sync before wrangler deploy');
41
64
  },
42
- execute: async (options) => execute(options),
65
+ execute: async (options) => execute(cmd, options),
43
66
  });
67
+ return cmd;
44
68
  },
45
69
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ProxyScaffoldUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ProxyScaffoldUtils.ts"],"names":[],"mappings":"AAKA,KAAK,4BAA4B,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,2BAA2B,CAAC,OAAO,EAAE,QAAQ,IAAI;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3E,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,0BAA0B,CAAC,OAAO,IAAI;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIvE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,iBAA2B,KAAG,MAExF,CAAC;AAmBF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAQvE,CAAC;AAmBF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,MAuBhF,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,EAChB,mBAAmB,MAAM,KACxB,MAaF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,4BAA4B,KACpC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAoB3C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,EAAE,QAAQ,EACpD,SAAS,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,KACtD,0BAA0B,CAAC,OAAO,CAqBpC,CAAC"}
1
+ {"version":3,"file":"ProxyScaffoldUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ProxyScaffoldUtils.ts"],"names":[],"mappings":"AAKA,KAAK,4BAA4B,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,2BAA2B,CAAC,OAAO,EAAE,QAAQ,IAAI;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3E,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,0BAA0B,CAAC,OAAO,IAAI;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIvE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,iBAA2B,KAAG,MAExF,CAAC;AAmBF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAQvE,CAAC;AAmBF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,MAuBhF,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,EAChB,mBAAmB,MAAM,KACxB,MAaF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,4BAA4B,KACpC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAmB3C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,EAAE,QAAQ,EACpD,SAAS,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,KACtD,0BAA0B,CAAC,OAAO,CAqBpC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
2
2
  import { isNonEmptyString } from '../../helper/index.js';
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from '../../node-singletons/fs.js';
4
- import { join } from '../../node-singletons/path.js';
4
+ import { dirname, join } from '../../node-singletons/path.js';
5
5
  export const trimNonEmptyOption = (value) => {
6
6
  if (!isNonEmptyString(value))
7
7
  return undefined;
@@ -93,8 +93,7 @@ export const ensureProxyEntrypoint = (options) => {
93
93
  if (existsSync(entryFilePath)) {
94
94
  return { created: false, entryFilePath };
95
95
  }
96
- const lastSlashIndex = entryFilePath.lastIndexOf('/');
97
- const entryDir = lastSlashIndex > 0 ? entryFilePath.slice(0, lastSlashIndex) : options.cwd;
96
+ const entryDir = dirname(entryFilePath);
98
97
  mkdirSync(entryDir, { recursive: true });
99
98
  writeFileSync(entryFilePath, [
100
99
  `export { ${options.exportName} } from '${options.moduleSpecifier}';`,
@@ -1 +1 @@
1
- {"version":3,"file":"PutCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/PutCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0OvF,eAAO,MAAM,UAAU;cACX,YAAY;EAWtB,CAAC;AAEH,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"PutCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/PutCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAqFvF,eAAO,MAAM,UAAU;cACX,YAAY;EAWtB,CAAC;AAEH,eAAe,UAAU,CAAC"}