@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
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Assemble is the operation that stages the project's code for deployment. The as
|
|
|
40
40
|
|
|
41
41
|
1. Cleaning Workspace - Cleans workspace to start with an empty workspace
|
|
42
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
|
|
43
|
+
1. Copying App Content - Copies over application content (src/, resources/, support/, bin/)
|
|
44
44
|
1. Excluding Pre-Compile Files - Any files that should be excluded pre-compilation, are removed
|
|
45
45
|
1. Compiling - Compiles the code in the new workspace, isolating it from your local development
|
|
46
46
|
1. Excluding Post-Compile Files - Removes any files that should be excluded, post compilation
|
package/__index__.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { CommonPackConfig, DockerPackFactory, DockerPackConfig } from './support/bin/types';
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/pack",
|
|
3
|
-
"
|
|
4
|
-
"version": "3.0.0-rc.2",
|
|
3
|
+
"version": "3.0.0-rc.20",
|
|
5
4
|
"description": "Code packing utilities",
|
|
6
5
|
"keywords": [
|
|
7
6
|
"travetto",
|
|
@@ -15,9 +14,9 @@
|
|
|
15
14
|
"email": "travetto.framework@gmail.com",
|
|
16
15
|
"name": "Travetto Framework"
|
|
17
16
|
},
|
|
17
|
+
"main": "__index__.ts",
|
|
18
18
|
"files": [
|
|
19
|
-
"
|
|
20
|
-
"bin",
|
|
19
|
+
"__index__.ts",
|
|
21
20
|
"support"
|
|
22
21
|
],
|
|
23
22
|
"repository": {
|
|
@@ -25,21 +24,27 @@
|
|
|
25
24
|
"directory": "module/pack"
|
|
26
25
|
},
|
|
27
26
|
"dependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"
|
|
27
|
+
"@rollup/plugin-commonjs": "^24.0.1",
|
|
28
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
29
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
30
|
+
"@rollup/plugin-terser": "^0.4.0",
|
|
31
|
+
"@travetto/base": "^3.0.0-rc.16",
|
|
32
|
+
"rollup": "^3.17.2",
|
|
33
|
+
"rollup-plugin-sourcemaps": "^0.6.3"
|
|
31
34
|
},
|
|
32
35
|
"peerDependencies": {
|
|
33
|
-
"@travetto/cli": "^3.0.0-rc.
|
|
36
|
+
"@travetto/cli": "^3.0.0-rc.18"
|
|
34
37
|
},
|
|
35
38
|
"peerDependenciesMeta": {
|
|
36
39
|
"@travetto/cli": {
|
|
37
40
|
"optional": true
|
|
38
41
|
}
|
|
39
42
|
},
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
+
"travetto": {
|
|
44
|
+
"displayName": "Pack",
|
|
45
|
+
"profiles": [
|
|
46
|
+
"build"
|
|
47
|
+
]
|
|
43
48
|
},
|
|
44
49
|
"publishConfig": {
|
|
45
50
|
"access": "public"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { OutputOptions } from 'rollup';
|
|
2
|
+
import type terser from '@rollup/plugin-terser';
|
|
3
|
+
|
|
4
|
+
import { Env } from '@travetto/base';
|
|
5
|
+
import { ManifestModule, Package, path, RootIndex } from '@travetto/manifest';
|
|
6
|
+
|
|
7
|
+
const INTRO = {
|
|
8
|
+
commonjs: `
|
|
9
|
+
globalThis.crypto = require('crypto');
|
|
10
|
+
try { require('./.env.js')} catch {}
|
|
11
|
+
|
|
12
|
+
function __importStar(mod) {
|
|
13
|
+
if (mod && mod.__esModule) return mod;
|
|
14
|
+
var result = {};
|
|
15
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
16
|
+
result['default'] = mod;
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
`,
|
|
20
|
+
module: `
|
|
21
|
+
globalThis.crypto = await import('crypto');
|
|
22
|
+
try {await import('./.env.js')} catch {}
|
|
23
|
+
`
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function getFilesFromModule(m: ManifestModule): string[] {
|
|
27
|
+
return [
|
|
28
|
+
...m.files.$index ?? [],
|
|
29
|
+
...m.files.src ?? [],
|
|
30
|
+
...m.files.bin ?? [],
|
|
31
|
+
...(m.files.support ?? [])
|
|
32
|
+
.filter(f => !/support\/(test|doc)/.test(f[0]))
|
|
33
|
+
]
|
|
34
|
+
.filter(([, t]) => t === 'ts' || t === 'js' || t === 'json')
|
|
35
|
+
.map(([f]) => path.resolve(m.outputFolder, f.replace(/[.]ts$/, '.js')));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getOutput(): OutputOptions {
|
|
39
|
+
const format: Package['type'] = Env.get('BUNDLE_FORMAT', 'commonjs');
|
|
40
|
+
return {
|
|
41
|
+
format,
|
|
42
|
+
intro: INTRO[format],
|
|
43
|
+
sourcemapPathTransform: (src, map): string =>
|
|
44
|
+
path.resolve(path.dirname(map), src).replace(`${RootIndex.manifest.workspacePath}/`, ''),
|
|
45
|
+
sourcemap:
|
|
46
|
+
Env.getBoolean('BUNDLE_SOURCEMAP') ?? false,
|
|
47
|
+
sourcemapExcludeSources:
|
|
48
|
+
!(Env.getBoolean('BUNDLE_SOURCES') ?? false),
|
|
49
|
+
compact:
|
|
50
|
+
Env.getBoolean('BUNDLE_COMPRESS') ?? true,
|
|
51
|
+
dir: Env.get('BUNDLE_OUTPUT')!,
|
|
52
|
+
...(format === 'commonjs' ? {} : {
|
|
53
|
+
inlineDynamicImports: true
|
|
54
|
+
}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getEntry(): string {
|
|
59
|
+
return Env.get('BUNDLE_ENTRY')!;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getFiles(): string[] {
|
|
63
|
+
return [...RootIndex.getModuleList('all')]
|
|
64
|
+
.map(x => RootIndex.manifest.modules[x])
|
|
65
|
+
.filter(m => m.profiles.includes('std'))
|
|
66
|
+
.flatMap(getFilesFromModule);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function getTerserConfig(): Parameters<typeof terser>[0] {
|
|
70
|
+
return {
|
|
71
|
+
mangle: true,
|
|
72
|
+
keep_classnames: true,
|
|
73
|
+
keep_fnames: true,
|
|
74
|
+
ecma: 2020,
|
|
75
|
+
compress: {},
|
|
76
|
+
output: {
|
|
77
|
+
shebang: false,
|
|
78
|
+
comments: false,
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
import { path, RootIndex } from '@travetto/manifest';
|
|
4
|
+
import { ExecUtil } from '@travetto/base';
|
|
5
|
+
import { cliTpl } from '@travetto/cli';
|
|
6
|
+
|
|
7
|
+
import { ActiveShellCommand } from './shell';
|
|
8
|
+
import { DockerPackConfig, DockerPackFactoryModule } from './types';
|
|
9
|
+
|
|
10
|
+
export class DockerPackOperation {
|
|
11
|
+
|
|
12
|
+
static getDockerTags(cfg: DockerPackConfig): string[] {
|
|
13
|
+
return (cfg.dockerTag ?? []).map(x => cfg.dockerRegistry ? `${cfg.dockerRegistry}/${cfg.dockerName}:${x}` : `${cfg.dockerName}:${x}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Write Docker File
|
|
18
|
+
*/
|
|
19
|
+
static async* writeDockerFile(cfg: DockerPackConfig): AsyncIterable<string[]> {
|
|
20
|
+
const dockerFile = path.resolve(cfg.workspace, 'Dockerfile');
|
|
21
|
+
const title = cliTpl`${{ title: 'Generating Docker File' }} ${{ path: dockerFile }} ${{ param: cfg.dockerFactory }}`;
|
|
22
|
+
const factory = RootIndex.getFromImport(cfg.dockerFactory);
|
|
23
|
+
if (!factory) {
|
|
24
|
+
throw new Error(`Unable to resolve docker factory at ${cfg.dockerFactory}`);
|
|
25
|
+
}
|
|
26
|
+
const mod: DockerPackFactoryModule = await import(factory.import);
|
|
27
|
+
const content = (await mod.factory(cfg)).trim();
|
|
28
|
+
|
|
29
|
+
if (cfg.ejectFile) {
|
|
30
|
+
yield ActiveShellCommand.comment(title);
|
|
31
|
+
yield* ActiveShellCommand.createFile(dockerFile, content.split(/\n/));
|
|
32
|
+
} else {
|
|
33
|
+
yield [title];
|
|
34
|
+
await fs.writeFile(dockerFile, content, 'utf8');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Pull Docker Base Image
|
|
40
|
+
*/
|
|
41
|
+
static async* pullDockerBaseImage(cfg: DockerPackConfig): AsyncIterable<string[]> {
|
|
42
|
+
const title = cliTpl`${{ title: 'Pulling Docker Base Image' }} ${{ param: cfg.dockerImage }}`;
|
|
43
|
+
|
|
44
|
+
const command = ['docker', 'pull', cfg.dockerImage];
|
|
45
|
+
|
|
46
|
+
if (cfg.ejectFile) {
|
|
47
|
+
yield ActiveShellCommand.comment(title);
|
|
48
|
+
yield command;
|
|
49
|
+
} else {
|
|
50
|
+
yield [title];
|
|
51
|
+
await ExecUtil.spawn(command[0], command.slice(1), {}).result;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Building Docker Container
|
|
57
|
+
*/
|
|
58
|
+
static async* buildDockerContainer(cfg: DockerPackConfig): AsyncIterable<string[]> {
|
|
59
|
+
const title = cliTpl`${{ title: 'Building Docker Container' }} ${{ param: cfg.dockerTag?.join(',') }}`;
|
|
60
|
+
const cmd = ['docker', 'build', ...DockerPackOperation.getDockerTags(cfg).flatMap(x => ['-t', x]), '.'];
|
|
61
|
+
|
|
62
|
+
if (cfg.ejectFile) {
|
|
63
|
+
yield ActiveShellCommand.comment(title);
|
|
64
|
+
yield ActiveShellCommand.chdir(cfg.workspace);
|
|
65
|
+
yield cmd;
|
|
66
|
+
yield ActiveShellCommand.chdir(path.cwd());
|
|
67
|
+
} else {
|
|
68
|
+
yield [title];
|
|
69
|
+
await ExecUtil.spawn(cmd[0], cmd.slice(1), { cwd: cfg.workspace, stdio: [0, 'pipe', 2] }).result;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Push Docker Container
|
|
75
|
+
*/
|
|
76
|
+
static async* pushDockerContainer(cfg: DockerPackConfig): AsyncIterable<string[]> {
|
|
77
|
+
if (!cfg.dockerPush) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const tags = DockerPackOperation.getDockerTags(cfg);
|
|
81
|
+
const title = cliTpl`${{ title: 'Push Container to registry' }} ${{ param: cfg.dockerRegistry }}`;
|
|
82
|
+
const cmd = ['docker', 'image', 'push'];
|
|
83
|
+
|
|
84
|
+
if (cfg.ejectFile) {
|
|
85
|
+
yield ActiveShellCommand.comment(title);
|
|
86
|
+
for (const tag of tags) {
|
|
87
|
+
yield [...cmd, tag];
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
yield [title];
|
|
91
|
+
for (const tag of tags) {
|
|
92
|
+
await ExecUtil.spawn(cmd[0], [...cmd.slice(1), tag], { stdio: [0, 'pipe', 2] }).result;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
import { path, RootIndex } from '@travetto/manifest';
|
|
4
|
+
import { ExecUtil } from '@travetto/base';
|
|
5
|
+
import { cliTpl } from '@travetto/cli';
|
|
6
|
+
|
|
7
|
+
import { CommonPackConfig } from './types';
|
|
8
|
+
import { PackUtil } from './util';
|
|
9
|
+
import { ActiveShellCommand, ShellCommands } from './shell';
|
|
10
|
+
|
|
11
|
+
async function writeRawFile(file: string, contents: string, mode?: string): Promise<void> {
|
|
12
|
+
await fs.writeFile(file, contents, { encoding: 'utf8', mode });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class PackOperation {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Clean out pack workspace, removing all content
|
|
19
|
+
*/
|
|
20
|
+
static async * clean(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
21
|
+
if (!cfg.clean) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const title = cliTpl`${{ title: 'Cleaning Output' }} ${{ path: cfg.workspace }}`;
|
|
26
|
+
|
|
27
|
+
if (cfg.ejectFile) {
|
|
28
|
+
yield ActiveShellCommand.comment(title);
|
|
29
|
+
yield ActiveShellCommand.rmRecursive(cfg.workspace);
|
|
30
|
+
if (cfg.output) {
|
|
31
|
+
yield ActiveShellCommand.rmRecursive(cfg.output);
|
|
32
|
+
}
|
|
33
|
+
yield ActiveShellCommand.mkdir(cfg.workspace);
|
|
34
|
+
} else {
|
|
35
|
+
yield [title];
|
|
36
|
+
await fs.rm(cfg.workspace, { recursive: true, force: true });
|
|
37
|
+
if (cfg.output) {
|
|
38
|
+
await fs.rm(cfg.output, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
await fs.mkdir(cfg.workspace, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Invoke bundler (rollup) to produce output in workspace folder
|
|
46
|
+
*/
|
|
47
|
+
static async * bundle(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
48
|
+
const cwd = RootIndex.outputRoot;
|
|
49
|
+
|
|
50
|
+
const bundleCommand = ['npx', 'rollup', '-c', 'node_modules/@travetto/pack/support/bin/rollup.js'];
|
|
51
|
+
|
|
52
|
+
const env = Object.fromEntries(([
|
|
53
|
+
['BUNDLE_ENTRY', cfg.entryPoint],
|
|
54
|
+
['BUNDLE_ENTRY_NAME', cfg.entryCommand],
|
|
55
|
+
['BUNDLE_COMPRESS', cfg.minify],
|
|
56
|
+
['BUNDLE_SOURCEMAP', cfg.sourcemap],
|
|
57
|
+
['BUNDLE_SOURCES', cfg.includeSources],
|
|
58
|
+
['BUNDLE_OUTPUT', cfg.workspace],
|
|
59
|
+
['BUNDLE_FORMAT', RootIndex.manifest.moduleType],
|
|
60
|
+
['TRV_MANIFEST', RootIndex.getModule(cfg.module)!.outputPath]
|
|
61
|
+
] as const)
|
|
62
|
+
.filter(x => x[1] === false || x[1])
|
|
63
|
+
.map(x => [x[0], `${x[1]}`])
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const props = (['minify', 'sourcemap', 'entryPoint'] as const)
|
|
67
|
+
.map(k => cliTpl`${{ subtitle: k }}=${{ param: cfg[k] }}`).join(' ');
|
|
68
|
+
|
|
69
|
+
const title = cliTpl`${{ title: 'Bundling Output' }} ${props}`;
|
|
70
|
+
|
|
71
|
+
if (cfg.ejectFile) {
|
|
72
|
+
yield ActiveShellCommand.comment(title);
|
|
73
|
+
yield* Object.entries(env).filter(x => !!x[1]).map(x =>
|
|
74
|
+
ActiveShellCommand.export(x[0], x[1])
|
|
75
|
+
);
|
|
76
|
+
yield ActiveShellCommand.chdir(cwd);
|
|
77
|
+
yield bundleCommand;
|
|
78
|
+
yield ActiveShellCommand.chdir(path.cwd());
|
|
79
|
+
} else {
|
|
80
|
+
yield [title];
|
|
81
|
+
await ExecUtil.spawn(bundleCommand[0], bundleCommand.slice(1), { cwd, env, stdio: ['inherit', 'pipe', 'pipe'] }).result;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Write out package.json, to help define how output .js file should be interpreted
|
|
87
|
+
*/
|
|
88
|
+
static async * writePackageJson(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
89
|
+
const file = 'package.json';
|
|
90
|
+
const title = cliTpl`${{ title: 'Writing' }} ${{ path: file }}`;
|
|
91
|
+
const pkg = { type: RootIndex.manifest.moduleType };
|
|
92
|
+
|
|
93
|
+
if (cfg.ejectFile) {
|
|
94
|
+
yield ActiveShellCommand.comment(title);
|
|
95
|
+
yield* ActiveShellCommand.createFile(
|
|
96
|
+
path.resolve(cfg.workspace, file),
|
|
97
|
+
[JSON.stringify(pkg)]
|
|
98
|
+
);
|
|
99
|
+
} else {
|
|
100
|
+
yield [title];
|
|
101
|
+
await writeRawFile(
|
|
102
|
+
path.resolve(cfg.workspace, file),
|
|
103
|
+
JSON.stringify(pkg, null, 2)
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Define .env.js file to control manifest location
|
|
110
|
+
*/
|
|
111
|
+
static async * writeEnv(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
112
|
+
const file = '.env.js';
|
|
113
|
+
const title = cliTpl`${{ title: 'Writing' }} ${{ path: file }}`;
|
|
114
|
+
const env = {
|
|
115
|
+
TRV_MANIFEST: `node_modules/${cfg.module}`,
|
|
116
|
+
TRV_CLI_IPC: ''
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (cfg.ejectFile) {
|
|
120
|
+
yield ActiveShellCommand.comment(title);
|
|
121
|
+
yield* ActiveShellCommand.createFile(
|
|
122
|
+
path.resolve(cfg.workspace, file),
|
|
123
|
+
PackUtil.buildEnvJS(env)
|
|
124
|
+
);
|
|
125
|
+
} else {
|
|
126
|
+
yield [title];
|
|
127
|
+
await writeRawFile(
|
|
128
|
+
path.resolve(cfg.workspace, file),
|
|
129
|
+
PackUtil.buildEnvJS(env).join('\n')
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Create launcher scripts (.sh, .cmd) to run output
|
|
136
|
+
*/
|
|
137
|
+
static async * writeEntryScript(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
138
|
+
const title = 'Writing entry scripts';
|
|
139
|
+
|
|
140
|
+
const files = ([['posix', 'sh'], ['win32', 'cmd']] as const)
|
|
141
|
+
.map(([type, ext]) => ({
|
|
142
|
+
fileTitle: cliTpl`${{ title }} ${{ path: `${cfg.entryCommand}.${ext}` }} args=(${{ param: cfg.entryArguments.join(' ') }})`,
|
|
143
|
+
file: `${cfg.entryCommand}.${ext}`,
|
|
144
|
+
text: [
|
|
145
|
+
ShellCommands[type].scriptOpen(),
|
|
146
|
+
ShellCommands[type].chdirScript(),
|
|
147
|
+
ShellCommands[type].callCommandWithAllArgs('node', cfg.entryCommand, ...cfg.entryArguments),
|
|
148
|
+
].map(x => x.join(' '))
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
if (cfg.ejectFile) {
|
|
152
|
+
for (const { fileTitle, text, file } of files) {
|
|
153
|
+
yield ActiveShellCommand.comment(fileTitle);
|
|
154
|
+
yield* ActiveShellCommand.createFile(path.resolve(cfg.workspace, file), text, '755');
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
for (const { fileTitle, text, file } of files) {
|
|
158
|
+
yield [fileTitle];
|
|
159
|
+
await writeRawFile(path.resolve(cfg.workspace, file), text.join('\n'), '755');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Copy over /resources folder into workspace, will get packaged into final output
|
|
166
|
+
*/
|
|
167
|
+
static async * copyResources(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
168
|
+
const resources = {
|
|
169
|
+
count: RootIndex.mainModule.files.resources?.length ?? 0,
|
|
170
|
+
src: path.resolve(RootIndex.mainModule.sourcePath, 'resources'),
|
|
171
|
+
dest: path.resolve(cfg.workspace, 'resources')
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const copyFiles = [
|
|
175
|
+
RootIndex.manifest.modules[RootIndex.mainModule.name],
|
|
176
|
+
RootIndex.manifest.modules['@travetto/manifest']
|
|
177
|
+
].map(mod => ({
|
|
178
|
+
src: path.resolve(RootIndex.outputRoot, mod.outputFolder, 'package.json'),
|
|
179
|
+
dest: path.resolve(cfg.workspace, mod.outputFolder, 'package.json'),
|
|
180
|
+
destFolder: path.resolve(cfg.workspace, mod.outputFolder)
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
const title = cliTpl`${{ title: 'Copying over resources' }}`;
|
|
184
|
+
|
|
185
|
+
if (cfg.ejectFile) {
|
|
186
|
+
yield ActiveShellCommand.comment(title);
|
|
187
|
+
yield* copyFiles.flatMap(mod => [
|
|
188
|
+
ActiveShellCommand.mkdir(path.dirname(mod.dest)),
|
|
189
|
+
ActiveShellCommand.copy(mod.src, mod.dest)
|
|
190
|
+
]);
|
|
191
|
+
if (resources.count) {
|
|
192
|
+
yield ActiveShellCommand.copyRecursive(resources.src, path.resolve(cfg.workspace, 'resources'));
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
yield [title];
|
|
196
|
+
|
|
197
|
+
for (const { src, dest, destFolder } of copyFiles) {
|
|
198
|
+
await fs.mkdir(destFolder, { recursive: true });
|
|
199
|
+
await fs.copyFile(src, dest);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (resources.count) {
|
|
203
|
+
await fs.mkdir(path.dirname(resources.dest), { recursive: true });
|
|
204
|
+
await PackUtil.copyRecursive(resources.src, resources.dest);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Generate the trv-app-cache.json for @travetto/app, which is needed for 'running' programs
|
|
211
|
+
*/
|
|
212
|
+
static async * primeAppCache(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
213
|
+
const isRun = cfg.entryCommand === 'cli' && cfg.entryArguments.filter(x => !x.startsWith('-'))[0] === 'run';
|
|
214
|
+
if (!isRun) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const appCacheCmd = ['npx', 'trv', 'main', '@travetto/app/support/bin/list'];
|
|
219
|
+
const sub = path.join(RootIndex.manifest.modules[RootIndex.mainModule.name].outputFolder, 'trv-app-cache.json');
|
|
220
|
+
const title = cliTpl`${{ title: 'Generating App Cache' }} ${{ path: sub }}`;
|
|
221
|
+
const env = { DEBUG: '0', TRV_MODULE: cfg.module };
|
|
222
|
+
const appCache = path.resolve(cfg.workspace, sub);
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
if (cfg.ejectFile) {
|
|
226
|
+
yield ActiveShellCommand.comment(title);
|
|
227
|
+
yield ActiveShellCommand.mkdir(path.dirname(appCache));
|
|
228
|
+
yield [...Object.entries(env).map(x => `${x[0]}=${x[1]}`), ...appCacheCmd, '>', appCache];
|
|
229
|
+
} else {
|
|
230
|
+
yield [title];
|
|
231
|
+
const { stdout } = await ExecUtil.spawn(appCacheCmd[0], appCacheCmd.slice(1), { env }).result;
|
|
232
|
+
|
|
233
|
+
await fs.mkdir(path.dirname(appCache), { recursive: true });
|
|
234
|
+
await fs.writeFile(appCache, stdout, 'utf8');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Produce the output manifest, only including prod dependencies
|
|
240
|
+
*/
|
|
241
|
+
static async * writeManifest(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
242
|
+
const out = path.resolve(cfg.workspace, 'node_modules', cfg.module);
|
|
243
|
+
const cmd = ['npx', 'trv', 'manifest', out, 'prod'];
|
|
244
|
+
const env = { TRV_MODULE: cfg.module };
|
|
245
|
+
const title = cliTpl`${{ title: 'Writing Manifest' }} ${{ path: path.join('node_modules', cfg.module) }}`;
|
|
246
|
+
|
|
247
|
+
if (cfg.ejectFile) {
|
|
248
|
+
yield ActiveShellCommand.comment(title);
|
|
249
|
+
yield [...Object.entries(env).map(([k, v]) => `${k}=${v}`), ...cmd];
|
|
250
|
+
} else {
|
|
251
|
+
yield [title];
|
|
252
|
+
await ExecUtil.spawn(cmd[0], cmd.slice(1), { env, stdio: ['inherit', 'ignore', 'inherit'] }).result;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Generate ZIP file for workspace
|
|
258
|
+
*/
|
|
259
|
+
static async * compress(cfg: CommonPackConfig): AsyncIterable<string[]> {
|
|
260
|
+
const title = cliTpl`${{ title: 'Compressing' }} ${{ path: cfg.output }}`;
|
|
261
|
+
|
|
262
|
+
if (cfg.ejectFile) {
|
|
263
|
+
yield ActiveShellCommand.comment(title);
|
|
264
|
+
yield ActiveShellCommand.chdir(cfg.workspace);
|
|
265
|
+
yield ActiveShellCommand.zip(cfg.output);
|
|
266
|
+
yield ActiveShellCommand.chdir(path.cwd());
|
|
267
|
+
} else {
|
|
268
|
+
yield [title];
|
|
269
|
+
const [cmd, ...args] = ActiveShellCommand.zip(cfg.output);
|
|
270
|
+
await ExecUtil.spawn(cmd, args, { cwd: cfg.workspace }).result;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AcornNode, Plugin } from 'rollup';
|
|
2
|
+
import { walk } from 'estree-walker';
|
|
3
|
+
import MagicString from 'magic-string';
|
|
4
|
+
|
|
5
|
+
const BRAND = '__imp';
|
|
6
|
+
|
|
7
|
+
const DYNAMIC_IMPORT = (imports: string[]): string => `
|
|
8
|
+
function ${BRAND}(path) {
|
|
9
|
+
switch (path) {
|
|
10
|
+
${imports.map(p => ` case '${p}': return import('${p}');`).join('\n')}
|
|
11
|
+
default: return import(path); // Fall back for built-ins
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
globalThis.${BRAND} = ${BRAND}`;
|
|
15
|
+
|
|
16
|
+
export function travettoImportPlugin(entry: string, files: string[]): Plugin {
|
|
17
|
+
const imports = files
|
|
18
|
+
.map(x => x.split('node_modules/').pop()!)
|
|
19
|
+
.flatMap(x => x.endsWith('__index__.js') ? [x.replace('__index__.js', ''), x] : [x]);
|
|
20
|
+
|
|
21
|
+
const out: Plugin = {
|
|
22
|
+
name: 'travetto-import',
|
|
23
|
+
transform(code, id) {
|
|
24
|
+
const parsed = this.parse(code);
|
|
25
|
+
|
|
26
|
+
let ms: MagicString | undefined;
|
|
27
|
+
|
|
28
|
+
if (id.includes(entry)) {
|
|
29
|
+
(ms ??= new MagicString(code).append(DYNAMIC_IMPORT(imports)));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
walk(parsed, {
|
|
33
|
+
enter: (node) => {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
35
|
+
const impNode = node as AcornNode & { source?: { type: string } };
|
|
36
|
+
if (impNode.type !== 'ImportExpression' || impNode.source?.type === 'Literal') {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
(ms ??= new MagicString(code)).overwrite(impNode.start, impNode.start + 6, BRAND);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (ms !== undefined) {
|
|
44
|
+
return {
|
|
45
|
+
code: ms.toString(),
|
|
46
|
+
map: ms.generateMap({ file: id, includeContent: true, hires: true })
|
|
47
|
+
};
|
|
48
|
+
} else {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import commonjsRequire from '@rollup/plugin-commonjs';
|
|
2
|
+
import nodeResolve from '@rollup/plugin-node-resolve';
|
|
3
|
+
import terser from '@rollup/plugin-terser';
|
|
4
|
+
import jsonImport from '@rollup/plugin-json';
|
|
5
|
+
import sourceMaps from 'rollup-plugin-sourcemaps';
|
|
6
|
+
import type { RollupOptions } from 'rollup';
|
|
7
|
+
|
|
8
|
+
import { RootIndex } from '@travetto/manifest';
|
|
9
|
+
|
|
10
|
+
import { getEntry, getOutput, getTerserConfig, getFiles } from './config';
|
|
11
|
+
import { travettoImportPlugin } from './rollup-esm-dynamic-import';
|
|
12
|
+
|
|
13
|
+
const NEVER_INCLUDE = new Set(['node-forge', '@parcel/watcher']);
|
|
14
|
+
|
|
15
|
+
export default function buildConfig(): RollupOptions {
|
|
16
|
+
const output = getOutput();
|
|
17
|
+
const entry = getEntry();
|
|
18
|
+
const files = getFiles();
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
input: [entry],
|
|
22
|
+
output,
|
|
23
|
+
plugins: [
|
|
24
|
+
jsonImport(),
|
|
25
|
+
commonjsRequire({
|
|
26
|
+
ignore: id => NEVER_INCLUDE.has(id),
|
|
27
|
+
dynamicRequireRoot: RootIndex.manifest.workspacePath,
|
|
28
|
+
dynamicRequireTargets: (output.format === 'commonjs' ? files : [])
|
|
29
|
+
}),
|
|
30
|
+
...(output.format === 'module' ? [travettoImportPlugin(entry, files)] : []),
|
|
31
|
+
nodeResolve({ preferBuiltins: true }),
|
|
32
|
+
...(output.sourcemap !== 'hidden' && output.sourcemap !== false ? [sourceMaps({})] : []),
|
|
33
|
+
...(output.compact ? [terser(getTerserConfig())] : [])
|
|
34
|
+
]
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { path } from '@travetto/manifest';
|
|
2
|
+
import { stripAnsiCodes } from '@travetto/terminal';
|
|
3
|
+
|
|
4
|
+
import { ShellCommandImpl } from './types';
|
|
5
|
+
|
|
6
|
+
const escape = (text: string): string =>
|
|
7
|
+
text
|
|
8
|
+
.replaceAll('"', '\\"')
|
|
9
|
+
.replaceAll('$', '\\$');
|
|
10
|
+
|
|
11
|
+
export const ShellCommands: Record<'win32' | 'posix', ShellCommandImpl> = {
|
|
12
|
+
win32: {
|
|
13
|
+
var: (name: string) => `%${name}%`,
|
|
14
|
+
scriptOpen: () => [],
|
|
15
|
+
chdirScript: () => ['cd', '%~p0'],
|
|
16
|
+
callCommandWithAllArgs: (cmd, ...args) => [cmd, ...args, '%*'],
|
|
17
|
+
createFile: (file, text) => [
|
|
18
|
+
['@echo', 'off'],
|
|
19
|
+
...text.map((line, i) =>
|
|
20
|
+
['echo', `"${escape(line)}"`, i === 0 ? '>' : '>>', file]
|
|
21
|
+
)
|
|
22
|
+
],
|
|
23
|
+
copy: (src, dest) => ['copy', src, dest],
|
|
24
|
+
copyRecursive: (src, dest) => ['xcopy', '/y', '/h', '/s', path.toNative(src), path.toNative(dest)],
|
|
25
|
+
rmRecursive: (dest) => ['rmdir', '/Q', '/S', dest],
|
|
26
|
+
mkdir: (dest) => ['md', dest],
|
|
27
|
+
export: (key, value) => ['set', `${key}=${value}`],
|
|
28
|
+
chdir: (dest) => ['cd', dest],
|
|
29
|
+
comment: (message) => ['\nREM', stripAnsiCodes(message), '\n'],
|
|
30
|
+
zip: (outputFile) => ['powershell', 'Compress-Archive', '-Path', '.', '-DestinationPath', outputFile]
|
|
31
|
+
},
|
|
32
|
+
posix: {
|
|
33
|
+
var: (name: string) => `$${name}`,
|
|
34
|
+
scriptOpen: () => ['#!/bin/sh'],
|
|
35
|
+
chdirScript: () => ['cd', '$(dirname "$0")'],
|
|
36
|
+
callCommandWithAllArgs: (cmd, ...args) => [cmd, ...args, '$@'],
|
|
37
|
+
createFile: (file, text, mode) => [
|
|
38
|
+
...text.map((line, i) =>
|
|
39
|
+
['echo', `"${escape(line)}"`, i === 0 ? '>' : '>>', file]),
|
|
40
|
+
...(mode ? [['chmod', mode, file]] : [])
|
|
41
|
+
],
|
|
42
|
+
copy: (src, dest) => ['cp', src, dest],
|
|
43
|
+
copyRecursive: (src, dest) => ['cp', '-r', '-p', src, dest],
|
|
44
|
+
rmRecursive: (dest) => ['rm', '-rf', dest],
|
|
45
|
+
mkdir: (dest) => ['mkdir', '-p', dest],
|
|
46
|
+
export: (key, value) => ['export', `${key}=${value}`],
|
|
47
|
+
chdir: (dest) => ['cd', dest],
|
|
48
|
+
comment: (message) => ['\n#', stripAnsiCodes(message), '\n'],
|
|
49
|
+
zip: (outputFile) => ['zip', '-r', outputFile, '.']
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const ActiveShellCommand = ShellCommands[process.platform === 'win32' ? 'win32' : 'posix'];
|