Skip to content

Commit 5dc33ad

Browse files
committed
build(rolldown): migrate esbuild → rolldown + adopt INLINED_ define convention
Replace the esbuild bundle invocation with a rolldown config (rolldown.config.mts): single entry src/extension.ts → out/main.js, CJS for the extension host, vscode + tree-sitter-java externalized, and the esbuild --loader equivalents mapped via moduleTypes (.wasm→binary, .py→text, .go→asset). --minify stays gated behind MINIFY for prepublish. Adopt the fleet-canonical INLINED_ compile-time define convention (see socket-cli): the package.json version inlines via process.env['INLINED_EXTENSION_VERSION'], applied by the cascaded defineGuarded plugin. Source uses quoted bracket access (TS4111 forbids dot access on process.env's index signature); the plugin normalizes dot and quoted-bracket member access to one dotted define key. Drop the obsolete EXTENSION_VERSION ambient global; rename src/esbuild.d.ts → src/assets.d.ts. Add a regression test for defineGuarded covering dot/single/double/TS/TSX rewrites plus assign-target and dynamic-access guards. Replace scripts/validate-esbuild-minify.mts with validate-rolldown-minify.mts: assert the default (MINIFY-unset) build emits unminified output, while allowing the publish-only MINIFY=1 path. Stop the bleeding from the lib-6 export-map split: fix stale @socketsecurity/lib/logger imports → /logger/default (lib-stable form, matching the wheelhouse template) in scripts/test.mts, scripts/lint.mts, .claude/hooks/setup-security-tools/update.mts, and @socketsecurity/lib/logger → /logger/default in src/data/go/wasm-executor.ts; /fs → /fs/safe in two src files. Wheelhouse template/manifest reconciliation (validator rename + fleet rule) follows in a separate wheelhouse push. Assisted-by: Claude Code:opus-4-7
1 parent 4b3a3fc commit 5dc33ad

16 files changed

Lines changed: 706 additions & 476 deletions

File tree

.claude/hooks/setup-security-tools/update.mts

Lines changed: 81 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import path from 'node:path'
1818
import { fileURLToPath } from 'node:url'
1919

2020
import { httpDownload, httpRequest } from '@socketsecurity/lib/http-request'
21-
import { getDefaultLogger } from '@socketsecurity/lib/logger'
21+
import { getDefaultLogger } from '@socketsecurity/lib-stable/logger/default'
2222
import { spawn } from '@socketsecurity/lib/spawn'
2323

2424
const logger = getDefaultLogger()
@@ -105,9 +105,7 @@ async function ghApiLatestRelease(repo: string): Promise<GhRelease> {
105105
{ stdio: 'pipe' },
106106
)
107107
const stdout =
108-
typeof result.stdout === 'string'
109-
? result.stdout
110-
: result.stdout.toString()
108+
typeof result.stdout === 'string' ? result.stdout : result.stdout.toString()
111109
return JSON.parse(stdout) as GhRelease
112110
}
113111

@@ -142,7 +140,11 @@ function readConfig(): Config {
142140
}
143141

144142
async function writeConfig(config: Config): Promise<void> {
145-
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, undefined, 2) + '\n', 'utf8')
143+
await fs.writeFile(
144+
CONFIG_FILE,
145+
JSON.stringify(config, undefined, 2) + '\n',
146+
'utf8',
147+
)
146148
}
147149

148150
// ── Checksum computation ──
@@ -153,7 +155,10 @@ async function computeSha256(filePath: string): Promise<string> {
153155
}
154156

155157
async function downloadAndHash(url: string): Promise<string> {
156-
const tmpFile = path.join(tmpdir(), `security-tools-update-${Date.now()}-${Math.random().toString(36).slice(2)}`)
158+
const tmpFile = path.join(
159+
tmpdir(),
160+
`security-tools-update-${Date.now()}-${Math.random().toString(36).slice(2)}`,
161+
)
157162
try {
158163
await httpDownload(url, tmpFile, { retries: 2 })
159164
return await computeSha256(tmpFile)
@@ -180,7 +185,8 @@ async function updateZizmor(config: Config): Promise<UpdateResult> {
180185
return { tool, skipped: true, updated: false, reason: 'not in config' }
181186
}
182187

183-
const repo = toolConfig.repository?.replace(/^[^:]+:/, '') ?? 'zizmorcore/zizmor'
188+
const repo =
189+
toolConfig.repository?.replace(/^[^:]+:/, '') ?? 'zizmorcore/zizmor'
184190

185191
let release: GhRelease
186192
try {
@@ -204,7 +210,8 @@ async function updateZizmor(config: Config): Promise<UpdateResult> {
204210
// Respect the soak window for third-party tools.
205211
if (!isOlderThanSoakWindow(release.published_at)) {
206212
const ageDays = (
207-
(Date.now() - new Date(release.published_at).getTime()) / 86_400_000
213+
(Date.now() - new Date(release.published_at).getTime()) /
214+
86_400_000
208215
).toFixed(1)
209216
const soakMinutes = SOAK_WINDOW_MS / MS_PER_MINUTE
210217
const soakLabel = formatSoakWindow(soakMinutes)
@@ -243,7 +250,9 @@ async function updateZizmor(config: Config): Promise<UpdateResult> {
243250

244251
// Compute checksums for each asset in the config.
245252
const currentChecksums = toolConfig.checksums ?? {}
246-
const newChecksums: Record<string, string> = { __proto__: null } as unknown as Record<string, string>
253+
const newChecksums: Record<string, string> = {
254+
__proto__: null,
255+
} as unknown as Record<string, string>
247256
let allFound = true
248257

249258
for (const assetName of Object.keys(currentChecksums)) {
@@ -279,23 +288,35 @@ async function updateZizmor(config: Config): Promise<UpdateResult> {
279288
newChecksums[assetName] = newHash
280289
const oldHash = currentChecksums[assetName]
281290
if (oldHash && oldHash !== newHash) {
282-
logger.log(` ${assetName}: ${oldHash.slice(0, 12)}... -> ${newHash.slice(0, 12)}...`)
291+
logger.log(
292+
` ${assetName}: ${oldHash.slice(0, 12)}... -> ${newHash.slice(0, 12)}...`,
293+
)
283294
} else if (oldHash === newHash) {
284295
logger.log(` ${assetName}: unchanged`)
285296
}
286297
}
287298

288299
if (!allFound) {
289300
logger.warn('Some assets could not be verified. Skipping version bump.')
290-
return { tool, skipped: true, updated: false, reason: 'incomplete asset checksums' }
301+
return {
302+
tool,
303+
skipped: true,
304+
updated: false,
305+
reason: 'incomplete asset checksums',
306+
}
291307
}
292308

293309
// Update config.
294310
toolConfig.version = latestVersion
295311
toolConfig.checksums = newChecksums
296312
logger.log(`Updated zizmor: ${currentVersion} -> ${latestVersion}`)
297313

298-
return { tool, skipped: false, updated: true, reason: `${currentVersion} -> ${latestVersion}` }
314+
return {
315+
tool,
316+
skipped: false,
317+
updated: true,
318+
reason: `${currentVersion} -> ${latestVersion}`,
319+
}
299320
}
300321

301322
// ── SFW update ──
@@ -306,12 +327,22 @@ async function updateSfwTool(
306327
): Promise<UpdateResult> {
307328
const toolConfig = config.tools[toolName]
308329
if (!toolConfig) {
309-
return { tool: toolName, skipped: true, updated: false, reason: 'not in config' }
330+
return {
331+
tool: toolName,
332+
skipped: true,
333+
updated: false,
334+
reason: 'not in config',
335+
}
310336
}
311337

312338
const repo = toolConfig.repository?.replace(/^[^:]+:/, '')
313339
if (!repo) {
314-
return { tool: toolName, skipped: true, updated: false, reason: 'no repository' }
340+
return {
341+
tool: toolName,
342+
skipped: true,
343+
updated: false,
344+
reason: 'no repository',
345+
}
315346
}
316347

317348
let release: GhRelease
@@ -320,15 +351,24 @@ async function updateSfwTool(
320351
} catch (e) {
321352
const msg = e instanceof Error ? e.message : String(e)
322353
logger.warn(`Failed to fetch ${toolName} releases: ${msg}`)
323-
return { tool: toolName, skipped: true, updated: false, reason: `API error: ${msg}` }
354+
return {
355+
tool: toolName,
356+
skipped: true,
357+
updated: false,
358+
reason: `API error: ${msg}`,
359+
}
324360
}
325361

326-
logger.log(` ${toolName}: latest ${release.tag_name} (published ${release.published_at.slice(0, 10)})`)
362+
logger.log(
363+
` ${toolName}: latest ${release.tag_name} (published ${release.published_at.slice(0, 10)})`,
364+
)
327365

328366
const currentChecksums = toolConfig.checksums ?? {}
329367
const platforms = toolConfig.platforms ?? {}
330368
const prefix = toolName === 'sfw-enterprise' ? 'sfw' : 'sfw-free'
331-
const newChecksums: Record<string, string> = { __proto__: null } as unknown as Record<string, string>
369+
const newChecksums: Record<string, string> = {
370+
__proto__: null,
371+
} as unknown as Record<string, string>
332372
let changed = false
333373
let allFound = true
334374

@@ -344,7 +384,9 @@ async function updateSfwTool(
344384
const hash = await downloadAndHash(url)
345385
newChecksums[sfwPlatform] = hash
346386
if (currentChecksums[sfwPlatform] !== hash) {
347-
logger.log(` ${sfwPlatform}: ${(currentChecksums[sfwPlatform] ?? '').slice(0, 12)}... -> ${hash.slice(0, 12)}...`)
387+
logger.log(
388+
` ${sfwPlatform}: ${(currentChecksums[sfwPlatform] ?? '').slice(0, 12)}... -> ${hash.slice(0, 12)}...`,
389+
)
348390
changed = true
349391
}
350392
} catch (e) {
@@ -355,17 +397,34 @@ async function updateSfwTool(
355397
}
356398

357399
if (!allFound) {
358-
logger.warn(` Some ${toolName} assets could not be downloaded. Skipping update.`)
359-
return { tool: toolName, skipped: true, updated: false, reason: 'incomplete downloads' }
400+
logger.warn(
401+
` Some ${toolName} assets could not be downloaded. Skipping update.`,
402+
)
403+
return {
404+
tool: toolName,
405+
skipped: true,
406+
updated: false,
407+
reason: 'incomplete downloads',
408+
}
360409
}
361410

362411
if (changed) {
363412
toolConfig.version = release.tag_name
364413
toolConfig.checksums = newChecksums
365-
return { tool: toolName, skipped: false, updated: true, reason: 'checksums updated' }
414+
return {
415+
tool: toolName,
416+
skipped: false,
417+
updated: true,
418+
reason: 'checksums updated',
419+
}
366420
}
367421

368-
return { tool: toolName, skipped: false, updated: false, reason: 'already current' }
422+
return {
423+
tool: toolName,
424+
skipped: false,
425+
updated: false,
426+
reason: 'already current',
427+
}
369428
}
370429

371430
async function updateSfw(config: Config): Promise<UpdateResult[]> {

.config/rolldown/define-guarded.mts

Lines changed: 96 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)