@travetto/pack 3.0.0-rc.7 → 3.0.0-rc.9

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.
@@ -1,19 +1,70 @@
1
- export type CommonConfig = {
2
- name?: string;
3
- file?: string;
1
+ import { ListOptionConfig, OptionConfig } from '@travetto/cli';
2
+
3
+ export type CommonPackConfig = {
4
4
  workspace: string;
5
- active?: boolean;
6
- postProcess?: { [key: string]: (<T extends CommonConfig>(cfg: T) => Promise<void>) }[];
7
- preProcess?: { [key: string]: (<T extends CommonConfig>(cfg: T) => Promise<void>) }[];
5
+ output: string;
6
+ clean: boolean;
7
+ ejectFile: string;
8
+ module: string;
9
+
10
+ // Bundle
11
+ entryPoint: string;
12
+ entryCommand: string;
13
+ entryArguments: string[];
14
+ minify: boolean;
15
+ sourcemap: boolean;
16
+ includeSources: boolean;
17
+ };
18
+
19
+ export type CommonPackOptions = {
20
+ workspace: OptionConfig<string>;
21
+ output: OptionConfig<string>;
22
+ clean: OptionConfig<boolean>;
23
+ ejectFile: OptionConfig<string>;
24
+
25
+ // Bundle
26
+ entryPoint: OptionConfig<string>;
27
+ entryCommand: OptionConfig<string>;
28
+ minify: OptionConfig<boolean>;
29
+ sourcemap: OptionConfig<boolean>;
30
+ includeSources: OptionConfig<boolean>;
31
+ };
32
+
33
+ export type DockerPackConfig = {
34
+ dockerFactory: string;
35
+ dockerImage: string;
36
+ dockerName: string;
37
+ dockerTag: string[];
38
+ dockerPort: string[];
39
+ dockerPush: boolean;
40
+ dockerRegistry: string;
41
+ } & CommonPackConfig;
42
+
43
+ export type DockerPackOptions = {
44
+ dockerFactory: OptionConfig<string>;
45
+ dockerImage: OptionConfig<string>;
46
+ dockerName: OptionConfig<string>;
47
+ dockerTag: ListOptionConfig<string>;
48
+ dockerPort: ListOptionConfig<string>;
49
+ dockerPush: OptionConfig<boolean>;
50
+ dockerRegistry: OptionConfig<string>;
51
+ } & CommonPackOptions;
52
+
53
+ export type ShellCommandImpl = {
54
+ var(name: string): string;
55
+ createFile(file: string, text: string[], mode?: string): string[][];
56
+ scriptOpen(): string[];
57
+ chdirScript(): string[];
58
+ callCommandWithAllArgs(cmd: string, ...args: string[]): string[];
59
+ copy(src: string, dest: string): string[];
60
+ copyRecursive(src: string, dest: string): string[];
61
+ rmRecursive(dest: string): string[];
62
+ mkdir(dest: string): string[];
63
+ export(key: string, value: string): string[];
64
+ chdir(dest: string): string[];
65
+ comment(message: string): string[];
66
+ zip(output: string): string[];
8
67
  };
9
68
 
10
- export type PackOperation<T extends CommonConfig, K extends string> = {
11
- key: K;
12
- title: string;
13
- defaults?: Partial<T>;
14
- overrides?: Partial<T>;
15
- extend?(src: Partial<T>, dest: Partial<T>): Partial<T>;
16
- context(cfg: T): Promise<string> | string;
17
- exec(cfg: T): AsyncGenerator<string>;
18
- buildConfig(configs: Partial<T>[]): T;
19
- };
69
+ export type DockerPackFactory = (cfg: DockerPackConfig) => (string | Promise<string>);
70
+ export type DockerPackFactoryModule = { factory: DockerPackFactory };
@@ -1,162 +1,19 @@
1
1
  import fs from 'fs/promises';
2
2
 
3
- import glob from 'picomatch';
4
-
5
3
  import { path, RootIndex } from '@travetto/manifest';
6
- import { cliTpl } from '@travetto/cli';
7
4
  import { ExecUtil } from '@travetto/base';
8
- import { stripAnsiCodes } from '@travetto/terminal';
9
5
 
10
- import { CommonConfig, PackOperation } from './types';
6
+ import { ActiveShellCommand } from './shell';
11
7
 
12
- /**
13
- * Shared packing utils
14
- */
15
8
  export class PackUtil {
16
-
17
- static #modes: Partial<CommonConfig>[];
18
-
19
- /**
20
- * Build configuration object for an operation with a set of configs
21
- */
22
- static buildConfig<T extends CommonConfig>(
23
- op: { defaults?: Partial<T>, overrides?: Partial<T>, extend?(src: Partial<T>, dest: Partial<T>): Partial<T> },
24
- configs: Partial<T>[]
25
- ): T {
26
- const inputs = [
27
- op.defaults! ?? {},
28
- ...configs,
29
- op.overrides! ?? {}
30
- ].filter(x => Object.keys(x).length > 0);
31
-
32
- const res = inputs.reduce((out: Partial<T>, config: Partial<T>): Partial<T> => {
33
- const final = {
34
- active: config.active ?? out.active,
35
- workspace: config.workspace ?? out.workspace,
36
- preProcess: [...(config.preProcess! ?? []), ...(out.preProcess ?? [])],
37
- postProcess: [...(config.postProcess! ?? []), ...(out.postProcess ?? [])],
38
- ...op.extend?.(config, out)
39
- };
40
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
41
- return final as Partial<T>;
42
- }, {});
43
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
44
- return res as T;
45
- }
46
-
47
- /**
48
- * Find pack modes with associated metadata
49
- */
50
- static async modeList(): Promise<Partial<CommonConfig>[]> {
51
- if (!this.#modes) {
52
- this.#modes = await Promise.all(
53
- RootIndex.findSupport({ filter: f => /\/pack[.].*[.]/.test(f) })
54
- .map(async (x) => {
55
- const req: Partial<CommonConfig> = (await import(x.output)).config;
56
- req.file = x.import.replace(/^node_modules\//, '');
57
- return req;
58
- })
59
- );
60
- }
61
- return this.#modes;
62
- }
63
-
64
-
65
- /**
66
- * Build file include/exclude lists/checker
67
- */
68
- static excludeChecker(files: string[], base: string): (file: string) => boolean {
69
- const all = files.map(x => {
70
- const negate = x.startsWith('!') || x.startsWith('^');
71
- x = negate ? x.substring(1) : x;
72
- x = x.replace(/^[.][/]/g, `${base}/`);
73
- const match: (f: string) => boolean = glob(x, { nocase: true, dot: true, basename: true, contains: true, cwd: base });
74
- Object.defineProperty(match, 'source', { value: x });
75
- return [match, negate] as const;
76
- });
77
-
78
- return (f: string): boolean => {
79
- let exclude = undefined;
80
- f = path.resolve(base, f);
81
- for (const [match, n] of all) {
82
- if ((n || exclude === undefined) && match(f)) {
83
- if (n) { // Fast exit if negating
84
- return false;
85
- }
86
- exclude = match;
87
- }
88
- }
89
- return !!exclude;
90
- };
91
- }
92
-
93
- /**
94
- * Update .env.js with new env data
95
- */
96
- static async writeEnvJs(workspace: string, env: Record<string, string | undefined>): Promise<void> {
97
- const out = path.resolve(workspace, '.env.js');
98
- let src = '';
99
- if (!!(await fs.stat(out).catch(() => { }))) {
100
- src = await fs.readFile(out, 'utf8');
101
- }
102
- const lines = Object.entries(env).map(([k, v]) => v ? `process.env['${k}'] = \`${v.replace(/`/g, '\\`')}\`;` : '');
103
- const content = `${src}\n${lines.join('\n')}`;
104
- await fs.writeFile(out, content, { encoding: 'utf8' });
105
- }
106
-
107
9
  /**
108
- * Run operation with logging
10
+ * Generate env.js
109
11
  */
110
- static async runOperation<T extends CommonConfig>(op: PackOperation<T, string>, cfg: T, indent = 0): Promise<void> {
111
- const spacer = ' '.repeat(indent);
112
- const ctx = await op.context(cfg);
113
- const title = cliTpl`${{ title: op.title }} ${ctx}`;
114
- const width = Math.max(stripAnsiCodes(title).length, 50); // eslint-disable-line
115
-
116
- let i = 0;
117
- function stdout(msg?: string): void {
118
- if (i++ > 0) {
119
- process.stdout.write(cliTpl`${spacer}${{ param: 'done' }}\n`);
120
- }
121
- if (msg) {
122
- process.stdout.write(cliTpl`${spacer}${{ output: '᳁' }} ${{ path: msg.padEnd(width - 15) }} ... `);
123
- }
124
- }
125
-
126
- async function runPhase(phase: 'preProcess' | 'postProcess'): Promise<void> {
127
- for (const el of cfg[phase] ?? []) {
128
- const [name, fn] = Object.entries(el)[0];
129
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
130
- await stdout(name as string);
131
- await fn(cfg);
132
- }
133
- }
134
-
135
- let message: string | undefined;
136
-
137
- process.stdout.write(`${spacer}${title}\n`);
138
- process.stdout.write(`${spacer}${'-'.repeat(width)}\n`);
139
-
140
- await runPhase('preProcess');
141
-
142
- for await (const msg of op.exec(cfg)) {
143
- if (msg.includes('Success')) { // We are done
144
- message = msg;
145
- break;
146
- } else {
147
- stdout(msg);
148
- }
149
- }
150
-
151
- await runPhase('postProcess');
152
-
153
- // Wrap up
154
- stdout();
155
-
156
- if (message !== undefined) {
157
- process.stdout.write(`${spacer}${'-'.repeat(width)}\n`);
158
- process.stdout.write(`${spacer}${message}\n`);
159
- }
12
+ static buildEnvJS(env: Record<string, string | number | boolean | undefined>): string[] {
13
+ const entries = Object.entries(env)
14
+ .filter(([k, v]) => (v !== undefined))
15
+ .map(([k, v]) => [k, `${v}`]);
16
+ return entries.map(([k, v]) => `process.env.${k} = '${v}';`);
160
17
  }
161
18
 
162
19
  /**
@@ -166,13 +23,41 @@ export class PackUtil {
166
23
  * @param ignore Should errors be ignored
167
24
  */
168
25
  static async copyRecursive(src: string, dest: string, ignore = false): Promise<void> {
169
- const [cmd, args] = process.platform === 'win32' ?
170
- ['xcopy', ['/y', '/h', '/s', path.toNative(src), path.toNative(dest)]] :
171
- ['cp', ['-r', '-p', src, dest]];
172
-
26
+ const [cmd, ...args] = ActiveShellCommand.copyRecursive(src, dest);
173
27
  const res = await ExecUtil.spawn(cmd, args, { catchAsResult: true }).result;
174
28
  if (res.code && !ignore) {
175
29
  throw new Error(`Failed to copy ${src} to ${dest}`);
176
30
  }
177
31
  }
32
+
33
+ /**
34
+ * Finalize eject output
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 = [
50
+ ActiveShellCommand.scriptOpen(),
51
+ ...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
+ ].join('\n');
55
+
56
+ if (file === '-' || file === '/dev/stdout') {
57
+ console.log!(content);
58
+ } else {
59
+ await fs.mkdir(path.dirname(file), { recursive: true });
60
+ await fs.writeFile(file, content, 'utf8');
61
+ }
62
+ }
178
63
  }
@@ -1,10 +1,14 @@
1
- import { BaseOptions, BasePackCommand } from './cli.pack-base';
2
- import { Pack, AllConfig } from './bin/pack';
1
+ import { BasePackCommand } from './pack.base';
2
+ import { CommonPackConfig, CommonPackOptions } from './bin/types';
3
3
 
4
- export class PackCommand extends BasePackCommand<BaseOptions, AllConfig, ''> {
5
- operation = Pack;
4
+ /**
5
+ * Standard pack support
6
+ */
7
+ export class PackCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
6
8
 
7
- getOptions(): BaseOptions {
8
- return this.commonOptions();
9
+ name = 'pack';
10
+
11
+ getOptions(): CommonPackOptions {
12
+ return this.getCommonOptions();
9
13
  }
10
14
  }
@@ -1,29 +1,36 @@
1
- import { OptionConfig, ListOptionConfig } from '@travetto/cli';
1
+ import { DockerPackConfig, DockerPackOptions } from './bin/types';
2
+ import { DockerPackOperation } from './bin/docker-operation';
3
+ import { BasePackCommand, PackOperationShape } from './pack.base';
2
4
 
3
- import { BaseOptions, BasePackCommand } from './cli.pack-base';
4
- import { Docker, DockerConfig } from './bin/docker';
5
5
 
6
- type Options = BaseOptions & {
7
- image: OptionConfig<string>;
8
- name: OptionConfig<string>;
9
- tag: ListOptionConfig<string>;
10
- port: ListOptionConfig<string>;
11
- push: OptionConfig<boolean>;
12
- registry: OptionConfig<string>;
13
- };
6
+ /**
7
+ * Standard docker support for pack
8
+ */
9
+ export class PackDockerCommand extends BasePackCommand<DockerPackOptions, DockerPackConfig> {
14
10
 
15
- export class PackDockerCommand extends BasePackCommand<Options, DockerConfig, 'docker'> {
16
- operation = Docker;
11
+ name = 'pack:docker';
17
12
 
18
- getOptions(): Options {
13
+ getOptions(): DockerPackOptions {
14
+ const opts = this.getCommonOptions();
19
15
  return {
20
- ...this.commonOptions(),
21
- image: this.option({ desc: 'Docker Image to extend' }),
22
- name: this.option({ desc: 'Image Name' }),
23
- tag: this.listOption({ desc: 'Image Tag' }),
24
- port: this.listOption({ desc: 'Image Port' }),
25
- push: this.boolOption({ short: 'x', desc: 'Push Tags' }),
26
- registry: this.option({ desc: 'Registry' })
16
+ ...opts,
17
+ dockerFactory: this.option({ short: 'df', desc: 'Docker Factory source', def: '@travetto/pack/support/pack.dockerfile' }),
18
+ dockerImage: this.option({ short: 'di', desc: 'Docker Image to extend', def: 'node:18-alpine3.16' }),
19
+ dockerName: this.option({ short: 'dn', desc: 'Docker Image Name', def: this.monoRoot ? '<module>' : this.getSimpleModuleName() }),
20
+ dockerTag: this.listOption({ short: 'dt', desc: 'Docker Image Tag', def: ['latest'] }),
21
+ dockerPort: this.listOption({ short: 'dp', desc: 'Docker Image Port' }),
22
+ dockerPush: this.boolOption({ short: 'dx', desc: 'Docker Push Tags' }),
23
+ dockerRegistry: this.option({ short: 'dr', desc: 'Docker Registry' })
27
24
  };
28
25
  }
26
+
27
+ getOperations(): PackOperationShape<DockerPackConfig>[] {
28
+ return [
29
+ ...super.getOperations(),
30
+ DockerPackOperation.writeDockerFile,
31
+ DockerPackOperation.pullDockerBaseImage,
32
+ DockerPackOperation.buildDockerContainer,
33
+ DockerPackOperation.pushDockerContainer
34
+ ];
35
+ }
29
36
  }
@@ -1,19 +1,24 @@
1
- import { OptionConfig } from '@travetto/cli';
1
+ import { CommonPackConfig, CommonPackOptions } from './bin/types';
2
+ import { PackOperation } from './bin/operation';
3
+ import { BasePackCommand, PackOperationShape } from './pack.base';
2
4
 
3
- import { BaseOptions, BasePackCommand } from './cli.pack-base';
4
- import { Zip, ZipConfig } from './bin/zip';
5
+ /**
6
+ * Standard zip support for pack
7
+ */
8
+ export class PackZipCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
5
9
 
6
- type Options = BaseOptions & {
7
- output: OptionConfig<string>;
8
- };
10
+ name = 'pack:zip';
9
11
 
10
- export class PackZipCommand extends BasePackCommand<Options, ZipConfig, 'zip'> {
11
- operation = Zip;
12
+ getOptions(): CommonPackOptions {
13
+ const opts = this.getCommonOptions();
14
+ opts.output.def = this.monoRoot ? '<module>.zip' : `${this.getSimpleModuleName()}.zip`;
15
+ return opts;
16
+ }
12
17
 
13
- getOptions(): Options {
14
- return {
15
- ...this.commonOptions(),
16
- output: this.option({ desc: 'Output File' })
17
- };
18
+ getOperations(): PackOperationShape<CommonPackConfig>[] {
19
+ return [
20
+ ...super.getOperations(),
21
+ PackOperation.compress
22
+ ];
18
23
  }
19
24
  }
@@ -0,0 +1,138 @@
1
+ import os from 'os';
2
+
3
+ import { CliCommand, cliTpl } from '@travetto/cli';
4
+ import { path, RootIndex } from '@travetto/manifest';
5
+ import { TimeUtil } from '@travetto/base';
6
+ import { GlobalTerminal } from '@travetto/terminal';
7
+
8
+ import { CommonPackConfig, CommonPackOptions } from './bin/types';
9
+ import { PackOperation } from './bin/operation';
10
+ import { PackUtil } from './bin/util';
11
+
12
+ export type PackOperationShape<T extends CommonPackConfig> = ((config: T) => AsyncIterable<string[]>);
13
+
14
+ export abstract class BasePackCommand<T extends CommonPackOptions, S extends CommonPackConfig> extends CliCommand<{}> {
15
+
16
+ get monoRoot(): boolean {
17
+ return !!RootIndex.manifest.monoRepo && path.cwd() === RootIndex.manifest.workspacePath;
18
+ }
19
+
20
+ getArgs(): string | undefined {
21
+ return this.monoRoot ? '<module> [args...]' : '[args...]';
22
+ }
23
+
24
+ getCommonOptions(): CommonPackOptions {
25
+ return {
26
+ workspace: this.option({ short: 'w', desc: 'Workspace for building' }),
27
+ clean: this.boolOption({ short: 'c', desc: 'Clean workspace', def: true }),
28
+ 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' }),
32
+ minify: this.boolOption({ short: 'm', desc: 'Minify output', def: true }),
33
+ sourcemap: this.boolOption({ short: 'sm', desc: 'Bundle source maps' }),
34
+ includeSources: this.boolOption({ short: 'is', desc: 'Include source with source maps' }),
35
+ ejectFile: this.option({ short: 'x', desc: 'Eject commands to file' }),
36
+ };
37
+ }
38
+
39
+ abstract getOptions(): T;
40
+
41
+ get cmd(): S {
42
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
43
+ return super.cmd as S;
44
+ }
45
+
46
+ getSimpleModuleName(): string {
47
+ return RootIndex.mainPackage.name.replace(/[\/]/, '_').replace(/@/, '');
48
+ }
49
+
50
+ getOperations(): PackOperationShape<S>[] {
51
+ const ops: ((config: S) => AsyncIterable<string[]>)[] = [];
52
+
53
+ if (this.cmd.clean) {
54
+ ops.push(PackOperation.clean);
55
+ }
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
+ }
69
+
70
+ getModule(moduleName: string): string {
71
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
72
+ let module = this.monoRoot ? moduleName : RootIndex.mainModule.name;
73
+ module = RootIndex.getModuleByFolder(module)?.name ?? module;
74
+
75
+ // Reinitialize for module
76
+ if (this.monoRoot) {
77
+ RootIndex.reinitForModule(module);
78
+ }
79
+
80
+ return module;
81
+ }
82
+
83
+ async buildConfig(): Promise<S> {
84
+ this.cmd.workspace ??= path.resolve(os.tmpdir(), RootIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
85
+ this.cmd.entryCommand ??= path.basename(this.cmd.entryPoint).replace(/[.][tj]s$/, '');
86
+ this.cmd.module = RootIndex.mainModule.name;
87
+ return this.cmd;
88
+ }
89
+
90
+ async action(module: string, args: string[]): Promise<void> {
91
+ const start = Date.now();
92
+ if (!module && this.monoRoot) {
93
+ this.showHelp(new Error('The module needs to specified when running from a monorepo root'));
94
+ }
95
+
96
+ module = this.getModule(module);
97
+
98
+ const cfg = await this.buildConfig();
99
+ cfg.entryArguments = Array.isArray(args) ? args : [];
100
+
101
+ for (const k in this.cmd) {
102
+ if (Object.hasOwn(this.cmd, k)) {
103
+ const v = this.cmd[k];
104
+ if (typeof v === 'string' && /<module>/.test(v)) {
105
+ // @ts-expect-error
106
+ this.cmd[k] = v.replace(/<module>/g, this.getSimpleModuleName());
107
+ }
108
+ }
109
+ }
110
+
111
+ // Resolve all files to absolute paths
112
+ if (this.cmd.output) {
113
+ this.cmd.output = path.resolve(this.cmd.output);
114
+ }
115
+ if (this.cmd.ejectFile) {
116
+ this.cmd.ejectFile = path.resolve(this.cmd.ejectFile);
117
+ }
118
+ this.cmd.workspace = path.resolve(this.cmd.workspace);
119
+
120
+ const stream = PackOperation.runOperations(cfg, this.getOperations());
121
+
122
+ // Eject to file
123
+ if (this.cmd.ejectFile) {
124
+ const output: string[] = [];
125
+ for await (const line of stream) {
126
+ output.push(line);
127
+ }
128
+ await PackUtil.writeEjectOutput(this.cmd.workspace, cfg.module, output, this.cmd.ejectFile);
129
+ } else {
130
+ await GlobalTerminal.streamLinesWithWaiting(stream, { initialDelay: 0, cycleDelay: 100, end: true });
131
+ let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.cmd.module }}`;
132
+ if (this.cmd.output) {
133
+ msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.cmd.output }}`;
134
+ }
135
+ await GlobalTerminal.writeLines(msg);
136
+ }
137
+ }
138
+ }
@@ -0,0 +1,9 @@
1
+ import { DockerPackFactory } from './bin/types';
2
+
3
+ export const factory: DockerPackFactory = cfg => `
4
+ FROM ${cfg.dockerImage}
5
+ WORKDIR /app
6
+ COPY . .
7
+ ${cfg.dockerPort.map(port => `EXPOSE ${port}`).join('\n')}
8
+ ENTRYPOINT ["/app/${cfg.entryCommand}.sh"]
9
+ `;
@@ -1,59 +0,0 @@
1
- import fs from 'fs/promises';
2
-
3
- import { path } from '@travetto/manifest';
4
- import { cliTpl } from '@travetto/cli';
5
- import { Env } from '@travetto/base';
6
-
7
- import { PackUtil } from '../util';
8
- import { CommonConfig, PackOperation } from '../types';
9
- import { AssembleUtil } from './util';
10
- export interface AssembleConfig extends CommonConfig {
11
- keepSource: boolean;
12
- readonly: boolean;
13
- add: Record<string, string>[];
14
- exclude: string[];
15
- env: Record<string, string | undefined>;
16
- }
17
-
18
- /**
19
- * Utils for packing source code and minimizing space usage
20
- */
21
- export const Assemble: PackOperation<AssembleConfig, 'assemble'> = {
22
- key: 'assemble',
23
- title: 'Assembling',
24
- context(cfg: AssembleConfig) {
25
- return `[readonly=${cfg.readonly},source=${cfg.keepSource}]`;
26
- },
27
- overrides: {
28
- keepSource: Env.getBoolean('PACK_ASSEMBLE_KEEP_SOURCE'),
29
- readonly: Env.getBoolean('PACK_ASSEMBLE_READONLY')
30
- },
31
- extend(src: Partial<AssembleConfig>, dest: Partial<AssembleConfig>): Partial<AssembleConfig> {
32
- return {
33
- keepSource: src.keepSource ?? dest.keepSource,
34
- readonly: src.readonly ?? dest.readonly,
35
- add: [...(src.add ?? []), ...(dest.add ?? [])],
36
- exclude: [...(src.exclude ?? []), ...(dest.exclude ?? [])],
37
- env: { ...(src.env ?? {}), ...(dest.env ?? {}) },
38
- };
39
- },
40
- buildConfig(configs: Partial<AssembleConfig>[]): AssembleConfig {
41
- return PackUtil.buildConfig(this, configs);
42
- },
43
- /**
44
- * Assemble the project into a workspace directory, optimized for space and runtime
45
- */
46
- async * exec({ workspace, add, exclude, env, keepSource }: AssembleConfig) {
47
- const ws = path.resolve(workspace!);
48
- yield 'Cleaning Workspace'; {
49
- await fs.rm(ws, { recursive: true, force: true }).catch(() => { });
50
- await fs.mkdir(ws);
51
- }
52
- yield 'Create Entrypoint'; await AssembleUtil.copyEntryPoint(ws);
53
- yield 'Copying Prod Dependencies'; await AssembleUtil.copyProdDependencies(ws, keepSource);
54
- yield 'Excluding Files'; await AssembleUtil.excludeFiles(ws, exclude);
55
- yield 'Copying Added Content'; await AssembleUtil.copyAddedContent(ws, add);
56
- yield 'Removing Empty Folders'; await AssembleUtil.removeEmptyFolders(ws);
57
- yield cliTpl`${{ success: 'Successfully' }} assembled project at ${{ path: workspace }}`;
58
- }
59
- };