@peripheries/engine 0.2.0 → 0.3.0
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/package.json +11 -3
- package/src/commands/build.mjs +4 -0
- package/src/commands/deploy.mjs +3 -2
- package/src/index.d.mts +2 -1
- package/src/lib/config.mjs +1 -1
- package/src/lib/run.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peripheries/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Build, check, knowledge and deploy for peripheries component repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"node": ">=22"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"engine": "
|
|
15
|
+
"engine": "bin/engine.mjs"
|
|
16
16
|
},
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
@@ -39,7 +39,15 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@peripheries/renderer": ">=0.6.2 <1",
|
|
42
|
-
"@peripheries/runtime": ">=0.6.2 <1"
|
|
42
|
+
"@peripheries/runtime": ">=0.6.2 <1",
|
|
43
|
+
"vite": ">=8.2 <9",
|
|
44
|
+
"@vitejs/plugin-react": ">=6 <7",
|
|
45
|
+
"typescript": ">=5.6 <6"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"typescript": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
43
51
|
},
|
|
44
52
|
"publishConfig": {
|
|
45
53
|
"access": "public"
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{spawnSync}from"node:child_process";import{existsSync}from"node:fs";import{createRequire}from"node:module";import{resolve}from"node:path";import{pathToFileURL}from"node:url";import{loadConfig}from"../lib/config.mjs";import{parseFlagValue}from"../lib/env.mjs";import{REPO_ROOT}from"../lib/root.mjs";import{runCommand}from"../lib/run.mjs";import{EXTERNALS}from"./externals.mjs";const argv=process.argv.slice(2);const only=parseFlagValue(argv,"lineage");const config=await loadConfig();const lineages=only?config.lineages.filter(l=>l.name===only):config.lineages;if(only&&lineages.length===0)throw new Error(`[build] --lineage ${only} is not in the config's lineages`);const fromRepo=createRequire(resolve(REPO_ROOT,"package.json"));const importFromRepo=name=>import(pathToFileURL(fromRepo.resolve(name)).href);function check(label,status){if(status!==0){console.error(`[build] ${label} failed (exit ${status}).`);process.exit(status??1)}}if(!argv.includes("--no-typecheck")&&existsSync(resolve(REPO_ROOT,"tsconfig.build.json"))){console.log("[build] typecheck: tsc -p tsconfig.build.json --noEmit");const tsc=fromRepo.resolve("typescript/bin/tsc");check("typecheck",spawnSync(process.execPath,[tsc,"-p","tsconfig.build.json","--noEmit"],{cwd:REPO_ROOT,stdio:"inherit"}).status)}process.env.NODE_ENV="production";const{build}=await importFromRepo("vite");const react=(await importFromRepo("@vitejs/plugin-react")).default;const external=[...EXTERNALS,...config.shared];for(const lineage of lineages){const entry=resolve(REPO_ROOT,lineage.entry);if(!existsSync(entry))throw new Error(`[build] no barrel at ${lineage.entry} for lineage "${lineage.name}"`);console.log(`
|
|
3
|
+
[build] ${lineage.name}: ${lineage.entry} \u2192 ${lineage.dist}/index.js`);await build({configFile:false,mode:"production",root:REPO_ROOT,logLevel:"warn",plugins:[react()],define:{"process.env.NODE_ENV":JSON.stringify("production"),__OA_BUNDLE_NAME__:JSON.stringify(config.org)},resolve:{alias:{"@":resolve(REPO_ROOT,"src")}},optimizeDeps:{exclude:external},build:{lib:{entry,formats:["es"],fileName:()=>"index.js"},rollupOptions:{external},outDir:resolve(REPO_ROOT,lineage.dist),emptyOutDir:true,sourcemap:true}});check(`${lineage.name} contracts`,runCommand("contracts",["--entry",lineage.entry,"--out",`${lineage.dist}/contracts.json`]));check(`${lineage.name} knowledge`,runCommand("knowledge",["--bundle",lineage.name]))}console.log(`
|
|
4
|
+
[build] \u2705 ${lineages.map(l=>l.name).join(", ")}`);
|
package/src/commands/deploy.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{execSync,spawnSync}from"node:child_process";import{loadConfig}from"../lib/config.mjs";import{parseFlagValue,parseTargetEnv}from"../lib/env.mjs";import{REPO_ROOT}from"../lib/root.mjs";import{runCommand}from"../lib/run.mjs";const root=REPO_ROOT;const argv=process.argv.slice(2);const target=parseTargetEnv(argv);const targetFlag=target==="local"?[]:[`--${target}`];const skipBuild=argv.includes("--skip-build");const only=parseFlagValue(argv,"lineage");const{lineages}=await loadConfig();const selected=only?lineages.filter(l=>l.name===only):lineages;if(only&&selected.length===0)throw new Error(`--lineage ${only} is not in the config's lineages (${lineages.map(l=>l.name).join(", ")})`);const git=args=>execSync(`git ${args}`,{cwd:root,encoding:"utf8"}).trim();const version=process.env.VERSION||(git("status --porcelain")===""?`v_${git("rev-parse --short HEAD")}`:`v_${target}_${new Date().toISOString().replace(/[-:T]/g,"").slice(0,14)}`);function check(label,status){if(status!==0){console.error(`[deploy] ${label} failed (exit ${status}). Later lineages were not deployed.`);process.exit(status??1)}}function build(lineage){const{script,env={}}=lineage.build;console.log(`
|
|
3
|
-
[deploy] ${lineage.name} build: npm run ${script}`);const r=spawnSync("npm",["run",script],{cwd:root,stdio:"inherit",env:{...process.env,VERSION:version,...env}});check(`${lineage.name} build`,r.status)}
|
|
2
|
+
import{execSync,spawnSync}from"node:child_process";import{loadConfig}from"../lib/config.mjs";import{parseFlagValue,parseTargetEnv}from"../lib/env.mjs";import{REPO_ROOT}from"../lib/root.mjs";import{runCommand}from"../lib/run.mjs";const root=REPO_ROOT;const argv=process.argv.slice(2);const target=parseTargetEnv(argv);const targetFlag=target==="local"?[]:[`--${target}`];const skipBuild=argv.includes("--skip-build");const only=parseFlagValue(argv,"lineage");const{lineages}=await loadConfig();const selected=only?lineages.filter(l=>l.name===only):lineages;if(only&&selected.length===0)throw new Error(`--lineage ${only} is not in the config's lineages (${lineages.map(l=>l.name).join(", ")})`);const git=args=>execSync(`git ${args}`,{cwd:root,encoding:"utf8"}).trim();const version=process.env.VERSION||(git("status --porcelain")===""?`v_${git("rev-parse --short HEAD")}`:`v_${target}_${new Date().toISOString().replace(/[-:T]/g,"").slice(0,14)}`);function check(label,status){if(status!==0){console.error(`[deploy] ${label} failed (exit ${status}). Later lineages were not deployed.`);process.exit(status??1)}}function build(lineage){if(lineage.build?.script){const{script,env={}}=lineage.build;console.log(`
|
|
3
|
+
[deploy] ${lineage.name} build: npm run ${script}`);const r=spawnSync("npm",["run",script],{cwd:root,stdio:"inherit",env:{...process.env,VERSION:version,...env}});check(`${lineage.name} build`,r.status);return}console.log(`
|
|
4
|
+
[deploy] ${lineage.name} build: engine build --lineage ${lineage.name}`);check(`${lineage.name} build`,runCommand("build",["--lineage",lineage.name],{VERSION:version}))}function step(lineage,command,args){console.log(`
|
|
4
5
|
[deploy] ${lineage.name} ${command}: engine ${command} ${args.join(" ")}`);check(`${lineage.name} ${command}`,runCommand(command,args,{VERSION:version}))}console.log(`[deploy] target=${target} version=${version} lineages=${selected.map(l=>l.name).join(", ")}`);for(const lineage of selected){if(!skipBuild)build(lineage);const bundle=lineage.name==="main"?[]:["--bundle",lineage.name];step(lineage,"upload",[...targetFlag,...bundle]);step(lineage,"register",[...targetFlag,...bundle]);step(lineage,"cutover",[...targetFlag,"--version",version,...bundle])}console.log(`
|
|
5
6
|
[deploy] \u2705 ${selected.map(l=>l.name).join(", ")} live at ${version} on ${target}.`);
|
package/src/index.d.mts
CHANGED
|
@@ -14,6 +14,7 @@ export type LineageSpec =
|
|
|
14
14
|
export type EngineConfig = {
|
|
15
15
|
org: string;
|
|
16
16
|
lineages?: LineageSpec[];
|
|
17
|
+
shared?: string[];
|
|
17
18
|
checks?: {
|
|
18
19
|
run?: string[];
|
|
19
20
|
peerRepos?: string[];
|
|
@@ -27,7 +28,7 @@ export type Lineage = {
|
|
|
27
28
|
entry: string;
|
|
28
29
|
sourceRoot: string | null;
|
|
29
30
|
dist: string;
|
|
30
|
-
build
|
|
31
|
+
build?: { script: string; env?: Record<string, string> };
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
export const DEFAULT_CHECKS: string[];
|
package/src/lib/config.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync,readFileSync}from"node:fs";import{resolve}from"node:path";import{pathToFileURL}from"node:url";import{REPO_ROOT}from"./root.mjs";const MAIN_LINEAGE="main";const DEFAULT_CHECKS=["validate-externals","check-wired","check-routes","check-design-refs","check-skills","check-work-orders","check-cutover-ownership","check-fixtures","knowledge"];const PUBLIC_LINEAGE="public";const CONFIG_FILES=["engine.config.ts","engine.config.mts","engine.config.mjs","engine.config.js"];function defineConfig(config){return config}function lineageDefaults(name,kind){if(name===MAIN_LINEAGE){return{name,kind:"main",entry:"src/index.ts",sourceRoot:null,dist:"dist"
|
|
1
|
+
import{existsSync,readFileSync}from"node:fs";import{resolve}from"node:path";import{pathToFileURL}from"node:url";import{REPO_ROOT}from"./root.mjs";const MAIN_LINEAGE="main";const DEFAULT_CHECKS=["validate-externals","check-wired","check-routes","check-design-refs","check-skills","check-work-orders","check-cutover-ownership","check-fixtures","knowledge"];const PUBLIC_LINEAGE="public";const CONFIG_FILES=["engine.config.ts","engine.config.mts","engine.config.mjs","engine.config.js"];function defineConfig(config){return config}function lineageDefaults(name,kind){if(name===MAIN_LINEAGE){return{name,kind:"main",entry:"src/index.ts",sourceRoot:null,dist:"dist"}}if(name===PUBLIC_LINEAGE){return{name,kind:"public",entry:"src/index.public.ts",sourceRoot:"components/public/",dist:"dist-public"}}const k=kind??"page";return{name,kind:k,entry:`src/index.${name}.ts`,sourceRoot:k==="form"?`components/form/${name}/`:`components/project_page/${name}/`,dist:`dist-bundles/${name}`}}function normalize(raw,origin){if(!raw||typeof raw!=="object")throw new Error(`[engine] ${origin} must export a config object`);if(typeof raw.org!=="string"||!raw.org)throw new Error(`[engine] ${origin}: \`org\` (the org slug) is required`);const list=raw.lineages??[MAIN_LINEAGE];const lineages=list.map(l=>{const spec=typeof l==="string"?{name:l}:l;if(!spec?.name)throw new Error(`[engine] ${origin}: every lineage needs a name`);return{...lineageDefaults(spec.name,spec.kind),...spec}});if(lineages[0]?.name!==MAIN_LINEAGE)throw new Error(`[engine] ${origin}: lineages must start with "main"`);const gated=raw.checks?.gated??{};const checks={run:raw.checks?.run??DEFAULT_CHECKS,peerRepos:raw.checks?.peerRepos??[],gated:{projectTemplates:gated.projectTemplates??[],orgTemplates:gated.orgTemplates??[]}};const shared=raw.shared??[];return{org:raw.org,lineages,checks,shared}}let cached;async function loadConfig(){if(cached)return cached;const file=CONFIG_FILES.map(f=>resolve(REPO_ROOT,f)).find(f=>existsSync(f));if(file){const mod=await import(pathToFileURL(file).href);cached=normalize(mod.default??mod,file);return cached}const pkg=JSON.parse(readFileSync(resolve(REPO_ROOT,"package.json"),"utf8"));let org=pkg.oaBundle?.name;const orgJson=resolve(REPO_ROOT,"template/config/org.json");if(existsSync(orgJson))org=JSON.parse(readFileSync(orgJson,"utf8")).slug??org;const lineages=(pkg.oaBundle?.lineages??[MAIN_LINEAGE]).map(n=>n==="workbooks"?{name:n,kind:"form"}:n);cached=normalize({org,lineages},"package.json oaBundle");return cached}async function lineageConfig(name){const{lineages}=await loadConfig();return lineages.find(l=>l.name===name)??lineageDefaults(name)}export{DEFAULT_CHECKS,MAIN_LINEAGE,PUBLIC_LINEAGE,defineConfig,lineageConfig,lineageDefaults,loadConfig};
|
package/src/lib/run.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync}from"node:child_process";import{existsSync}from"node:fs";import{dirname,resolve}from"node:path";import{fileURLToPath}from"node:url";import{REPO_ROOT}from"./root.mjs";const COMMANDS_DIR=resolve(dirname(fileURLToPath(import.meta.url)),"..","commands");const TSX=import.meta.resolve("tsx/esm");const COMMANDS={deploy:"deploy.mjs",check:"check.mjs",upload:"upload-bundle.mjs",register:"register-components.mjs",cutover:"cutover.mjs",knowledge:"emit-knowledge.mjs",contracts:"emit-contracts.mjs","bundle-size":"bundle-size.mjs","check-bundle-leak":"check-bundle-leak.mjs","validate-externals":"validate-externals.mjs","check-wired":"check-wired-bindings.mjs","check-routes":"check-template-routes.mjs","check-design-refs":"check-design-refs.mjs","check-skills":"check-skills.mjs","check-work-orders":"check-work-orders.mjs","check-cutover-ownership":"check-cutover-ownership.mjs","check-fixtures":"check-fixtures.mjs","check-props-schema":"check-props-schema.mjs"};function commandFile(name){if(!COMMANDS[name])return null;const file=resolve(COMMANDS_DIR,COMMANDS[name]);const ts=file.replace(/\.mjs$/,".mts");return existsSync(file)?file:existsSync(ts)?ts:null}function runCommand(name,args=[],env={}){const file=commandFile(name);if(!file)throw new Error(`[engine] unknown command "${name}"`);const r=spawnSync(process.execPath,["--import",TSX,file,...args],{cwd:REPO_ROOT,stdio:"inherit",env:{...process.env,ENGINE_ROOT:REPO_ROOT,...env}});return r.status??1}export{COMMANDS,commandFile,runCommand};
|
|
1
|
+
import{spawnSync}from"node:child_process";import{existsSync}from"node:fs";import{dirname,resolve}from"node:path";import{fileURLToPath}from"node:url";import{REPO_ROOT}from"./root.mjs";const COMMANDS_DIR=resolve(dirname(fileURLToPath(import.meta.url)),"..","commands");const TSX=import.meta.resolve("tsx/esm");const COMMANDS={build:"build.mjs",deploy:"deploy.mjs",check:"check.mjs",upload:"upload-bundle.mjs",register:"register-components.mjs",cutover:"cutover.mjs",knowledge:"emit-knowledge.mjs",contracts:"emit-contracts.mjs","bundle-size":"bundle-size.mjs","check-bundle-leak":"check-bundle-leak.mjs","validate-externals":"validate-externals.mjs","check-wired":"check-wired-bindings.mjs","check-routes":"check-template-routes.mjs","check-design-refs":"check-design-refs.mjs","check-skills":"check-skills.mjs","check-work-orders":"check-work-orders.mjs","check-cutover-ownership":"check-cutover-ownership.mjs","check-fixtures":"check-fixtures.mjs","check-props-schema":"check-props-schema.mjs"};function commandFile(name){if(!COMMANDS[name])return null;const file=resolve(COMMANDS_DIR,COMMANDS[name]);const ts=file.replace(/\.mjs$/,".mts");return existsSync(file)?file:existsSync(ts)?ts:null}function runCommand(name,args=[],env={}){const file=commandFile(name);if(!file)throw new Error(`[engine] unknown command "${name}"`);const r=spawnSync(process.execPath,["--import",TSX,file,...args],{cwd:REPO_ROOT,stdio:"inherit",env:{...process.env,ENGINE_ROOT:REPO_ROOT,...env}});return r.status??1}export{COMMANDS,commandFile,runCommand};
|