@jk2908/cxx 0.3.3 → 0.3.5
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/README.md +1 -4
- package/dist/build.d.ts +10 -4
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +157 -81
- package/dist/build.js.map +6 -5
- package/dist/index.js +1 -4
- package/dist/index.js.map +2 -2
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/next/cxx-loader.cjs +50 -152
- package/dist/next/cxx-loader.cjs.map +8 -8
- package/dist/next/index.d.ts +5 -17
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +160 -178
- package/dist/next/index.js.map +7 -6
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +0 -16
- package/dist/utils.d.ts.map +1 -1
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +193 -242
- package/dist/vite/index.js.map +7 -7
- package/package.json +1 -4
- package/src/build.ts +130 -40
- package/src/logger.ts +2 -7
- package/src/next/cxx-loader.js +1 -10
- package/src/next/index.ts +16 -150
- package/src/types.ts +0 -2
- package/src/utils.ts +0 -87
- package/src/vite/index.ts +49 -110
package/src/next/index.ts
CHANGED
|
@@ -1,154 +1,25 @@
|
|
|
1
|
-
import type { AsyncSubscription, Event } from '@parcel/watcher'
|
|
2
1
|
import type { NextConfig } from 'next'
|
|
3
2
|
|
|
4
|
-
import fs from 'node:fs/promises'
|
|
5
3
|
import path from 'node:path'
|
|
6
4
|
import { fileURLToPath } from 'node:url'
|
|
7
5
|
|
|
8
|
-
import type { Logger } from '../logger.js'
|
|
9
6
|
import type { PluginConfig } from '../types.js'
|
|
10
|
-
import { collect,
|
|
11
|
-
import {
|
|
7
|
+
import { collect, seedTypes, writeTypesForFile } from '../build.js'
|
|
8
|
+
import { Logger } from '../logger.js'
|
|
9
|
+
|
|
10
|
+
const typeLogger = new Logger('cxx')
|
|
12
11
|
|
|
13
12
|
const nextDir = path.dirname(fileURLToPath(import.meta.url))
|
|
14
13
|
const loader = path.join(nextDir, 'cxx-loader.cjs')
|
|
15
14
|
|
|
16
|
-
// keep the exact file inputs and their config so a single recursive watcher can filter events
|
|
17
|
-
const watchedFiles = new Map<string, { pluginConfig: PluginConfig; logger: Logger }>()
|
|
18
|
-
|
|
19
|
-
let subscription: AsyncSubscription | null = null
|
|
20
|
-
let subscriptionPromise: Promise<void> | null = null
|
|
21
|
-
let cleanupRegistered = false
|
|
22
|
-
let watcherLogger: Logger | null = null
|
|
23
|
-
|
|
24
|
-
// a single recursive watch avoids overlapping per-directory watchers; ignore the parts of the
|
|
25
|
-
// tree that never contain source we transform
|
|
26
|
-
const DEFAULT_IGNORE = [
|
|
27
|
-
'**/node_modules/**',
|
|
28
|
-
'**/.next/**',
|
|
29
|
-
`**/${GENERATED_DIR}/**`,
|
|
30
|
-
'**/.git/**',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
async function onEvent(event: Event['type'], filePath: string) {
|
|
34
|
-
const watched = watchedFiles.get(filePath)
|
|
35
|
-
if (!watched) return
|
|
36
|
-
|
|
37
|
-
const { pluginConfig, logger } = watched
|
|
38
|
-
|
|
39
|
-
if (event === 'delete') {
|
|
40
|
-
await writeTypesForFile(filePath, new Map())
|
|
41
|
-
logger.info(`updated types from ${filePath}`)
|
|
42
|
-
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let source: string
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
source = await fs.readFile(filePath, 'utf-8')
|
|
50
|
-
} catch (err) {
|
|
51
|
-
if (!isENOENT(err)) throw err
|
|
52
|
-
|
|
53
|
-
await writeTypesForFile(filePath, new Map())
|
|
54
|
-
logger.info(`updated types from ${filePath}`)
|
|
55
|
-
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const tags = source.includes('cxx')
|
|
60
|
-
? collect(source, filePath, pluginConfig).tags
|
|
61
|
-
: new Map()
|
|
62
|
-
|
|
63
|
-
await writeTypesForFile(filePath, tags)
|
|
64
|
-
logger.info(`updated types from ${filePath}`)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Start the watcher lazily, on the first file we actually process, so merely importing this module
|
|
69
|
-
* has no side effects.
|
|
70
|
-
*/
|
|
71
|
-
function ensureWatcher(pluginConfig: PluginConfig, logger: Logger) {
|
|
72
|
-
watcherLogger = logger
|
|
73
|
-
|
|
74
|
-
if (subscriptionPromise) return
|
|
75
|
-
|
|
76
|
-
const root = pluginConfig.watch?.root ?? process.cwd()
|
|
77
|
-
const ignore = [...DEFAULT_IGNORE, ...(pluginConfig.watch?.ignore ?? [])]
|
|
78
|
-
|
|
79
|
-
subscriptionPromise = (async () => {
|
|
80
|
-
// lazily imported so the native module is only loaded when watching is needed
|
|
81
|
-
const { subscribe } = await import('@parcel/watcher')
|
|
82
|
-
|
|
83
|
-
subscription = await subscribe(
|
|
84
|
-
root,
|
|
85
|
-
(watchErr, events) => {
|
|
86
|
-
if (watchErr) {
|
|
87
|
-
watcherLogger?.error(`failed to watch ${root}`, watchErr)
|
|
88
|
-
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
for (const event of events) {
|
|
93
|
-
const filePath = path.resolve(event.path)
|
|
94
|
-
if (!watchedFiles.has(filePath)) continue
|
|
95
|
-
|
|
96
|
-
void onEvent(event.type, filePath).catch(err => {
|
|
97
|
-
watcherLogger?.error(`failed to update types from ${filePath}`, err)
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
{ ignore },
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
registerCleanup()
|
|
105
|
-
})().catch(err => {
|
|
106
|
-
watcherLogger?.error('failed to start cxx watcher', err)
|
|
107
|
-
subscriptionPromise = null
|
|
108
|
-
})
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Close all active Parcel subscriptions.
|
|
113
|
-
*/
|
|
114
|
-
async function cleanup() {
|
|
115
|
-
const active = subscription
|
|
116
|
-
|
|
117
|
-
subscription = null
|
|
118
|
-
subscriptionPromise = null
|
|
119
|
-
watchedFiles.clear()
|
|
120
|
-
|
|
121
|
-
if (active) await active.unsubscribe()
|
|
122
|
-
}
|
|
123
|
-
|
|
124
15
|
/**
|
|
125
|
-
*
|
|
126
|
-
|
|
127
|
-
async function shutdown(signal: NodeJS.Signals) {
|
|
128
|
-
try {
|
|
129
|
-
await cleanup()
|
|
130
|
-
} finally {
|
|
131
|
-
// our `once` handlers have already been removed, so re-raising lets Node terminate as usual
|
|
132
|
-
process.kill(process.pid, signal)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function registerCleanup() {
|
|
137
|
-
if (cleanupRegistered) return
|
|
138
|
-
|
|
139
|
-
cleanupRegistered = true
|
|
140
|
-
process.once('SIGINT', () => void shutdown('SIGINT'))
|
|
141
|
-
process.once('SIGTERM', () => void shutdown('SIGTERM'))
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Transform one module and, in development, register it with the shared watcher state.
|
|
16
|
+
* Transform one module and persist its tag types. Deleted files are pruned from the types on the
|
|
17
|
+
* next rebuild, since `readPartials` drops any partial whose source is gone.
|
|
146
18
|
*/
|
|
147
19
|
export function processFile(
|
|
148
20
|
source: string,
|
|
149
21
|
filePath: string,
|
|
150
22
|
pluginConfig: PluginConfig,
|
|
151
|
-
logger: Logger,
|
|
152
23
|
) {
|
|
153
24
|
const resolvedFilePath = path.resolve(filePath)
|
|
154
25
|
|
|
@@ -157,15 +28,6 @@ export function processFile(
|
|
|
157
28
|
return { template: source, tags: new Map(), map: null }
|
|
158
29
|
}
|
|
159
30
|
|
|
160
|
-
// surface a duplicate-tag error from a previous background rebuild
|
|
161
|
-
const priorError = takeRebuildError()
|
|
162
|
-
if (priorError) throw priorError
|
|
163
|
-
|
|
164
|
-
if (process.env['NODE_ENV'] !== 'production') {
|
|
165
|
-
watchedFiles.set(resolvedFilePath, { pluginConfig, logger })
|
|
166
|
-
ensureWatcher(pluginConfig, logger)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
31
|
const result = collect(source, resolvedFilePath, pluginConfig)
|
|
170
32
|
|
|
171
33
|
void writeTypesForFile(resolvedFilePath, result.tags)
|
|
@@ -176,16 +38,20 @@ export function processFile(
|
|
|
176
38
|
const TURBOPACK_GLOB = '*.{tsx,jsx,ts,js}'
|
|
177
39
|
|
|
178
40
|
export function withCxx(nextConfig: NextConfig = {}, pluginConfig: PluginConfig = {}) {
|
|
179
|
-
|
|
180
|
-
|
|
41
|
+
// Seed on dev startup only, so a fresh checkout has types before any file is compiled. A
|
|
42
|
+
// production build is covered by the loader, and `next start` must not write at runtime.
|
|
43
|
+
if (process.env['NODE_ENV'] !== 'production') {
|
|
44
|
+
const seedRoot = pluginConfig.watch?.root ?? process.cwd()
|
|
45
|
+
|
|
46
|
+
void seedTypes(seedRoot, pluginConfig).catch(err =>
|
|
47
|
+
typeLogger.error('failed to seed cxx types', err),
|
|
48
|
+
)
|
|
49
|
+
}
|
|
181
50
|
|
|
182
51
|
const loaderItem = {
|
|
183
52
|
loader,
|
|
184
53
|
options: {
|
|
185
|
-
pluginConfig
|
|
186
|
-
...pluginConfig,
|
|
187
|
-
watch: { ...pluginConfig.watch, root: watchRoot },
|
|
188
|
-
},
|
|
54
|
+
pluginConfig,
|
|
189
55
|
},
|
|
190
56
|
}
|
|
191
57
|
|
package/src/types.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -8,90 +8,3 @@ export function pascalise(str: string) {
|
|
|
8
8
|
.map(capitalise)
|
|
9
9
|
.join('')
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
export type Batcher<K, V> = {
|
|
13
|
-
/**
|
|
14
|
-
* Queue a value for a key. Queueing the same key again replaces the previous value.
|
|
15
|
-
*/
|
|
16
|
-
add: (key: K, value: V) => void
|
|
17
|
-
/**
|
|
18
|
-
* Run any waiting work now and resolve once it has finished.
|
|
19
|
-
*/
|
|
20
|
-
flush: () => Promise<void>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Group bursts of work and run them together. Every key queued within `wait` is
|
|
25
|
-
* included once, and a key queued while a batch is running is handled in the next
|
|
26
|
-
* batch instead of replacing the one in progress.
|
|
27
|
-
*/
|
|
28
|
-
export function createBatcher<K, V>(
|
|
29
|
-
wait: number,
|
|
30
|
-
flush: (batch: Map<K, V>) => void | Promise<void>,
|
|
31
|
-
): Batcher<K, V> {
|
|
32
|
-
// work waiting to run, keyed so each key is only queued once
|
|
33
|
-
const pending = new Map<K, V>()
|
|
34
|
-
// waits for a burst of changes to settle before running
|
|
35
|
-
let timer: ReturnType<typeof setTimeout> | null = null
|
|
36
|
-
// the run in progress, so `flush` can wait for it and we never start a second
|
|
37
|
-
let current: Promise<void> | null = null
|
|
38
|
-
|
|
39
|
-
function drain() {
|
|
40
|
-
// a run is already going, so let it pick up the new work
|
|
41
|
-
if (current) return current
|
|
42
|
-
|
|
43
|
-
const run = (async () => {
|
|
44
|
-
// keep looping while there is work, including work added during a flush
|
|
45
|
-
while (pending.size > 0) {
|
|
46
|
-
// snapshot the queued work
|
|
47
|
-
const batch = new Map(pending)
|
|
48
|
-
// empty the queue right away, so anything added during flush waits for the next loop
|
|
49
|
-
pending.clear()
|
|
50
|
-
|
|
51
|
-
await flush(batch)
|
|
52
|
-
}
|
|
53
|
-
})()
|
|
54
|
-
|
|
55
|
-
current = run
|
|
56
|
-
run.then(
|
|
57
|
-
() => {
|
|
58
|
-
if (current === run) current = null
|
|
59
|
-
},
|
|
60
|
-
() => {
|
|
61
|
-
if (current === run) current = null
|
|
62
|
-
},
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
return run
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function schedule() {
|
|
69
|
-
// cancel the previous wait, so the timer restarts from now
|
|
70
|
-
if (timer) clearTimeout(timer)
|
|
71
|
-
|
|
72
|
-
// run once the calls stop coming for `wait` ms
|
|
73
|
-
timer = setTimeout(() => {
|
|
74
|
-
// the timer has fired, so drop the stale handle
|
|
75
|
-
timer = null
|
|
76
|
-
// the flush callback handles its own errors, so just start the run
|
|
77
|
-
void drain().catch(() => {})
|
|
78
|
-
}, wait)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
add(key, value) {
|
|
83
|
-
// the newest value for this key wins
|
|
84
|
-
pending.set(key, value)
|
|
85
|
-
schedule()
|
|
86
|
-
},
|
|
87
|
-
flush() {
|
|
88
|
-
// run now instead of waiting out the timer
|
|
89
|
-
if (timer) {
|
|
90
|
-
clearTimeout(timer)
|
|
91
|
-
timer = null
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return drain()
|
|
95
|
-
},
|
|
96
|
-
}
|
|
97
|
-
}
|
package/src/vite/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { realpathSync } from 'node:fs'
|
|
2
|
-
import fs from 'node:fs/promises'
|
|
3
2
|
import path from 'node:path'
|
|
4
3
|
|
|
5
4
|
import { type Plugin, type ResolvedConfig, type ViteDevServer } from 'vite'
|
|
@@ -8,15 +7,13 @@ import type { PluginConfig } from '../types.js'
|
|
|
8
7
|
import {
|
|
9
8
|
collect,
|
|
10
9
|
flushTypes,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
refreshFile,
|
|
11
|
+
seedTypes,
|
|
12
|
+
SOURCE_EXTENSIONS,
|
|
13
13
|
writeTypesForFile,
|
|
14
14
|
} from '../build.js'
|
|
15
15
|
import { GENERATED_DIR } from '../config.js'
|
|
16
16
|
import { Logger } from '../logger.js'
|
|
17
|
-
import { createBatcher } from '../utils.js'
|
|
18
|
-
|
|
19
|
-
const ACCEPTED_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx'])
|
|
20
17
|
|
|
21
18
|
type WatchEvent = 'add' | 'change' | 'unlink'
|
|
22
19
|
|
|
@@ -24,48 +21,45 @@ function normaliseWatchPath(p: string) {
|
|
|
24
21
|
return p.replace(/\\/g, '/')
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
/** Tiny glob matcher for the ignore patterns we support (`**`, `*`, `?`). */
|
|
28
|
-
function globToRegExp(glob: string) {
|
|
29
|
-
const pattern = glob
|
|
30
|
-
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
31
|
-
.replace(/\*\*(\/|$)/g, '.*$1')
|
|
32
|
-
.replace(/\*/g, '[^/]*')
|
|
33
|
-
.replace(/\?/g, '[^/]')
|
|
34
|
-
|
|
35
|
-
return new RegExp(`^${pattern}$`)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
24
|
export default function cxx(pluginConfig: PluginConfig = {}) {
|
|
39
25
|
const logger = new Logger()
|
|
40
26
|
|
|
41
27
|
// resolved from Vite's root in `configResolved`, not from `process.cwd()`
|
|
42
28
|
let watchRoot = normaliseWatchPath(process.cwd())
|
|
43
|
-
|
|
29
|
+
let seeded = false
|
|
30
|
+
|
|
31
|
+
// realpath is synchronous, so cache it per directory to keep it off the transform hot path
|
|
32
|
+
const realpaths = new Map<string, string>()
|
|
44
33
|
|
|
45
34
|
function resolveWatchFile(filePath: string) {
|
|
46
35
|
const absolutePath = path.resolve(watchRoot, filePath)
|
|
47
36
|
const parentPath = path.dirname(absolutePath)
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
const resolvedParentPath = normaliseWatchPath(realpathSync.native(parentPath))
|
|
38
|
+
let resolvedParentPath = realpaths.get(parentPath)
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
40
|
+
if (resolvedParentPath === undefined) {
|
|
41
|
+
try {
|
|
42
|
+
resolvedParentPath = normaliseWatchPath(realpathSync.native(parentPath))
|
|
43
|
+
} catch {
|
|
44
|
+
resolvedParentPath = normaliseWatchPath(parentPath)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
realpaths.set(parentPath, resolvedParentPath)
|
|
57
48
|
}
|
|
49
|
+
|
|
50
|
+
return normaliseWatchPath(path.join(resolvedParentPath, path.basename(absolutePath)))
|
|
58
51
|
}
|
|
59
52
|
|
|
60
|
-
/**
|
|
61
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Returns the canonical, watchable path, or null when the file is irrelevant.
|
|
55
|
+
*/
|
|
56
|
+
function watchedFile(filePath: string) {
|
|
62
57
|
const resolvedPath = resolveWatchFile(filePath)
|
|
63
58
|
|
|
64
59
|
if (
|
|
65
60
|
resolvedPath.startsWith(`${watchRoot}/`) &&
|
|
66
61
|
!resolvedPath.includes(`/${GENERATED_DIR}/`) &&
|
|
67
|
-
|
|
68
|
-
!ignored.some(regexp => regexp.test(resolvedPath))
|
|
62
|
+
SOURCE_EXTENSIONS.has(path.extname(resolvedPath))
|
|
69
63
|
) {
|
|
70
64
|
return resolvedPath
|
|
71
65
|
}
|
|
@@ -73,76 +67,34 @@ export default function cxx(pluginConfig: PluginConfig = {}) {
|
|
|
73
67
|
return null
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
async function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
source = await fs.readFile(file, 'utf-8')
|
|
81
|
-
} catch (err) {
|
|
82
|
-
if (!isENOENT(err)) throw err
|
|
70
|
+
async function handleEvent(event: WatchEvent, file: string) {
|
|
71
|
+
if (event === 'unlink') {
|
|
83
72
|
await writeTypesForFile(file, new Map())
|
|
84
|
-
|
|
73
|
+
} else {
|
|
74
|
+
await refreshFile(file, pluginConfig)
|
|
85
75
|
}
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
? collect(source, file, pluginConfig).tags
|
|
89
|
-
: new Map()
|
|
90
|
-
await writeTypesForFile(file, tags)
|
|
77
|
+
logger.info(`updated types from ${file}`)
|
|
91
78
|
}
|
|
92
79
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
async function scan(dir: string) {
|
|
98
|
-
let entries
|
|
80
|
+
function onWatch(event: WatchEvent) {
|
|
81
|
+
return (p: string) => {
|
|
82
|
+
const file = watchedFile(p)
|
|
83
|
+
if (!file) return
|
|
99
84
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return
|
|
85
|
+
void handleEvent(event, file).catch(err => {
|
|
86
|
+
logger.error(`failed to update types from ${file}`, err)
|
|
87
|
+
})
|
|
104
88
|
}
|
|
89
|
+
}
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const full = path.join(dir, entry.name)
|
|
111
|
-
|
|
112
|
-
if (entry.isDirectory()) {
|
|
113
|
-
await scan(full)
|
|
114
|
-
return
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (!ACCEPTED_EXTENSIONS.has(path.extname(entry.name))) return
|
|
118
|
-
|
|
119
|
-
const resolved = resolveWatchFile(full)
|
|
120
|
-
if (ignored.some(regexp => regexp.test(resolved))) return
|
|
91
|
+
async function seed() {
|
|
92
|
+
if (seeded) return
|
|
93
|
+
seeded = true
|
|
121
94
|
|
|
122
|
-
|
|
123
|
-
}),
|
|
124
|
-
)
|
|
95
|
+
await seedTypes(watchRoot, pluginConfig)
|
|
125
96
|
}
|
|
126
97
|
|
|
127
|
-
// collect change events that arrive close together and handle each file once.
|
|
128
|
-
// The file path is the key, so changes to different files are all kept, and a
|
|
129
|
-
// change that arrives during a rebuild runs after that rebuild finishes.
|
|
130
|
-
const queue = createBatcher<string, WatchEvent>(75, async batch => {
|
|
131
|
-
for (const [file, event] of batch) {
|
|
132
|
-
try {
|
|
133
|
-
if (event === 'unlink') {
|
|
134
|
-
await writeTypesForFile(file, new Map())
|
|
135
|
-
} else {
|
|
136
|
-
await recordFile(file)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
logger.info(`updated types from ${file}`)
|
|
140
|
-
} catch (err) {
|
|
141
|
-
logger.error(`failed to update types from ${file}`, err)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
|
|
146
98
|
return {
|
|
147
99
|
name: 'cxx',
|
|
148
100
|
enforce: 'pre',
|
|
@@ -154,16 +106,20 @@ export default function cxx(pluginConfig: PluginConfig = {}) {
|
|
|
154
106
|
} catch {
|
|
155
107
|
watchRoot = normaliseWatchPath(root)
|
|
156
108
|
}
|
|
109
|
+
|
|
110
|
+
realpaths.clear()
|
|
111
|
+
},
|
|
112
|
+
async buildStart() {
|
|
113
|
+
await seed()
|
|
157
114
|
},
|
|
158
115
|
transform(code, id) {
|
|
159
116
|
if (id.startsWith('\0') || id.includes('/node_modules/')) return null
|
|
160
|
-
|
|
161
117
|
// cheap bail-out before running the regex/lightningcss on every module
|
|
162
118
|
if (!code.includes('cxx')) return null
|
|
163
119
|
|
|
164
120
|
const cleanId = id.split('?')[0]
|
|
165
121
|
|
|
166
|
-
if (!
|
|
122
|
+
if (!SOURCE_EXTENSIONS.has(path.extname(cleanId))) return null
|
|
167
123
|
|
|
168
124
|
const { template, tags, map } = collect(code, cleanId, pluginConfig)
|
|
169
125
|
|
|
@@ -180,26 +136,9 @@ export default function cxx(pluginConfig: PluginConfig = {}) {
|
|
|
180
136
|
logger.info('Watching for changes...')
|
|
181
137
|
|
|
182
138
|
server.watcher
|
|
183
|
-
.on('add', (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
})
|
|
187
|
-
.on('change', (p: string) => {
|
|
188
|
-
const file = watchedFile(p)
|
|
189
|
-
if (file) queue.add(file, 'change')
|
|
190
|
-
})
|
|
191
|
-
.on('unlink', (p: string) => {
|
|
192
|
-
const file = watchedFile(p)
|
|
193
|
-
if (file) queue.add(file, 'unlink')
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
void scan(watchRoot)
|
|
197
|
-
.then(() => flushTypes())
|
|
198
|
-
.then(() => {
|
|
199
|
-
const err = takeRebuildError()
|
|
200
|
-
if (err) logger.error('failed to generate types', err)
|
|
201
|
-
})
|
|
202
|
-
.catch(err => logger.error('failed to scan for cxx templates', err))
|
|
139
|
+
.on('add', onWatch('add'))
|
|
140
|
+
.on('change', onWatch('change'))
|
|
141
|
+
.on('unlink', onWatch('unlink'))
|
|
203
142
|
},
|
|
204
143
|
async writeBundle() {
|
|
205
144
|
await flushTypes()
|