-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.ts
More file actions
85 lines (76 loc) · 3.44 KB
/
Copy pathbuild.ts
File metadata and controls
85 lines (76 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { build } from 'esbuild';
import { readFileSync, chmodSync, mkdirSync, statSync } from 'node:fs';
import { join } from 'node:path';
import { generateAll } from './codegen/index';
import { loadEnvLocal } from './codegen/env-local';
async function main(): Promise<void> {
// Local dev loads .env.local here; CI supplies env vars on the workflow
// step from repo secrets, and process.env always wins over the file.
loadEnvLocal();
await generateAll();
// Step 2: resolve version — an explicit POLYLANE_CLI_VERSION (e.g. the tag
// in the release workflow) wins over package.json.
const pkg = JSON.parse(readFileSync('package.json', 'utf-8')) as { version: string };
const version = process.env.POLYLANE_CLI_VERSION ?? pkg.version;
// Step 3: bundle with esbuild
mkdirSync('dist', { recursive: true });
const outfile = join('dist', 'polylane.mjs');
const define: Record<string, string> = {
'process.env.POLYLANE_CLI_VERSION': JSON.stringify(version),
};
// POLYLANE_ONBOARDING_RUN is a per-install runtime value (the website installer
// sets it, or ~/.polylane/onboarding-run holds it) resolved fresh on every
// invocation — it must NEVER be baked. esbuild `define` freezes a matching key
// regardless of dotted or bracket access, so a build machine that happened to
// have it set (e.g. .env.local) would otherwise stamp one run id into the
// bundle for every user. Exclude it from the sweep so no define ever matches.
// POLYLANE_TELEMETRY_NOTICE_ACK is likewise a per-run runtime value (the
// installer sets it after printing the telemetry disclosure itself).
const DEFINE_EXCLUDE = new Set(['POLYLANE_ONBOARDING_RUN', 'POLYLANE_TELEMETRY_NOTICE_ACK']);
// Bake every other POLYLANE_* env var visible at build time into the bundle, so
// the produced binary works without needing those vars set at runtime.
// - Locally: comes from .env.local (gitignored — your dev domain / dev OAuth)
// - In CI release: comes from GitHub repo secrets exposed in the workflow
// - Clean checkout with no env: bundle uses the prod fallbacks in source
const baked: string[] = [];
for (const [k, v] of Object.entries(process.env)) {
if (!k.startsWith('POLYLANE_') || v === undefined) continue;
if (DEFINE_EXCLUDE.has(k)) continue;
define[`process.env.${k}`] = JSON.stringify(v);
baked.push(k);
}
const result = await build({
entryPoints: ['src/main.ts'],
bundle: true,
// jsonc-parser's default UMD entry passes `require` into its factory,
// which esbuild can't follow; its ESM build bundles cleanly.
alias: { 'jsonc-parser': 'jsonc-parser/lib/esm/main.js' },
platform: 'node',
target: 'node18',
format: 'esm',
outfile,
minify: true,
sourcemap: false,
banner: {
js: `#!/usr/bin/env node
import { createRequire as __polylaneCreateRequire } from 'node:module';
const require = __polylaneCreateRequire(import.meta.url);`,
},
define,
logLevel: 'error',
});
if (result.errors.length > 0) {
for (const err of result.errors) {
process.stderr.write(`[build] error: ${err.text}\n`);
}
process.exit(1);
}
chmodSync(outfile, 0o755);
const size = statSync(outfile).size;
const tag = baked.length > 0 ? ` (baked: ${baked.join(', ')})` : '';
process.stderr.write(`[build] wrote ${outfile} (${(size / 1024).toFixed(1)} KB)${tag}\n`);
}
main().catch((err: Error) => {
process.stderr.write(`[build] error: ${err.message}\n`);
process.exit(1);
});