@travetto/pack 3.0.0-rc.9 → 3.0.1-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
@@ -1,267 +1,232 @@
1
1
  <!-- This file was generated by @travetto/doc and should not be modified directly -->
2
- <!-- Please modify https://github.com/travetto/travetto/tree/main/module/pack/doc.ts and execute "npx trv doc" to rebuild -->
2
+ <!-- Please modify https://github.com/travetto/travetto/tree/main/module/pack/DOC.ts and execute "npx trv doc" to rebuild -->
3
3
  # Pack
4
4
  ## Code packing utilities
5
5
 
6
6
  **Install: @travetto/pack**
7
7
  ```bash
8
8
  npm install @travetto/pack
9
+
10
+ # or
11
+
12
+ yarn add @travetto/pack
9
13
  ```
10
14
 
15
+ This module provides the necessary tools to produce deliverable output for [Travetto](https://travetto.dev) based projects. The main interaction with this module is through the command line interface, and the operations it provides. Under the covers, the code bundling is performed by [Rollup](https://rollupjs.org/), with specific configuration to support the frameworks runtime expectations.
16
+
17
+ There are three primary cli commands for packing your code:
18
+
19
+ * pack
20
+ * pack:zip
21
+ * pack:docker
22
+
11
23
  ## CLI - pack
12
24
 
13
25
  **Terminal: Pack usage**
14
26
  ```bash
15
27
  $ trv pack --help
16
28
 
17
- Usage: pack [options] [mode]
29
+ Usage: pack [options] [args...]
18
30
 
19
31
  Options:
20
- -w, --workspace <workspace> Working directory
21
- -h, --help display help for command
22
-
23
- Available Pack Modes:
24
- * default [support/pack.config.ts]
25
- * rest/docker [@travetto/rest/support/pack.docker.ts]
26
- * rest-aws-lambda/main [@travetto/rest-aws-lambda/support/pack.aws-lambda.ts]
32
+ -w, --workspace <workspace> Workspace for building
33
+ -c, --no-clean Disables: Clean workspace
34
+ -o, --output <output> Output Location
35
+ -e, --entry-point <entry-point> Entry point (default: "node_modules/@travetto/cli/support/cli.js")
36
+ -ec, --entry-command <entry-command> Entry command
37
+ -m, --no-minify Disables: Minify output
38
+ -sm, --sourcemap Bundle source maps
39
+ -is, --include-sources Include source with source maps
40
+ -x, --eject-file <eject-file> Eject commands to file
41
+ -h, --help display help for command
27
42
  ```
28
43
 
29
- This command line operation will compile your project, and produce a ready to use workspace as a deliverable. The pack operation is actually a wrapper around multiple sub-operations that are run in series to produce the desired final structure for deployment. The currently support operations are:
44
+ 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).
30
45
 
31
-
32
- * assemble
33
- * zip
34
- * docker
46
+ Specific to this CLI command, the `output` field determines where the final folder is written that contains all the compiled source.
35
47
 
36
- ### CLI - pack:assemble
48
+ ### Entry Point Configuration
49
+ Every application requires an entry point to determine execution flow (and in [Rollup](https://rollupjs.org/)'s case, tree-shaking as well.). By default the [Command Line Interface](https://github.com/travetto/travetto/tree/main/module/cli#readme "CLI infrastructure for Travetto framework") acts as the entry point. This bypasses the [Compiler](https://github.com/travetto/travetto/tree/main/module/compiler#readme "The compiler infrastructure for the Travetto framework") intentionally, as the compiler is not available at runtime.
37
50
 
38
- Assemble is the operation that stages the project's code for deployment. The assembly process goes through the following operations:
51
+ Within the command line, the `args` are positional arguments that will be passed to the entry point on application run.
39
52
 
40
-
41
- 1. Cleaning Workspace - Cleans workspace to start with an empty workspace
42
- 1. Copying Dependencies - Computes the prod dependencies and copies them into the new workspace
43
- 1. Copying App Content - Copies over application content (src/, resources/, support/, bin/)
44
- 1. Excluding Pre-Compile Files - Any files that should be excluded pre-compilation, are removed
45
- 1. Compiling - Compiles the code in the new workspace, isolating it from your local development
46
- 1. Excluding Post-Compile Files - Removes any files that should be excluded, post compilation
47
- 1. Copying Added Content - Adds in any additional content that is not in the standard locations
48
- 1. Removing Empty Folders - Purge all empty folders, recursively
49
- 1. Writing Env.js - Write out the .env.js file with computed any env vars that should be set for the deployed app
50
- 1. Remove Source Maps - If keep source is false, all source maps are purged from your app's code
51
- 1. Emptying .ts Files - If keep source is false, all .ts files are emptied, as compilation will not occur at runtime
52
-
53
- **Code: Assemble Default Config**
53
+ **Code: Packing an application run**
54
54
  ```typescript
55
- assemble: {
56
- active: true,
57
- cacheDir: 'cache',
58
- keepSource: true,
59
- readonly: true,
60
- env: {
61
- TRV_DYNAMIC: '0'
62
- },
63
- add: [
64
- { [mod('@travetto/cli/bin/trv.js')]: mod('.bin/trv') },
65
- { [mod('lodash/lodash.min.js')]: mod('lodash/lodash.js') },
66
- ],
67
- excludeCompile: [
68
- mod('@travetto/*/doc/'),
69
- mod('@travetto/*/e2e/'),
70
- mod('@travetto/*/test/'),
71
- ],
72
- exclude: [
73
- 'bower.json',
74
- 'LICENSE',
75
- 'LICENCE',
76
- '*.map',
77
- '*.md',
78
- '*.lock',
79
- '*.html',
80
- '*.mjs',
81
- mod('**/*.ts'),
82
- '*.d.ts',
55
+ $ npx trv pack run myapp
83
56
  ```
84
57
 
85
- **Terminal: Assemble Usage**
86
- ```bash
87
- $ trv pack:assemble --help
88
-
89
- Usage: pack:assemble [options] [mode]
58
+ Would then produce an executable script, in the output folder, that would look like:
90
59
 
91
- Options:
92
- -w, --workspace <workspace> Working directory
93
- -k, --keep-source Should source be preserved
94
- -r, --readonly Build a readonly deployable
95
- -h, --help display help for command
96
-
97
- Available Pack Modes:
98
- * default [support/pack.config.ts]
99
- * rest/docker [@travetto/rest/support/pack.docker.ts]
100
- * rest-aws-lambda/main [@travetto/rest-aws-lambda/support/pack.aws-lambda.ts]
60
+ **Code: Entry script for Packed application**
61
+ ```typescript
62
+ #!/bin/sh
63
+ cd $(dirname "$0")
64
+ node cli run myapp
101
65
  ```
102
66
 
103
- ### CLI - pack:zip
67
+ And this entry point would be what is executed by [docker](https://www.docker.com/community-edition), or whatever deployment mechanism is being used.
104
68
 
105
- Zip is an optional step, that can run post assembly. The only configuration it currently provides is the ability to specify the output location for the zip file.
69
+ ### General Packing Operations
70
+ Every [Pack](https://github.com/travetto/travetto/tree/main/module/pack#readme "Code packing utilities") operation extends from the base command, and that provides some consistent operations that run on every packing command.
106
71
 
107
- **Code: Zip Default Config**
108
- ```typescript
109
- zip: {
110
- active: false,
111
- output: 'output.zip'
112
- },
113
- ```
72
+
73
+ * `clean` - Empties workspace before beginning, controlled by the `--clean` flag, defaults to on
74
+ * `writeEnv` - Writes the .env.js files that includes the necessary details to start the application. This is primarily to identify the location of the manifest file needed to run.
75
+ * `writePackageJson` - Generates the [Package JSON](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) with the appropriate module type ([CommonJS](https://nodejs.org/api/modules.html) or [Ecmascript Module](https://nodejs.org/api/esm.html)) for interpreting plain `.js` files
76
+ * `writeEntryScript` - Create the entry script based on the `--entry-command`, `args`
77
+ * `copyResources` - Will pull in local `resources/**` files into the final output
78
+ * `primeAppCache` - Runs `trv run` to ensure the appropriate files are generated to allow for running the application. This only applies if the entry point is equivalent to `trv run`
79
+ * `writeManifest` - Produces the `prod`-ready manifest that is used at runtime. Removes all devDependencies from the manifest.json
80
+ * `bundle` - Invokes [Rollup](https://rollupjs.org/) with the appropriate file set to produce a single output .js file. Depending on the module type ([CommonJS](https://nodejs.org/api/modules.html) or [Ecmascript Module](https://nodejs.org/api/esm.html)) the build process differs to handle the dynamic loading that application does at runtime.
81
+
82
+ ## CLI - pack:zip
114
83
 
115
- **Terminal: Zip Usage**
84
+ This command is nearly identical to the standard `pack` operation, except for the `output` flag. In this scenario, the `output` flag determines the location and name of the final zip file.
85
+
86
+ **Terminal: Pack:zip usage**
116
87
  ```bash
117
88
  $ trv pack:zip --help
118
89
 
119
- Usage: pack:zip [options] [mode]
90
+ Usage: pack:zip [options] [args...]
120
91
 
121
92
  Options:
122
- -w, --workspace <workspace> Working directory
123
- -o, --output <output> Output File
124
- -h, --help display help for command
125
-
126
- Available Pack Modes:
127
- * default [support/pack.config.ts]
128
- * rest/docker [@travetto/rest/support/pack.docker.ts]
129
- * rest-aws-lambda/main [@travetto/rest-aws-lambda/support/pack.aws-lambda.ts]
93
+ -w, --workspace <workspace> Workspace for building
94
+ -c, --no-clean Disables: Clean workspace
95
+ -o, --output <output> Output Location (default: "travetto_pack.zip")
96
+ -e, --entry-point <entry-point> Entry point (default: "node_modules/@travetto/cli/support/cli.js")
97
+ -ec, --entry-command <entry-command> Entry command
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
130
103
  ```
131
104
 
132
- ### CLI - pack:docker
133
-
134
- Docker support is an optional step, that can run post assembly. This allows for building a docker image, and currently only supports the base images as the only configuration options.
105
+ ## CLI - pack:docker
135
106
 
136
- **Code: Docker Default Config**
137
- ```typescript
138
- docker: {
139
- active: false,
140
- image: 'node:16-alpine'
141
- }
142
- ```
107
+ This command starts off identical to the standard `pack` operation, but it contains a few additional flags, and ultimately a few additional operations to support creating of the final [docker](https://www.docker.com/community-edition) image.
143
108
 
144
- **Terminal: Docker Usage**
109
+ **Terminal: Pack:docker usage**
145
110
  ```bash
146
111
  $ trv pack:docker --help
147
112
 
148
- Usage: pack:docker [options] [mode]
113
+ Usage: pack:docker [options] [args...]
149
114
 
150
115
  Options:
151
- -w, --workspace <workspace> Working directory
152
- -i, --image <image> Docker Image to extend
153
- -n, --name <name> Image Name
154
- -t, --tag <tag> Image Tag (default: [])
155
- -p, --port <port> Image Port (default: [])
156
- -x, --push Push Tags
157
- -r, --registry <registry> Registry
158
- -h, --help display help for command
159
-
160
- Available Pack Modes:
161
- * default [support/pack.config.ts]
162
- * rest/docker [@travetto/rest/support/pack.docker.ts]
163
- * rest-aws-lambda/main [@travetto/rest-aws-lambda/support/pack.aws-lambda.ts]
116
+ -w, --workspace <workspace> Workspace for building
117
+ -c, --no-clean Disables: Clean workspace
118
+ -o, --output <output> Output Location
119
+ -e, --entry-point <entry-point> Entry point (default: "node_modules/@travetto/cli/support/cli.js")
120
+ -ec, --entry-command <entry-command> Entry command
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
164
133
  ```
165
134
 
166
- ### Modes
167
- Various modules may provide customizations to the default `pack.config.ts` to allow for easy integration with the packing process. A simple example of this is via the [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") module, for how to publish lambda packages.
135
+ 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.
168
136
 
169
- **Code: Rest, pack.lambda.ts**
170
- ```typescript
171
- import * as fs from 'fs/promises';
172
-
173
- import { PathUtil } from '@travetto/boot';
174
- import type { AllConfigPartial } from '@travetto/pack';
175
-
176
- export const config: AllConfigPartial = {
177
- name: 'rest-aws-lambda/main',
178
- assemble: {
179
- active: true,
180
- keepSource: false,
181
- exclude: [
182
- 'node_modules/node-forge'
183
- ],
184
- env: {
185
- NO_COLOR: '1'
186
- },
187
- postProcess: [{
188
- ['Lambda Entrypoint']: cfg =>
189
- fs.copyFile(
190
- PathUtil.resolveUnix(__dirname, 'aws-lambda.handler.js'),
191
- PathUtil.resolveUnix(cfg.workspace, 'index.js')
192
- )
193
- }],
194
- },
195
- zip: {
196
- active: true,
197
- output: 'dist/lambda.zip'
198
- }
199
- };
200
- ```
137
+ In addition to the standard operations, this command adds the following steps:
138
+
139
+ * `writeDockerFile` - Generate the docker file contents
140
+ * `pullDockerBaseImage` - Pull base image, to ensure its available and primed
141
+ * `buildDockerContainer` - Build final container
142
+ * `pushDockerContainer` - Push container with appropriate tags. Only applies if `--docker-push` is specified
143
+
144
+ ## Ejected File
145
+
146
+ As indicated, any of the pack operations can be ejected, and produce an output that can be run independent of the pack command. This is helpful when integrating with more complicated build processes.
201
147
 
202
- **Terminal: Invoking Pack with Mode**
148
+ **Terminal: Sample Ejected File**
203
149
  ```bash
204
- npx trv pack <mode>
205
- ```
150
+ $ trv pack:docker -x /dev/stdout run rest
206
151
 
207
- ## Configuration
152
+ #!/bin/sh
153
+ export DIST=/tmp/_home_tim_Code_travetto_related_todo-app
154
+ export TRV_OUT=<workspace-root>/.trv_output
155
+ export ROOT=<workspace-root>/related/todo-app
156
+ export MOD=@travetto/todo-app
208
157
 
209
- By default, the configuration consists of two components.
210
-
211
- * The default config in `support/pack.config.ts` and
212
- * The config selected to execute from the cli
158
+ # Cleaning Output $DIST
213
159
 
214
- These two configurations will be loaded and layered, with the selected config taking precedence.
160
+ rm -rf $DIST
161
+ mkdir -p $DIST
215
162
 
216
- **Code: Example pack.config.ts**
217
- ```typescript
218
- import type { AllConfigPartial } from '@travetto/pack';
219
-
220
- export const config: AllConfigPartial = {
221
- workspace: 'dist/alt',
222
- assemble: {
223
- active: true,
224
- add: [
225
- { assets: 'assets' },
226
- { '/secret/location/key.pem': 'resources/key.pem' }
227
- ]
228
- },
229
- zip: {
230
- active: true,
231
- output: 'dist/build.zip'
232
- }
233
- };
234
- ```
163
+ # Writing .env.js
235
164
 
236
- ### Environment Override
165
+ echo "process.env.TRV_MANIFEST = 'node_modules/$MOD';" > $DIST/.env.js
166
+ echo "process.env.TRV_CLI_IPC = '';" >> $DIST/.env.js
237
167
 
238
- When working with sub operations, passing command-line flags is challenging. To support a more natural usage, the sub operations
239
- allow their key parameters to be overridden via environment variables.
168
+ # Writing package.json
240
169
 
241
- **Code: Assemble Overrides**
242
- ```typescript
243
- overrides: {
244
- keepSource: CliUtil.toBool(process.env.PACK_ASSEMBLE_KEEP_SOURCE),
245
- readonly: CliUtil.toBool(process.env.PACK_ASSEMBLE_READONLY)
246
- },
247
- ```
170
+ echo "{\"type\":\"commonjs\"}" > $DIST/package.json
248
171
 
249
- **Code: Docker Overrides**
250
- ```typescript
251
- overrides: {
252
- image: process.env.PACK_DOCKER_IMAGE || undefined,
253
- name: process.env.PACK_DOCKER_NAME || undefined,
254
- app: process.env.PACK_DOCKER_APP || undefined,
255
- port: process.env.PACK_DOCKER_PORT ? [process.env.PACK_DOCKER_PORT] : undefined,
256
- registry: process.env.PACK_DOCKER_REGISTRY || undefined,
257
- push: CliUtil.toBool(process.env.PACK_DOCKER_PUSH),
258
- tag: process.env.PACK_DOCKER_TAG ? [process.env.PACK_DOCKER_TAG] : undefined
259
- },
260
- ```
172
+ # Writing entry scripts cli.sh args=(run rest)
261
173
 
262
- **Code: Zip Overrides**
263
- ```typescript
264
- overrides: {
265
- output: process.env.PACK_ZIP_OUTPUT || undefined
266
- },
174
+ echo "#!/bin/sh" > $DIST/cli.sh
175
+ echo "cd \$(dirname \"\$0\")" >> $DIST/cli.sh
176
+ echo "node cli run rest \$@" >> $DIST/cli.sh
177
+ chmod 755 $DIST/cli.sh
178
+
179
+ # Writing entry scripts cli.cmd args=(run rest)
180
+
181
+ echo "" > $DIST/cli.cmd
182
+ echo "cd %~p0" >> $DIST/cli.cmd
183
+ echo "node cli run rest %*" >> $DIST/cli.cmd
184
+ chmod 755 $DIST/cli.cmd
185
+
186
+ # Copying over resources
187
+
188
+ mkdir -p $DIST/node_modules/$MOD
189
+ cp $TRV_OUT/node_modules/$MOD/package.json $DIST/node_modules/$MOD/package.json
190
+ mkdir -p $DIST/node_modules/@travetto/manifest
191
+ cp $TRV_OUT/node_modules/@travetto/manifest/package.json $DIST/node_modules/@travetto/manifest/package.json
192
+ cp -r -p $ROOT/resources $DIST/resources
193
+
194
+ # Generating App Cache node_modules/$MOD/trv-app-cache.json
195
+
196
+ mkdir -p $DIST/node_modules/$MOD
197
+ DEBUG=0 TRV_MODULE=$MOD npx trv main @travetto/app/support/bin/list > $DIST/node_modules/$MOD/trv-app-cache.json
198
+
199
+ # Writing Manifest node_modules/$MOD
200
+
201
+ TRV_MODULE=$MOD npx trv manifest $DIST/node_modules/$MOD prod
202
+
203
+ # Bundling Output minify=true sourcemap= entryPoint=node_modules/@travetto/cli/support/cli.js
204
+
205
+ export BUNDLE_ENTRY=node_modules/@travetto/cli/support/cli.js
206
+ export BUNDLE_ENTRY_NAME=cli
207
+ export BUNDLE_COMPRESS=true
208
+ export BUNDLE_OUTPUT=$DIST
209
+ export BUNDLE_FORMAT=commonjs
210
+ export TRV_MANIFEST=$TRV_OUT/node_modules/$MOD
211
+ cd $TRV_OUT
212
+ npx rollup -c node_modules/@travetto/pack/support/bin/rollup.js
213
+ cd $ROOT
214
+
215
+ # Generating Docker File $DIST/Dockerfile @travetto/pack/support/pack.dockerfile
216
+
217
+ echo "FROM node:18-alpine3.16" > $DIST/Dockerfile
218
+ echo "WORKDIR /app" >> $DIST/Dockerfile
219
+ echo "COPY . ." >> $DIST/Dockerfile
220
+ echo "" >> $DIST/Dockerfile
221
+ echo "ENTRYPOINT [\"/app/cli.sh\"]" >> $DIST/Dockerfile
222
+
223
+ # Pulling Docker Base Image node:18-alpine3.16
224
+
225
+ docker pull node:18-alpine3.16
226
+
227
+ # Building Docker Container latest
228
+
229
+ cd $DIST
230
+ docker build -t travetto_todo-app:latest .
231
+ cd $ROOT
267
232
  ```
package/__index__.ts CHANGED
@@ -1 +1 @@
1
- export type { CommonPackConfig } from './support/bin/types';
1
+ export type { CommonPackConfig, DockerPackFactory, DockerPackConfig } from './support/bin/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/pack",
3
- "version": "3.0.0-rc.9",
3
+ "version": "3.0.1-rc.1",
4
4
  "description": "Code packing utilities",
5
5
  "keywords": [
6
6
  "travetto",
@@ -14,6 +14,7 @@
14
14
  "email": "travetto.framework@gmail.com",
15
15
  "name": "Travetto Framework"
16
16
  },
17
+ "main": "__index__.ts",
17
18
  "files": [
18
19
  "__index__.ts",
19
20
  "support"
@@ -25,14 +26,14 @@
25
26
  "dependencies": {
26
27
  "@rollup/plugin-commonjs": "^24.0.1",
27
28
  "@rollup/plugin-json": "^6.0.0",
28
- "@rollup/plugin-terser": "^0.4.0",
29
29
  "@rollup/plugin-node-resolve": "^15.0.1",
30
- "@travetto/base": "^3.0.0-rc.9",
31
- "rollup": "^3.12.1",
30
+ "@rollup/plugin-terser": "^0.4.0",
31
+ "@travetto/base": "^3.0.1-rc.1",
32
+ "rollup": "^3.17.2",
32
33
  "rollup-plugin-sourcemaps": "^0.6.3"
33
34
  },
34
35
  "peerDependencies": {
35
- "@travetto/cli": "^3.0.0-rc.10"
36
+ "@travetto/cli": "^3.0.1-rc.1"
36
37
  },
37
38
  "peerDependenciesMeta": {
38
39
  "@travetto/cli": {
@@ -6,6 +6,7 @@ import { cliTpl } from '@travetto/cli';
6
6
 
7
7
  import { ActiveShellCommand } from './shell';
8
8
  import { DockerPackConfig, DockerPackFactoryModule } from './types';
9
+ import { PackOperation } from './operation';
9
10
 
10
11
  export class DockerPackOperation {
11
12
 
@@ -18,15 +19,19 @@ export class DockerPackOperation {
18
19
  */
19
20
  static async* writeDockerFile(cfg: DockerPackConfig): AsyncIterable<string[]> {
20
21
  const dockerFile = path.resolve(cfg.workspace, 'Dockerfile');
21
- const title = cliTpl`${{ title: 'Generating Docker File' }} ${{ path: dockerFile }}`;
22
- const mod: DockerPackFactoryModule = await import(RootIndex.getFromImport(cfg.dockerFactory)!.import);
22
+
23
+ const factory = RootIndex.getFromImport(cfg.dockerFactory);
24
+ if (!factory) {
25
+ throw new Error(`Unable to resolve docker factory at ${cfg.dockerFactory}`);
26
+ }
27
+ const mod: DockerPackFactoryModule = await import(factory.import);
23
28
  const content = (await mod.factory(cfg)).trim();
24
29
 
30
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Generating Docker File' }} ${{ path: dockerFile }} ${{ param: cfg.dockerFactory }}`);
31
+
25
32
  if (cfg.ejectFile) {
26
- yield ActiveShellCommand.comment(title);
27
33
  yield* ActiveShellCommand.createFile(dockerFile, content.split(/\n/));
28
34
  } else {
29
- yield [title];
30
35
  await fs.writeFile(dockerFile, content, 'utf8');
31
36
  }
32
37
  }
@@ -35,15 +40,13 @@ export class DockerPackOperation {
35
40
  * Pull Docker Base Image
36
41
  */
37
42
  static async* pullDockerBaseImage(cfg: DockerPackConfig): AsyncIterable<string[]> {
38
- const title = cliTpl`${{ title: 'Pulling Docker Base Image' }} ${{ param: cfg.dockerImage }}`;
39
-
40
43
  const command = ['docker', 'pull', cfg.dockerImage];
41
44
 
45
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Pulling Docker Base Image' }} ${{ param: cfg.dockerImage }}`);
46
+
42
47
  if (cfg.ejectFile) {
43
- yield ActiveShellCommand.comment(title);
44
48
  yield command;
45
49
  } else {
46
- yield [title];
47
50
  await ExecUtil.spawn(command[0], command.slice(1), {}).result;
48
51
  }
49
52
  }
@@ -52,16 +55,15 @@ export class DockerPackOperation {
52
55
  * Building Docker Container
53
56
  */
54
57
  static async* buildDockerContainer(cfg: DockerPackConfig): AsyncIterable<string[]> {
55
- const title = cliTpl`${{ title: 'Building Docker Container' }} ${{ param: cfg.dockerTag?.join(',') }}`;
56
58
  const cmd = ['docker', 'build', ...DockerPackOperation.getDockerTags(cfg).flatMap(x => ['-t', x]), '.'];
57
59
 
60
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Building Docker Container' }} ${{ param: cfg.dockerTag?.join(',') }}`);
61
+
58
62
  if (cfg.ejectFile) {
59
- yield ActiveShellCommand.comment(title);
60
63
  yield ActiveShellCommand.chdir(cfg.workspace);
61
64
  yield cmd;
62
65
  yield ActiveShellCommand.chdir(path.cwd());
63
66
  } else {
64
- yield [title];
65
67
  await ExecUtil.spawn(cmd[0], cmd.slice(1), { cwd: cfg.workspace, stdio: [0, 'pipe', 2] }).result;
66
68
  }
67
69
  }
@@ -74,15 +76,18 @@ export class DockerPackOperation {
74
76
  return;
75
77
  }
76
78
  const tags = DockerPackOperation.getDockerTags(cfg);
77
- const title = cliTpl`${{ title: 'Push Container to registry' }} ${{ param: cfg.dockerRegistry }}`;
78
- const cmd = ['docker', 'image', 'push', ...tags];
79
+ const cmd = ['docker', 'image', 'push'];
80
+
81
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Push Container to registry' }} ${{ param: cfg.dockerRegistry }}`);
79
82
 
80
83
  if (cfg.ejectFile) {
81
- yield ActiveShellCommand.comment(title);
82
- yield cmd;
84
+ for (const tag of tags) {
85
+ yield [...cmd, tag];
86
+ }
83
87
  } else {
84
- yield [title];
85
- await ExecUtil.spawn(cmd[0], cmd.slice(1), { stdio: [0, 'pipe', 2] }).result;
88
+ for (const tag of tags) {
89
+ await ExecUtil.spawn(cmd[0], [...cmd.slice(1), tag], { stdio: [0, 'pipe', 2] }).result;
90
+ }
86
91
  }
87
92
  }
88
93
  }
@@ -14,22 +14,32 @@ async function writeRawFile(file: string, contents: string, mode?: string): Prom
14
14
 
15
15
  export class PackOperation {
16
16
 
17
+ static async * title(cfg: CommonPackConfig, title: string): AsyncIterable<string[]> {
18
+ if (cfg.ejectFile) {
19
+ yield ActiveShellCommand.comment(title);
20
+ yield ActiveShellCommand.echo(title);
21
+ } else {
22
+ yield [title];
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Clean out pack workspace, removing all content
28
+ */
17
29
  static async * clean(cfg: CommonPackConfig): AsyncIterable<string[]> {
18
30
  if (!cfg.clean) {
19
31
  return;
20
32
  }
21
33
 
22
- const title = cliTpl`${{ title: 'Cleaning Output' }} ${{ path: cfg.workspace }}`;
34
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Cleaning Output' }} ${{ path: cfg.workspace }}`);
23
35
 
24
36
  if (cfg.ejectFile) {
25
- yield ActiveShellCommand.comment(title);
26
37
  yield ActiveShellCommand.rmRecursive(cfg.workspace);
27
38
  if (cfg.output) {
28
39
  yield ActiveShellCommand.rmRecursive(cfg.output);
29
40
  }
30
41
  yield ActiveShellCommand.mkdir(cfg.workspace);
31
42
  } else {
32
- yield [title];
33
43
  await fs.rm(cfg.workspace, { recursive: true, force: true });
34
44
  if (cfg.output) {
35
45
  await fs.rm(cfg.output, { recursive: true, force: true });
@@ -38,14 +48,18 @@ export class PackOperation {
38
48
  }
39
49
  }
40
50
 
51
+ /**
52
+ * Invoke bundler (rollup) to produce output in workspace folder
53
+ */
41
54
  static async * bundle(cfg: CommonPackConfig): AsyncIterable<string[]> {
42
55
  const cwd = RootIndex.outputRoot;
43
56
 
44
57
  const bundleCommand = ['npx', 'rollup', '-c', 'node_modules/@travetto/pack/support/bin/rollup.js'];
45
58
 
59
+ const entryPointFile = RootIndex.getFromImport(cfg.entryPoint)!.outputFile.split(`${RootIndex.manifest.outputFolder}/`)[1];
60
+
46
61
  const env = Object.fromEntries(([
47
- ['BUNDLE_ENTRY', cfg.entryPoint],
48
- ['BUNDLE_ENTRY_NAME', cfg.entryCommand],
62
+ ['BUNDLE_ENTRY', entryPointFile],
49
63
  ['BUNDLE_COMPRESS', cfg.minify],
50
64
  ['BUNDLE_SOURCEMAP', cfg.sourcemap],
51
65
  ['BUNDLE_SOURCES', cfg.includeSources],
@@ -60,10 +74,9 @@ export class PackOperation {
60
74
  const props = (['minify', 'sourcemap', 'entryPoint'] as const)
61
75
  .map(k => cliTpl`${{ subtitle: k }}=${{ param: cfg[k] }}`).join(' ');
62
76
 
63
- const title = cliTpl`${{ title: 'Bundling Output' }} ${props}`;
77
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Bundling Output' }} ${props}`);
64
78
 
65
79
  if (cfg.ejectFile) {
66
- yield ActiveShellCommand.comment(title);
67
80
  yield* Object.entries(env).filter(x => !!x[1]).map(x =>
68
81
  ActiveShellCommand.export(x[0], x[1])
69
82
  );
@@ -71,24 +84,25 @@ export class PackOperation {
71
84
  yield bundleCommand;
72
85
  yield ActiveShellCommand.chdir(path.cwd());
73
86
  } else {
74
- yield [title];
75
87
  await ExecUtil.spawn(bundleCommand[0], bundleCommand.slice(1), { cwd, env, stdio: ['inherit', 'pipe', 'pipe'] }).result;
76
88
  }
77
89
  }
78
90
 
91
+ /**
92
+ * Write out package.json, to help define how output .js file should be interpreted
93
+ */
79
94
  static async * writePackageJson(cfg: CommonPackConfig): AsyncIterable<string[]> {
80
95
  const file = 'package.json';
81
- const title = cliTpl`${{ title: 'Writing' }} ${{ path: file }}`;
82
96
  const pkg = { type: RootIndex.manifest.moduleType };
83
97
 
98
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Writing' }} ${{ path: file }}`);
99
+
84
100
  if (cfg.ejectFile) {
85
- yield ActiveShellCommand.comment(title);
86
101
  yield* ActiveShellCommand.createFile(
87
102
  path.resolve(cfg.workspace, file),
88
103
  [JSON.stringify(pkg)]
89
104
  );
90
105
  } else {
91
- yield [title];
92
106
  await writeRawFile(
93
107
  path.resolve(cfg.workspace, file),
94
108
  JSON.stringify(pkg, null, 2)
@@ -96,22 +110,24 @@ export class PackOperation {
96
110
  }
97
111
  }
98
112
 
113
+ /**
114
+ * Define .env.js file to control manifest location
115
+ */
99
116
  static async * writeEnv(cfg: CommonPackConfig): AsyncIterable<string[]> {
100
117
  const file = '.env.js';
101
- const title = cliTpl`${{ title: 'Writing' }} ${{ path: file }}`;
102
118
  const env = {
103
119
  TRV_MANIFEST: `node_modules/${cfg.module}`,
104
120
  TRV_CLI_IPC: ''
105
121
  };
106
122
 
123
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Writing' }} ${{ path: file }}`);
124
+
107
125
  if (cfg.ejectFile) {
108
- yield ActiveShellCommand.comment(title);
109
126
  yield* ActiveShellCommand.createFile(
110
127
  path.resolve(cfg.workspace, file),
111
128
  PackUtil.buildEnvJS(env)
112
129
  );
113
130
  } else {
114
- yield [title];
115
131
  await writeRawFile(
116
132
  path.resolve(cfg.workspace, file),
117
133
  PackUtil.buildEnvJS(env).join('\n')
@@ -119,6 +135,9 @@ export class PackOperation {
119
135
  }
120
136
  }
121
137
 
138
+ /**
139
+ * Create launcher scripts (.sh, .cmd) to run output
140
+ */
122
141
  static async * writeEntryScript(cfg: CommonPackConfig): AsyncIterable<string[]> {
123
142
  const title = 'Writing entry scripts';
124
143
 
@@ -129,23 +148,26 @@ export class PackOperation {
129
148
  text: [
130
149
  ShellCommands[type].scriptOpen(),
131
150
  ShellCommands[type].chdirScript(),
132
- ShellCommands[type].callCommandWithAllArgs('node', cfg.entryCommand, ...cfg.entryArguments),
151
+ ShellCommands[type].callCommandWithAllArgs('node', cfg.entrySource, ...cfg.entryArguments),
133
152
  ].map(x => x.join(' '))
134
153
  }));
135
154
 
136
155
  if (cfg.ejectFile) {
137
156
  for (const { fileTitle, text, file } of files) {
138
- yield ActiveShellCommand.comment(fileTitle);
157
+ yield* PackOperation.title(cfg, fileTitle);
139
158
  yield* ActiveShellCommand.createFile(path.resolve(cfg.workspace, file), text, '755');
140
159
  }
141
160
  } else {
142
161
  for (const { fileTitle, text, file } of files) {
143
- yield [fileTitle];
162
+ yield* PackOperation.title(cfg, fileTitle);
144
163
  await writeRawFile(path.resolve(cfg.workspace, file), text.join('\n'), '755');
145
164
  }
146
165
  }
147
166
  }
148
167
 
168
+ /**
169
+ * Copy over /resources folder into workspace, will get packaged into final output
170
+ */
149
171
  static async * copyResources(cfg: CommonPackConfig): AsyncIterable<string[]> {
150
172
  const resources = {
151
173
  count: RootIndex.mainModule.files.resources?.length ?? 0,
@@ -162,10 +184,9 @@ export class PackOperation {
162
184
  destFolder: path.resolve(cfg.workspace, mod.outputFolder)
163
185
  }));
164
186
 
165
- const title = cliTpl`${{ title: 'Copying over resources' }}`;
187
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Copying over resources' }}`);
166
188
 
167
189
  if (cfg.ejectFile) {
168
- yield ActiveShellCommand.comment(title);
169
190
  yield* copyFiles.flatMap(mod => [
170
191
  ActiveShellCommand.mkdir(path.dirname(mod.dest)),
171
192
  ActiveShellCommand.copy(mod.src, mod.dest)
@@ -174,8 +195,6 @@ export class PackOperation {
174
195
  yield ActiveShellCommand.copyRecursive(resources.src, path.resolve(cfg.workspace, 'resources'));
175
196
  }
176
197
  } else {
177
- yield [title];
178
-
179
198
  for (const { src, dest, destFolder } of copyFiles) {
180
199
  await fs.mkdir(destFolder, { recursive: true });
181
200
  await fs.copyFile(src, dest);
@@ -188,25 +207,26 @@ export class PackOperation {
188
207
  }
189
208
  }
190
209
 
210
+ /**
211
+ * Generate the trv-app-cache.json for @travetto/app, which is needed for 'running' programs
212
+ */
191
213
  static async * primeAppCache(cfg: CommonPackConfig): AsyncIterable<string[]> {
192
- const isCli = cfg.entryCommand === 'cli';
193
- if (!isCli || !RootIndex.hasModule('@travetto/app')) {
214
+ const isRun = /entry[.]cli/.test(cfg.entryPoint) && cfg.entryArguments.filter(x => !x.startsWith('-'))[0] === 'run';
215
+ if (!isRun) {
194
216
  return;
195
217
  }
196
218
 
197
219
  const appCacheCmd = ['npx', 'trv', 'main', '@travetto/app/support/bin/list'];
198
220
  const sub = path.join(RootIndex.manifest.modules[RootIndex.mainModule.name].outputFolder, 'trv-app-cache.json');
199
- const title = cliTpl`${{ title: 'Generating App Cache' }} ${{ path: sub }}`;
200
221
  const env = { DEBUG: '0', TRV_MODULE: cfg.module };
201
222
  const appCache = path.resolve(cfg.workspace, sub);
202
223
 
224
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Generating App Cache' }} ${{ path: sub }}`);
203
225
 
204
226
  if (cfg.ejectFile) {
205
- yield ActiveShellCommand.comment(title);
206
227
  yield ActiveShellCommand.mkdir(path.dirname(appCache));
207
228
  yield [...Object.entries(env).map(x => `${x[0]}=${x[1]}`), ...appCacheCmd, '>', appCache];
208
229
  } else {
209
- yield [title];
210
230
  const { stdout } = await ExecUtil.spawn(appCacheCmd[0], appCacheCmd.slice(1), { env }).result;
211
231
 
212
232
  await fs.mkdir(path.dirname(appCache), { recursive: true });
@@ -214,42 +234,37 @@ export class PackOperation {
214
234
  }
215
235
  }
216
236
 
237
+ /**
238
+ * Produce the output manifest, only including prod dependencies
239
+ */
217
240
  static async * writeManifest(cfg: CommonPackConfig): AsyncIterable<string[]> {
218
241
  const out = path.resolve(cfg.workspace, 'node_modules', cfg.module);
219
242
  const cmd = ['npx', 'trv', 'manifest', out, 'prod'];
220
243
  const env = { TRV_MODULE: cfg.module };
221
- const title = cliTpl`${{ title: 'Writing Manifest' }} ${{ path: path.join('node_modules', cfg.module) }}`;
244
+
245
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Writing Manifest' }} ${{ path: path.join('node_modules', cfg.module) }}`);
222
246
 
223
247
  if (cfg.ejectFile) {
224
- yield ActiveShellCommand.comment(title);
225
248
  yield [...Object.entries(env).map(([k, v]) => `${k}=${v}`), ...cmd];
226
249
  } else {
227
- yield [title];
228
250
  await ExecUtil.spawn(cmd[0], cmd.slice(1), { env, stdio: ['inherit', 'ignore', 'inherit'] }).result;
229
251
  }
230
252
  }
231
253
 
254
+ /**
255
+ * Generate ZIP file for workspace
256
+ */
232
257
  static async * compress(cfg: CommonPackConfig): AsyncIterable<string[]> {
233
- const title = cliTpl`${{ title: 'Compressing' }} ${{ path: cfg.output }}`;
258
+
259
+ yield* PackOperation.title(cfg, cliTpl`${{ title: 'Compressing' }} ${{ path: cfg.output }}`);
234
260
 
235
261
  if (cfg.ejectFile) {
236
- yield ActiveShellCommand.comment(title);
237
262
  yield ActiveShellCommand.chdir(cfg.workspace);
238
263
  yield ActiveShellCommand.zip(cfg.output);
239
264
  yield ActiveShellCommand.chdir(path.cwd());
240
265
  } else {
241
- yield [title];
242
266
  const [cmd, ...args] = ActiveShellCommand.zip(cfg.output);
243
267
  await ExecUtil.spawn(cmd, args, { cwd: cfg.workspace }).result;
244
268
  }
245
269
  }
246
-
247
-
248
- static async * runOperations<S>(cfg: S, operations: ((config: S) => AsyncIterable<string[]>)[]): AsyncIterable<string> {
249
- for (const op of operations) {
250
- for await (const msg of op(cfg)) {
251
- yield msg.join(' ');
252
- }
253
- }
254
- }
255
270
  }
@@ -27,6 +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
31
  zip: (outputFile) => ['powershell', 'Compress-Archive', '-Path', '.', '-DestinationPath', outputFile]
31
32
  },
32
33
  posix: {
@@ -46,6 +47,7 @@ export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
46
47
  export: (key, value) => ['export', `${key}=${value}`],
47
48
  chdir: (dest) => ['cd', dest],
48
49
  comment: (message) => ['\n#', stripAnsiCodes(message), '\n'],
50
+ echo: (message) => ['echo', `"${escape(stripAnsiCodes(message))}\n"`],
49
51
  zip: (outputFile) => ['zip', '-r', outputFile, '.']
50
52
  },
51
53
  };
@@ -10,6 +10,7 @@ export type CommonPackConfig = {
10
10
  // Bundle
11
11
  entryPoint: string;
12
12
  entryCommand: string;
13
+ entrySource: string;
13
14
  entryArguments: string[];
14
15
  minify: boolean;
15
16
  sourcemap: boolean;
@@ -24,7 +25,6 @@ export type CommonPackOptions = {
24
25
 
25
26
  // Bundle
26
27
  entryPoint: OptionConfig<string>;
27
- entryCommand: OptionConfig<string>;
28
28
  minify: OptionConfig<boolean>;
29
29
  sourcemap: OptionConfig<boolean>;
30
30
  includeSources: OptionConfig<boolean>;
@@ -63,6 +63,7 @@ export type ShellCommandImpl = {
63
63
  export(key: string, value: string): string[];
64
64
  chdir(dest: string): string[];
65
65
  comment(message: string): string[];
66
+ echo(text: string): string[];
66
67
  zip(output: string): string[];
67
68
  };
68
69
 
@@ -1,3 +1,5 @@
1
+ import { path, RootIndex } from '@travetto/manifest';
2
+
1
3
  import { DockerPackConfig, DockerPackOptions } from './bin/types';
2
4
  import { DockerPackOperation } from './bin/docker-operation';
3
5
  import { BasePackCommand, PackOperationShape } from './pack.base';
@@ -24,6 +26,16 @@ export class PackDockerCommand extends BasePackCommand<DockerPackOptions, Docker
24
26
  };
25
27
  }
26
28
 
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;
33
+ }
34
+ cfg.dockerPort ??= [];
35
+ cfg.dockerTag ??= [];
36
+ return cfg;
37
+ }
38
+
27
39
  getOperations(): PackOperationShape<DockerPackConfig>[] {
28
40
  return [
29
41
  ...super.getOperations(),
@@ -11,24 +11,50 @@ import { PackUtil } from './bin/util';
11
11
 
12
12
  export type PackOperationShape<T extends CommonPackConfig> = ((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
+ ];
24
+
14
25
  export abstract class BasePackCommand<T extends CommonPackOptions, S extends CommonPackConfig> extends CliCommand<{}> {
15
26
 
16
27
  get monoRoot(): boolean {
17
28
  return !!RootIndex.manifest.monoRepo && path.cwd() === RootIndex.manifest.workspacePath;
18
29
  }
19
30
 
31
+ get entries(): string[] {
32
+ return RootIndex.findSupport({ filter: x => x.includes('entry.') })
33
+ .map(x => x.import.replace(/[.][^.]+s$/, ''));
34
+ }
35
+
36
+ /**
37
+ * Add help output
38
+ */
39
+ async help(): Promise<string> {
40
+ const entryPoints = this.entries.map(x => cliTpl`${{ subtitle: '*' }} ${{ identifier: x }}`);
41
+
42
+ return ['', cliTpl`${{ title: 'Available Entry Points:' }}`, '', ...entryPoints, ''].join('\n');
43
+ }
44
+
45
+
20
46
  getArgs(): string | undefined {
21
47
  return this.monoRoot ? '<module> [args...]' : '[args...]';
22
48
  }
23
49
 
24
50
  getCommonOptions(): CommonPackOptions {
51
+ const entries = this.entries;
52
+ const mainEntry = this.entries.find(x => x.startsWith('@travetto/cli'))!;
25
53
  return {
26
54
  workspace: this.option({ short: 'w', desc: 'Workspace for building' }),
27
55
  clean: this.boolOption({ short: 'c', desc: 'Clean workspace', def: true }),
28
56
  output: this.option({ short: 'o', desc: 'Output Location' }),
29
-
30
- entryPoint: this.option({ short: 'e', desc: 'Entry point', def: 'node_modules/@travetto/cli/support/cli.js' }),
31
- entryCommand: this.option({ short: 'ec', desc: 'Entry command' }),
57
+ entryPoint: this.choiceOption({ short: 'e', desc: 'Entry point', def: mainEntry, choices: entries }),
32
58
  minify: this.boolOption({ short: 'm', desc: 'Minify output', def: true }),
33
59
  sourcemap: this.boolOption({ short: 'sm', desc: 'Bundle source maps' }),
34
60
  includeSources: this.boolOption({ short: 'is', desc: 'Include source with source maps' }),
@@ -48,25 +74,21 @@ export abstract class BasePackCommand<T extends CommonPackOptions, S extends Com
48
74
  }
49
75
 
50
76
  getOperations(): PackOperationShape<S>[] {
51
- const ops: ((config: S) => AsyncIterable<string[]>)[] = [];
77
+ return BASIC_OP_SET.slice(0);
78
+ }
52
79
 
53
- if (this.cmd.clean) {
54
- ops.push(PackOperation.clean);
80
+ /**
81
+ * Run all operations
82
+ */
83
+ async * runOperations(cfg: S): AsyncIterable<string> {
84
+ for (const op of this.getOperations()) {
85
+ for await (const msg of op(cfg)) {
86
+ yield msg.join(' ');
87
+ }
55
88
  }
56
-
57
- ops.push(
58
- PackOperation.writeEnv,
59
- PackOperation.writePackageJson,
60
- PackOperation.writeEntryScript,
61
- PackOperation.copyResources,
62
- PackOperation.primeAppCache,
63
- PackOperation.writeManifest,
64
- PackOperation.bundle,
65
- );
66
-
67
- return ops;
68
89
  }
69
90
 
91
+
70
92
  getModule(moduleName: string): string {
71
93
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
72
94
  let module = this.monoRoot ? moduleName : RootIndex.mainModule.name;
@@ -82,15 +104,20 @@ export abstract class BasePackCommand<T extends CommonPackOptions, S extends Com
82
104
 
83
105
  async buildConfig(): Promise<S> {
84
106
  this.cmd.workspace ??= path.resolve(os.tmpdir(), RootIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
85
- this.cmd.entryCommand ??= path.basename(this.cmd.entryPoint).replace(/[.][tj]s$/, '');
107
+ this.cmd.entrySource = `${path.basename(this.cmd.entryPoint)}.js`;
108
+ this.cmd.entryCommand = path.basename(this.cmd.entryPoint).replace(/entry[.]/, '');
86
109
  this.cmd.module = RootIndex.mainModule.name;
87
110
  return this.cmd;
88
111
  }
89
112
 
90
113
  async action(module: string, args: string[]): Promise<void> {
114
+ if (Array.isArray(module)) {
115
+ args = module;
116
+ module = RootIndex.mainModule.name;
117
+ }
91
118
  const start = Date.now();
92
119
  if (!module && this.monoRoot) {
93
- this.showHelp(new Error('The module needs to specified when running from a monorepo root'));
120
+ return this.showHelp(new Error('The module needs to specified when running from a monorepo root'));
94
121
  }
95
122
 
96
123
  module = this.getModule(module);
@@ -117,7 +144,7 @@ export abstract class BasePackCommand<T extends CommonPackOptions, S extends Com
117
144
  }
118
145
  this.cmd.workspace = path.resolve(this.cmd.workspace);
119
146
 
120
- const stream = PackOperation.runOperations(cfg, this.getOperations());
147
+ const stream = this.runOperations(cfg);
121
148
 
122
149
  // Eject to file
123
150
  if (this.cmd.ejectFile) {
@@ -127,7 +154,13 @@ export abstract class BasePackCommand<T extends CommonPackOptions, S extends Com
127
154
  }
128
155
  await PackUtil.writeEjectOutput(this.cmd.workspace, cfg.module, output, this.cmd.ejectFile);
129
156
  } else {
130
- await GlobalTerminal.streamLinesWithWaiting(stream, { initialDelay: 0, cycleDelay: 100, end: true });
157
+ await GlobalTerminal.streamLinesWithWaiting(stream, {
158
+ initialDelay: 0,
159
+ cycleDelay: 100,
160
+ end: false,
161
+ position: 'inline',
162
+ committedPrefix: String.fromCharCode(171)
163
+ });
131
164
  let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.cmd.module }}`;
132
165
  if (this.cmd.output) {
133
166
  msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.cmd.output }}`;