@travetto/pack 3.0.0-rc.2 → 3.0.0-rc.20

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.
@@ -0,0 +1,70 @@
1
+ import { ListOptionConfig, OptionConfig } from '@travetto/cli';
2
+
3
+ export type CommonPackConfig = {
4
+ workspace: string;
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[];
67
+ };
68
+
69
+ export type DockerPackFactory = (cfg: DockerPackConfig) => (string | Promise<string>);
70
+ export type DockerPackFactoryModule = { factory: DockerPackFactory };
@@ -0,0 +1,63 @@
1
+ import fs from 'fs/promises';
2
+
3
+ import { path, RootIndex } from '@travetto/manifest';
4
+ import { ExecUtil } from '@travetto/base';
5
+
6
+ import { ActiveShellCommand } from './shell';
7
+
8
+ export class PackUtil {
9
+ /**
10
+ * Generate env.js
11
+ */
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}';`);
17
+ }
18
+
19
+ /**
20
+ * Remove directory, determine if errors should be ignored
21
+ * @param src The folder to copy
22
+ * @param dest The folder to copy to
23
+ * @param ignore Should errors be ignored
24
+ */
25
+ static async copyRecursive(src: string, dest: string, ignore = false): Promise<void> {
26
+ const [cmd, ...args] = ActiveShellCommand.copyRecursive(src, dest);
27
+ const res = await ExecUtil.spawn(cmd, args, { catchAsResult: true }).result;
28
+ if (res.code && !ignore) {
29
+ throw new Error(`Failed to copy ${src} to ${dest}`);
30
+ }
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
+ }
63
+ }
@@ -0,0 +1,14 @@
1
+ import { BasePackCommand } from './pack.base';
2
+ import { CommonPackConfig, CommonPackOptions } from './bin/types';
3
+
4
+ /**
5
+ * Standard pack support
6
+ */
7
+ export class PackCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
8
+
9
+ name = 'pack';
10
+
11
+ getOptions(): CommonPackOptions {
12
+ return this.getCommonOptions();
13
+ }
14
+ }
@@ -0,0 +1,48 @@
1
+ import { path, RootIndex } from '@travetto/manifest';
2
+
3
+ import { DockerPackConfig, DockerPackOptions } from './bin/types';
4
+ import { DockerPackOperation } from './bin/docker-operation';
5
+ import { BasePackCommand, PackOperationShape } from './pack.base';
6
+
7
+
8
+ /**
9
+ * Standard docker support for pack
10
+ */
11
+ export class PackDockerCommand extends BasePackCommand<DockerPackOptions, DockerPackConfig> {
12
+
13
+ name = 'pack:docker';
14
+
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
+ }
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
+
39
+ getOperations(): PackOperationShape<DockerPackConfig>[] {
40
+ return [
41
+ ...super.getOperations(),
42
+ DockerPackOperation.writeDockerFile,
43
+ DockerPackOperation.pullDockerBaseImage,
44
+ DockerPackOperation.buildDockerContainer,
45
+ DockerPackOperation.pushDockerContainer
46
+ ];
47
+ }
48
+ }
@@ -0,0 +1,24 @@
1
+ import { CommonPackConfig, CommonPackOptions } from './bin/types';
2
+ import { PackOperation } from './bin/operation';
3
+ import { BasePackCommand, PackOperationShape } from './pack.base';
4
+
5
+ /**
6
+ * Standard zip support for pack
7
+ */
8
+ export class PackZipCommand extends BasePackCommand<CommonPackOptions, CommonPackConfig> {
9
+
10
+ name = 'pack:zip';
11
+
12
+ getOptions(): CommonPackOptions {
13
+ const opts = this.getCommonOptions();
14
+ opts.output.def = this.monoRoot ? '<module>.zip' : `${this.getSimpleModuleName()}.zip`;
15
+ return opts;
16
+ }
17
+
18
+ getOperations(): PackOperationShape<CommonPackConfig>[] {
19
+ return [
20
+ ...super.getOperations(),
21
+ PackOperation.compress
22
+ ];
23
+ }
24
+ }
@@ -0,0 +1,150 @@
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
+ 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
+
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
+ getArgs(): string | undefined {
32
+ return this.monoRoot ? '<module> [args...]' : '[args...]';
33
+ }
34
+
35
+ getCommonOptions(): CommonPackOptions {
36
+ return {
37
+ workspace: this.option({ short: 'w', desc: 'Workspace for building' }),
38
+ clean: this.boolOption({ short: 'c', desc: 'Clean workspace', def: true }),
39
+ output: this.option({ short: 'o', desc: 'Output Location' }),
40
+
41
+ entryPoint: this.option({ short: 'e', desc: 'Entry point', def: 'node_modules/@travetto/cli/support/cli.js' }),
42
+ entryCommand: this.option({ short: 'ec', desc: 'Entry command' }),
43
+ minify: this.boolOption({ short: 'm', desc: 'Minify output', def: true }),
44
+ sourcemap: this.boolOption({ short: 'sm', desc: 'Bundle source maps' }),
45
+ includeSources: this.boolOption({ short: 'is', desc: 'Include source with source maps' }),
46
+ ejectFile: this.option({ short: 'x', desc: 'Eject commands to file' }),
47
+ };
48
+ }
49
+
50
+ abstract getOptions(): T;
51
+
52
+ get cmd(): S {
53
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
54
+ return super.cmd as S;
55
+ }
56
+
57
+ getSimpleModuleName(): string {
58
+ return RootIndex.mainPackage.name.replace(/[\/]/, '_').replace(/@/, '');
59
+ }
60
+
61
+ getOperations(): PackOperationShape<S>[] {
62
+ return BASIC_OP_SET.slice(0);
63
+ }
64
+
65
+ /**
66
+ * Run all operations
67
+ */
68
+ async * runOperations(cfg: S): AsyncIterable<string> {
69
+ for (const op of this.getOperations()) {
70
+ for await (const msg of op(cfg)) {
71
+ yield msg.join(' ');
72
+ }
73
+ }
74
+ }
75
+
76
+
77
+ getModule(moduleName: string): string {
78
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
79
+ let module = this.monoRoot ? moduleName : RootIndex.mainModule.name;
80
+ module = RootIndex.getModuleByFolder(module)?.name ?? module;
81
+
82
+ // Reinitialize for module
83
+ if (this.monoRoot) {
84
+ RootIndex.reinitForModule(module);
85
+ }
86
+
87
+ return module;
88
+ }
89
+
90
+ async buildConfig(): Promise<S> {
91
+ this.cmd.workspace ??= path.resolve(os.tmpdir(), RootIndex.mainModule.sourcePath.replace(/[\/\\: ]/g, '_'));
92
+ this.cmd.entryCommand ??= path.basename(this.cmd.entryPoint).replace(/[.][tj]s$/, '');
93
+ this.cmd.module = RootIndex.mainModule.name;
94
+ return this.cmd;
95
+ }
96
+
97
+ async action(module: string, args: string[]): Promise<void> {
98
+ const start = Date.now();
99
+ if (!module && this.monoRoot) {
100
+ return this.showHelp(new Error('The module needs to specified when running from a monorepo root'));
101
+ }
102
+
103
+ module = this.getModule(module);
104
+
105
+ const cfg = await this.buildConfig();
106
+ cfg.entryArguments = Array.isArray(args) ? args : [];
107
+
108
+ for (const k in this.cmd) {
109
+ if (Object.hasOwn(this.cmd, k)) {
110
+ const v = this.cmd[k];
111
+ if (typeof v === 'string' && /<module>/.test(v)) {
112
+ // @ts-expect-error
113
+ this.cmd[k] = v.replace(/<module>/g, this.getSimpleModuleName());
114
+ }
115
+ }
116
+ }
117
+
118
+ // Resolve all files to absolute paths
119
+ if (this.cmd.output) {
120
+ this.cmd.output = path.resolve(this.cmd.output);
121
+ }
122
+ if (this.cmd.ejectFile) {
123
+ this.cmd.ejectFile = path.resolve(this.cmd.ejectFile);
124
+ }
125
+ this.cmd.workspace = path.resolve(this.cmd.workspace);
126
+
127
+ const stream = this.runOperations(cfg);
128
+
129
+ // Eject to file
130
+ if (this.cmd.ejectFile) {
131
+ const output: string[] = [];
132
+ for await (const line of stream) {
133
+ output.push(line);
134
+ }
135
+ await PackUtil.writeEjectOutput(this.cmd.workspace, cfg.module, output, this.cmd.ejectFile);
136
+ } else {
137
+ await GlobalTerminal.streamLinesWithWaiting(stream, {
138
+ initialDelay: 0,
139
+ cycleDelay: 100,
140
+ end: true,
141
+ commitedPrefix: String.fromCharCode(171)
142
+ });
143
+ let msg = cliTpl`${{ success: 'Success' }} (${{ identifier: TimeUtil.prettyDeltaSinceTime(start) }}) ${{ subtitle: 'module' }}=${{ param: this.cmd.module }}`;
144
+ if (this.cmd.output) {
145
+ msg = cliTpl`${msg} ${{ subtitle: 'output' }}=${{ path: this.cmd.output }}`;
146
+ }
147
+ await GlobalTerminal.writeLines(msg);
148
+ }
149
+ }
150
+ }
@@ -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
+ `;
package/bin/cli-pack.ts DELETED
@@ -1,10 +0,0 @@
1
- import { BaseOptions, BasePackCommand } from './pack-base';
2
- import { Pack, AllConfig } from './operation/pack';
3
-
4
- export class PackCommand extends BasePackCommand<BaseOptions, AllConfig> {
5
- operation = Pack;
6
-
7
- getOptions(): BaseOptions {
8
- return this.commonOptions();
9
- }
10
- }
@@ -1,21 +0,0 @@
1
- import { OptionConfig } from '@travetto/cli/src/command';
2
-
3
- import { BaseOptions, BasePackCommand } from './pack-base';
4
- import { Assemble, AssembleConfig } from './operation/assemble';
5
-
6
- type Options = BaseOptions & {
7
- keepSource: OptionConfig<boolean>;
8
- readonly: OptionConfig<boolean>;
9
- };
10
-
11
- export class PackAssembleCommand extends BasePackCommand<Options, AssembleConfig> {
12
- operation = Assemble;
13
-
14
- getOptions(): Options {
15
- return {
16
- ...this.commonOptions(),
17
- keepSource: this.boolOption({ desc: 'Should source be preserved' }),
18
- readonly: this.boolOption({ desc: 'Build a readonly deployable' })
19
- };
20
- }
21
- }
@@ -1,54 +0,0 @@
1
- import * as fs from 'fs/promises';
2
-
3
- import { FsUtil, PathUtil } from '@travetto/boot';
4
- import { CliCommand, OptionConfig, ListOptionConfig } from '@travetto/cli/src/command';
5
-
6
- type Options = {
7
- app: OptionConfig<string>;
8
- image: OptionConfig<string>;
9
- port: OptionConfig<number>;
10
- add: ListOptionConfig<string>;
11
- output: OptionConfig<string>;
12
- };
13
-
14
- export class PackDockerExportCommand extends CliCommand<Options> {
15
-
16
- name = 'pack:docker-export';
17
-
18
- getOptions(): Options {
19
- return {
20
- app: this.option({ desc: 'The application target to run', def: 'rest' }),
21
- image: this.option({ desc: 'Docker image to extend', def: 'node:16-alpine' }),
22
- port: this.intOption({ desc: 'Expose port', def: 3000 }),
23
- add: this.listOption({ desc: 'Files to include' }),
24
- output: this.option({ desc: 'Docker file name', def: 'Dockerfile' })
25
- };
26
- }
27
-
28
- async action(...args: unknown[]): Promise<void> {
29
- const files = ['src', 'bin', 'support', 'resources', 'package.json', 'package-lock.json', ...this.cmd.add]
30
- .filter(x => FsUtil.existsSync(PathUtil.resolveUnix(x)));
31
-
32
- const content = `
33
- FROM ${this.cmd.image} as build
34
- WORKDIR /build
35
- ${files.map(x => `COPY ${x} ${x}`).join('\n')}
36
- ENV NODE_OPTIONS "--no-deprecation"
37
- RUN npm ci
38
- RUN npx trv pack:assemble -w /app
39
-
40
- FROM ${this.cmd.image} as scratch
41
- COPY --from=build /app /app
42
- EXPOSE ${this.cmd.port}
43
- WORKDIR /app
44
- ENV NODE_OPTIONS "--no-deprecation"
45
- CMD ["node", "./node_modules/@travetto/cli/bin/trv", "run", "${this.cmd.app}"]
46
- `;
47
-
48
- if (this.cmd.output === '-' || this.cmd.output === '/dev/stdout' || !this.cmd.output) {
49
- console.log(content);
50
- } else {
51
- await fs.writeFile(this.cmd.output, content, { encoding: 'utf8' });
52
- }
53
- }
54
- }
@@ -1,29 +0,0 @@
1
- import { OptionConfig, ListOptionConfig } from '@travetto/cli/src/command';
2
-
3
- import { BaseOptions, BasePackCommand } from './pack-base';
4
- import { Docker, DockerConfig } from './operation/docker';
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
- };
14
-
15
- export class PackDockerCommand extends BasePackCommand<Options, DockerConfig> {
16
- operation = Docker;
17
-
18
- getOptions(): Options {
19
- 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' })
27
- };
28
- }
29
- }
@@ -1,19 +0,0 @@
1
- import { OptionConfig } from '@travetto/cli/src/command';
2
-
3
- import { BaseOptions, BasePackCommand } from './pack-base';
4
- import { Zip, ZipConfig } from './operation/zip';
5
-
6
- type Options = BaseOptions & {
7
- output: OptionConfig<string>;
8
- };
9
-
10
- export class PackZipCommand extends BasePackCommand<Options, ZipConfig> {
11
- operation = Zip;
12
-
13
- getOptions(): Options {
14
- return {
15
- ...this.commonOptions(),
16
- output: this.option({ desc: 'Output File' })
17
- };
18
- }
19
- }
@@ -1,151 +0,0 @@
1
- import * as path from 'path';
2
- import { promises as fs } from 'fs';
3
-
4
- import { ExecUtil, PathUtil, ScanFs, FsUtil } from '@travetto/boot';
5
-
6
- import { DependenciesUtil, DepType } from './dependencies';
7
- import { PackUtil } from './util';
8
-
9
- const MODULE_DIRS = ['src', 'bin', 'support', 'resources', 'index.ts', 'package.json', 'tsconfig.trv.json'];
10
-
11
- /**
12
- * Utils for assembling
13
- */
14
- export class AssembleUtil {
15
-
16
- /**
17
- * Minimize cached source files, by removing source mapping info
18
- */
19
- static async cleanCache(cache: string): Promise<void> {
20
- for (const el of await fs.readdir(cache)) {
21
- if (el.endsWith('.ts') || el.endsWith('.js')) {
22
- const content = (await fs.readFile(`${cache}/${el}`, 'utf8')).replace(/\/\/# sourceMap.*/g, '');
23
- await fs.writeFile(`${cache}/${el}`, content);
24
- }
25
- }
26
- }
27
-
28
- /**
29
- * Minimize cached source files, by removing source mapping info
30
- */
31
- static async cleanBoot(ws: string): Promise<void> {
32
- for (const el of await ScanFs.scanDir({
33
- testFile: f => f.endsWith('.js') || f.endsWith('.d.ts'),
34
- testDir: x => true
35
- }, `${ws}/node_modules/@travetto/boot`)) {
36
- if (el.file.endsWith('.d.ts')) {
37
- await fs.writeFile(el.file, '');
38
- } else if (el.file.endsWith('.js')) {
39
- const content = (await fs.readFile(el.file, 'utf8')).replace(/\/\/# sourceMap.*/g, '');
40
- await fs.writeFile(el.file, content);
41
- }
42
- }
43
- }
44
-
45
- /**
46
- * Truncate all app source files, and framework source files
47
- */
48
- static async purgeSource(folders: string[]): Promise<void> {
49
- for (const sub of folders) {
50
- for (const f of await ScanFs.scanDir({ testFile: x => x.endsWith('.ts'), testDir: x => true }, sub)) {
51
- if (f.stats?.isFile() && !f.module.startsWith('cli/')) {
52
- await fs.writeFile(f.file, '');
53
- }
54
- }
55
- }
56
- }
57
-
58
- /**
59
- * Copy a module
60
- */
61
- static async copyModule(root: string, target: string): Promise<void> {
62
- for (const f of MODULE_DIRS) {
63
- const sourceFile = PathUtil.resolveUnix(root, f);
64
- const targetFile = PathUtil.resolveUnix(target, f);
65
- const found = await FsUtil.exists(sourceFile);
66
- if (found) {
67
- if (found.isFile()) {
68
- await fs.copyFile(sourceFile, targetFile);
69
- } else {
70
- await fs.mkdir(targetFile, { recursive: true });
71
- await FsUtil.copyRecursive(`${sourceFile}/*`, targetFile);
72
- }
73
- }
74
- }
75
- }
76
-
77
- /**
78
- * Purge workspace using file rules
79
- */
80
- static async excludeFiles(root: string, files: string[]): Promise<void> {
81
- const checker = PackUtil.excludeChecker(files, root);
82
- for (const el of await ScanFs.scanDir({ testDir: x => true, testFile: checker, withHidden: true }, root)) {
83
- if (!el.stats || !el.stats.isFile()) { continue; }
84
- try {
85
- await fs.unlink(el.file);
86
- } catch { }
87
- }
88
- }
89
-
90
- /**
91
- * Copy over all prod dependencies
92
- */
93
- static async copyDependencies(workspace: string, types: DepType[] = ['prod', 'opt', 'peer']): Promise<void> {
94
-
95
- for (const el of await DependenciesUtil.resolveDependencies({ types })) {
96
- const sub = PathUtil.normalizeFrameworkPath(el.file, 'node_modules/')
97
- .replace(/.*?node_modules/, 'node_modules');
98
-
99
- const tgt = PathUtil.resolveUnix(workspace, sub);
100
- await fs.mkdir(path.dirname(tgt), { recursive: true });
101
-
102
- if (el.dep.startsWith('@travetto')) {
103
- await this.copyModule(el.file, tgt);
104
- } else {
105
- if (!(await FsUtil.exists(tgt))) {
106
- await FsUtil.copyRecursive(el.file, tgt);
107
- }
108
- }
109
- }
110
- await FsUtil.copyRecursive(
111
- PathUtil.resolveUnix(path.dirname(require.resolve('@travetto/boot/bin/main.js'))),
112
- PathUtil.resolveUnix(workspace, 'node_modules/@travetto/boot/bin')
113
- );
114
- await FsUtil.copyRecursive(
115
- PathUtil.resolveUnix(path.dirname(require.resolve('@travetto/base/bin/main.js'))),
116
- PathUtil.resolveUnix(workspace, 'node_modules/@travetto/base/bin')
117
- );
118
- }
119
-
120
- /**
121
- * Compile workspace
122
- */
123
- static async buildWorkspace(root: string, cacheDir: string): Promise<void> {
124
- await ExecUtil.spawn('node', ['./node_modules/@travetto/cli/bin/trv.js', 'build'],
125
- {
126
- cwd: root, isolatedEnv: true,
127
- env: { TRV_ENV: 'prod', TRV_READONLY: '0', TRV_CACHE: cacheDir, TRV_NODE_VERSION: process.env.TRV_NODE_VERSION },
128
- stdio: ['pipe', 'pipe', 2]
129
- }).result;
130
- }
131
-
132
- /**
133
- * Copy over added content
134
- */
135
- static async copyAddedContent(workspace: string, files: Record<string, string>[]): Promise<void> {
136
- for (const a of files) {
137
- let [src, dest] = Object.entries(a)[0];
138
- [src, dest] = [PathUtil.resolveUnix(src), PathUtil.resolveUnix(workspace, dest)];
139
- const stat = await FsUtil.exists(src);
140
- if (stat) {
141
- if (stat.isFile()) {
142
- await fs.mkdir(path.dirname(dest), { recursive: true });
143
- await fs.copyFile(src, dest);
144
- } else {
145
- await fs.mkdir(path.dirname(dest), { recursive: true });
146
- await FsUtil.copyRecursive(src, dest);
147
- }
148
- }
149
- }
150
- }
151
- }