@travetto/compiler
Advanced tools
Comparing version 3.4.0-rc.0 to 3.4.0-rc.1
@@ -11,7 +11,5 @@ // @ts-check | ||
/** @typedef {import('@travetto/manifest/src/types').ManifestContext} Ctx */ | ||
/** @typedef {import('@travetto/compiler/support/types').EntryOp} EntryOp */ | ||
/** @return {Promise<import('@travetto/compiler/support/entry.trvc').main>} */ | ||
const $getEntry = async (/** @type {Ctx} */ ctx) => { | ||
/** @return {Promise<ReturnType<import('@travetto/compiler/support/entry.trvc').main>>} */ | ||
export const getEntry = async () => { | ||
const ctx = await getManifestContext(); | ||
const tsconfigFile = path.resolve(ctx.workspacePath, 'tsconfig.json'); | ||
@@ -54,19 +52,6 @@ if (!(await fs.stat(tsconfigFile).catch(() => undefined))) { | ||
try { return require(files[0]).main; } | ||
catch { return import(files[0]).then(x => x.main); } | ||
}; | ||
async function $compile(/** @type {Ctx} ctx*/ ctx, /** @type {EntryOp} op */ op) { | ||
const rootCtx = await (ctx.monoRepo ? getManifestContext(ctx.workspacePath) : ctx); | ||
return (await $getEntry(ctx))(ctx, rootCtx, op, process.argv.slice(3)); | ||
} | ||
/** | ||
* @template T | ||
* @param {(ctx: Ctx, compile: typeof $compile) => Promise<T>} fn | ||
* @returns {Promise<T>} | ||
*/ | ||
export async function withContext(fn) { | ||
const ctx = await getManifestContext(); | ||
return fn(ctx, $compile); | ||
} | ||
try { return require(files[0]).main(rootCtx, ctx); } | ||
catch { return import(files[0]).then(v => v.main(rootCtx, ctx)); } | ||
}; |
#!/usr/bin/env node | ||
// @ts-check | ||
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
import { getEntry } from './common.js'; | ||
import { withContext } from './common.js'; | ||
/** @typedef {import('@travetto/manifest/src/types').ManifestContext} Ctx */ | ||
const stop = async (/** @typedef {Ctx} */ ctx) => { | ||
if (await fetch(`${ctx.compilerUrl}/stop`).then(v => v.ok, () => false)) { | ||
console.log(`Stopped server ${ctx.workspacePath}: [${ctx.compilerUrl}]`); | ||
} else { | ||
console.log(`Server not running ${ctx.workspacePath}: [${ctx.compilerUrl}]`); | ||
} | ||
}; | ||
const info = async (/** @typedef {Ctx} */ctx) => console.log( | ||
JSON.stringify(await fetch(ctx.compilerUrl).then(v => v.json(), () => undefined) ?? { state: 'Server not running' }, null, 2) | ||
); | ||
const clean = async (/** @typedef {Ctx} */ctx) => { | ||
const folders = [ctx.outputFolder, ctx.compilerFolder]; | ||
if (await fetch(`${ctx.compilerUrl}/clean`).then(v => v.ok, () => false)) { | ||
return console.log(`Clean triggered ${ctx.workspacePath}:`, folders); | ||
} else { | ||
await Promise.all(folders.map(f => fs.rm(path.resolve(ctx.workspacePath, f), { force: true, recursive: true }))); | ||
return console.log(`Cleaned ${ctx.workspacePath}:`, folders); | ||
} | ||
}; | ||
const help = () => [ | ||
@@ -46,18 +19,18 @@ 'npx trvc [command]', | ||
withContext(async (ctx, compile) => { | ||
const op = process.argv[2]; | ||
getEntry().then(async (ops) => { | ||
const [op, ...args] = process.argv.slice(2); | ||
switch (op) { | ||
case 'restart': return stop(ctx).then(() => compile(ctx, 'watch')); | ||
case 'stop': return stop(ctx); | ||
case 'info': return info(ctx); | ||
case 'clean': return clean(ctx); | ||
case 'watch': | ||
case 'start': return compile(ctx, 'watch'); | ||
case 'build': | ||
case 'manifest': return compile(ctx, op); | ||
case undefined: | ||
case 'help': return console.log(`\n${help()}\n`); | ||
case 'restart': return ops.stop().then(() => ops.compile('watch')); | ||
case 'stop': return ops.stop(); | ||
case 'info': return ops.info().then(v => console.log(JSON.stringify(v, null, 2))); | ||
case 'clean': return ops.clean(); | ||
case 'manifest': return ops.manifest(args); | ||
case 'start': return ops.compile('watch'); | ||
case 'watch': | ||
case 'build': return ops.compile(op); | ||
default: console.error(`Unknown trvc operation: ${op}\n`); return console.error(help()); | ||
} | ||
}); |
{ | ||
"name": "@travetto/compiler", | ||
"version": "3.4.0-rc.0", | ||
"version": "3.4.0-rc.1", | ||
"description": "The compiler infrastructure for the Travetto framework", | ||
@@ -34,9 +34,9 @@ "keywords": [ | ||
"@parcel/watcher": "^2.3.0", | ||
"@travetto/manifest": "^3.4.0-rc.0", | ||
"@travetto/manifest": "^3.4.0-rc.1", | ||
"@travetto/terminal": "^3.4.0-rc.0", | ||
"@travetto/transformer": "^3.4.0-rc.0", | ||
"@types/node": "^20.8.9" | ||
"@travetto/transformer": "^3.4.0-rc.1", | ||
"@types/node": "^20.8.10" | ||
}, | ||
"peerDependencies": { | ||
"@travetto/cli": "^3.4.0-rc.0" | ||
"@travetto/cli": "^3.4.0-rc.2" | ||
}, | ||
@@ -50,3 +50,3 @@ "peerDependenciesMeta": { | ||
"displayName": "Compiler", | ||
"profiles": [ | ||
"roles": [ | ||
"compile" | ||
@@ -53,0 +53,0 @@ ] |
@@ -24,3 +24,3 @@ <!-- This file was generated by @travetto/doc and should not be modified directly --> | ||
## CLI | ||
The compiler cli, [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L7) is a compilation aware entry point, that has the ability to check for active builds, and ongoing watch operations to ensure only one process is building at a time. Within the framework, regardless of mono-repo or not, always builds the entire project. With the efficient caching behavior, this leads to generally a minimal overhead but allows for centralization of all operations. | ||
The compiler cli, [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L4) is the entry point for compilation-related operations. It has the ability to check for active builds, and ongoing watch operations to ensure only one process is building at a time. Within the framework, regardless of mono-repo or not, the compilation always targets the entire project. With the efficient caching behavior, this leads to generally a minimal overhead but allows for centralization of all operations. | ||
@@ -41,3 +41,3 @@ The compiler cli supports the following operations: | ||
2029-03-14T04:00:00.618Z info [compiler-server] Starting server http://127.0.0.1:29222 | ||
2029-03-14T04:00:00.618Z info [compiler-server] Starting server http://127.0.0.1:25539 | ||
2029-03-14T04:00:00.837Z debug [compiler-client] Starting watch for events of type "log" | ||
@@ -91,2 +91,2 @@ 2029-03-14T04:00:01.510Z debug [event-stream ] Started event stream | ||
### Bootstrapping | ||
Given that the framework is distributed as [Typescript](https://typescriptlang.org) only files, there is a bootstrapping problem that needs to be mitigated. The [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L7) entrypoint, along with a small context utility in [Manifest](https://github.com/travetto/travetto/tree/main/module/manifest#readme "Support for project indexing, manifesting, along with file watching") are the only [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) files needed to run the project. The [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L7) entry point will compile `@travetto/compiler/support/*` files as the set that is used at startup. These files are also accessible to the compiler as they get re-compiled after the fact. | ||
Given that the framework is distributed as [Typescript](https://typescriptlang.org) only files, there is a bootstrapping problem that needs to be mitigated. The [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L4) entrypoint, along with a small context utility in [Manifest](https://github.com/travetto/travetto/tree/main/module/manifest#readme "Support for project indexing, manifesting, along with file watching") are the only [Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) files needed to run the project. The [trvc](https://github.com/travetto/travetto/tree/main/module/compiler/bin/trvc.js#L4) entry point will compile `@travetto/compiler/support/*` files as the set that is used at startup. These files are also accessible to the compiler as they get re-compiled after the fact. |
@@ -0,1 +1,4 @@ | ||
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
import type { ManifestContext } from '@travetto/manifest'; | ||
@@ -7,34 +10,65 @@ | ||
import { CompilerRunner } from './server/runner'; | ||
import type { BuildOp, EntryOp } from './types'; | ||
import type { CompilerOp, CompilerServerInfo } from './types'; | ||
import { CompilerClientUtil } from './server/client'; | ||
import { CommonUtil } from './util'; | ||
async function build(root: ManifestContext, op: BuildOp): Promise<void> { | ||
const server = await new CompilerServer(root, op).listen(); | ||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
export const main = (root: ManifestContext, ctx: ManifestContext) => { | ||
const ops = { | ||
/** Stop the server */ | ||
async stop(): Promise<void> { | ||
if (await fetch(`${ctx.compilerUrl}/stop`).then(v => v.ok, () => false)) { | ||
console.log(`Stopped server ${ctx.workspacePath}: [${ctx.compilerUrl}]`); | ||
} else { | ||
console.log(`Server not running ${ctx.workspacePath}: [${ctx.compilerUrl}]`); | ||
} | ||
}, | ||
// Wait for build to be ready | ||
if (server) { | ||
await server.processEvents(async function* (signal) { | ||
const { changed, manifest } = await CompilerSetup.setup(root); | ||
yield* CompilerRunner.runProcess(root, manifest, changed, op === 'watch', signal); | ||
}); | ||
} else { | ||
await CompilerClientUtil.waitForBuild(root); | ||
} | ||
} | ||
/** Get server info */ | ||
info(): Promise<CompilerServerInfo> { | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
return fetch(ctx.compilerUrl).then(v => v.json(), () => ({ state: 'Server not running' })) as Promise<CompilerServerInfo>; | ||
}, | ||
/** | ||
* Main entry point for trv.js | ||
*/ | ||
export async function main(ctx: ManifestContext, root: ManifestContext, op: EntryOp, args: (string | undefined)[] = []): Promise<((mod: string) => Promise<unknown>) | undefined> { | ||
LogUtil.initLogs(ctx, op); | ||
switch (op) { | ||
case 'manifest': await CompilerSetup.exportManifest(ctx, ...args.filter(x => !x?.startsWith('-'))); return; | ||
case 'watch': | ||
case 'build': await build(root, op); return; | ||
case 'run': { | ||
await build(root, 'build'); | ||
/** Clean the server */ | ||
async clean(): Promise<void> { | ||
const folders = [ctx.outputFolder, ctx.compilerFolder]; | ||
if (await fetch(`${ctx.compilerUrl}/clean`).then(v => v.ok, () => false)) { | ||
return console.log(`Clean triggered ${ctx.workspacePath}:`, folders); | ||
} else { | ||
await Promise.all(folders.map(f => fs.rm(path.resolve(ctx.workspacePath, f), { force: true, recursive: true }))); | ||
return console.log(`Cleaned ${ctx.workspacePath}:`, folders); | ||
} | ||
}, | ||
/** Main entry point for compilation */ | ||
async compile(op: CompilerOp, setupOnly = false): Promise<(mod: string) => Promise<unknown>> { | ||
LogUtil.initLogs(ctx, op === 'run' ? 'error' : 'info'); | ||
const server = await new CompilerServer(root, op).listen(); | ||
// Wait for build to be ready | ||
if (server) { | ||
await server.processEvents(async function* (signal) { | ||
const { changed, manifest } = await CompilerSetup.setup(root); | ||
if (!setupOnly) { | ||
yield* CompilerRunner.runProcess(root, manifest, changed, op, signal); | ||
} else { | ||
yield* []; | ||
} | ||
}); | ||
} else { | ||
await CompilerClientUtil.waitForBuild(root); | ||
} | ||
return CommonUtil.moduleLoader(ctx); | ||
}, | ||
/** Manifest entry point */ | ||
async manifest(args: (string | undefined)[] = []): Promise<void> { | ||
await ops.compile('run', true); | ||
await CompilerSetup.exportManifest(ctx, ...args.filter(x => !x?.startsWith('-'))); return; | ||
} | ||
} | ||
} | ||
}; | ||
return ops; | ||
}; | ||
import type { ManifestContext } from '@travetto/manifest'; | ||
import type { CompilerLogEvent, CompilerLogLevel, EntryOp } from './types'; | ||
import type { CompilerLogEvent, CompilerLogLevel } from './types'; | ||
@@ -7,3 +7,3 @@ export type CompilerLogger = (level: CompilerLogLevel, message: string, ...args: unknown[]) => void; | ||
const LEVEL_TO_PRI = Object.fromEntries((['debug', 'info', 'warn', 'error'] as const).map((x, i) => [x, i + 1])); | ||
const LEVEL_TO_PRI: Record<CompilerLogLevel, number> = { debug: 1, info: 2, warn: 3, error: 4 }; | ||
@@ -16,3 +16,3 @@ const SCOPE_MAX = 15; | ||
static logLevel?: CompilerLogLevel; | ||
static logLevel: CompilerLogLevel = 'error'; | ||
@@ -22,7 +22,7 @@ /** | ||
*/ | ||
static initLogs(ctx: ManifestContext, op: EntryOp): void { | ||
static initLogs(ctx: ManifestContext, defaultLevel: CompilerLogLevel): void { | ||
// Listen only if we aren't in quiet | ||
if ((process.env.TRV_BUILD || !process.env.TRV_QUIET) && op !== 'manifest') { | ||
if ((process.env.TRV_BUILD || !process.env.TRV_QUIET)) { | ||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions | ||
this.logLevel = (process.env.TRV_BUILD as 'debug') ?? (op === 'run' ? 'warn' : 'info'); | ||
this.logLevel = (process.env.TRV_BUILD as 'debug') || defaultLevel; | ||
} | ||
@@ -33,2 +33,9 @@ this.root = ctx.workspacePath; | ||
/** | ||
* Is the log level active? | ||
*/ | ||
static isLevelActive(lvl: CompilerLogLevel): boolean { | ||
return LEVEL_TO_PRI[this.logLevel] <= LEVEL_TO_PRI[lvl]; | ||
} | ||
/** | ||
* Log message with filtering by level | ||
@@ -53,3 +60,3 @@ */ | ||
static sendLogEventToConsole(ev: CompilerLogEvent): void { | ||
if (this.logLevel && LEVEL_TO_PRI[this.logLevel] <= LEVEL_TO_PRI[ev.level]) { | ||
if (this.isLevelActive(ev.level)) { | ||
const params = [ev.message, ...ev.args ?? []].map(x => typeof x === 'string' ? x.replaceAll(LogUtil.root, '.') : x); | ||
@@ -56,0 +63,0 @@ if (ev.scope) { |
@@ -6,3 +6,3 @@ import cp from 'child_process'; | ||
import type { CompilerProgressEvent, CompilerServerEvent } from '../types'; | ||
import type { CompilerOp, CompilerProgressEvent, CompilerServerEvent } from '../types'; | ||
import { AsyncQueue } from '../queue'; | ||
@@ -39,3 +39,4 @@ import { LogUtil } from '../log'; | ||
*/ | ||
static async* runProcess(ctx: ManifestContext, manifest: ManifestRoot, changed: DeltaEvent[], watch: boolean, signal: AbortSignal): AsyncIterable<CompilerServerEvent> { | ||
static async* runProcess(ctx: ManifestContext, manifest: ManifestRoot, changed: DeltaEvent[], op: CompilerOp, signal: AbortSignal): AsyncIterable<CompilerServerEvent> { | ||
const watch = op === 'watch'; | ||
if (!changed.length && !watch) { | ||
@@ -49,4 +50,6 @@ yield { type: 'state', payload: { state: 'compile-end' } }; | ||
// Track progress | ||
this.trackProgress(ctx, CompilerClientUtil.fetchEvents(ctx, 'progress', signal, ev => !!ev.complete)); | ||
// Track progress if not in run mode | ||
if (op !== 'run') { | ||
this.trackProgress(ctx, CompilerClientUtil.fetchEvents(ctx, 'progress', signal, ev => !!ev.complete)); | ||
} | ||
@@ -53,0 +56,0 @@ const compiler = path.resolve(ctx.workspacePath, ctx.compilerFolder); |
@@ -7,3 +7,3 @@ import http from 'http'; | ||
import type { BuildOp, CompilerServerEvent, CompilerServerEventType, CompilerServerInfo } from '../types'; | ||
import type { CompilerMode, CompilerOp, CompilerServerEvent, CompilerServerEventType, CompilerServerInfo } from '../types'; | ||
import { LogUtil } from '../log'; | ||
@@ -27,3 +27,3 @@ import { CompilerClientUtil } from './client'; | ||
constructor(ctx: ManifestContext, op: BuildOp) { | ||
constructor(ctx: ManifestContext, op: CompilerOp) { | ||
this.#ctx = ctx; | ||
@@ -33,3 +33,3 @@ this.info = { | ||
iteration: Date.now(), | ||
type: op, | ||
mode: op === 'run' ? 'build' : op, | ||
serverPid: process.pid, | ||
@@ -51,4 +51,4 @@ compilerPid: -1, | ||
get op(): BuildOp { | ||
return this.info.type; | ||
get mode(): CompilerMode { | ||
return this.info.mode; | ||
} | ||
@@ -67,3 +67,3 @@ | ||
const info = await CompilerClientUtil.getServerInfo(this.#ctx); | ||
resolve((info && info.type === 'build' && this.op === 'watch') ? 'retry' : 'running'); | ||
resolve((info && info.mode === 'build' && this.mode === 'watch') ? 'retry' : 'running'); | ||
} else { | ||
@@ -70,0 +70,0 @@ reject(err); |
@@ -1,4 +0,3 @@ | ||
export type BuildOp = 'build' | 'watch'; | ||
export type EntryOp = BuildOp | 'manifest' | 'run'; | ||
export type TotalOp = EntryOp | 'stop' | 'clean' | 'info'; | ||
export type CompilerMode = 'build' | 'watch'; | ||
export type CompilerOp = CompilerMode | 'run'; | ||
@@ -25,5 +24,5 @@ export type CompilerStateType = 'startup' | 'init' | 'compile-start' | 'compile-end' | 'watch-start' | 'watch-end' | 'reset' | 'close'; | ||
state: CompilerStateType; | ||
type: BuildOp; | ||
mode: CompilerMode, | ||
iteration: number; | ||
url: string; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
74632
1621
4
0
Updated@types/node@^20.8.10