@travetto/pack 3.0.3 → 3.1.0-rc.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/README.md CHANGED
@@ -26,20 +26,21 @@ There are three primary cli commands for packing your code:
26
26
  ```bash
27
27
  $ trv pack --help
28
28
 
29
- Usage: pack [options] [args...]
29
+ Usage: pack [options]
30
30
 
31
31
  Options:
32
- -w, --workspace <workspace> Workspace for building
33
- -c, --no-clean Disables: Clean workspace
34
- -o, --output <output> Output location
35
- -es, --main-scripts <main-scripts> Create entry scripts
36
- -f, --main-name <main-name> Main name for build artifact
37
- -e, --entry-point <entry-point> Entry point (default: "@travetto/cli/support/entry.cli")
38
- -m, --no-minify Disables: Minify output
39
- -sm, --sourcemap Bundle source maps
40
- -is, --include-sources Include source with source maps
41
- -x, --eject-file <eject-file> Eject commands to file
42
- -h, --help display help for command
32
+ -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
33
+ --clean, --no-clean Clean workspace (default: true)
34
+ -o, --output <string> Output location
35
+ --main-scripts, --no-main-scripts Create entry scripts (default: true)
36
+ -f, --main-name <string> Main name for build artifact
37
+ -e, --entry-point <string> Entry point (default: "@travetto/cli/support/entry.cli")
38
+ --minify, --no-minify Minify output (default: true)
39
+ -sm, --sourcemap Bundle source maps (default: false)
40
+ -is, --include-sources Include source with source maps (default: false)
41
+ -x, --eject-file <string> Eject commands to file
42
+ -m, --module <string> Module to run for
43
+ -h, --help display help for command
43
44
  ```
44
45
 
45
46
  This command line operation will compile your project, and produce a ready to use workspace as a deliverable. Additionally, you can pass in a file to the `eject-file` flag that will allow for a script to be produced (base on the host operating system).
@@ -86,20 +87,21 @@ This command is nearly identical to the standard `pack` operation, except for th
86
87
  ```bash
87
88
  $ trv pack:zip --help
88
89
 
89
- Usage: pack:zip [options] [args...]
90
+ Usage: pack:zip [options]
90
91
 
91
92
  Options:
92
- -w, --workspace <workspace> Workspace for building
93
- -c, --no-clean Disables: Clean workspace
94
- -o, --output <output> Output location (default: "travetto_pack.zip")
95
- -es, --main-scripts <main-scripts> Create entry scripts
96
- -f, --main-name <main-name> Main name for build artifact
97
- -e, --entry-point <entry-point> Entry point (default: "@travetto/cli/support/entry.cli")
98
- -m, --no-minify Disables: Minify output
99
- -sm, --sourcemap Bundle source maps
100
- -is, --include-sources Include source with source maps
101
- -x, --eject-file <eject-file> Eject commands to file
102
- -h, --help display help for command
93
+ -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
94
+ --clean, --no-clean Clean workspace (default: true)
95
+ -o, --output <string> Output location (default: "travetto_pack.zip")
96
+ --main-scripts, --no-main-scripts Create entry scripts (default: true)
97
+ -f, --main-name <string> Main name for build artifact
98
+ -e, --entry-point <string> Entry point (default: "@travetto/cli/support/entry.cli")
99
+ --minify, --no-minify Minify output (default: true)
100
+ -sm, --sourcemap Bundle source maps (default: false)
101
+ -is, --include-sources Include source with source maps (default: false)
102
+ -x, --eject-file <string> Eject commands to file
103
+ -m, --module <string> Module to run for
104
+ -h, --help display help for command
103
105
  ```
104
106
 
105
107
  ## CLI - pack:docker
@@ -109,27 +111,28 @@ This command starts off identical to the standard `pack` operation, but it conta
109
111
  ```bash
110
112
  $ trv pack:docker --help
111
113
 
112
- Usage: pack:docker [options] [args...]
114
+ Usage: pack:docker [options]
113
115
 
114
116
  Options:
115
- -w, --workspace <workspace> Workspace for building
116
- -c, --no-clean Disables: Clean workspace
117
- -o, --output <output> Output location
118
- -es, --main-scripts <main-scripts> Create entry scripts
119
- -f, --main-name <main-name> Main name for build artifact
120
- -e, --entry-point <entry-point> Entry point (default: "@travetto/cli/support/entry.cli")
121
- -m, --no-minify Disables: Minify output
122
- -sm, --sourcemap Bundle source maps
123
- -is, --include-sources Include source with source maps
124
- -x, --eject-file <eject-file> Eject commands to file
125
- -df, --docker-factory <docker-factory> Docker Factory source (default: "@travetto/pack/support/pack.dockerfile")
126
- -di, --docker-image <docker-image> Docker Image to extend (default: "node:18-alpine3.16")
127
- -dn, --docker-name <docker-name> Docker Image Name (default: "travetto_pack")
128
- -dt, --docker-tag <docker-tag> Docker Image Tag (default: ["latest"])
129
- -dp, --docker-port <docker-port> Docker Image Port (default: [])
130
- -dx, --docker-push Docker Push Tags
131
- -dr, --docker-registry <docker-registry> Docker Registry
132
- -h, --help display help for command
117
+ -w, --workspace <string> Workspace for building (default: "/tmp/<temp-folder>")
118
+ --clean, --no-clean Clean workspace (default: true)
119
+ -o, --output <string> Output location
120
+ --main-scripts, --no-main-scripts Create entry scripts (default: true)
121
+ -f, --main-name <string> Main name for build artifact
122
+ -e, --entry-point <string> Entry point (default: "@travetto/cli/support/entry.cli")
123
+ --minify, --no-minify Minify output (default: true)
124
+ -sm, --sourcemap Bundle source maps (default: false)
125
+ -is, --include-sources Include source with source maps (default: false)
126
+ -x, --eject-file <string> Eject commands to file
127
+ -df, --docker-factory <string> Docker Factory source (default: "@travetto/pack/support/pack.dockerfile")
128
+ -di, --docker-image <string> Docker Image to extend (default: "node:18-alpine3.16")
129
+ -dn, --docker-name <string> Docker Image Name (default: "travetto_pack")
130
+ -dt, --docker-tag <string> Docker Image Tag (default: ["latest"])
131
+ -dp, --docker-port <number> Docker Image Port (default: [])
132
+ -dx, --docker-push Docker Push Tags (default: false)
133
+ -dr, --docker-registry <string> Docker Registry
134
+ -m, --module <string> Module to run for
135
+ -h, --help display help for command
133
136
  ```
134
137
 
135
138
  The additional flags provided are allow for specifying the base image, the final docker image name (and tags), and which registry to push to (if any). Additionally, there are flags for exposing which ports the image should expect to open as well. When using the `--eject-file` flag, the output script will produce the entire Dockerfile output inline, so that it can be easily modified as needed.
@@ -145,82 +148,78 @@ As indicated, any of the pack operations can be ejected, and produce an output t
145
148
 
146
149
  **Terminal: Sample Ejected File**
147
150
  ```bash
148
- $ trv pack:docker -x /dev/stdout run rest
151
+ $ trv pack:docker -x /dev/stdout run:rest
149
152
 
150
153
  #!/bin/sh
151
- export DIST=/tmp/_home_tim_Code_travetto_related_todo-app
154
+ export DIST=/tmp/<temp-folder>
152
155
  export TRV_OUT=<workspace-root>/.trv_output
153
156
  export ROOT=<workspace-root>/related/todo-app
154
157
  export MOD=@travetto/todo-app
155
158
 
156
159
  # Cleaning Output $DIST
157
160
 
158
- echo "Cleaning Output $DIST
159
- "
161
+ echo "Cleaning Output $DIST"
162
+
160
163
  rm -rf $DIST
161
164
  mkdir -p $DIST
162
165
 
163
166
  # Writing .env.js
164
167
 
165
- echo "Writing .env.js
166
- "
168
+ echo "Writing .env.js"
169
+
167
170
  echo "process.env.TRV_MANIFEST = 'node_modules/$MOD';" > $DIST/.env.js
171
+ echo "process.env.TRV_MODULE = '$MOD';" >> $DIST/.env.js
168
172
  echo "process.env.TRV_CLI_IPC = '';" >> $DIST/.env.js
169
173
 
170
174
  # Writing package.json
171
175
 
172
- echo "Writing package.json
173
- "
176
+ echo "Writing package.json"
177
+
174
178
  echo "{\"type\":\"commonjs\"}" > $DIST/package.json
175
179
 
176
- # Writing entry scripts entry.cli.sh args=(run rest)
180
+ # Writing entry scripts todo-app.sh args=(run:rest)
181
+
182
+ echo "Writing entry scripts todo-app.sh args=(run:rest)"
177
183
 
178
- echo "Writing entry scripts entry.cli.sh args=(run rest)
179
- "
180
- echo "#!/bin/sh" > $DIST/entry.cli.sh
181
- echo "cd \$(dirname \"\$0\")" >> $DIST/entry.cli.sh
182
- echo "node entry.cli.js run rest \$@" >> $DIST/entry.cli.sh
183
- chmod 755 $DIST/entry.cli.sh
184
+ echo "#!/bin/sh" > $DIST/todo-app.sh
185
+ echo "cd \$(dirname \"\$0\")" >> $DIST/todo-app.sh
186
+ echo "node todo-app.js run:rest \$@" >> $DIST/todo-app.sh
187
+ chmod 755 $DIST/todo-app.sh
184
188
 
185
- # Writing entry scripts entry.cli.cmd args=(run rest)
189
+ # Writing entry scripts todo-app.cmd args=(run:rest)
186
190
 
187
- echo "Writing entry scripts entry.cli.cmd args=(run rest)
188
- "
189
- echo "" > $DIST/entry.cli.cmd
190
- echo "cd %~p0" >> $DIST/entry.cli.cmd
191
- echo "node entry.cli.js run rest %*" >> $DIST/entry.cli.cmd
192
- chmod 755 $DIST/entry.cli.cmd
191
+ echo "Writing entry scripts todo-app.cmd args=(run:rest)"
192
+
193
+ echo "" > $DIST/todo-app.cmd
194
+ echo "cd %~p0" >> $DIST/todo-app.cmd
195
+ echo "node todo-app.js run:rest %*" >> $DIST/todo-app.cmd
196
+ chmod 755 $DIST/todo-app.cmd
193
197
 
194
198
  # Copying over resources
195
199
 
196
- echo "Copying over resources
197
- "
200
+ echo "Copying over resources"
201
+
198
202
  mkdir -p $DIST/node_modules/$MOD
199
203
  cp $TRV_OUT/node_modules/$MOD/package.json $DIST/node_modules/$MOD/package.json
200
204
  mkdir -p $DIST/node_modules/@travetto/manifest
201
205
  cp $TRV_OUT/node_modules/@travetto/manifest/package.json $DIST/node_modules/@travetto/manifest/package.json
202
206
  cp -r -p $ROOT/resources $DIST/resources
203
207
 
204
- # Generating App Cache node_modules/$MOD/trv-app-cache.json
205
-
206
- echo "Generating App Cache node_modules/$MOD/trv-app-cache.json
207
- "
208
- mkdir -p $DIST/node_modules/$MOD
209
- DEBUG=0 TRV_MODULE=$MOD npx trv main @travetto/app/support/bin/list > $DIST/node_modules/$MOD/trv-app-cache.json
210
-
211
208
  # Writing Manifest node_modules/$MOD
212
209
 
213
- echo "Writing Manifest node_modules/$MOD
214
- "
210
+ echo "Writing Manifest node_modules/$MOD"
211
+
215
212
  TRV_MODULE=$MOD npx trv manifest $DIST/node_modules/$MOD prod
216
213
 
217
- # Bundling Output minify=true sourcemap= entryPoint=@travetto/cli/support/entry.cli
214
+ # Bundling Output minify=true sourcemap=false entryPoint=@travetto/cli/support/entry.cli
215
+
216
+ echo "Bundling Output minify=true sourcemap=false entryPoint=@travetto/cli/support/entry.cli"
218
217
 
219
- echo "Bundling Output minify=true sourcemap= entryPoint=@travetto/cli/support/entry.cli
220
- "
221
218
  export BUNDLE_ENTRY=node_modules/@travetto/cli/support/entry.cli.js
222
- export BUNDLE_MAIN_FILE=entry.cli.js
219
+ export BUNDLE_MAIN_FILE=todo-app.js
223
220
  export BUNDLE_COMPRESS=true
221
+ export BUNDLE_SOURCEMAP=false
222
+ export BUNDLE_SOURCES=false
224
223
  export BUNDLE_OUTPUT=$DIST
225
224
  export BUNDLE_FORMAT=commonjs
226
225
  export TRV_MANIFEST=$TRV_OUT/node_modules/$MOD
@@ -230,24 +229,24 @@ cd $ROOT
230
229
 
231
230
  # Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile
232
231
 
233
- echo "Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile
234
- "
232
+ echo "Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile"
233
+
235
234
  echo "FROM node:18-alpine3.16" > $DIST/Dockerfile
236
235
  echo "WORKDIR /app" >> $DIST/Dockerfile
237
236
  echo "COPY . ." >> $DIST/Dockerfile
238
237
  echo "" >> $DIST/Dockerfile
239
- echo "ENTRYPOINT [\"/app/entry.cli.sh\"]" >> $DIST/Dockerfile
238
+ echo "ENTRYPOINT [\"/app/todo-app.sh\"]" >> $DIST/Dockerfile
240
239
 
241
240
  # Pulling Docker Base Image node:18-alpine3.16
242
241
 
243
- echo "Pulling Docker Base Image node:18-alpine3.16
244
- "
242
+ echo "Pulling Docker Base Image node:18-alpine3.16"
243
+
245
244
  docker pull node:18-alpine3.16
246
245
 
247
246
  # Building Docker Container latest
248
247
 
249
- echo "Building Docker Container latest
250
- "
248
+ echo "Building Docker Container latest"
249
+
251
250
  cd $DIST
252
251
  docker build -t travetto_todo-app:latest .
253
252
  cd $ROOT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/pack",
3
- "version": "3.0.3",
3
+ "version": "3.1.0-rc.1",
4
4
  "description": "Code packing utilities",
5
5
  "keywords": [
6
6
  "travetto",
@@ -28,12 +28,12 @@
28
28
  "@rollup/plugin-json": "^6.0.0",
29
29
  "@rollup/plugin-node-resolve": "^15.0.1",
30
30
  "@rollup/plugin-terser": "^0.4.0",
31
- "@travetto/base": "^3.0.3",
31
+ "@travetto/base": "^3.1.0-rc.0",
32
32
  "rollup": "^3.17.2",
33
33
  "rollup-plugin-sourcemaps": "^0.6.3"
34
34
  },
35
35
  "peerDependencies": {
36
- "@travetto/cli": "^3.0.3"
36
+ "@travetto/cli": "^3.1.0-rc.1"
37
37
  },
38
38
  "peerDependenciesMeta": {
39
39
  "@travetto/cli": {
@@ -12,6 +12,9 @@ async function writeRawFile(file: string, contents: string, mode?: string): Prom
12
12
  await fs.writeFile(file, contents, { encoding: 'utf8', mode });
13
13
  }
14
14
 
15
+ /**
16
+ * General pack operations
17
+ */
15
18
  export class PackOperation {
16
19
 
17
20
  static async * title(cfg: CommonPackConfig, title: string): AsyncIterable<string[]> {
@@ -118,6 +121,7 @@ export class PackOperation {
118
121
  const file = '.env.js';
119
122
  const env = {
120
123
  TRV_MANIFEST: `node_modules/${cfg.module}`,
124
+ TRV_MODULE: cfg.module,
121
125
  TRV_CLI_IPC: ''
122
126
  };
123
127
 
@@ -212,33 +216,6 @@ export class PackOperation {
212
216
  }
213
217
  }
214
218
 
215
- /**
216
- * Generate the trv-app-cache.json for @travetto/app, which is needed for 'running' programs
217
- */
218
- static async * primeAppCache(cfg: CommonPackConfig): AsyncIterable<string[]> {
219
- const isRun = /entry[.]cli/.test(cfg.entryPoint) && cfg.entryArguments.filter(x => !x.startsWith('-'))[0] === 'run';
220
- if (!isRun) {
221
- return;
222
- }
223
-
224
- const appCacheCmd = ['npx', 'trv', 'main', '@travetto/app/support/bin/list'];
225
- const sub = path.join(RootIndex.manifest.modules[RootIndex.mainModule.name].outputFolder, 'trv-app-cache.json');
226
- const env = { DEBUG: '0', TRV_MODULE: cfg.module };
227
- const appCache = path.resolve(cfg.workspace, sub);
228
-
229
- yield* PackOperation.title(cfg, cliTpl`${{ title: 'Generating App Cache' }} ${{ path: sub }}`);
230
-
231
- if (cfg.ejectFile) {
232
- yield ActiveShellCommand.mkdir(path.dirname(appCache));
233
- yield [...Object.entries(env).map(x => `${x[0]}=${x[1]}`), ...appCacheCmd, '>', appCache];
234
- } else {
235
- const { stdout } = await ExecUtil.spawn(appCacheCmd[0], appCacheCmd.slice(1), { env }).result;
236
-
237
- await fs.mkdir(path.dirname(appCache), { recursive: true });
238
- await fs.writeFile(appCache, stdout, 'utf8');
239
- }
240
- }
241
-
242
219
  /**
243
220
  * Produce the output manifest, only including prod dependencies
244
221
  */
@@ -27,7 +27,7 @@ export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
27
27
  export: (key, value) => ['set', `${key}=${value}`],
28
28
  chdir: (dest) => ['cd', dest],
29
29
  comment: (message) => ['\nREM', stripAnsiCodes(message), '\n'],
30
- echo: (message) => ['echo', `"${escape(stripAnsiCodes(message))}\n"`],
30
+ echo: (message) => ['echo', `"${escape(stripAnsiCodes(message))}"\n`],
31
31
  zip: (outputFile) => ['powershell', 'Compress-Archive', '-Path', '.', '-DestinationPath', outputFile]
32
32
  },
33
33
  posix: {
@@ -47,7 +47,7 @@ export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
47
47
  export: (key, value) => ['export', `${key}=${value}`],
48
48
  chdir: (dest) => ['cd', dest],
49
49
  comment: (message) => ['\n#', stripAnsiCodes(message), '\n'],
50
- echo: (message) => ['echo', `"${escape(stripAnsiCodes(message))}\n"`],
50
+ echo: (message) => ['echo', `"${escape(stripAnsiCodes(message))}"\n`],
51
51
  zip: (outputFile) => ['zip', '-r', outputFile, '.']
52
52
  },
53
53
  };
@@ -1,12 +1,10 @@
1
- import { ListOptionConfig, OptionConfig } from '@travetto/cli';
2
-
3
1
  export type CommonPackConfig = {
4
2
  workspace: string;
5
3
  output: string;
6
4
  clean: boolean;
7
- ejectFile: string;
5
+ ejectFile?: string;
8
6
  mainName: string;
9
- mainScripts: boolean;
7
+ mainScripts?: boolean;
10
8
  module: string;
11
9
 
12
10
  // Bundle
@@ -17,40 +15,17 @@ export type CommonPackConfig = {
17
15
  includeSources: boolean;
18
16
  };
19
17
 
20
- export type CommonPackOptions = {
21
- workspace: OptionConfig<string>;
22
- output: OptionConfig<string>;
23
- clean: OptionConfig<boolean>;
24
- ejectFile: OptionConfig<string>;
25
- mainName: OptionConfig<string>;
26
- mainScripts: OptionConfig<boolean>;
27
-
28
- // Bundle
29
- entryPoint: OptionConfig<string>;
30
- minify: OptionConfig<boolean>;
31
- sourcemap: OptionConfig<boolean>;
32
- includeSources: OptionConfig<boolean>;
33
- };
34
18
 
35
19
  export type DockerPackConfig = {
36
20
  dockerFactory: string;
37
21
  dockerImage: string;
38
22
  dockerName: string;
39
- dockerTag: string[];
40
- dockerPort: string[];
41
- dockerPush: boolean;
42
- dockerRegistry: string;
23
+ dockerTag?: string[];
24
+ dockerPort?: number[];
25
+ dockerPush?: boolean;
26
+ dockerRegistry?: string;
43
27
  } & CommonPackConfig;
44
28
 
45
- export type DockerPackOptions = {
46
- dockerFactory: OptionConfig<string>;
47
- dockerImage: OptionConfig<string>;
48
- dockerName: OptionConfig<string>;
49
- dockerTag: ListOptionConfig<string>;
50
- dockerPort: ListOptionConfig<string>;
51
- dockerPush: OptionConfig<boolean>;
52
- dockerRegistry: OptionConfig<string>;
53
- } & CommonPackOptions;
54
29
 
55
30
  export type ShellCommandImpl = {
56
31
  var(name: string): string;
@@ -33,31 +33,33 @@ export class PackUtil {
33
33
  /**
34
34
  * Finalize eject output
35
35
  */
36
- static async writeEjectOutput(
37
- workspace: string,
38
- module: string,
39
- output: string[],
40
- file: string
41
- ): Promise<void> {
42
- const vars = {
43
- DIST: workspace,
44
- TRV_OUT: RootIndex.outputRoot,
45
- ROOT: path.cwd(),
46
- MOD: module
47
- };
48
-
49
- const content = [
36
+ static async writeEjectOutput(workspace: string, module: string, output: AsyncIterable<string>, file: string): Promise<void> {
37
+ const vars = { DIST: workspace, TRV_OUT: RootIndex.outputRoot, ROOT: path.cwd(), MOD: module };
38
+
39
+ const replaceArgs = (text: string): string => Object.entries(vars)
40
+ .reduce((str, [k, v]) => str.replaceAll(v, ActiveShellCommand.var(k)), text);
41
+
42
+ const preamble = [
50
43
  ActiveShellCommand.scriptOpen(),
51
44
  ...Object.entries(vars).map(([k, v]) => ActiveShellCommand.export(k, v).join(' ')),
52
- Object.entries(vars).reduce((text, [k, v]) => text.replaceAll(v, ActiveShellCommand.var(k)), output.join('\n')),
53
- '', ''
54
45
  ].join('\n');
55
46
 
56
- if (file === '-' || file === '/dev/stdout') {
57
- console.log!(content);
58
- } else {
47
+ let stream: fs.FileHandle | undefined;
48
+
49
+ if (!(file === '-' || file === '/dev/stdout')) {
59
50
  await fs.mkdir(path.dirname(file), { recursive: true });
60
- await fs.writeFile(file, content, 'utf8');
51
+ await fs.truncate(file);
52
+ stream = await fs.open(file, 'utf8');
61
53
  }
54
+
55
+ const write = (text: string): Promise<unknown> | unknown => stream ? stream.write(`${text}\n`) : process.stdout.write(`${text}\n`);
56
+
57
+ await write(preamble);
58
+ for await (const line of output) {
59
+ await write(replaceArgs(line));
60
+ }
61
+ await write('\n');
62
+
63
+ await stream?.close();
62
64
  }
63
65
  }
@@ -1,14 +1,9 @@
1
+ import { CliCommand } from '@travetto/cli';
2
+
1
3
  import { BasePackCommand } from './pack.base';
2
- import { CommonPackConfig, CommonPackOptions } from './bin/types';
3
4
 
4
5
  /**
5
6
  * Standard pack support
6
7
  */
7
- export class PackCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
8
-
9
- name = 'pack';
10
-
11
- getOptions(): CommonPackOptions {
12
- return this.getCommonOptions();
13
- }
14
- }
8
+ @CliCommand({ fields: ['module'] })
9
+ export class PackCommand extends BasePackCommand { }
@@ -1,42 +1,52 @@
1
1
  import { path, RootIndex } from '@travetto/manifest';
2
+ import { CliCommand, CliFlag, CliUtil, CliValidationError } from '@travetto/cli';
2
3
 
3
- import { DockerPackConfig, DockerPackOptions } from './bin/types';
4
4
  import { DockerPackOperation } from './bin/docker-operation';
5
5
  import { BasePackCommand, PackOperationShape } from './pack.base';
6
6
 
7
-
8
7
  /**
9
8
  * Standard docker support for pack
10
9
  */
11
- export class PackDockerCommand extends BasePackCommand<DockerPackOptions, DockerPackConfig> {
12
-
13
- name = 'pack:docker';
10
+ @CliCommand({ fields: ['module'] })
11
+ export class PackDockerCommand extends BasePackCommand {
12
+ @CliFlag({ desc: 'Docker Factory source ', short: 'df', envVars: ['PACK_DOCKER_FACTORY'] })
13
+ dockerFactory = '@travetto/pack/support/pack.dockerfile';
14
+ @CliFlag({ desc: 'Docker Image to extend ', short: 'di', envVars: ['PACK_DOCKER_IMAGE'] })
15
+ dockerImage = 'node:18-alpine3.16';
16
+ @CliFlag({ desc: 'Docker Image Name ', short: 'dn', envVars: ['PACK_DOCKER_IMAGE'] })
17
+ dockerName = CliUtil.monoRoot ? '<module>' : CliUtil.getSimpleModuleName();
18
+ @CliFlag({ desc: 'Docker Image Tag ', short: 'dt', envVars: ['PACK_DOCKER_TAGS'] })
19
+ dockerTag: string[] = ['latest'];
20
+ @CliFlag({ desc: 'Docker Image Port ', short: 'dp', envVars: ['PACK_DOCKER_PORT'] })
21
+ dockerPort: number[] = [];
22
+ @CliFlag({ desc: 'Docker Push Tags ', short: 'dx', envVars: ['PACK_DOCKER_PUSH'] })
23
+ dockerPush = false;
24
+ @CliFlag({ desc: 'Docker Registry ', short: 'dr', envVars: ['PACK_DOCKER_REGISTRY'] })
25
+ dockerRegistry?: string;
14
26
 
15
- getOptions(): DockerPackOptions {
16
- const opts = this.getCommonOptions();
17
- return {
18
- ...opts,
19
- dockerFactory: this.option({ short: 'df', desc: 'Docker Factory source', def: '@travetto/pack/support/pack.dockerfile' }),
20
- dockerImage: this.option({ short: 'di', desc: 'Docker Image to extend', def: 'node:18-alpine3.16' }),
21
- dockerName: this.option({ short: 'dn', desc: 'Docker Image Name', def: this.monoRoot ? '<module>' : this.getSimpleModuleName() }),
22
- dockerTag: this.listOption({ short: 'dt', desc: 'Docker Image Tag', def: ['latest'] }),
23
- dockerPort: this.listOption({ short: 'dp', desc: 'Docker Image Port' }),
24
- dockerPush: this.boolOption({ short: 'dx', desc: 'Docker Push Tags' }),
25
- dockerRegistry: this.option({ short: 'dr', desc: 'Docker Registry' })
26
- };
27
+ async validate(...unknownArgs: string[]): Promise<CliValidationError[] | undefined> {
28
+ const errs: CliValidationError[] = [];
29
+ if (this.dockerPort?.length) {
30
+ for (let i = 0; i < this.dockerPort.length; i++) {
31
+ if (this.dockerPort[i] < 1) {
32
+ errs.push({ source: 'flag', message: `dockerPort[${i}] is less than (1)` });
33
+ } else if (this.dockerPort[i] > 65536) {
34
+ errs.push({ source: 'flag', message: `dockerPort[${i}] is greater than (65536)` });
35
+ }
36
+ }
37
+ }
38
+ return errs;
27
39
  }
28
40
 
29
- async buildConfig(): Promise<DockerPackConfig> {
30
- const cfg = await super.buildConfig();
31
- if (cfg.dockerFactory.startsWith('.')) {
32
- cfg.dockerFactory = RootIndex.getFromSource(path.resolve(cfg.dockerFactory))?.import ?? cfg.dockerFactory;
41
+ finalize(unknownArgs: string[]): void {
42
+ super.finalize(unknownArgs);
43
+ if (this.dockerFactory.startsWith('.')) {
44
+ this.dockerFactory = RootIndex.getFromSource(path.resolve(this.dockerFactory))?.import ?? this.dockerFactory;
33
45
  }
34
- cfg.dockerPort ??= [];
35
- cfg.dockerTag ??= [];
36
- return cfg;
46
+ this.dockerName = this.dockerName.replace('<module>', CliUtil.getSimpleModuleName(this.module ?? ''));
37
47
  }
38
48
 
39
- getOperations(): PackOperationShape<DockerPackConfig>[] {
49
+ getOperations(): PackOperationShape<this>[] {
40
50
  return [
41
51
  ...super.getOperations(),
42
52
  DockerPackOperation.writeDockerFile,
@@ -1,21 +1,19 @@
1
- import { CommonPackConfig, CommonPackOptions } from './bin/types';
1
+ import { CliCommand, CliUtil } from '@travetto/cli';
2
+
2
3
  import { PackOperation } from './bin/operation';
3
4
  import { BasePackCommand, PackOperationShape } from './pack.base';
4
5
 
5
6
  /**
6
7
  * Standard zip support for pack
7
8
  */
8
- export class PackZipCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
9
-
10
- name = 'pack:zip';
9
+ @CliCommand({ fields: ['module'] })
10
+ export class PackZipCommand extends BasePackCommand {
11
11
 
12
- getOptions(): CommonPackOptions {
13
- const opts = this.getCommonOptions();
14
- opts.output.def = this.monoRoot ? '<module>.zip' : `${this.getSimpleModuleName()}.zip`;
15
- return opts;
12
+ initialize(): void {
13
+ this.output = CliUtil.monoRoot ? '<module>.zip' : `${CliUtil.getSimpleModuleName()}.zip`;
16
14
  }
17
15
 
18
- getOperations(): PackOperationShape<CommonPackConfig>[] {
16
+ getOperations(): PackOperationShape<this>[] {
19
17
  return [
20
18
  ...super.getOperations(),
21
19
  PackOperation.compress
@@ -1,149 +1,117 @@
1
1
  import os from 'os';
2
2
 
3
- import { CliCommand, cliTpl } from '@travetto/cli';
3
+ import { CliCommandShape, CliFlag, cliTpl, CliUtil } from '@travetto/cli';
4
4
  import { path, RootIndex } from '@travetto/manifest';
5
5
  import { TimeUtil } from '@travetto/base';
6
6
  import { GlobalTerminal } from '@travetto/terminal';
7
+ import { Ignore, Required, Schema } from '@travetto/schema';
7
8
 
8
- import { CommonPackConfig, CommonPackOptions } from './bin/types';
9
9
  import { PackOperation } from './bin/operation';
10
10
  import { PackUtil } from './bin/util';
11
11
 
12
- export type PackOperationShape<T extends CommonPackConfig> = ((config: T) => AsyncIterable<string[]>);
12
+ export type PackOperationShape<T> = ((config: T) => AsyncIterable<string[]>);
13
13
 
14
- const BASIC_OP_SET = [
15
- PackOperation.clean,
16
- PackOperation.writeEnv,
17
- PackOperation.writePackageJson,
18
- PackOperation.writeEntryScript,
19
- PackOperation.copyResources,
20
- PackOperation.primeAppCache,
21
- PackOperation.writeManifest,
22
- PackOperation.bundle,
23
- ];
14
+ @Schema()
15
+ export abstract class BasePackCommand implements CliCommandShape {
24
16
 
25
- export abstract class BasePackCommand<T extends CommonPackOptions, S extends CommonPackConfig> extends CliCommand<{}> {
26
-
27
- get monoRoot(): boolean {
28
- return !!RootIndex.manifest.monoRepo && path.cwd() === RootIndex.manifest.workspacePath;
29
- }
30
-
31
- get entryPoints(): string[] {
17
+ static get entryPoints(): string[] {
32
18
  return RootIndex.findSupport({ filter: x => x.includes('entry.') })
33
19
  .map(x => x.import.replace(/[.][^.]+s$/, ''));
34
20
  }
35
21
 
36
- getArgs(): string | undefined {
37
- return this.monoRoot ? '<module> [args...]' : '[args...]';
38
- }
22
+ #unknownArgs?: string[];
39
23
 
40
- getCommonOptions(): CommonPackOptions {
41
- const mainEntry = this.entryPoints.find(x => x.startsWith('@travetto/cli'))!;
42
- return {
43
- workspace: this.option({ short: 'w', desc: 'Workspace for building' }),
44
- clean: this.boolOption({ short: 'c', desc: 'Clean workspace', def: true }),
45
- output: this.option({ short: 'o', desc: 'Output location' }),
46
- mainScripts: this.option({ short: 'es', desc: 'Create entry scripts' }),
47
- mainName: this.option({ short: 'f', desc: 'Main name for build artifact' }),
48
- entryPoint: this.option({ short: 'e', desc: 'Entry point', def: mainEntry }),
49
- minify: this.boolOption({ short: 'm', desc: 'Minify output', def: true }),
50
- sourcemap: this.boolOption({ short: 'sm', desc: 'Bundle source maps' }),
51
- includeSources: this.boolOption({ short: 'is', desc: 'Include source with source maps' }),
52
- ejectFile: this.option({ short: 'x', desc: 'Eject commands to file' }),
53
- };
54
- }
24
+ @CliFlag({ desc: 'Workspace for building', short: 'w' })
25
+ workspace: string = path.resolve(os.tmpdir(), RootIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
55
26
 
56
- abstract getOptions(): T;
27
+ @CliFlag({ desc: 'Clean workspace' })
28
+ clean = true;
57
29
 
58
- get cmd(): S {
59
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
60
- return super.cmd as S;
61
- }
30
+ @CliFlag({ desc: 'Output location', short: 'o' })
31
+ @Required(false)
32
+ output: string;
62
33
 
63
- getSimpleModuleName(): string {
64
- return RootIndex.mainPackage.name.replace(/[\/]/, '_').replace(/@/, '');
65
- }
34
+ @CliFlag({ desc: 'Create entry scripts', short: 'es' })
35
+ mainScripts: boolean = true;
36
+
37
+ @CliFlag({ desc: 'Main name for build artifact', short: 'f' })
38
+ @Required(false)
39
+ mainName: string;
40
+
41
+ @CliFlag({ desc: 'Entry point', short: 'e' })
42
+ @Required(false)
43
+ entryPoint: string = '@travetto/cli/support/entry.cli';
66
44
 
67
- getOperations(): PackOperationShape<S>[] {
68
- return BASIC_OP_SET.slice(0);
45
+ @CliFlag({ desc: 'Minify output' })
46
+ minify = true;
47
+
48
+ @CliFlag({ desc: 'Bundle source maps', short: 'sm' })
49
+ sourcemap = false;
50
+
51
+ @CliFlag({ desc: 'Include source with source maps', short: 'is' })
52
+ includeSources = false;
53
+
54
+ @CliFlag({ desc: 'Eject commands to file', short: 'x' })
55
+ ejectFile?: string;
56
+
57
+ @Ignore()
58
+ module: string;
59
+
60
+ /** Entry arguments */
61
+ @Ignore()
62
+ entryArguments: string[] = [];
63
+
64
+ getOperations(): PackOperationShape<this>[] {
65
+ return [
66
+ PackOperation.clean,
67
+ PackOperation.writeEnv,
68
+ PackOperation.writePackageJson,
69
+ PackOperation.writeEntryScript,
70
+ PackOperation.copyResources,
71
+ PackOperation.writeManifest,
72
+ PackOperation.bundle,
73
+ ];
69
74
  }
70
75
 
71
76
  /**
72
77
  * Run all operations
73
78
  */
74
- async * runOperations(cfg: S): AsyncIterable<string> {
79
+ async * runOperations(): AsyncIterable<string> {
75
80
  for (const op of this.getOperations()) {
76
- for await (const msg of op(cfg)) {
81
+ for await (const msg of op(this)) {
77
82
  yield msg.join(' ');
78
83
  }
79
84
  }
80
85
  }
81
86
 
87
+ finalize(unknown: string[]): void {
88
+ this.#unknownArgs = unknown;
82
89
 
83
- getModule(moduleName: string): string {
84
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
85
- let module = this.monoRoot ? moduleName : RootIndex.mainModule.name;
86
- module = RootIndex.getModuleByFolder(module)?.name ?? module;
87
-
88
- // Reinitialize for module
89
- if (this.monoRoot) {
90
- RootIndex.reinitForModule(module);
91
- }
92
-
93
- return module;
94
- }
95
-
96
- async buildConfig(): Promise<S> {
97
- this.cmd.workspace ??= path.resolve(os.tmpdir(), RootIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
98
- this.cmd.module = RootIndex.mainModule.name;
99
- this.cmd.mainName ??= path.basename(this.cmd.entryPoint);
100
- return this.cmd;
101
- }
102
-
103
- async action(module: string, args: string[]): Promise<void> {
104
- if (Array.isArray(module)) {
105
- args = module;
106
- module = RootIndex.mainModule.name;
107
- }
108
- const start = Date.now();
109
- if (!module && this.monoRoot) {
110
- return this.showHelp(new Error('The module needs to specified when running from a monorepo root'));
111
- }
112
-
113
- module = this.getModule(module);
114
-
115
- const cfg = await this.buildConfig();
116
- cfg.entryArguments = Array.isArray(args) ? args : [];
117
-
118
- for (const k in this.cmd) {
119
- if (Object.hasOwn(this.cmd, k)) {
120
- const v = this.cmd[k];
121
- if (typeof v === 'string' && /<module>/.test(v)) {
122
- // @ts-expect-error
123
- this.cmd[k] = v.replace(/<module>/g, this.getSimpleModuleName());
124
- }
125
- }
126
- }
90
+ this.output = this.output?.replace('<module>', CliUtil.getSimpleModuleName(this.module ?? ''));
127
91
 
128
92
  // Resolve all files to absolute paths
129
- if (this.cmd.output) {
130
- this.cmd.output = path.resolve(this.cmd.output);
93
+ if (this.output) {
94
+ this.output = path.resolve(this.output);
131
95
  }
132
- if (this.cmd.ejectFile) {
133
- this.cmd.ejectFile = path.resolve(this.cmd.ejectFile);
96
+ if (this.ejectFile) {
97
+ this.ejectFile = path.resolve(this.ejectFile);
134
98
  }
135
- this.cmd.workspace = path.resolve(this.cmd.workspace);
99
+ this.workspace = path.resolve(this.workspace);
100
+ }
101
+
102
+ async main(args: string[] = []): Promise<void> {
103
+ this.entryArguments = [...args, ...this.#unknownArgs ?? []];
104
+ this.module ||= RootIndex.mainModule.name;
105
+ this.mainName ??= path.basename(this.module);
136
106
 
137
- const stream = this.runOperations(cfg);
107
+ const stream = this.runOperations();
138
108
 
139
109
  // Eject to file
140
- if (this.cmd.ejectFile) {
141
- const output: string[] = [];
142
- for await (const line of stream) {
143
- output.push(line);
144
- }
145
- await PackUtil.writeEjectOutput(this.cmd.workspace, cfg.module, output, this.cmd.ejectFile);
110
+ if (this.ejectFile) {
111
+ await PackUtil.writeEjectOutput(this.workspace, this.module, stream, this.ejectFile);
146
112
  } else {
113
+ const start = Date.now();
114
+
147
115
  await GlobalTerminal.streamLinesWithWaiting(stream, {
148
116
  initialDelay: 0,
149
117
  cycleDelay: 100,
@@ -151,9 +119,9 @@ export abstract class BasePackCommand<T extends CommonPackOptions, S extends Com
151
119
  position: 'inline',
152
120
  committedPrefix: String.fromCharCode(171)
153
121
  });
154
- let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.cmd.module }}`;
155
- if (this.cmd.output) {
156
- msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.cmd.output }}`;
122
+ let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.module }}`;
123
+ if (this.output) {
124
+ msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.output }}`;
157
125
  }
158
126
  await GlobalTerminal.writeLines(msg);
159
127
  }
@@ -4,6 +4,6 @@ export const factory: DockerPackFactory = cfg => `
4
4
  FROM ${cfg.dockerImage}
5
5
  WORKDIR /app
6
6
  COPY . .
7
- ${cfg.dockerPort.map(port => `EXPOSE ${port}`).join('\n')}
7
+ ${cfg.dockerPort?.map(port => `EXPOSE ${port}`).join('\n') ?? ''}
8
8
  ENTRYPOINT ["/app/${cfg.mainName}.sh"]
9
9
  `;