Skip to content

Commit 0b9c30d

Browse files
committed
chore: bump version
1 parent 55a48eb commit 0b9c30d

File tree

7 files changed

+197
-75
lines changed

7 files changed

+197
-75
lines changed

.changeset/youhua-postinstall.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@weapp-tailwindcss/merge": patch
3+
---
4+
5+
- 调整 postinstall 引导脚本,优先加载 ESM 版本并补充回退与错误处理逻辑。

packages/merge/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"release": "pnpm publish",
6161
"lint": "eslint .",
6262
"lint:fix": "eslint . --fix",
63-
"postinstall": "node scripts/postinstall.cjs"
63+
"postinstall": "node scripts/postinstall.mjs"
6464
},
6565
"publishConfig": {
6666
"exports": {

packages/merge/scripts/postinstall.cjs

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { existsSync as defaultExistsSync } from 'node:fs'
2+
import { createRequire } from 'node:module'
3+
import path from 'node:path'
4+
import process from 'node:process'
5+
import { fileURLToPath, pathToFileURL } from 'node:url'
6+
7+
const requireFn = createRequire(import.meta.url)
8+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
9+
10+
/**
11+
* @param {object} [options]
12+
* @param {(path: string) => boolean} [options.existsSync]
13+
* @param {(path: string) => Promise<unknown>} [options.loadEsm]
14+
* @param {(path: string) => unknown | Promise<unknown>} [options.loadCjs]
15+
* @param {{ log: typeof console.log, error: typeof console.error }} [options.logger]
16+
*/
17+
export async function run(options = {}) {
18+
const {
19+
existsSync = defaultExistsSync,
20+
loadEsm = async filePath => import(pathToFileURL(filePath).href),
21+
loadCjs = filePath => requireFn(filePath),
22+
logger = console,
23+
} = options
24+
25+
const esmPath = path.resolve(__dirname, '../dist/postinstall.js')
26+
const cjsPath = path.resolve(__dirname, '../dist/postinstall.cjs')
27+
28+
const hasEsm = existsSync(esmPath)
29+
const hasCjs = existsSync(cjsPath)
30+
31+
const loadErrors = []
32+
33+
if (hasEsm) {
34+
try {
35+
await loadEsm(esmPath)
36+
return
37+
}
38+
catch (error) {
39+
loadErrors.push(error)
40+
}
41+
}
42+
43+
if (hasCjs) {
44+
try {
45+
await loadCjs(cjsPath)
46+
return
47+
}
48+
catch (error) {
49+
loadErrors.push(error)
50+
}
51+
}
52+
53+
if (!hasEsm && !hasCjs) {
54+
logger.log('postinstall bundle not found')
55+
return
56+
}
57+
58+
logger.error('Failed to load postinstall bundle.')
59+
for (const error of loadErrors) {
60+
logger.error(error)
61+
}
62+
process.exitCode = process.exitCode ?? 1
63+
}
64+
65+
const entryUrl = (() => {
66+
const candidate = process.argv[1]
67+
if (!candidate) {
68+
return undefined
69+
}
70+
try {
71+
return pathToFileURL(candidate).href
72+
}
73+
catch {
74+
return undefined
75+
}
76+
})()
77+
78+
if (entryUrl === import.meta.url) {
79+
run().catch((error) => {
80+
console.error('Failed to execute postinstall entry.', error)
81+
process.exitCode = process.exitCode ?? 1
82+
})
83+
}

packages/merge/src/postinstall.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,19 @@ function ensureVariant(distDir: string, variant: RuntimeVariant): {
210210
}
211211

212212
function main() {
213-
const distDir = fileURLToPath(new URL('../dist/', import.meta.url))
213+
const resolveDistDir = (): string => {
214+
// When executed via the CJS bundle (loaded through the bootstrap script), __dirname is available
215+
if (typeof __dirname === 'string') {
216+
return __dirname
217+
}
218+
219+
// Fallback for the ESM bundle evaluated directly
220+
// eslint-disable-next-line no-new-func
221+
const getImportMetaUrl = new Function('return import.meta.url') as () => string
222+
return fileURLToPath(new URL('./', getImportMetaUrl()))
223+
}
224+
225+
const distDir = resolveDistDir()
214226

215227
if (!fs.existsSync(distDir)) {
216228
warn('dist directory not found. Skipping runtime switch.')
Lines changed: 93 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,104 @@
1-
import fs from 'node:fs'
2-
import { createRequire } from 'node:module'
31
import path from 'node:path'
4-
import { fileURLToPath } from 'node:url'
5-
import vm from 'node:vm'
6-
import { describe, expect, it, vi } from 'vitest'
2+
import { fileURLToPath, pathToFileURL } from 'node:url'
3+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
74

8-
const requireFn = createRequire(import.meta.url)
95
const testDir = path.dirname(fileURLToPath(import.meta.url))
10-
const scriptPath = path.resolve(testDir, '../scripts/postinstall.cjs')
11-
const builtScriptPath = path.resolve(testDir, '../dist/postinstall.cjs')
12-
const scriptSource = fs.readFileSync(scriptPath, 'utf8')
13-
14-
function executeLegacyPostinstall(hasBuiltScript: boolean) {
15-
const existsSync = vi.fn(() => hasBuiltScript)
16-
let distModuleLoads = 0
17-
const consoleLog = vi.fn()
18-
19-
const contextRequire = (specifier: string) => {
20-
if (specifier === 'node:fs') {
21-
return {
22-
existsSync,
23-
}
24-
}
25-
if (specifier === 'node:path') {
26-
return requireFn('node:path')
27-
}
28-
if (specifier === builtScriptPath) {
29-
distModuleLoads += 1
30-
return {}
31-
}
32-
throw new Error(`Unexpected require: ${specifier}`)
33-
}
34-
35-
const context = {
36-
require: contextRequire,
37-
module: { exports: {} },
38-
exports: {},
39-
__dirname: path.dirname(scriptPath),
40-
console: { log: consoleLog },
41-
}
42-
43-
vm.runInNewContext(scriptSource, context, { filename: scriptPath })
44-
45-
return {
46-
existsSync,
47-
consoleLog,
48-
distModuleLoads,
49-
}
6+
const scriptPath = path.resolve(testDir, '../scripts/postinstall.mjs')
7+
const scriptUrl = pathToFileURL(scriptPath).href
8+
const esmBundlePath = path.resolve(testDir, '../dist/postinstall.js')
9+
const cjsBundlePath = path.resolve(testDir, '../dist/postinstall.cjs')
10+
11+
interface Logger {
12+
log: (...args: unknown[]) => void
13+
error: (...args: unknown[]) => void
14+
}
15+
16+
interface RunOptions {
17+
existsSync?: (file: string) => boolean
18+
loadEsm?: (file: string) => Promise<unknown>
19+
loadCjs?: (file: string) => unknown | Promise<unknown>
20+
logger?: Logger
21+
}
22+
23+
const originalExitCode = process.exitCode
24+
25+
async function runWithOptions(options?: RunOptions) {
26+
const { run } = await import(scriptUrl) as { run: (options?: RunOptions) => Promise<void> }
27+
await run(options)
5028
}
5129

52-
describe('legacy postinstall entry', () => {
53-
it('skips when built postinstall script is missing', () => {
54-
const result = executeLegacyPostinstall(false)
30+
beforeEach(() => {
31+
process.exitCode = undefined
32+
})
33+
34+
afterEach(() => {
35+
vi.restoreAllMocks()
36+
process.exitCode = originalExitCode
37+
})
38+
39+
describe('postinstall bootstrap script', () => {
40+
it('prefers the ESM bundle when available', async () => {
41+
const existsSync = vi.fn((file: string) => file === esmBundlePath)
42+
const loadEsm = vi.fn(async () => {})
43+
const loadCjs = vi.fn()
44+
const logger = { log: vi.fn(), error: vi.fn() }
5545

56-
expect(result.existsSync).toHaveBeenCalledWith(builtScriptPath)
57-
expect(result.consoleLog).toHaveBeenCalledWith('postinstall.cjs not found')
58-
expect(result.distModuleLoads).toBe(0)
46+
await runWithOptions({ existsSync, loadEsm, loadCjs, logger })
47+
48+
expect(loadEsm).toHaveBeenCalledWith(esmBundlePath)
49+
expect(loadCjs).not.toHaveBeenCalled()
50+
expect(logger.log).not.toHaveBeenCalled()
51+
expect(logger.error).not.toHaveBeenCalled()
52+
})
53+
54+
it('falls back to the CJS bundle when ESM is unavailable', async () => {
55+
const existsSync = vi.fn((file: string) => file === cjsBundlePath)
56+
const loadEsm = vi.fn()
57+
const loadCjs = vi.fn(async () => {})
58+
const logger = { log: vi.fn(), error: vi.fn() }
59+
60+
await runWithOptions({ existsSync, loadEsm, loadCjs, logger })
61+
62+
expect(loadEsm).not.toHaveBeenCalled()
63+
expect(loadCjs).toHaveBeenCalledWith(cjsBundlePath)
64+
expect(logger.log).not.toHaveBeenCalled()
65+
expect(logger.error).not.toHaveBeenCalled()
5966
})
6067

61-
it('loads built postinstall script when present', () => {
62-
const result = executeLegacyPostinstall(true)
68+
it('logs when no bundle is present', async () => {
69+
const existsSync = vi.fn(() => false)
70+
const loadEsm = vi.fn()
71+
const loadCjs = vi.fn()
72+
const logger = { log: vi.fn(), error: vi.fn() }
73+
74+
await runWithOptions({ existsSync, loadEsm, loadCjs, logger })
75+
76+
expect(loadEsm).not.toHaveBeenCalled()
77+
expect(loadCjs).not.toHaveBeenCalled()
78+
expect(logger.log).toHaveBeenCalledWith('postinstall bundle not found')
79+
expect(logger.error).not.toHaveBeenCalled()
80+
})
81+
82+
it('reports errors when both bundle loads fail', async () => {
83+
const existsSync = vi.fn((file: string) => file === esmBundlePath || file === cjsBundlePath)
84+
const esmError = new Error('esm failed')
85+
const cjsError = new Error('cjs failed')
86+
const loadEsm = vi.fn(async () => {
87+
throw esmError
88+
})
89+
const loadCjs = vi.fn(async () => {
90+
throw cjsError
91+
})
92+
const logger = { log: vi.fn(), error: vi.fn() }
93+
94+
await runWithOptions({ existsSync, loadEsm, loadCjs, logger })
6395

64-
expect(result.existsSync).toHaveBeenCalledWith(builtScriptPath)
65-
expect(result.consoleLog).not.toHaveBeenCalled()
66-
expect(result.distModuleLoads).toBe(1)
96+
expect(loadEsm).toHaveBeenCalledWith(esmBundlePath)
97+
expect(loadCjs).toHaveBeenCalledWith(cjsBundlePath)
98+
expect(logger.error).toHaveBeenCalledWith('Failed to load postinstall bundle.')
99+
expect(logger.error).toHaveBeenCalledWith(esmError)
100+
expect(logger.error).toHaveBeenCalledWith(cjsError)
101+
expect(process.exitCode).toBe(1)
102+
expect(logger.log).not.toHaveBeenCalled()
67103
})
68104
})

scripts/push-templates.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ async function syncTemplate(url: string): Promise<void> {
5959

6060
const branch = await getCurrentBranch(repoDir)
6161
await execa('git', ['reset', '--hard', `origin/${branch}`], { cwd: repoDir, stdio: 'inherit' })
62-
await execa('git', ['clean', '-fdx'], { cwd: repoDir, stdio: 'inherit' })
62+
// 保留被 .gitignore 忽略的缓存目录,避免每次清理 node_modules/dist 时的额外开销
63+
await execa('git', ['clean', '-fd'], { cwd: repoDir, stdio: 'inherit' })
6364

6465
console.log(`同步 ${localDir} -> ${repoDir}`)
6566
await execa(

0 commit comments

Comments
 (0)