@vidact/start 0.2.0-beta.0 → 0.2.0-beta.4

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/client.d.ts +18 -16
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +137 -165
  5. package/dist/client.js.map +1 -1
  6. package/dist/index-client.d.ts +5 -4
  7. package/dist/index-client.js +4 -4
  8. package/dist/index.d.ts +5 -4
  9. package/dist/index.js +4 -4
  10. package/dist/link-client.d.ts +6 -4
  11. package/dist/link-client.d.ts.map +1 -1
  12. package/dist/link-client.js +8 -4
  13. package/dist/link-client.js.map +1 -1
  14. package/dist/link-contract.d.ts +10 -7
  15. package/dist/link-contract.d.ts.map +1 -1
  16. package/dist/link-contract.js +11 -7
  17. package/dist/link-contract.js.map +1 -1
  18. package/dist/link.d.ts +6 -4
  19. package/dist/link.d.ts.map +1 -1
  20. package/dist/link.js +8 -4
  21. package/dist/link.js.map +1 -1
  22. package/dist/router.d.ts +57 -55
  23. package/dist/router.d.ts.map +1 -1
  24. package/dist/router.js +150 -157
  25. package/dist/router.js.map +1 -1
  26. package/dist/server.d.ts +18 -16
  27. package/dist/server.d.ts.map +1 -1
  28. package/dist/server.js +86 -99
  29. package/dist/server.js.map +1 -1
  30. package/dist/snapshot.d.ts +13 -10
  31. package/dist/snapshot.d.ts.map +1 -1
  32. package/dist/snapshot.js +19 -20
  33. package/dist/snapshot.js.map +1 -1
  34. package/dist/virtual.d.ts +3 -2
  35. package/dist/virtual.js +1 -2
  36. package/dist/vite.d.ts +18 -15
  37. package/dist/vite.d.ts.map +1 -1
  38. package/dist/vite.js +144 -171
  39. package/dist/vite.js.map +1 -1
  40. package/package.json +8 -7
  41. package/src/client.ts +262 -0
  42. package/src/index-client.ts +3 -0
  43. package/src/index.ts +3 -0
  44. package/src/link-client.ts +10 -0
  45. package/src/link-contract.ts +17 -0
  46. package/src/link.ts +10 -0
  47. package/src/router.ts +282 -0
  48. package/src/server.ts +200 -0
  49. package/src/snapshot.ts +40 -0
  50. package/src/virtual.ts +5 -0
  51. package/src/vite.ts +256 -0
  52. package/dist/index-client.d.ts.map +0 -1
  53. package/dist/index-client.js.map +0 -1
  54. package/dist/index.d.ts.map +0 -1
  55. package/dist/index.js.map +0 -1
  56. package/dist/virtual.d.ts.map +0 -1
  57. package/dist/virtual.js.map +0 -1
package/src/server.ts ADDED
@@ -0,0 +1,200 @@
1
+ import { renderToReadableStream } from '@vidact/runtime/framework/server'
2
+ import { createElement, type ServerChild, type ServerComponent } from '@vidact/runtime/server'
3
+
4
+ import {
5
+ composeRouteMatches,
6
+ matchRoutes,
7
+ resolveRouteMatches,
8
+ routeLoaderData,
9
+ runRouteLoaders,
10
+ type ResolvedRouteMatch,
11
+ type RouteManifest,
12
+ type RouteServerHandler,
13
+ type StartComponent,
14
+ } from './router.ts'
15
+ import {
16
+ encodeStartSnapshot,
17
+ VIDACT_START_NAVIGATION_HEADER,
18
+ VIDACT_START_PROTOCOL,
19
+ VIDACT_START_SNAPSHOT_MEDIA_TYPE,
20
+ } from './snapshot.ts'
21
+
22
+ const DEFAULT_ROOT_ID = 'vidact-start-root'
23
+ const DEFAULT_SNAPSHOT_ID = 'vidact-start-snapshot'
24
+
25
+ export interface StartDocumentContext {
26
+ readonly applicationHtml: string
27
+ readonly clientEntry: string | undefined
28
+ readonly rootId: string
29
+ readonly snapshot: string
30
+ readonly snapshotId: string
31
+ }
32
+
33
+ export interface StartHandlerOptions {
34
+ readonly clientEntry?: string
35
+ readonly manifest: RouteManifest
36
+ readonly notFound?: (request: Request) => Response | Promise<Response>
37
+ readonly renderDocument?: (context: StartDocumentContext) => string | Promise<string>
38
+ readonly rootId?: string
39
+ readonly snapshotId?: string
40
+ }
41
+
42
+ export function createStartHandler(
43
+ options: StartHandlerOptions,
44
+ ): (request: Request) => Promise<Response> {
45
+ const rootId = options.rootId ?? DEFAULT_ROOT_ID
46
+ const snapshotId = options.snapshotId ?? DEFAULT_SNAPSHOT_ID
47
+ return async (request) => {
48
+ const url = new URL(request.url)
49
+ const matches = matchRoutes(options.manifest, url.pathname)
50
+ if (matches.length === 0) {
51
+ return options.notFound === undefined
52
+ ? new Response('Not found', { status: 404 })
53
+ : await options.notFound(request)
54
+ }
55
+ const resolved = await resolveRouteMatches(matches)
56
+ const endpoint = endpointHandler(resolved, request.method)
57
+ if (endpoint !== undefined) {
58
+ const response = await endpoint({
59
+ params: resolved.at(-1)!.params,
60
+ request,
61
+ })
62
+ return responseForRequest(request, response)
63
+ }
64
+ const canRender = resolved.some((match) => match.definition.options.component !== undefined)
65
+ if ((request.method !== 'GET' && request.method !== 'HEAD') || !canRender) {
66
+ const allow = allowedMethods(resolved, canRender)
67
+ if (allow.length === 0) {
68
+ return options.notFound === undefined
69
+ ? new Response('Not found', { status: 404 })
70
+ : await options.notFound(request)
71
+ }
72
+ return new Response('Method not allowed', {
73
+ status: 405,
74
+ headers: { allow: allow.join(', ') },
75
+ })
76
+ }
77
+ let loaded
78
+ try {
79
+ loaded = await runRouteLoaders(resolved, request)
80
+ } catch (error) {
81
+ if (isResponse(error)) return responseForRequest(request, error)
82
+ throw error
83
+ }
84
+ const snapshot = escapeScriptText(
85
+ encodeStartSnapshot({
86
+ protocol: VIDACT_START_PROTOCOL,
87
+ pathname: `${url.pathname}${url.search}`,
88
+ loaderData: routeLoaderData(loaded),
89
+ }),
90
+ )
91
+ if (request.headers.get(VIDACT_START_NAVIGATION_HEADER) === '1') {
92
+ return new Response(request.method === 'HEAD' ? null : snapshot, {
93
+ headers: { 'content-type': `${VIDACT_START_SNAPSHOT_MEDIA_TYPE}; charset=utf-8` },
94
+ })
95
+ }
96
+
97
+ const application = composeRouteMatches(
98
+ loaded,
99
+ (component, props) =>
100
+ createElement(component as unknown as ServerComponent, props) as ServerChild,
101
+ request.url,
102
+ ) as ServerChild
103
+ const stream = await renderToReadableStream(() => application, {
104
+ identifierPrefix: 'start-',
105
+ })
106
+ const applicationHtml = await new Response(stream).text()
107
+ const documentContext = {
108
+ applicationHtml,
109
+ clientEntry: options.clientEntry,
110
+ rootId,
111
+ snapshot,
112
+ snapshotId,
113
+ }
114
+ const html =
115
+ options.renderDocument === undefined
116
+ ? defaultDocument(documentContext)
117
+ : await options.renderDocument(documentContext)
118
+ return new Response(request.method === 'HEAD' ? null : html, {
119
+ headers: { 'content-type': 'text/html; charset=utf-8' },
120
+ })
121
+ }
122
+ }
123
+
124
+ function responseForRequest(request: Request, response: Response): Response {
125
+ return request.method === 'HEAD' ? new Response(null, response) : response
126
+ }
127
+
128
+ function isResponse(value: unknown): value is Response {
129
+ if (value instanceof Response) return true
130
+ if (
131
+ typeof value !== 'object' ||
132
+ value === null ||
133
+ Object.prototype.hasOwnProperty.call(value, Symbol.toStringTag) ||
134
+ Object.prototype.toString.call(value) !== '[object Response]'
135
+ ) {
136
+ return false
137
+ }
138
+ try {
139
+ const candidate = value as Response
140
+ return (
141
+ typeof candidate.arrayBuffer === 'function' &&
142
+ typeof candidate.clone === 'function' &&
143
+ typeof candidate.headers?.get === 'function' &&
144
+ Number.isInteger(candidate.status)
145
+ )
146
+ } catch {
147
+ return false
148
+ }
149
+ }
150
+
151
+ function endpointHandler(
152
+ matches: readonly ResolvedRouteMatch[],
153
+ method: string,
154
+ ): RouteServerHandler | undefined {
155
+ const handlers = matches.at(-1)?.definition.options.server?.handlers
156
+ return handlers?.[method.toUpperCase()] ?? (method === 'HEAD' ? handlers?.GET : undefined)
157
+ }
158
+
159
+ function allowedMethods(
160
+ matches: readonly ResolvedRouteMatch[],
161
+ canRender: boolean,
162
+ ): readonly string[] {
163
+ const methods = new Set<string>()
164
+ if (canRender) {
165
+ methods.add('GET')
166
+ methods.add('HEAD')
167
+ }
168
+ const handlers = matches.at(-1)?.definition.options.server?.handlers
169
+ for (const method of Object.keys(handlers ?? {})) methods.add(method.toUpperCase())
170
+ if (methods.has('GET')) methods.add('HEAD')
171
+ return [...methods].toSorted(
172
+ (left, right) => methodRank(left) - methodRank(right) || left.localeCompare(right),
173
+ )
174
+ }
175
+
176
+ function methodRank(method: string): number {
177
+ return method === 'GET' ? 0 : method === 'HEAD' ? 1 : 2
178
+ }
179
+
180
+ function defaultDocument(context: StartDocumentContext): string {
181
+ const clientScript =
182
+ context.clientEntry === undefined
183
+ ? ''
184
+ : `<script type="module" src="${escapeAttribute(context.clientEntry)}"></script>`
185
+ return `<!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><div id="${escapeAttribute(context.rootId)}">${context.applicationHtml}</div><script id="${escapeAttribute(context.snapshotId)}" type="application/json">${context.snapshot}</script>${clientScript}</body></html>`
186
+ }
187
+
188
+ function escapeAttribute(value: string): string {
189
+ return value
190
+ .replaceAll('&', '&amp;')
191
+ .replaceAll('"', '&quot;')
192
+ .replaceAll('<', '&lt;')
193
+ .replaceAll('>', '&gt;')
194
+ }
195
+
196
+ function escapeScriptText(value: string): string {
197
+ return value.replaceAll('&', '\\u0026').replaceAll('<', '\\u003c').replaceAll('>', '\\u003e')
198
+ }
199
+
200
+ export type { StartComponent }
@@ -0,0 +1,40 @@
1
+ import {
2
+ decodeFrameworkValue,
3
+ encodeFrameworkValue,
4
+ type FrameworkValue,
5
+ } from '@vidact/runtime/framework/protocol'
6
+
7
+ export const VIDACT_START_PROTOCOL = 'vidact-start-v1'
8
+ export const VIDACT_START_NAVIGATION_HEADER = 'x-vidact-start-navigation'
9
+ export const VIDACT_START_SNAPSHOT_MEDIA_TYPE = 'application/x-vidact-start+json'
10
+
11
+ export interface StartSnapshot {
12
+ readonly protocol: typeof VIDACT_START_PROTOCOL
13
+ readonly loaderData: Readonly<Record<string, FrameworkValue>>
14
+ readonly pathname: string
15
+ }
16
+
17
+ export function encodeStartSnapshot(snapshot: StartSnapshot): string {
18
+ return encodeFrameworkValue(snapshot as unknown as FrameworkValue)
19
+ }
20
+
21
+ export function decodeStartSnapshot(payload: string): StartSnapshot {
22
+ const value = decodeFrameworkValue(payload)
23
+ if (
24
+ !isRecord(value) ||
25
+ value.protocol !== VIDACT_START_PROTOCOL ||
26
+ typeof value.pathname !== 'string' ||
27
+ !isRecord(value.loaderData)
28
+ ) {
29
+ throw new TypeError('invalid Vidact Start snapshot')
30
+ }
31
+ return {
32
+ protocol: VIDACT_START_PROTOCOL,
33
+ pathname: value.pathname,
34
+ loaderData: value.loaderData as Readonly<Record<string, FrameworkValue>>,
35
+ }
36
+ }
37
+
38
+ function isRecord(value: unknown): value is Record<string, unknown> {
39
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
40
+ }
package/src/virtual.ts ADDED
@@ -0,0 +1,5 @@
1
+ // Shipped verbatim as dist/virtual.d.ts: an ambient declaration cannot be bundled
2
+ // without becoming a module augmentation, so it names the built router file.
3
+ declare module 'virtual:vidact-start/routes' {
4
+ export const routeManifest: import('./router.js').RouteManifest
5
+ }
package/src/vite.ts ADDED
@@ -0,0 +1,256 @@
1
+ import { readdir } from 'node:fs/promises'
2
+ import type { IncomingMessage, ServerResponse } from 'node:http'
3
+ import path from 'node:path'
4
+
5
+ import { vidact, type VidactPluginOptions } from '@vidact/vite'
6
+ import {
7
+ isRunnableDevEnvironment,
8
+ normalizePath,
9
+ type Plugin,
10
+ type ResolvedConfig,
11
+ type ViteDevServer,
12
+ } from 'vite'
13
+
14
+ const PUBLIC_ROUTES_ID = 'virtual:vidact-start/routes'
15
+ const INTERNAL_ROUTES_ID = `\0${PUBLIC_ROUTES_ID}`
16
+ const ROUTE_FILE = /\.(?:[cm]?[jt]sx?)$/u
17
+ const IGNORED_ROUTE_FILE = /(?:^|\.)\b(?:test|spec)\.[cm]?[jt]sx?$/u
18
+
19
+ export interface VidactStartOptions {
20
+ readonly compiler?: Omit<VidactPluginOptions, 'target'>
21
+ readonly routesDirectory?: string
22
+ readonly serverEntry?: string | false
23
+ readonly serverExport?: string
24
+ }
25
+
26
+ export interface GeneratedRouteRecord {
27
+ readonly file: string
28
+ readonly id: string
29
+ readonly parentId: string | null
30
+ readonly path: string
31
+ }
32
+
33
+ export function vidactStart(options: VidactStartOptions = {}): Plugin[] {
34
+ const compiler = options.compiler ?? {}
35
+ const features = [...new Set(['framework', ...(compiler.features ?? [])])] as NonNullable<
36
+ VidactPluginOptions['features']
37
+ >
38
+ const plugins = [
39
+ vidactForEnvironment('client', { ...compiler, target: 'hydrate', features }),
40
+ vidactForEnvironment('ssr', { ...compiler, target: 'server', features }),
41
+ routeManifestPlugin(options.routesDirectory),
42
+ ]
43
+ if (options.serverEntry !== false) {
44
+ plugins.push(
45
+ developmentServerPlugin(
46
+ options.serverEntry ?? '/src/server.ts',
47
+ options.serverExport ?? 'default',
48
+ ),
49
+ )
50
+ }
51
+ return plugins
52
+ }
53
+
54
+ function routeManifestPlugin(configuredRoutesDirectory: string | undefined): Plugin {
55
+ let config: ResolvedConfig
56
+ let routesDirectory: string
57
+ let server: ViteDevServer | undefined
58
+ return {
59
+ name: 'vidact-start-routes',
60
+ configResolved(resolved) {
61
+ config = resolved
62
+ routesDirectory = path.resolve(config.root, configuredRoutesDirectory ?? 'src/routes')
63
+ },
64
+ configureServer(viteServer) {
65
+ server = viteServer
66
+ viteServer.watcher.add(routesDirectory)
67
+ },
68
+ resolveId(source) {
69
+ return source === PUBLIC_ROUTES_ID ? INTERNAL_ROUTES_ID : null
70
+ },
71
+ async load(id) {
72
+ if (id !== INTERNAL_ROUTES_ID) return null
73
+ return generateRouteModule(await discoverRouteRecords(routesDirectory))
74
+ },
75
+ handleHotUpdate(context) {
76
+ if (!isRouteFile(routesDirectory, context.file)) return
77
+ const module = server?.moduleGraph.getModuleById(INTERNAL_ROUTES_ID)
78
+ if (module !== undefined) server?.moduleGraph.invalidateModule(module)
79
+ server?.ws.send({ type: 'full-reload' })
80
+ return []
81
+ },
82
+ }
83
+ }
84
+
85
+ function vidactForEnvironment(
86
+ environmentName: 'client' | 'ssr',
87
+ options: VidactPluginOptions,
88
+ ): Plugin {
89
+ const plugin = vidact(options)
90
+ return {
91
+ ...plugin,
92
+ name: `${plugin.name}:start:${environmentName}`,
93
+ applyToEnvironment: (environment) => environment.name === environmentName,
94
+ }
95
+ }
96
+
97
+ function developmentServerPlugin(serverEntry: string, serverExport: string): Plugin {
98
+ return {
99
+ name: 'vidact-start-development-server',
100
+ config: () => ({ appType: 'custom' }),
101
+ configureServer(server) {
102
+ return () => {
103
+ server.middlewares.use((nodeRequest, nodeResponse, next) => {
104
+ void serveDevelopmentRequest(
105
+ server,
106
+ serverEntry,
107
+ serverExport,
108
+ nodeRequest,
109
+ nodeResponse,
110
+ ).catch((error: unknown) => {
111
+ if (error instanceof Error) server.ssrFixStacktrace(error)
112
+ next(error)
113
+ })
114
+ })
115
+ }
116
+ },
117
+ }
118
+ }
119
+
120
+ async function serveDevelopmentRequest(
121
+ server: ViteDevServer,
122
+ serverEntry: string,
123
+ serverExport: string,
124
+ nodeRequest: IncomingMessage,
125
+ nodeResponse: ServerResponse,
126
+ ): Promise<void> {
127
+ const environment = server.environments.ssr
128
+ if (!isRunnableDevEnvironment(environment)) {
129
+ throw new Error("Vidact Start requires Vite's runnable SSR development environment")
130
+ }
131
+ const module = (await environment.runner.import(serverEntry)) as Record<string, unknown>
132
+ const handler = module[serverExport]
133
+ if (typeof handler !== 'function') {
134
+ throw new TypeError(`${serverEntry} must export a ${serverExport} request handler`)
135
+ }
136
+ const request = await nodeRequestToRequest(nodeRequest)
137
+ let response = await (handler as (request: Request) => Response | Promise<Response>)(request)
138
+ if (!(response instanceof Response)) {
139
+ throw new TypeError(`${serverEntry} ${serverExport} must return a Response`)
140
+ }
141
+ if (response.headers.get('content-type')?.startsWith('text/html') === true) {
142
+ const html = await server.transformIndexHtml(nodeRequest.url ?? '/', await response.text())
143
+ response = new Response(html, response)
144
+ }
145
+ await sendNodeResponse(nodeResponse, response)
146
+ }
147
+
148
+ async function nodeRequestToRequest(request: IncomingMessage): Promise<Request> {
149
+ const headers = new Headers()
150
+ for (const [name, value] of Object.entries(request.headers)) {
151
+ if (Array.isArray(value)) for (const item of value) headers.append(name, item)
152
+ else if (value !== undefined) headers.set(name, value)
153
+ }
154
+ const forwardedProtocol = headers.get('x-forwarded-proto')?.split(',', 1)[0]?.trim()
155
+ const protocol =
156
+ forwardedProtocol ?? (Reflect.get(request.socket, 'encrypted') === true ? 'https' : 'http')
157
+ const url = new URL(request.url ?? '/', `${protocol}://${headers.get('host') ?? 'localhost'}`)
158
+ const body =
159
+ request.method === 'GET' || request.method === 'HEAD'
160
+ ? undefined
161
+ : await readRequestBody(request)
162
+ return new Request(url, {
163
+ method: request.method ?? 'GET',
164
+ headers,
165
+ ...(body === undefined ? {} : { body }),
166
+ })
167
+ }
168
+
169
+ async function readRequestBody(request: IncomingMessage): Promise<ArrayBuffer> {
170
+ const chunks: Uint8Array[] = []
171
+ for await (const chunk of request) {
172
+ chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)
173
+ }
174
+ return Uint8Array.from(Buffer.concat(chunks)).buffer
175
+ }
176
+
177
+ async function sendNodeResponse(response: ServerResponse, webResponse: Response): Promise<void> {
178
+ response.statusCode = webResponse.status
179
+ response.statusMessage = webResponse.statusText
180
+ for (const [name, value] of webResponse.headers) response.setHeader(name, value)
181
+ const cookies = webResponse.headers.getSetCookie()
182
+ if (cookies.length > 0) response.setHeader('set-cookie', cookies)
183
+ response.end(Buffer.from(await webResponse.arrayBuffer()))
184
+ }
185
+
186
+ export async function discoverRouteRecords(
187
+ routesDirectory: string,
188
+ ): Promise<readonly GeneratedRouteRecord[]> {
189
+ let filenames: string[]
190
+ try {
191
+ filenames = await readdir(routesDirectory, { recursive: true })
192
+ } catch (error) {
193
+ if (isMissingDirectory(error)) return []
194
+ throw error
195
+ }
196
+ const records = filenames
197
+ .filter((filename) => ROUTE_FILE.test(filename) && !IGNORED_ROUTE_FILE.test(filename))
198
+ .map((filename) => routeFileToRecord(filename, routesDirectory))
199
+ const ids = new Set(records.map((record) => record.id))
200
+ return Object.freeze(
201
+ records
202
+ .map((record) => Object.freeze({ ...record, parentId: parentRouteId(record.id, ids) }))
203
+ .toSorted((left, right) => left.id.localeCompare(right.id)),
204
+ )
205
+ }
206
+
207
+ export function routeFileToRecord(filename: string, routesDirectory: string): GeneratedRouteRecord {
208
+ const normalizedFilename = normalizePath(filename)
209
+ const id = normalizedFilename.replace(ROUTE_FILE, '')
210
+ if (id.length === 0) throw new TypeError(`invalid route filename ${filename}`)
211
+ const routeSegments = id
212
+ .split('/')
213
+ .filter((segment) => segment !== '__root' && segment !== 'index' && !segment.startsWith('_'))
214
+ .map((segment) =>
215
+ segment === '$' ? '*' : segment.startsWith('$') ? `:${segment.slice(1)}` : segment,
216
+ )
217
+ return {
218
+ file: normalizePath(path.resolve(routesDirectory, normalizedFilename)),
219
+ id,
220
+ parentId: null,
221
+ path: routeSegments.length === 0 ? '/' : `/${routeSegments.join('/')}`,
222
+ }
223
+ }
224
+
225
+ function parentRouteId(id: string, ids: ReadonlySet<string>): string | null {
226
+ if (id === '__root') return null
227
+ const segments = id.split('/')
228
+ if (segments.at(-1) === 'index') segments.pop()
229
+ while (segments.length > 0) {
230
+ const candidate = segments.join('/')
231
+ if (candidate !== id && ids.has(candidate)) return candidate
232
+ segments.pop()
233
+ }
234
+ return ids.has('__root') ? '__root' : null
235
+ }
236
+
237
+ function generateRouteModule(records: readonly GeneratedRouteRecord[]): string {
238
+ const entries = records
239
+ .map(
240
+ (record) =>
241
+ `{ id: ${JSON.stringify(record.id)}, parentId: ${JSON.stringify(record.parentId)}, path: ${JSON.stringify(record.path)}, load: () => import(${JSON.stringify(record.file)}) }`,
242
+ )
243
+ .join(',\n ')
244
+ return `import { createRouteManifest } from '@vidact/start'\n\nexport const routeManifest = createRouteManifest([\n ${entries}\n])\n`
245
+ }
246
+
247
+ function isRouteFile(routesDirectory: string, filename: string): boolean {
248
+ const relative = path.relative(routesDirectory, filename)
249
+ return (
250
+ !relative.startsWith('..') && ROUTE_FILE.test(relative) && !IGNORED_ROUTE_FILE.test(relative)
251
+ )
252
+ }
253
+
254
+ function isMissingDirectory(error: unknown): boolean {
255
+ return typeof error === 'object' && error !== null && Reflect.get(error, 'code') === 'ENOENT'
256
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-client.d.ts","sourceRoot":"","sources":["../src/index-client.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-client.js","sourceRoot":"","sources":["../src/index-client.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"virtual.d.ts","sourceRoot":"","sources":["../src/virtual.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,6BAA6B,CAAC;IACpC,MAAM,aAAa,EAAE,OAAO,aAAa,EAAE,aAAa,CAAA;CAChE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"virtual.js","sourceRoot":"","sources":["../src/virtual.ts"],"names":[],"mappings":""}