@graftland/hmr 0.3.0 → 0.3.2
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -18
- package/dist/index.js.map +1 -1
- package/dist/internal/changes.js +4 -4
- package/dist/internal/changes.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +328 -335
- package/src/internal/changes.ts +104 -102
package/src/internal/changes.ts
CHANGED
|
@@ -90,8 +90,9 @@ export const changes = (
|
|
|
90
90
|
Effect.gen(function* () {
|
|
91
91
|
if (paths.length === 0) return Stream.empty
|
|
92
92
|
const fs = yield* FileSystem.FileSystem
|
|
93
|
-
const roots = yield* Effect.forEach(
|
|
94
|
-
|
|
93
|
+
const roots = yield* Effect.forEach(
|
|
94
|
+
paths,
|
|
95
|
+
Effect.fnUntraced(function* (path: string) {
|
|
95
96
|
const canonical = yield* fs.realPath(path)
|
|
96
97
|
const info = yield* fs.stat(canonical)
|
|
97
98
|
return {
|
|
@@ -137,10 +138,10 @@ export const changes = (
|
|
|
137
138
|
)
|
|
138
139
|
// Watch only graph directories, never recursively traverse an application root.
|
|
139
140
|
// Missing descendants use their nearest existing ancestor until they appear.
|
|
140
|
-
const existingDirectory
|
|
141
|
+
const existingDirectory: (
|
|
141
142
|
path: string,
|
|
142
|
-
)
|
|
143
|
-
Effect.
|
|
143
|
+
) => Effect.Effect<string, import("effect").PlatformError.PlatformError> =
|
|
144
|
+
Effect.fnUntraced(function* (path: string) {
|
|
144
145
|
const info = yield* missing(fs.stat(path))
|
|
145
146
|
return info?.type === "Directory" || dirname(path) === path
|
|
146
147
|
? path
|
|
@@ -188,105 +189,106 @@ export const changes = (
|
|
|
188
189
|
readonly checked: number
|
|
189
190
|
}
|
|
190
191
|
const observed = yield* Ref.make(HashMap.empty<string, Observation>())
|
|
191
|
-
const scan = (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const audit =
|
|
227
|
-
events !== undefined ||
|
|
228
|
-
previous === undefined ||
|
|
229
|
-
!sameVersion(previous.baseline, baseline) ||
|
|
230
|
-
previous.stat !== stat ||
|
|
231
|
-
now - previous.checked >= 10000
|
|
232
|
-
const content = audit
|
|
233
|
-
? yield* missing(fs.readFile(path)).pipe(
|
|
234
|
-
Effect.map((bytes) =>
|
|
235
|
-
bytes === undefined ? undefined : digest(bytes),
|
|
236
|
-
),
|
|
237
|
-
)
|
|
238
|
-
: previous.content
|
|
239
|
-
const expected =
|
|
240
|
-
previous === undefined
|
|
241
|
-
? baseline
|
|
242
|
-
: {
|
|
243
|
-
content:
|
|
244
|
-
baseline.content === undefined ||
|
|
245
|
-
sameVersion(previous.baseline, baseline)
|
|
246
|
-
? previous.content
|
|
247
|
-
: baseline.content,
|
|
248
|
-
resolution: sameVersion(previous.baseline, baseline)
|
|
249
|
-
? previous.resolution
|
|
250
|
-
: baseline.resolution,
|
|
251
|
-
}
|
|
252
|
-
return {
|
|
253
|
-
url,
|
|
254
|
-
observation: {
|
|
255
|
-
baseline,
|
|
256
|
-
content,
|
|
257
|
-
resolution,
|
|
258
|
-
stat,
|
|
259
|
-
checked: audit ? now : previous.checked,
|
|
260
|
-
},
|
|
261
|
-
changed:
|
|
262
|
-
expected.content !== content ||
|
|
263
|
-
expected.resolution !== resolution,
|
|
264
|
-
}
|
|
265
|
-
}),
|
|
266
|
-
{ concurrency: 8 },
|
|
267
|
-
)
|
|
268
|
-
// The immutable snapshot keeps its bytes alive while owners can be released.
|
|
269
|
-
// A stale result cannot acknowledge a newer import, even when bytes coincide.
|
|
270
|
-
return yield* withFiles((current) =>
|
|
271
|
-
Ref.modify(observed, (seen) => {
|
|
272
|
-
let next = HashMap.filter(seen, (_, url) =>
|
|
273
|
-
HashMap.has(current, url),
|
|
274
|
-
)
|
|
275
|
-
let changed = HashSet.empty<string>()
|
|
276
|
-
for (const { url, observation, changed: differs } of checked) {
|
|
277
|
-
if (
|
|
278
|
-
!Option.exists(HashMap.get(current, url), (version) =>
|
|
279
|
-
sameVersion(version, observation.baseline),
|
|
192
|
+
const scan = Effect.fnUntraced(function* (
|
|
193
|
+
events: HashSet.HashSet<string> | undefined,
|
|
194
|
+
) {
|
|
195
|
+
const loaded = yield* files
|
|
196
|
+
const before = yield* Ref.get(observed)
|
|
197
|
+
const now = yield* Clock.currentTimeMillis
|
|
198
|
+
const selected = Array.filter(
|
|
199
|
+
Array.fromIterable(loaded),
|
|
200
|
+
([url]) =>
|
|
201
|
+
events === undefined ||
|
|
202
|
+
Array.some(Array.fromIterable(events), (path) => {
|
|
203
|
+
const file = fileURLToPath(url)
|
|
204
|
+
return file === path || String.startsWith(`${path}/`)(file)
|
|
205
|
+
}),
|
|
206
|
+
)
|
|
207
|
+
const checked = yield* Effect.forEach(
|
|
208
|
+
selected,
|
|
209
|
+
Effect.fnUntraced(function* ([
|
|
210
|
+
url,
|
|
211
|
+
baseline,
|
|
212
|
+
]: (typeof selected)[number]) {
|
|
213
|
+
const path = fileURLToPath(url)
|
|
214
|
+
const previous = Option.getOrUndefined(HashMap.get(before, url))
|
|
215
|
+
const info = yield* missing(fs.stat(path))
|
|
216
|
+
const stat =
|
|
217
|
+
info === undefined
|
|
218
|
+
? "missing"
|
|
219
|
+
: `${info.size}:${Option.getOrUndefined(info.mtime)?.getTime()}:${Option.getOrUndefined(info.ino)}`
|
|
220
|
+
const resolution =
|
|
221
|
+
baseline.resolution === undefined
|
|
222
|
+
? undefined
|
|
223
|
+
: yield* missing(fs.realPath(path)).pipe(
|
|
224
|
+
Effect.map((path) =>
|
|
225
|
+
path === undefined ? undefined : pathToFileURL(path).href,
|
|
226
|
+
),
|
|
280
227
|
)
|
|
228
|
+
const audit =
|
|
229
|
+
events !== undefined ||
|
|
230
|
+
previous === undefined ||
|
|
231
|
+
!sameVersion(previous.baseline, baseline) ||
|
|
232
|
+
previous.stat !== stat ||
|
|
233
|
+
now - previous.checked >= 10000
|
|
234
|
+
const content = audit
|
|
235
|
+
? yield* missing(fs.readFile(path)).pipe(
|
|
236
|
+
Effect.map((bytes) =>
|
|
237
|
+
bytes === undefined ? undefined : digest(bytes),
|
|
238
|
+
),
|
|
281
239
|
)
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
240
|
+
: previous.content
|
|
241
|
+
const expected =
|
|
242
|
+
previous === undefined
|
|
243
|
+
? baseline
|
|
244
|
+
: {
|
|
245
|
+
content:
|
|
246
|
+
baseline.content === undefined ||
|
|
247
|
+
sameVersion(previous.baseline, baseline)
|
|
248
|
+
? previous.content
|
|
249
|
+
: baseline.content,
|
|
250
|
+
resolution: sameVersion(previous.baseline, baseline)
|
|
251
|
+
? previous.resolution
|
|
252
|
+
: baseline.resolution,
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
url,
|
|
256
|
+
observation: {
|
|
257
|
+
baseline,
|
|
258
|
+
content,
|
|
259
|
+
resolution,
|
|
260
|
+
stat,
|
|
261
|
+
checked: audit ? now : previous.checked,
|
|
262
|
+
},
|
|
263
|
+
changed:
|
|
264
|
+
expected.content !== content ||
|
|
265
|
+
expected.resolution !== resolution,
|
|
266
|
+
}
|
|
267
|
+
}),
|
|
268
|
+
{ concurrency: 8 },
|
|
269
|
+
)
|
|
270
|
+
// The immutable snapshot keeps its bytes alive while owners can be released.
|
|
271
|
+
// A stale result cannot acknowledge a newer import, even when bytes coincide.
|
|
272
|
+
return yield* withFiles((current) =>
|
|
273
|
+
Ref.modify(observed, (seen) => {
|
|
274
|
+
let next = HashMap.filter(seen, (_, url) =>
|
|
275
|
+
HashMap.has(current, url),
|
|
276
|
+
)
|
|
277
|
+
let changed = HashSet.empty<string>()
|
|
278
|
+
for (const { url, observation, changed: differs } of checked) {
|
|
279
|
+
if (
|
|
280
|
+
!Option.exists(HashMap.get(current, url), (version) =>
|
|
281
|
+
sameVersion(version, observation.baseline),
|
|
282
|
+
)
|
|
283
|
+
)
|
|
284
|
+
continue
|
|
285
|
+
next = HashMap.set(next, url, observation)
|
|
286
|
+
if (differs) changed = HashSet.add(changed, url)
|
|
287
|
+
}
|
|
288
|
+
return [changed, next]
|
|
289
|
+
}),
|
|
290
|
+
)
|
|
291
|
+
})
|
|
290
292
|
return Stream.merge(
|
|
291
293
|
native,
|
|
292
294
|
Stream.tick("1 second").pipe(
|