@travetto/pack 4.1.2 → 5.0.0-rc.0

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 ArcSine Technologies
3
+ Copyright (c) 2023 ArcSine Technologies
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -29,7 +29,7 @@ $ trv pack --help
29
29
  Usage: pack [options]
30
30
 
31
31
  Options:
32
- -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
32
+ -b, --build-dir <string> Workspace for building (default: "/tmp/<temp-folder>")
33
33
  --clean, --no-clean Clean workspace (default: true)
34
34
  -o, --output <string> Output location
35
35
  --main-scripts, --no-main-scripts Create entry scripts (default: true)
@@ -42,6 +42,7 @@ Options:
42
42
  -r, --rollup-configuration <string> Rollup configuration file (default: "@travetto/pack/support/rollup/build")
43
43
  --env-file <string> Env Flag File Name (default: ".env")
44
44
  --manifest-file <string> Manifest File Name (default: "manifest.json")
45
+ -wr, --include-workspace-resources Include workspace resources (default: false)
45
46
  -m, --module <module> Module to run for
46
47
  -h, --help display help for command
47
48
  ```
@@ -93,7 +94,7 @@ $ trv pack:zip --help
93
94
  Usage: pack:zip [options]
94
95
 
95
96
  Options:
96
- -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
97
+ -b, --build-dir <string> Workspace for building (default: "/tmp/<temp-folder>")
97
98
  --clean, --no-clean Clean workspace (default: true)
98
99
  -o, --output <string> Output location (default: "travetto_pack.zip")
99
100
  --main-scripts, --no-main-scripts Create entry scripts (default: true)
@@ -106,6 +107,7 @@ Options:
106
107
  -r, --rollup-configuration <string> Rollup configuration file (default: "@travetto/pack/support/rollup/build")
107
108
  --env-file <string> Env Flag File Name (default: ".env")
108
109
  --manifest-file <string> Manifest File Name (default: "manifest.json")
110
+ -wr, --include-workspace-resources Include workspace resources (default: false)
109
111
  -m, --module <module> Module to run for
110
112
  -h, --help display help for command
111
113
  ```
@@ -120,7 +122,7 @@ $ trv pack:docker --help
120
122
  Usage: pack:docker [options]
121
123
 
122
124
  Options:
123
- -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
125
+ -b, --build-dir <string> Workspace for building (default: "/tmp/<temp-folder>")
124
126
  --clean, --no-clean Clean workspace (default: true)
125
127
  -o, --output <string> Output location
126
128
  --main-scripts, --no-main-scripts Create entry scripts (default: true)
@@ -133,8 +135,9 @@ Options:
133
135
  -r, --rollup-configuration <string> Rollup configuration file (default: "@travetto/pack/support/rollup/build")
134
136
  --env-file <string> Env Flag File Name (default: ".env")
135
137
  --manifest-file <string> Manifest File Name (default: "manifest.json")
138
+ -wr, --include-workspace-resources Include workspace resources (default: false)
136
139
  -df, --docker-factory <string> Docker Factory source (default: "@travetto/pack/support/pack.dockerfile")
137
- -di, --docker-image <string> Docker Image to extend (default: "node:20-alpine")
140
+ -di, --docker-image <string> Docker Image to extend (default: "node:22-alpine")
138
141
  -dn, --docker-name <string> Docker Image Name (default: "travetto_pack")
139
142
  -dt, --docker-tag <string> Docker Image Tag (default: ["latest"])
140
143
  -dp, --docker-port <number> Docker Image Port (default: [])
@@ -183,6 +186,7 @@ echo "NODE_ENV=production" > $DIST/.env
183
186
  echo "TRV_MANIFEST=manifest.json" >> $DIST/.env
184
187
  echo "TRV_MODULE=$MOD" >> $DIST/.env
185
188
  echo "TRV_CLI_IPC=" >> $DIST/.env
189
+ echo "TRV_RESOURCE_OVERRIDES=@#resources=@@#resources" >> $DIST/.env
186
190
 
187
191
  # Writing package.json
188
192
 
@@ -203,16 +207,15 @@ chmod 755 $DIST/todo-app.sh
203
207
 
204
208
  echo "Writing entry scripts todo-app.cmd args=(run:rest)"
205
209
 
206
- echo "" > $DIST/todo-app.cmd
207
- echo "cd %~p0" >> $DIST/todo-app.cmd
210
+ echo "cd %~p0" > $DIST/todo-app.cmd
208
211
  echo "node todo-app.js run:rest %*" >> $DIST/todo-app.cmd
209
212
  chmod 755 $DIST/todo-app.cmd
210
213
 
211
- # Copying over resources
214
+ # Copying over module resources
212
215
 
213
- echo "Copying over resources"
216
+ echo "Copying over module resources"
214
217
 
215
- cp -r -p $ROOT/resources $DIST/resources
218
+ cp -r -p $ROOT/resources/* $DIST/resources
216
219
 
217
220
  # Writing Manifest manifest.json
218
221
 
@@ -237,21 +240,21 @@ cd $TRV_OUT
237
240
  npx rollup -c $TRV_OUT/node_modules/@travetto/pack/support/rollup/build.js
238
241
  cd $ROOT
239
242
 
240
- # Pulling Docker Base Image node:20-alpine
243
+ # Pulling Docker Base Image node:22-alpine
241
244
 
242
- echo "Pulling Docker Base Image node:20-alpine"
245
+ echo "Pulling Docker Base Image node:22-alpine"
243
246
 
244
- docker pull node:20-alpine
247
+ docker pull node:22-alpine
245
248
 
246
- # Detected Image OS node:20-alpine as alpine
249
+ # Detected Image OS node:22-alpine as alpine
247
250
 
248
- echo "Detected Image OS node:20-alpine as alpine"
251
+ echo "Detected Image OS node:22-alpine as alpine"
249
252
 
250
253
  # Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile
251
254
 
252
255
  echo "Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile"
253
256
 
254
- echo "FROM node:20-alpine" > $DIST/Dockerfile
257
+ echo "FROM node:22-alpine" > $DIST/Dockerfile
255
258
  echo "RUN addgroup -g 2000 app && adduser -D -G app -u 2000 app" >> $DIST/Dockerfile
256
259
  echo "RUN mkdir /app && chown app:app /app" >> $DIST/Dockerfile
257
260
  echo "COPY --chown=\"app:app\" . /app" >> $DIST/Dockerfile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/pack",
3
- "version": "4.1.2",
3
+ "version": "5.0.0-rc.0",
4
4
  "description": "Code packing utilities",
5
5
  "keywords": [
6
6
  "travetto",
@@ -29,12 +29,12 @@
29
29
  "@rollup/plugin-json": "^6.1.0",
30
30
  "@rollup/plugin-node-resolve": "^15.2.3",
31
31
  "@rollup/plugin-terser": "^0.4.4",
32
- "@travetto/base": "^4.1.2",
33
- "@travetto/terminal": "^4.1.1",
32
+ "@travetto/base": "^5.0.0-rc.0",
33
+ "@travetto/terminal": "^5.0.0-rc.0",
34
34
  "rollup": "^4.18.0"
35
35
  },
36
36
  "peerDependencies": {
37
- "@travetto/cli": "^4.1.2"
37
+ "@travetto/cli": "^5.0.0-rc.0"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@travetto/cli": {
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@ import { type OutputOptions } from 'rollup';
2
2
  import type terser from '@rollup/plugin-terser';
3
3
 
4
4
  export type CommonPackConfig = {
5
- workspace: string;
5
+ buildDir: string;
6
6
  output: string;
7
7
  clean: boolean;
8
8
  ejectFile?: string;
@@ -13,6 +13,7 @@ export type CommonPackConfig = {
13
13
  envFile: string;
14
14
  env?: string;
15
15
  manifestFile: string;
16
+ workspaceResourceFolder: string;
16
17
 
17
18
  // Bundle
18
19
  rollupConfiguration: string;
@@ -49,8 +50,6 @@ export type DockerPackConfig = {
49
50
  export type ShellCommandImpl = {
50
51
  var(name: string): string;
51
52
  createFile(file: string, text: string[], mode?: string): string[][];
52
- scriptOpen(): string[];
53
- chdirScript(): string[];
54
53
  callCommandWithAllArgs(cmd: string, ...args: string[]): string[];
55
54
  copy(src: string, dest: string): string[];
56
55
  copyRecursive(src: string, dest: string, inclusive?: boolean): string[];
@@ -61,6 +60,7 @@ export type ShellCommandImpl = {
61
60
  comment(message: string): string[];
62
61
  echo(text: string): string[];
63
62
  zip(output: string): string[];
63
+ script(lines: string[], chdir?: boolean): { ext: string, contents: string[] };
64
64
  };
65
65
 
66
66
  export type DockerPackFactory = (cfg: DockerPackConfig) => (string | Promise<string>);
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
+ import path from 'node:path';
2
3
 
3
- import { path, RuntimeIndex } from '@travetto/manifest';
4
+ import { RuntimeIndex } from '@travetto/manifest';
4
5
  import { cliTpl } from '@travetto/cli';
5
6
 
6
7
  import { ActiveShellCommand } from './shell';
@@ -30,7 +31,7 @@ export class DockerPackOperation {
30
31
  * Write Docker File
31
32
  */
32
33
  static async* writeDockerFile(cfg: DockerPackConfig): AsyncIterable<string[]> {
33
- const dockerFile = path.resolve(cfg.workspace, 'Dockerfile');
34
+ const dockerFile = path.resolve(cfg.buildDir, 'Dockerfile');
34
35
 
35
36
  const factory = RuntimeIndex.getFromImport(cfg.dockerFactory);
36
37
  if (!factory) {
@@ -76,11 +77,11 @@ export class DockerPackOperation {
76
77
  yield* PackOperation.title(cfg, cliTpl`${{ title: 'Building Docker Container' }} ${{ param: cfg.dockerTag?.join(',') }}`);
77
78
 
78
79
  if (cfg.ejectFile) {
79
- yield ActiveShellCommand.chdir(cfg.workspace);
80
+ yield ActiveShellCommand.chdir(cfg.buildDir);
80
81
  yield cmd;
81
- yield ActiveShellCommand.chdir(path.cwd());
82
+ yield ActiveShellCommand.chdir(path.resolve());
82
83
  } else {
83
- await PackUtil.runCommand(cmd, { cwd: cfg.workspace, stdio: [0, 'pipe', 2] });
84
+ await PackUtil.runCommand(cmd, { cwd: cfg.buildDir, stdio: [0, 'pipe', 2] });
84
85
  const [image] = JSON.parse(await PackUtil.runCommand(['docker', 'inspect', cfg.dockerImage]));
85
86
  yield [cliTpl`${{ title: 'Built Docker Container ' }} ${{ identifier: 'sizeMb' }}=${{ param: Math.trunc(image.Size / 2 ** 20) }}`];
86
87
  }
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
+ import path from 'node:path';
2
3
 
3
- import { path, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
4
+ import { RuntimeIndex, RuntimeContext } from '@travetto/manifest';
4
5
  import { cliTpl } from '@travetto/cli';
5
6
  import { Env } from '@travetto/base';
6
7
 
@@ -30,20 +31,20 @@ export class PackOperation {
30
31
  return;
31
32
  }
32
33
 
33
- yield* PackOperation.title(cfg, cliTpl`${{ title: 'Cleaning Output' }} ${{ path: cfg.workspace }}`);
34
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Cleaning Output' }} ${{ path: cfg.buildDir }}`);
34
35
 
35
36
  if (cfg.ejectFile) {
36
- yield ActiveShellCommand.rmRecursive(cfg.workspace);
37
+ yield ActiveShellCommand.rmRecursive(cfg.buildDir);
37
38
  if (cfg.output) {
38
39
  yield ActiveShellCommand.rmRecursive(cfg.output);
39
40
  }
40
- yield ActiveShellCommand.mkdir(cfg.workspace);
41
+ yield ActiveShellCommand.mkdir(cfg.buildDir);
41
42
  } else {
42
- await fs.rm(cfg.workspace, { recursive: true, force: true });
43
+ await fs.rm(cfg.buildDir, { recursive: true, force: true });
43
44
  if (cfg.output) {
44
45
  await fs.rm(cfg.output, { recursive: true, force: true });
45
46
  }
46
- await fs.mkdir(cfg.workspace, { recursive: true });
47
+ await fs.mkdir(cfg.buildDir, { recursive: true });
47
48
  }
48
49
  }
49
50
 
@@ -65,7 +66,7 @@ export class PackOperation {
65
66
  ['BUNDLE_COMPRESS', cfg.minify],
66
67
  ['BUNDLE_SOURCEMAP', cfg.sourcemap],
67
68
  ['BUNDLE_SOURCES', cfg.includeSources],
68
- ['BUNDLE_OUTPUT', cfg.workspace],
69
+ ['BUNDLE_OUTPUT', cfg.buildDir],
69
70
  ['BUNDLE_FORMAT', RuntimeContext.workspace.type],
70
71
  ['BUNDLE_ENV_FILE', cfg.envFile]
71
72
  ] as const)
@@ -86,10 +87,10 @@ export class PackOperation {
86
87
  );
87
88
  yield ActiveShellCommand.chdir(cwd);
88
89
  yield bundleCommand;
89
- yield ActiveShellCommand.chdir(path.cwd());
90
+ yield ActiveShellCommand.chdir(path.resolve());
90
91
  } else {
91
92
  await PackUtil.runCommand(bundleCommand, { cwd, env: { ...process.env, ...env } });
92
- const stat = await fs.stat(path.resolve(cfg.workspace, cfg.mainFile));
93
+ const stat = await fs.stat(path.resolve(cfg.buildDir, cfg.mainFile));
93
94
  yield [cliTpl`${{ title: 'Bundled Output ' }} ${{ identifier: 'sizeKb' }}=${{ param: Math.trunc(stat.size / 2 ** 10) }}`];
94
95
  }
95
96
  }
@@ -105,12 +106,12 @@ export class PackOperation {
105
106
 
106
107
  if (cfg.ejectFile) {
107
108
  yield* ActiveShellCommand.createFile(
108
- path.resolve(cfg.workspace, file),
109
+ path.resolve(cfg.buildDir, file),
109
110
  [JSON.stringify(pkg)]
110
111
  );
111
112
  } else {
112
113
  await PackUtil.writeRawFile(
113
- path.resolve(cfg.workspace, file),
114
+ path.resolve(cfg.buildDir, file),
114
115
  [JSON.stringify(pkg, null, 2)]
115
116
  );
116
117
  }
@@ -120,24 +121,30 @@ export class PackOperation {
120
121
  * Define .env.js file to control manifest location
121
122
  */
122
123
  static async * writeEnv(cfg: CommonPackConfig): AsyncIterable<string[]> {
123
- const file = path.resolve(cfg.workspace, cfg.envFile);
124
+ const file = path.resolve(cfg.buildDir, cfg.envFile);
124
125
  const env = {
125
126
  ...Env.NODE_ENV.export('production'),
126
127
  ...Env.TRV_MANIFEST.export(cfg.manifestFile),
127
128
  ...Env.TRV_MODULE.export(cfg.module),
128
- ...Env.TRV_CLI_IPC.export(undefined)
129
+ ...Env.TRV_CLI_IPC.export(undefined),
130
+ ...Env.TRV_RESOURCE_OVERRIDES.export({
131
+ '@#resources': '@@#resources',
132
+ ...(cfg.includeWorkspaceResources ? {
133
+ '@@#resources': `@@#${cfg.workspaceResourceFolder}`
134
+ } : {})
135
+ })
129
136
  };
130
137
 
131
138
  yield* PackOperation.title(cfg, cliTpl`${{ title: 'Writing' }} ${{ path: file }}`);
132
139
 
133
140
  if (cfg.ejectFile) {
134
141
  yield* ActiveShellCommand.createFile(
135
- path.resolve(cfg.workspace, file),
142
+ path.resolve(cfg.buildDir, file),
136
143
  PackUtil.buildEnvFile(env)
137
144
  );
138
145
  } else {
139
146
  await PackUtil.writeRawFile(
140
- path.resolve(cfg.workspace, file),
147
+ path.resolve(cfg.buildDir, file),
141
148
  PackUtil.buildEnvFile(env)
142
149
  );
143
150
  }
@@ -152,27 +159,21 @@ export class PackOperation {
152
159
  }
153
160
 
154
161
  const title = 'Writing entry scripts';
162
+ for (const sh of [ShellCommands.posix, ShellCommands.win32]) {
163
+ const { ext, contents } = sh.script(
155
164
 
156
- const files = ([['posix', 'sh'], ['win32', 'cmd']] as const)
157
- .map(([type, ext]) => ({
158
- fileTitle: cliTpl`${{ title }} ${{ path: `${cfg.mainName}.${ext}` }} args=(${{ param: cfg.entryArguments.join(' ') }})`,
159
- file: `${cfg.mainName}.${ext}`,
160
- text: [
161
- ShellCommands[type].scriptOpen(),
162
- ShellCommands[type].chdirScript(),
163
- ShellCommands[type].callCommandWithAllArgs('node', cfg.mainFile, ...cfg.entryArguments),
164
- ].map(x => x.join(' '))
165
- }));
165
+ sh.callCommandWithAllArgs('node', cfg.mainFile, ...cfg.entryArguments), true
166
+ );
167
+ const file = `${cfg.mainName}${ext}`;
168
+ const args = cfg.entryArguments.join(' ');
166
169
 
167
- if (cfg.ejectFile) {
168
- for (const { fileTitle, text, file } of files) {
169
- yield* PackOperation.title(cfg, fileTitle);
170
- yield* ActiveShellCommand.createFile(path.resolve(cfg.workspace, file), text, '755');
171
- }
172
- } else {
173
- for (const { fileTitle, text, file } of files) {
174
- yield* PackOperation.title(cfg, fileTitle);
175
- await PackUtil.writeRawFile(path.resolve(cfg.workspace, file), text, '755');
170
+ yield* PackOperation.title(cfg, cliTpl`${{ title }} ${{ path: file }} args=(${{ param: args }})`);
171
+
172
+ if (cfg.ejectFile) {
173
+ yield* ActiveShellCommand.createFile(path.resolve(cfg.buildDir, file), contents, '755');
174
+
175
+ } else {
176
+ await PackUtil.writeRawFile(path.resolve(cfg.buildDir, file), contents, '755');
176
177
  }
177
178
  }
178
179
  }
@@ -187,13 +188,12 @@ export class PackOperation {
187
188
 
188
189
  yield* PackOperation.title(cfg, cliTpl`${{ title: 'Copying over workspace resources' }}`);
189
190
 
190
- const dest = path.resolve(cfg.workspace, 'workspace-resources');
191
+ const dest = path.resolve(cfg.buildDir, cfg.workspaceResourceFolder);
191
192
  const src = RuntimeContext.workspaceRelative('resources');
192
193
 
193
194
  if (cfg.ejectFile) {
194
195
  yield ActiveShellCommand.copyRecursive(src, dest, true);
195
196
  } else {
196
- await fs.mkdir(dest, { recursive: true });
197
197
  await PackUtil.copyRecursive(src, dest, true);
198
198
  }
199
199
  }
@@ -205,19 +205,18 @@ export class PackOperation {
205
205
  const resources = {
206
206
  count: RuntimeIndex.mainModule.files.resources?.length ?? 0,
207
207
  src: path.resolve(RuntimeIndex.mainModule.sourcePath, 'resources'),
208
- dest: path.resolve(cfg.workspace, 'resources')
208
+ dest: path.resolve(cfg.buildDir, 'resources')
209
209
  };
210
210
 
211
211
  yield* PackOperation.title(cfg, cliTpl`${{ title: 'Copying over module resources' }}`);
212
212
 
213
213
  if (cfg.ejectFile) {
214
214
  if (resources.count) {
215
- yield ActiveShellCommand.copyRecursive(resources.src, path.resolve(cfg.workspace, 'resources'));
215
+ yield ActiveShellCommand.copyRecursive(resources.src, path.resolve(cfg.buildDir, 'resources'), true);
216
216
  }
217
217
  } else {
218
218
  if (resources.count) {
219
- await fs.mkdir(path.dirname(resources.dest), { recursive: true });
220
- await PackUtil.copyRecursive(resources.src, resources.dest);
219
+ await PackUtil.copyRecursive(resources.src, resources.dest, true);
221
220
  }
222
221
  }
223
222
  }
@@ -226,7 +225,7 @@ export class PackOperation {
226
225
  * Produce the output manifest, only including prod dependencies
227
226
  */
228
227
  static async * writeManifest(cfg: CommonPackConfig): AsyncIterable<string[]> {
229
- const out = path.resolve(cfg.workspace, cfg.manifestFile);
228
+ const out = path.resolve(cfg.buildDir, cfg.manifestFile);
230
229
  const cmd = ['npx', 'trvc', 'manifest', '--prod', out];
231
230
  const env = { ...Env.TRV_MODULE.export(cfg.module) };
232
231
 
@@ -247,13 +246,13 @@ export class PackOperation {
247
246
  yield* PackOperation.title(cfg, cliTpl`${{ title: 'Compressing' }} ${{ path: cfg.output }}`);
248
247
 
249
248
  if (cfg.ejectFile) {
250
- yield ActiveShellCommand.chdir(cfg.workspace);
251
249
  await ActiveShellCommand.mkdir(path.dirname(cfg.output));
250
+ yield ActiveShellCommand.chdir(cfg.buildDir);
252
251
  yield ActiveShellCommand.zip(cfg.output);
253
- yield ActiveShellCommand.chdir(path.cwd());
252
+ yield ActiveShellCommand.chdir(path.resolve());
254
253
  } else {
255
254
  await fs.mkdir(path.dirname(cfg.output), { recursive: true });
256
- await PackUtil.runCommand(ActiveShellCommand.zip(cfg.output), { cwd: cfg.workspace });
255
+ await PackUtil.runCommand(ActiveShellCommand.zip(cfg.output), { cwd: cfg.buildDir });
257
256
  }
258
257
  }
259
258
  }
@@ -1,6 +1,5 @@
1
1
  import util from 'node:util';
2
-
3
- import { path } from '@travetto/manifest';
2
+ import path from 'node:path';
4
3
 
5
4
  import { ShellCommandImpl } from '../../src/types';
6
5
 
@@ -13,12 +12,12 @@ const escapedArgs = (args: string[]): string[] => args.map(x =>
13
12
  x.includes(' ') || x.includes('"') ? `'${x}'` : (x.includes("'") ? `"${x}"` : x)
14
13
  );
15
14
 
15
+ const toWin = (file: string): string => file.replace(/[\\\/]+/g, path.win32.sep);
16
+
16
17
  export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
17
18
  win32: {
18
19
  var: (name: string) => `%${name}%`,
19
- scriptOpen: () => [],
20
- chdirScript: () => ['cd', '%~p0'],
21
- callCommandWithAllArgs: (cmd, ...args) => [cmd, ...escapedArgs(args), '%*'],
20
+ callCommandWithAllArgs: (cmd, ...args) => [[cmd, ...escapedArgs(args), '%*'].join(' ')],
22
21
  createFile: (file, text) => [
23
22
  ['@echo', 'off'],
24
23
  ...text.map((line, i) =>
@@ -27,20 +26,25 @@ export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
27
26
  ],
28
27
  copy: (src, dest) => ['copy', src, dest],
29
28
  copyRecursive: (src, dest, inclusive) =>
30
- ['xcopy', '/y', '/h', '/s', inclusive ? `${path.toNative(src)}\\*.*` : path.toNative(src), path.toNative(dest)],
29
+ ['xcopy', '/y', '/h', '/s', inclusive ? `${toWin(src)}\\*.*` : toWin(src), toWin(dest)],
31
30
  rmRecursive: (dest) => ['rmdir', '/Q', '/S', dest],
32
31
  mkdir: (dest) => ['md', dest],
33
32
  export: (key, value) => ['set', `${key}=${value}`],
34
33
  chdir: (dest) => ['cd', dest],
35
34
  comment: (message) => ['\nREM', util.stripVTControlCharacters(message), '\n'],
36
35
  echo: (message) => ['echo', `"${escape(util.stripVTControlCharacters(message))}"\n`],
37
- zip: (outputFile) => ['powershell', 'Compress-Archive', '-Path', '.', '-DestinationPath', outputFile]
36
+ zip: (outputFile) => ['powershell', 'Compress-Archive', '-Path', '.', '-DestinationPath', outputFile],
37
+ script: (lines: string[], changeDir: boolean = false) => ({
38
+ ext: '.cmd',
39
+ contents: [
40
+ ...(changeDir ? ['cd %~p0'] : []),
41
+ ...lines,
42
+ ]
43
+ })
38
44
  },
39
45
  posix: {
40
46
  var: (name: string) => `$${name}`,
41
- scriptOpen: () => ['#!/bin/sh'],
42
- chdirScript: () => ['cd', '$(dirname "$0")'],
43
- callCommandWithAllArgs: (cmd, ...args) => [cmd, ...escapedArgs(args), '$@'],
47
+ callCommandWithAllArgs: (cmd, ...args) => [[cmd, ...escapedArgs(args), '$@'].join(' ')],
44
48
  createFile: (file, text, mode) => [
45
49
  ...text.map((line, i) =>
46
50
  ['echo', `"${escape(line)}"`, i === 0 ? '>' : '>>', file]),
@@ -55,7 +59,15 @@ export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
55
59
  chdir: (dest) => ['cd', dest],
56
60
  comment: (message) => ['\n#', util.stripVTControlCharacters(message), '\n'],
57
61
  echo: (message) => ['echo', `"${escape(util.stripVTControlCharacters(message))}"\n`],
58
- zip: (outputFile) => ['zip', '-r', outputFile, '.']
62
+ zip: (outputFile) => ['zip', '-r', outputFile, '.'],
63
+ script: (lines: string[], changeDir: boolean = false) => ({
64
+ ext: '.sh',
65
+ contents: [
66
+ '#!/bin/sh',
67
+ ...(changeDir ? ['cd $(dirname "$0")'] : []),
68
+ ...lines,
69
+ ]
70
+ })
59
71
  },
60
72
  };
61
73
 
@@ -1,7 +1,8 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import { spawn, SpawnOptions } from 'node:child_process';
3
+ import path from 'node:path';
3
4
 
4
- import { path, RuntimeIndex } from '@travetto/manifest';
5
+ import { RuntimeIndex } from '@travetto/manifest';
5
6
  import { AppError, ExecUtil } from '@travetto/base';
6
7
 
7
8
  import { ActiveShellCommand } from './shell';
@@ -20,13 +21,19 @@ export class PackUtil {
20
21
  * Remove directory, determine if errors should be ignored
21
22
  * @param src The folder to copy
22
23
  * @param dest The folder to copy to
23
- * @param ignore Should errors be ignored
24
24
  */
25
- static async copyRecursive(src: string, dest: string, inclusive: boolean = false, ignore = false): Promise<void> {
26
- const [cmd, ...args] = ActiveShellCommand.copyRecursive(src, dest, inclusive);
27
- const res = await ExecUtil.getResult(spawn(cmd, args, { shell: true }), { catch: true });
28
- if (res.code && !ignore) {
29
- throw new Error(`Failed to copy ${src} to ${dest}`);
25
+ static async copyRecursive(src: string, dest: string, inclusive: boolean = false, ignoreFailure = false): Promise<void> {
26
+ try {
27
+ let final = dest;
28
+ if (!inclusive) {
29
+ final = path.resolve(dest, path.basename(src));
30
+ }
31
+ await fs.mkdir(final, { recursive: true });
32
+ await fs.cp(src, final, { recursive: true });
33
+ } catch (err) {
34
+ if (!ignoreFailure) {
35
+ throw new Error(`Failed to copy ${src} to ${dest}`);
36
+ }
30
37
  }
31
38
  }
32
39
 
@@ -34,15 +41,14 @@ export class PackUtil {
34
41
  * Finalize eject output
35
42
  */
36
43
  static async writeEjectOutput(workspace: string, module: string, output: AsyncIterable<string>, file: string): Promise<void> {
37
- const vars = { DIST: workspace, TRV_OUT: RuntimeIndex.outputRoot, ROOT: path.cwd(), MOD: module };
44
+ const vars = { DIST: workspace, TRV_OUT: RuntimeIndex.outputRoot, ROOT: path.resolve(), MOD: module };
38
45
 
39
46
  const replaceArgs = (text: string): string => Object.entries(vars)
40
47
  .reduce((str, [k, v]) => str.replaceAll(v, ActiveShellCommand.var(k)), text);
41
48
 
42
- const preamble = [
43
- ActiveShellCommand.scriptOpen(),
44
- ...Object.entries(vars).map(([k, v]) => ActiveShellCommand.export(k, v).join(' ')),
45
- ].join('\n');
49
+ const preamble = ActiveShellCommand.script(
50
+ Object.entries(vars).map(([k, v]) => ActiveShellCommand.export(k, v).join(' ')),
51
+ ).contents;
46
52
 
47
53
  let stream: fs.FileHandle | undefined;
48
54
 
@@ -54,7 +60,9 @@ export class PackUtil {
54
60
 
55
61
  const write = (text: string): Promise<unknown> | unknown => stream ? stream.write(`${text}\n`) : process.stdout.write(`${text}\n`);
56
62
 
57
- await write(preamble);
63
+ for (const line of preamble) {
64
+ write(line);
65
+ }
58
66
  for await (const line of output) {
59
67
  await write(replaceArgs(line));
60
68
  }
@@ -1,4 +1,6 @@
1
- import { path, RuntimeIndex } from '@travetto/manifest';
1
+ import path from 'node:path';
2
+
3
+ import { RuntimeIndex } from '@travetto/manifest';
2
4
  import { CliCommand, CliFlag, CliUtil, CliValidationError } from '@travetto/cli';
3
5
  import { Ignore, Required } from '@travetto/schema';
4
6
 
@@ -6,9 +8,7 @@ import { DockerPackOperation } from './bin/docker-operation';
6
8
  import { BasePackCommand, PackOperationShape } from './pack.base';
7
9
  import { DockerPackConfig } from '../src/types';
8
10
 
9
- const NODE_MAJOR = +process.version.match(/\d+/)![0];
10
- const DEFAULT_USER_ID = 2000;
11
- const DEFAULT_USER = 'app';
11
+ const NODE_MAJOR = process.version.match(/\d+/)?.[0] ?? '22';
12
12
 
13
13
  /**
14
14
  * Standard docker support for pack
@@ -40,6 +40,15 @@ export class PackDockerCommand extends BasePackCommand {
40
40
  @Ignore()
41
41
  dockerRuntime: DockerPackConfig['dockerRuntime'];
42
42
 
43
+ @Ignore()
44
+ appFolder = 'app';
45
+
46
+ @Ignore()
47
+ defaultUser = this.appFolder;
48
+
49
+ @Ignore()
50
+ defaultUserId = 2000;
51
+
43
52
  async validate(...args: string[]): Promise<CliValidationError[] | undefined> {
44
53
  const errs: CliValidationError[] = [];
45
54
  if (this.dockerPort?.length) {
@@ -65,11 +74,11 @@ export class PackDockerCommand extends BasePackCommand {
65
74
  const groupIsNum = /^\d+$/.test(groupOrGid);
66
75
  const userIsNum = /^\d+$/.test(userOrUid);
67
76
 
68
- const uid = userIsNum ? +userOrUid : DEFAULT_USER_ID;
69
- const gid = groupIsNum ? +groupOrGid : DEFAULT_USER_ID;
70
- const group = (!groupIsNum ? groupOrGid : undefined) || DEFAULT_USER;
71
- const user = (!userIsNum ? userOrUid : undefined) || DEFAULT_USER;
72
- this.dockerRuntime = { user, uid, group, gid, folder: `/${DEFAULT_USER}`, packages: this.dockerRuntimePackages };
77
+ const uid = userIsNum ? +userOrUid : this.defaultUserId;
78
+ const gid = groupIsNum ? +groupOrGid : this.defaultUserId;
79
+ const group = (!groupIsNum ? groupOrGid : undefined) || this.defaultUser;
80
+ const user = (!userIsNum ? userOrUid : undefined) || this.defaultUser;
81
+ this.dockerRuntime = { user, uid, group, gid, folder: `/${this.appFolder}`, packages: this.dockerRuntimePackages };
73
82
  }
74
83
 
75
84
  preHelp(): void {
@@ -1,7 +1,8 @@
1
1
  import os from 'node:os';
2
+ import path from 'node:path';
2
3
 
3
4
  import { CliCommandShape, CliFlag, ParsedState, cliTpl } from '@travetto/cli';
4
- import { path, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
5
+ import { RuntimeIndex, RuntimeContext } from '@travetto/manifest';
5
6
  import { TimeUtil } from '@travetto/base';
6
7
  import { Terminal } from '@travetto/terminal';
7
8
  import { Ignore, Required, Schema } from '@travetto/schema';
@@ -26,8 +27,8 @@ export abstract class BasePackCommand implements CliCommandShape {
26
27
  @Ignore()
27
28
  _parsed: ParsedState;
28
29
 
29
- @CliFlag({ desc: 'Workspace for building', short: 'w' })
30
- workspace: string = path.resolve(os.tmpdir(), RuntimeIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
30
+ @CliFlag({ desc: 'Workspace for building', short: 'b' })
31
+ buildDir: string = path.resolve(os.tmpdir(), RuntimeIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
31
32
 
32
33
  @CliFlag({ desc: 'Clean workspace' })
33
34
  clean = true;
@@ -81,6 +82,9 @@ export abstract class BasePackCommand implements CliCommandShape {
81
82
  @Ignore()
82
83
  entryArguments: string[] = [];
83
84
 
85
+ @Ignore()
86
+ workspaceResourceFolder: string = 'resources-workspace';
87
+
84
88
  getOperations(): PackOperationShape<this>[] {
85
89
  return [
86
90
  PackOperation.clean,
@@ -109,7 +113,7 @@ export abstract class BasePackCommand implements CliCommandShape {
109
113
  // Resolve all files to absolute paths
110
114
  this.output = this.output ? path.resolve(this.output) : undefined!;
111
115
  this.ejectFile = this.ejectFile ? path.resolve(this.ejectFile) : undefined;
112
- this.workspace = path.resolve(this.workspace);
116
+ this.buildDir = path.resolve(this.buildDir);
113
117
 
114
118
  // Update entry points
115
119
  this.entryArguments = [...this.entryArguments ?? [], ...args, ...this._parsed.unknown];
@@ -121,14 +125,14 @@ export abstract class BasePackCommand implements CliCommandShape {
121
125
 
122
126
  // Eject to file
123
127
  if (this.ejectFile) {
124
- await PackUtil.writeEjectOutput(this.workspace, this.module, stream, this.ejectFile);
128
+ await PackUtil.writeEjectOutput(this.buildDir, this.module, stream, this.ejectFile);
125
129
  } else {
126
130
  const start = Date.now();
127
131
  const term = new Terminal();
128
132
 
129
133
  await term.streamLines(stream);
130
134
 
131
- let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.module }}`;
135
+ let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.asClock(Date.now() - start) }}) ${{ subtitle: 'module' }}=${{ param: this.module }}`;
132
136
  if (this.output) {
133
137
  msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.output }}`;
134
138
  }
@@ -1,8 +1,9 @@
1
- import type { OutputOptions } from 'rollup';
1
+ import path from 'node:path';
2
2
 
3
+ import type { OutputOptions } from 'rollup';
3
4
  import type terser from '@rollup/plugin-terser';
4
5
 
5
- import { ManifestModule, ManifestModuleUtil, NodeModuleType, path, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
6
+ import { ManifestModule, ManifestModuleUtil, NodeModuleType, RuntimeIndex, RuntimeContext } from '@travetto/manifest';
6
7
  import { EnvProp } from '@travetto/base';
7
8
  import { CoreRollupConfig } from '../../src/types';
8
9