@travetto/compiler 7.0.3 → 7.0.5

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,88 +0,0 @@
1
- // @ts-check
2
- /* eslint-disable no-undef */
3
- import { stat, readFile, writeFile, mkdir, rm, readdir } from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { createRequire } from 'node:module';
6
-
7
- const COMP_MOD = '@travetto/compiler';
8
- const SOURCE_EXT_REGEX = /[.][cm]?[tj]sx?$/;
9
- const BARE_IMPORT_REGEX = /^(@[^/]+[/])?[^.][^@/]+$/;
10
- const OUTPUT_EXT = '.js';
11
- const REQUIRE = createRequire(import.meta.filename);
12
-
13
- async function writeIfStale(sourceFile = '', destinationFile = '', transform = async (text = '') => text) {
14
- const [srcStat, destStat] = await Promise.all([sourceFile, destinationFile].map(file => stat(`${file}`).then(stats => stats.mtimeMs, () => 0)));
15
-
16
- if (!destStat || destStat < srcStat) {
17
- const text = sourceFile ? await readFile(sourceFile, 'utf8') : '';
18
- await mkdir(path.dirname(destinationFile), { recursive: true });
19
- await writeFile(destinationFile, await transform(text), 'utf8');
20
- }
21
- }
22
-
23
- async function transpile(content = '', full = true) {
24
- const ts = (await import('typescript')).default;
25
- return ts.transpile(content, {
26
- target: ts.ScriptTarget.ES2022,
27
- module: ts.ModuleKind.ESNext,
28
- importHelpers: true,
29
- sourceMap: false,
30
- inlineSourceMap: true,
31
- allowImportingTsExtensions: true,
32
- ...(full ? { esModuleInterop: true, allowSyntheticDefaultImports: true } : {})
33
- });
34
- }
35
-
36
- async function getContext() {
37
- const ctxFile = REQUIRE.resolve('@travetto/manifest/src/context.ts');
38
- const ctxDest = path.resolve(import.meta.dirname, 'gen.context.js');
39
- await writeIfStale(ctxFile, ctxDest, content => transpile(content, false));
40
- const ctx = await import(ctxDest).then((/** @type {import('@travetto/manifest')} */ value) => value.getManifestContext());
41
-
42
- const srcPath = path.resolve.bind(path, ctx.workspace.path, ctx.build.compilerModuleFolder);
43
- const destPath = (file = '') =>
44
- path.resolve(ctx.workspace.path, ctx.build.compilerFolder, 'node_modules', file).replace(SOURCE_EXT_REGEX, OUTPUT_EXT);
45
-
46
- return {
47
- srcPath,
48
- destPath,
49
- tsconfig: path.resolve(ctx.workspace.path, 'tsconfig.json'),
50
- cleanImports: (text = '') => text
51
- .replace(/from ['"]((@travetto|[.]+)[^'"]+)['"]/g, (_, location, module) => {
52
- const root = (module === '@travetto' ? destPath(location) : location).replace(SOURCE_EXT_REGEX, OUTPUT_EXT);
53
- const suffix = root.endsWith(OUTPUT_EXT) ? '' : (BARE_IMPORT_REGEX.test(location) ? `/__index__${OUTPUT_EXT}` : OUTPUT_EXT);
54
- return `from '${root}${suffix}'`;
55
- }),
56
- loadMain: () => import(destPath(`${COMP_MOD}/support/entry.main.ts`))
57
- .then((/** @type {import('../support/entry.main.ts')} */ value) => value.main(ctx)),
58
- supportFiles: () => readdir(srcPath('support'), { recursive: true, encoding: 'utf8' })
59
- .then(files => files.filter(file => file.endsWith('.ts')).map(file => `support/${file}`))
60
- };
61
- }
62
-
63
- /** @template T */
64
- export async function load(/** @type {(operations: import('../support/entry.main.ts').Operations) => T} */ callback) {
65
- const ctx = await getContext();
66
-
67
- try {
68
- await writeIfStale('', ctx.tsconfig,
69
- async () => JSON.stringify({ extends: `${COMP_MOD}/tsconfig.trv.json` }, null, 2));
70
-
71
- await writeIfStale(ctx.srcPath('package.json'), ctx.destPath(`${COMP_MOD}/package.json`),
72
- async text => JSON.stringify({ ...JSON.parse(text || '{}'), type: 'module' }, null, 2));
73
-
74
- await Promise.all((await ctx.supportFiles()).map(file =>
75
- writeIfStale(ctx.srcPath(file), ctx.destPath(`${COMP_MOD}/${file}`),
76
- text => transpile(ctx.cleanImports(text)))));
77
-
78
- process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
79
- process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
80
- const result = await ctx.loadMain();
81
- // @ts-ignore
82
- try { module.enableCompileCache(); } catch { }
83
- return callback(result);
84
- } catch (error) {
85
- await rm(ctx.destPath(COMP_MOD), { recursive: true, force: true });
86
- throw error;
87
- }
88
- }
@@ -1,73 +0,0 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { createRequire } from 'node:module';
4
- // eslint-disable-next-line no-bitwise
5
- const toPort = (location) => (Math.abs([...location].reduce((a, b) => (a * 33) ^ b.charCodeAt(0), 5381)) % 29000) + 20000;
6
- const toPosix = (location) => location.replaceAll('\\', '/');
7
- const readPackage = (file) => ({ ...JSON.parse(readFileSync(file, 'utf8')), path: toPosix(path.dirname(file)) });
8
- /** Find package */
9
- function findPackage(base, pred) {
10
- let folder = `${base}/.`;
11
- let previous;
12
- let pkg;
13
- const packages = [];
14
- do {
15
- pkg && packages.push(pkg);
16
- previous = folder;
17
- folder = path.dirname(folder);
18
- const folderPkg = path.resolve(folder, 'package.json');
19
- pkg = existsSync(folderPkg) ? readPackage(folderPkg) : pkg;
20
- } while (previous !== folder && // Not at root
21
- !pred(pkg) && // Matches criteria
22
- !existsSync(path.resolve(folder, '.git')) // Not at source root
23
- );
24
- if (!pkg) {
25
- throw new Error('Could not find a package.json');
26
- }
27
- else if (!pred(pkg) && packages.length) {
28
- // We never matched, lets fallback to the first package.json found
29
- pkg = packages[0];
30
- }
31
- return pkg;
32
- }
33
- /**
34
- * Gets build context
35
- */
36
- export function getManifestContext(root = process.cwd()) {
37
- const workspace = findPackage(root, pkg => !!pkg?.workspaces || !!pkg?.travetto?.build?.isolated);
38
- const build = workspace.travetto?.build ?? {};
39
- const resolve = createRequire(path.resolve(workspace.path, 'node_modules')).resolve.bind(null);
40
- const wsPrefix = `${workspace.path}/`;
41
- const moduleName = process.env.TRV_MODULE === workspace.name ? workspace.path : process.env.TRV_MODULE;
42
- const modPkg = (!!workspace.workspaces && moduleName) ?
43
- readPackage(resolve(`${moduleName}/package.json`)) :
44
- findPackage(root, pkg => !!pkg) ?? workspace;
45
- if (workspace.type !== 'module') {
46
- console.error('ERROR: Only ESM modules are supported, package.json must be of type module');
47
- process.exit(1);
48
- }
49
- return {
50
- workspace: {
51
- name: workspace.name ?? 'untitled',
52
- path: workspace.path,
53
- mono: !!workspace.workspaces,
54
- manager: existsSync(path.resolve(workspace.path, 'yarn.lock')) ? 'yarn' : 'npm',
55
- defaultEnv: workspace.travetto?.defaultEnv ?? 'local'
56
- },
57
- build: {
58
- compilerUrl: build.compilerUrl ?? `http://localhost:${toPort(wsPrefix)}`,
59
- compilerModuleFolder: toPosix(path.dirname(resolve('@travetto/compiler/package.json'))).replace(wsPrefix, ''),
60
- compilerFolder: toPosix(build.compilerFolder ?? '.trv/compiler'),
61
- outputFolder: toPosix(build.outputFolder ?? '.trv/output'),
62
- toolFolder: toPosix(build.toolFolder ?? '.trv/tool'),
63
- typesFolder: toPosix(build.typesFolder ?? '.trv/types')
64
- },
65
- main: {
66
- name: modPkg.name ?? 'untitled',
67
- folder: modPkg.path.replace(wsPrefix, ''),
68
- version: modPkg.version,
69
- description: modPkg.description
70
- }
71
- };
72
- }
73
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ25ELE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBTzVDLHNDQUFzQztBQUN0QyxNQUFNLE1BQU0sR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQztBQUMxSSxNQUFNLE9BQU8sR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQzdFLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBWSxFQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFOUgsbUJBQW1CO0FBQ25CLFNBQVMsV0FBVyxDQUFDLElBQVksRUFBRSxJQUEyQjtJQUM1RCxJQUFJLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDO0lBQ3pCLElBQUksUUFBZ0IsQ0FBQztJQUNyQixJQUFJLEdBQW9CLENBQUM7SUFDekIsTUFBTSxRQUFRLEdBQVUsRUFBRSxDQUFDO0lBRTNCLEdBQUcsQ0FBQztRQUNGLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFCLFFBQVEsR0FBRyxNQUFNLENBQUM7UUFDbEIsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDdkQsR0FBRyxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDN0QsQ0FBQyxRQUNDLFFBQVEsS0FBSyxNQUFNLElBQUksY0FBYztRQUNyQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxtQkFBbUI7UUFDakMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxxQkFBcUI7TUFDL0Q7SUFFRixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDVCxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDbkQsQ0FBQztTQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3pDLGtFQUFrRTtRQUNsRSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxPQUFlLE9BQU8sQ0FBQyxHQUFHLEVBQUU7SUFDN0QsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNsRyxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsUUFBUSxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUM7SUFDOUMsTUFBTSxPQUFPLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0YsTUFBTSxRQUFRLEdBQUcsR0FBRyxTQUFTLENBQUMsSUFBSSxHQUFHLENBQUM7SUFDdEMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEtBQUssU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7SUFDdkcsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLFVBQVUsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQ3JELFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxVQUFVLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRCxXQUFXLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFNBQVMsQ0FBQztJQUUvQyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDaEMsT0FBTyxDQUFDLEtBQUssQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO1FBQzVGLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQztJQUVELE9BQU87UUFDTCxTQUFTLEVBQUU7WUFDVCxJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUksSUFBSSxVQUFVO1lBQ2xDLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtZQUNwQixJQUFJLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVO1lBQzVCLE9BQU8sRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSztZQUMvRSxVQUFVLEVBQUUsU0FBUyxDQUFDLFFBQVEsRUFBRSxVQUFVLElBQUksT0FBTztTQUN0RDtRQUNELEtBQUssRUFBRTtZQUNMLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxJQUFJLG9CQUFvQixNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDeEUsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQzdHLGNBQWMsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsSUFBSSxlQUFlLENBQUM7WUFDaEUsWUFBWSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxJQUFJLGFBQWEsQ0FBQztZQUMxRCxVQUFVLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksV0FBVyxDQUFDO1lBQ3BELFdBQVcsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsSUFBSSxZQUFZLENBQUM7U0FDeEQ7UUFDRCxJQUFJLEVBQUU7WUFDSixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksSUFBSSxVQUFVO1lBQy9CLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3pDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztZQUN2QixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7U0FDaEM7S0FDRixDQUFDO0FBQ0osQ0FBQyJ9
@@ -1,3 +0,0 @@
1
- // @trv-no-transform
2
- import { Compiler } from '../src/compiler.ts';
3
- Compiler.main();
@@ -1,118 +0,0 @@
1
- // @trv-no-transform
2
- import fs from 'node:fs/promises';
3
-
4
- import type { ManifestContext } from '@travetto/manifest';
5
-
6
- import { isComplilerEventType, type CompilerMode, type CompilerServerInfo } from './types.ts';
7
- import { Log } from './log.ts';
8
- import { CompilerSetup } from './setup.ts';
9
- import { CompilerServer } from './server/server.ts';
10
- import { CompilerRunner } from './server/runner.ts';
11
- import { CompilerClient } from './server/client.ts';
12
- import { CommonUtil } from './util.ts';
13
-
14
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
15
- export const main = (ctx: ManifestContext) => {
16
- const client = new CompilerClient(ctx, Log.scoped('client'));
17
- const buildFolders = [ctx.build.outputFolder, ctx.build.compilerFolder, ctx.build.typesFolder];
18
- Log.root = ctx.workspace.path;
19
- Log.initLevel('error');
20
-
21
- /** Main entry point for compilation */
22
- const compile = async (operation: CompilerMode, setupOnly = false): Promise<void> => {
23
- const server = await new CompilerServer(ctx, operation).listen();
24
- const log = Log.scoped('main');
25
-
26
- // Wait for build to be ready
27
- if (server) {
28
- log.debug('Start Server');
29
- await server.processEvents(async function* (signal) {
30
- const changed = await CompilerSetup.setup(ctx);
31
- if (!setupOnly) {
32
- yield* CompilerRunner.runProcess(ctx, changed, operation, signal);
33
- }
34
- });
35
- log.debug('End Server');
36
- } else {
37
- log.info('Server already running, waiting for initial compile to complete');
38
- const controller = new AbortController();
39
- Log.consumeProgressEvents(() => client.fetchEvents('progress', { until: event => !!event.complete, signal: controller.signal }));
40
- await client.waitForState(['compile-end', 'watch-start'], 'Successfully built');
41
- controller.abort();
42
- }
43
- };
44
-
45
- const operations = {
46
- /** Stop the server */
47
- async stop(): Promise<void> {
48
- if (await client.stop()) {
49
- console.log(`Stopped server ${ctx.workspace.path}: ${client}`);
50
- } else {
51
- console.log(`Server not running ${ctx.workspace.path}: ${client}`);
52
- }
53
- },
54
-
55
- /** Restart the server */
56
- async restart(): Promise<void> { await client.stop().then(() => operations.watch()); },
57
-
58
- /** Get server info */
59
- info: (): Promise<CompilerServerInfo | undefined> => client.info(),
60
-
61
- /** Clean the server */
62
- async clean(): Promise<void> {
63
- if (await client.clean()) {
64
- return console.log(`Clean triggered ${ctx.workspace.path}:`, buildFolders);
65
- } else {
66
- try {
67
- await Promise.all(buildFolders.map(file => fs.rm(CommonUtil.resolveWorkspace(ctx, file), { force: true, recursive: true })));
68
- } catch { }
69
- return console.log(`Cleaned ${ctx.workspace.path}:`, buildFolders);
70
- }
71
- },
72
-
73
- /** Stream events */
74
- events: async (type: string, handler: (event: unknown) => unknown): Promise<void> => {
75
- if (isComplilerEventType(type)) {
76
- for await (const event of client.fetchEvents(type)) { await handler(event); }
77
- } else {
78
- throw new Error(`Unknown event type: ${type}`);
79
- }
80
- },
81
-
82
- /** Build the project */
83
- async build(): Promise<void> {
84
- Log.initLevel('info');
85
- await compile('build');
86
- },
87
-
88
- /** Build and watch the project */
89
- async watch(): Promise<void> {
90
- Log.initLevel('info');
91
- await compile('watch');
92
- },
93
-
94
- /** Set arguments and import module */
95
- async exec(mod: string, args?: string[]): Promise<unknown> {
96
- Log.initLevel('none');
97
- if (!(await client.isWatching())) { // Short circuit if we can
98
- Log.initLevel('error');
99
- await compile('build');
100
- }
101
-
102
- process.env.TRV_MANIFEST = CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.main.name); // Setup for running
103
- if (args) {
104
- process.argv = [process.argv0, mod, ...args];
105
- }
106
- return import(CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', mod)); // Return function to run import on a module
107
- },
108
-
109
- /** Manifest entry point */
110
- async manifest(output?: string, prod?: boolean): Promise<void> {
111
- await compile('build', true);
112
- await CompilerSetup.exportManifest(ctx, output, prod); return;
113
- }
114
- };
115
- return operations;
116
- };
117
-
118
- export type Operations = ReturnType<typeof main>;
@@ -1,80 +0,0 @@
1
- import cp from 'node:child_process';
2
- import { rmSync } from 'node:fs';
3
-
4
- import type { ManifestContext, DeltaEvent } from '@travetto/manifest';
5
-
6
- import type { CompilerEvent, CompilerMode } from '../types.ts';
7
- import { AsyncQueue } from '../queue.ts';
8
- import { Log } from '../log.ts';
9
- import { CommonUtil } from '../util.ts';
10
-
11
- const log = Log.scoped('compiler-exec');
12
- const isEvent = (value: unknown): value is CompilerEvent => !!value && typeof value === 'object' && 'type' in value;
13
-
14
- /**
15
- * Running the compiler
16
- */
17
- export class CompilerRunner {
18
-
19
- /**
20
- * Run compile process
21
- */
22
- static async * runProcess(ctx: ManifestContext, changed: DeltaEvent[], mode: CompilerMode, signal: AbortSignal): AsyncIterable<CompilerEvent> {
23
- if (signal.aborted) {
24
- log.debug('Skipping, shutting down');
25
- return;
26
- }
27
-
28
- const watch = mode === 'watch';
29
- if (!changed.length && !watch) {
30
- yield { type: 'state', payload: { state: 'compile-end' } };
31
- log.debug('Skipped');
32
- return;
33
- } else {
34
- const changedList = changed.slice(0, 10).map(event => `${event.module}/${event.file}`);
35
- log.debug(`Started watch=${watch} changed=${changedList}`);
36
- }
37
-
38
- const main = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', '@travetto/compiler/support/entry.compiler.js');
39
- const deltaFile = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, `manifest-delta-${Date.now()}.json`);
40
-
41
- const changedFiles = changed[0]?.file === '*' ? ['*'] : changed.map(event => event.sourceFile);
42
-
43
- const queue = new AsyncQueue<CompilerEvent>();
44
-
45
- try {
46
- await CommonUtil.writeTextFile(deltaFile, changedFiles.join('\n'));
47
-
48
- log.info('Launching compiler');
49
- const subProcess = cp.spawn(process.argv0, [main, deltaFile, `${watch}`], {
50
- env: {
51
- ...process.env,
52
- TRV_MANIFEST: CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder, 'node_modules', ctx.workspace.name),
53
- },
54
- detached: true,
55
- stdio: ['pipe', 1, 2, 'ipc'],
56
- })
57
- .on('message', message => isEvent(message) && queue.add(message))
58
- .on('exit', () => queue.close());
59
-
60
- const kill = (): unknown => {
61
- log.debug('Shutting down process');
62
- return (subProcess.connected ? subProcess.send('shutdown', () => subProcess.kill()) : subProcess.kill());
63
- };
64
-
65
- process.once('SIGINT', kill);
66
- signal.addEventListener('abort', kill);
67
-
68
- yield* queue;
69
-
70
- if (subProcess.exitCode !== 0) {
71
- log.error(`Terminated during compilation, code=${subProcess.exitCode}, killed=${subProcess.killed}`);
72
- }
73
- process.off('SIGINT', kill);
74
-
75
- log.debug('Finished');
76
- } finally {
77
- rmSync(deltaFile, { force: true });
78
- }
79
- }
80
- }
package/support/setup.ts DELETED
@@ -1,246 +0,0 @@
1
- import { createRequire } from 'node:module';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
-
5
- import type { DeltaEvent, ManifestContext, Package } from '@travetto/manifest';
6
-
7
- import { Log } from './log.ts';
8
- import { CommonUtil } from './util.ts';
9
- import { TypescriptUtil } from './ts-util.ts';
10
-
11
- type ModFile = { input: string, output: string, stale: boolean };
12
-
13
- const SOURCE_SEED = ['package.json', '__index__.ts', 'src', 'support', 'bin'];
14
- const PRECOMPILE_MODS = ['@travetto/manifest', '@travetto/transformer', '@travetto/compiler'];
15
- const RECENT_STAT = (stat: { ctimeMs: number, mtimeMs: number }): number => Math.max(stat.ctimeMs, stat.mtimeMs);
16
- const REQUIRE = createRequire(path.resolve('node_modules')).resolve.bind(null);
17
-
18
- const SOURCE_EXT_REGEX = /[.][cm]?[tj]s$/;
19
- const BARE_IMPORT_REGEX = /^(@[^/]+[/])?[^.][^@/]+$/;
20
- const OUTPUT_EXT = '.js';
21
-
22
- /**
23
- * Compiler Setup Utilities
24
- */
25
- export class CompilerSetup {
26
-
27
- /**
28
- * Import compiled manifest utilities
29
- */
30
- static #importManifest = (ctx: ManifestContext): Promise<
31
- Pick<typeof import('@travetto/manifest'), 'ManifestDeltaUtil' | 'ManifestUtil'>
32
- > => {
33
- const all = ['util', 'delta'].map(file =>
34
- import(CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', `@travetto/manifest/src/${file}${OUTPUT_EXT}`))
35
- );
36
- return Promise.all(all).then(results => Object.assign({}, ...results));
37
- };
38
-
39
- /** Convert a file to a given ext */
40
- static #sourceToExtension(sourceFile: string, ext: string): string {
41
- return sourceFile.replace(SOURCE_EXT_REGEX, ext);
42
- }
43
-
44
- /**
45
- * Get the output file name for a given input
46
- */
47
- static #sourceToOutputExt(sourceFile: string): string {
48
- return this.#sourceToExtension(sourceFile, OUTPUT_EXT);
49
- }
50
-
51
- /**
52
- * Output a file, support for ts, js, and package.json
53
- */
54
- static async #transpileFile(ctx: ManifestContext, sourceFile: string, outputFile: string): Promise<void> {
55
- const type = CommonUtil.getFileType(sourceFile);
56
- if (type === 'js' || type === 'ts') {
57
- const compilerOut = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules');
58
-
59
- const text = (await fs.readFile(sourceFile, 'utf8'))
60
- .replace(/from ['"](([.]+|@travetto)[/][^']+)['"]/g, (_, clause, moduleName) => {
61
- const root = this.#sourceToOutputExt(clause);
62
- const suffix = root.endsWith(OUTPUT_EXT) ? '' : (BARE_IMPORT_REGEX.test(clause) ? `/__index__${OUTPUT_EXT}` : OUTPUT_EXT);
63
- const prefix = moduleName === '@travetto' ? `${compilerOut}/` : '';
64
- return `from '${prefix}${root}${suffix}'`;
65
- });
66
-
67
- const ts = (await import('typescript')).default;
68
- const content = ts.transpile(text, {
69
- ...await TypescriptUtil.getCompilerOptions(ctx),
70
- sourceMap: false,
71
- inlineSourceMap: true,
72
- importHelpers: true,
73
- }, sourceFile);
74
- await CommonUtil.writeTextFile(outputFile, content);
75
- } else if (type === 'package-json') {
76
- const pkg: Package = JSON.parse(await fs.readFile(sourceFile, 'utf8'));
77
- const main = pkg.main ? this.#sourceToOutputExt(pkg.main) : undefined;
78
- const files = pkg.files?.map(file => this.#sourceToOutputExt(file));
79
-
80
- const content = JSON.stringify({ ...pkg, main, type: 'module', files }, null, 2);
81
- await CommonUtil.writeTextFile(outputFile, content);
82
- }
83
- }
84
-
85
- /**
86
- * Scan directory to find all project sources for comparison
87
- */
88
- static async #getModuleSources(ctx: ManifestContext, module: string, seed: string[]): Promise<ModFile[]> {
89
- const inputFolder = path.dirname(REQUIRE(`${module}/package.json`));
90
-
91
- const folders = seed.filter(folder => !/[.]/.test(folder)).map(folder => path.resolve(inputFolder, folder));
92
- const files = seed.filter(file => /[.]/.test(file)).map(file => path.resolve(inputFolder, file));
93
-
94
- while (folders.length) {
95
- const sub = folders.pop();
96
- if (!sub) {
97
- continue;
98
- }
99
-
100
- for (const file of await fs.readdir(sub).catch(() => [])) {
101
- if (file.startsWith('.')) {
102
- continue;
103
- }
104
- const resolvedInput = path.resolve(sub, file).replaceAll('\\', '/'); // To posix
105
- const stat = await fs.stat(resolvedInput);
106
-
107
- if (stat.isDirectory()) {
108
- folders.push(resolvedInput);
109
- } else {
110
- switch (CommonUtil.getFileType(file)) {
111
- case 'js': case 'ts': files.push(resolvedInput);
112
- }
113
- }
114
- }
115
- }
116
-
117
- const outputFolder = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerFolder, 'node_modules', module);
118
- const out: ModFile[] = [];
119
- for (const input of files) {
120
- const output = this.#sourceToOutputExt(input.replace(inputFolder, outputFolder));
121
- const inputTs = await fs.stat(input).then(RECENT_STAT, () => 0);
122
- if (inputTs) {
123
- const outputTs = await fs.stat(output).then(RECENT_STAT, () => 0);
124
- await fs.mkdir(path.dirname(output), { recursive: true });
125
- out.push({ input, output, stale: inputTs > outputTs });
126
- }
127
- }
128
-
129
- return out;
130
- }
131
-
132
- /**
133
- * Recompile folder if stale
134
- */
135
- static async #compileIfStale(ctx: ManifestContext, scope: string, mod: string, seed: string[]): Promise<string[]> {
136
- const files = await this.#getModuleSources(ctx, mod, seed);
137
- const changes = files.filter(file => file.stale).map(file => file.input);
138
- const out: string[] = [];
139
-
140
- try {
141
- await Log.wrap(scope, async log => {
142
- if (files.some(file => file.stale)) {
143
- log.debug('Starting', mod);
144
- for (const file of files) {
145
- if (file.stale) {
146
- await this.#transpileFile(ctx, file.input, file.output);
147
- }
148
- }
149
- if (changes.length) {
150
- out.push(...changes.map(file => `${mod}/${file}`));
151
- log.debug(`Source changed: ${changes.join(', ')}`, mod);
152
- }
153
- log.debug('Completed', mod);
154
- } else {
155
- log.debug('Skipped', mod);
156
- }
157
- }, false);
158
- } catch (error) {
159
- console.error(error);
160
- }
161
- return out;
162
- }
163
-
164
- /**
165
- * Export manifest
166
- */
167
- static async exportManifest(ctx: ManifestContext, output?: string, prod?: boolean): Promise<void> {
168
- const { ManifestUtil } = await this.#importManifest(ctx);
169
- let manifest = await ManifestUtil.buildManifest(ctx);
170
-
171
- // If in prod mode, only include std modules
172
- if (prod) {
173
- manifest = ManifestUtil.createProductionManifest(manifest);
174
- }
175
- if (output) {
176
- output = await ManifestUtil.writeManifestToFile(output, manifest);
177
- } else {
178
- console.log(JSON.stringify(manifest, null, 2));
179
- }
180
- }
181
-
182
- /**
183
- * Sets up compiler, and produces a set of changes that need to be processed
184
- */
185
- static async setup(ctx: ManifestContext): Promise<DeltaEvent[]> {
186
- let changes = 0;
187
-
188
- await Log.wrap('precompile', async () => {
189
- for (const mod of PRECOMPILE_MODS) {
190
- changes += (await this.#compileIfStale(ctx, 'precompile', mod, SOURCE_SEED)).length;
191
- }
192
- });
193
-
194
- const { ManifestUtil, ManifestDeltaUtil } = await this.#importManifest(ctx);
195
-
196
- const manifest = await Log.wrap('manifest', () =>
197
- ManifestUtil.buildManifest(ManifestUtil.getWorkspaceContext(ctx)));
198
-
199
- await Log.wrap('transformers', async () => {
200
- for (const mod of Object.values(manifest.modules)) {
201
- if (mod.files.$transformer?.length) {
202
- changes += (await this.#compileIfStale(ctx, 'transformers', mod.name,
203
- ['package.json', ...mod.files.$transformer!.map(file => file[0])])).length;
204
- }
205
- }
206
- });
207
-
208
- const delta = await Log.wrap('delta', async log => {
209
- if (changes) {
210
- log.debug('Skipping, everything changed');
211
- return [{ type: 'update', file: '*', module: ctx.workspace.name, sourceFile: '' } as const];
212
- } else {
213
- return ManifestDeltaUtil.produceDelta(manifest);
214
- }
215
- });
216
-
217
- if (changes) {
218
- await Log.wrap('reset', async log => {
219
- await fs.rm(CommonUtil.resolveWorkspace(ctx, ctx.build.outputFolder), { recursive: true, force: true });
220
- log.info('Clearing output due to compiler changes');
221
- }, false);
222
- }
223
-
224
- // Write manifest
225
- await Log.wrap('manifest', async log => {
226
- await ManifestUtil.writeManifest(manifest);
227
- log.debug(`Wrote manifest ${ctx.workspace.name}`);
228
-
229
- // Update all manifests when in mono repo
230
- if (delta.length && ctx.workspace.mono) {
231
- const names: string[] = [];
232
- const mods = Object.values(manifest.modules).filter(mod => mod.workspace && mod.name !== ctx.workspace.name);
233
- for (const mod of mods) {
234
- const modCtx = ManifestUtil.getModuleContext(ctx, mod.sourceFolder, true);
235
- const modManifest = await ManifestUtil.buildManifest(modCtx);
236
- await ManifestUtil.writeManifest(modManifest);
237
- names.push(mod.name);
238
- }
239
- log.debug(`Changes triggered ${delta.slice(0, 10).map(event => `${event.type}:${event.module}:${event.file}`)}`);
240
- log.debug(`Rewrote monorepo manifests [changes=${delta.length}] ${names.slice(0, 10).join(', ')}`);
241
- }
242
- });
243
-
244
- return delta.filter(event => event.type === 'create' || event.type === 'update');
245
- }
246
- }
@@ -1,42 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import type { CompilerOptions } from 'typescript';
3
-
4
- import type { ManifestContext } from '@travetto/manifest';
5
- import { CommonUtil } from './util.ts';
6
-
7
- const OPT_CACHE: Record<string, CompilerOptions> = {};
8
-
9
- export class TypescriptUtil {
10
- /**
11
- * Returns the compiler options
12
- */
13
- static async getCompilerOptions(ctx: ManifestContext): Promise<{}> {
14
- if (!(ctx.workspace.path in OPT_CACHE)) {
15
- let tsconfig = CommonUtil.resolveWorkspace(ctx, 'tsconfig.json');
16
-
17
- if (!await fs.stat(tsconfig).then(() => true, () => false)) {
18
- tsconfig = CommonUtil.resolveWorkspace(ctx, ctx.build.compilerModuleFolder, 'tsconfig.trv.json');
19
- }
20
-
21
- const ts = (await import('typescript')).default;
22
-
23
- const { options } = ts.parseJsonSourceFileConfigFileContent(
24
- ts.readJsonConfigFile(tsconfig, ts.sys.readFile), ts.sys, ctx.workspace.path
25
- );
26
-
27
- OPT_CACHE[ctx.workspace.path] = {
28
- ...options,
29
- noEmit: false,
30
- emitDeclarationOnly: false,
31
- allowJs: true,
32
- resolveJsonModule: true,
33
- sourceRoot: ctx.workspace.path,
34
- rootDir: ctx.workspace.path,
35
- outDir: CommonUtil.resolveWorkspace(ctx),
36
- moduleResolution: ts.ModuleResolutionKind.Bundler,
37
- module: ts.ModuleKind.ESNext,
38
- };
39
- }
40
- return OPT_CACHE[ctx.workspace.path];
41
- }
42
- }