@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.
- package/README.md +1 -1
- package/__index__.ts +1 -0
- package/package.json +16 -11
- package/support/bin/config.ts +81 -0
- package/support/bin/docker-operation.ts +96 -0
- package/support/bin/operation.ts +273 -0
- package/support/bin/rollup-esm-dynamic-import.ts +55 -0
- package/support/bin/rollup.ts +36 -0
- package/support/bin/shell.ts +53 -0
- package/support/bin/types.ts +70 -0
- package/support/bin/util.ts +63 -0
- package/support/cli.pack.ts +14 -0
- package/support/cli.pack_docker.ts +48 -0
- package/support/cli.pack_zip.ts +24 -0
- package/support/pack.base.ts +150 -0
- package/support/pack.dockerfile.ts +9 -0
- package/bin/cli-pack.ts +0 -10
- package/bin/cli-pack_assemble.ts +0 -21
- package/bin/cli-pack_docker-export.ts +0 -54
- package/bin/cli-pack_docker.ts +0 -29
- package/bin/cli-pack_zip.ts +0 -19
- package/bin/lib/assemble.ts +0 -151
- package/bin/lib/dependencies.ts +0 -103
- package/bin/lib/types.ts +0 -19
- package/bin/lib/util.ts +0 -175
- package/bin/operation/assemble.ts +0 -75
- package/bin/operation/docker.ts +0 -96
- package/bin/operation/pack.ts +0 -69
- package/bin/operation/zip.ts +0 -51
- package/bin/pack-base.ts +0 -100
- package/index.d.ts +0 -5
- package/support/pack.config.ts +0 -66
|
@@ -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
|
-
}
|
package/bin/cli-pack_assemble.ts
DELETED
|
@@ -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
|
-
}
|
package/bin/cli-pack_docker.ts
DELETED
|
@@ -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
|
-
}
|
package/bin/cli-pack_zip.ts
DELETED
|
@@ -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
|
-
}
|
package/bin/lib/assemble.ts
DELETED
|
@@ -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
|
-
}
|