Skip to content

Commit 4fde0ca

Browse files
committed
refactor(devframe): shrink remote-assets surface and LOC
Collapse the remote-assets module's public API from eight exports to one (resolveStaticAssetsSource) — cache-path helpers, createRemoteAssetsStore, resolveInstalledRemoteAssets, and the store options interfaces are now private, and the error page moves into serve-static as an internal helper. resolveStaticAssetsSource takes the project storage dir directly (dropping the options object), so every call site loses the cacheRoot plumbing; the build adapter reuses it too instead of hand-rolling install/materialize. RemoteAssetsStore.serve now returns a web Response, letting serve-static drop the RemoteAssetsServedFile / RemoteAssetsServeOptions types and the bespoke miss/stream/cancel handling. Net ~370 fewer lines.
1 parent 2fe5e18 commit 4fde0ca

12 files changed

Lines changed: 324 additions & 695 deletions

File tree

packages/devframe/src/adapters/build.ts

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { existsSync } from 'node:fs'
55
import fs from 'node:fs/promises'
66
import process from 'node:process'
77
import { colors as c } from 'devframe/utils/colors'
8-
import { createRemoteAssetsStore, remoteAssetsCacheDir, remoteAssetsCacheRoot, resolveInstalledRemoteAssets } from 'devframe/utils/remote-assets'
8+
import { resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
99
import { structuredCloneStringify } from 'devframe/utils/structured-clone'
1010
import { dirname, resolve } from 'pathe'
1111
import {
@@ -70,28 +70,17 @@ export async function createBuild(d: DevframeDefinition, options: CreateBuildOpt
7070

7171
const host = createH3DevframeHost({ origin: 'http://localhost', appName: d.id })
7272

73-
// Copy author's SPA into the output root. A remote-assets source copies
74-
// from the locally installed assets package when present, otherwise every
75-
// listed file is materialized from the provider — a static deploy must be
76-
// self-contained.
77-
if (typeof distSource === 'string') {
78-
console.log(c.cyan`[devframe] copying SPA from ${distSource} -> ${outDir}`)
79-
await fs.cp(distSource, outDir, { recursive: true })
73+
// A static deploy must be self-contained: a local dir (or a remote source
74+
// backed by a locally installed package) is copied; an uninstalled remote
75+
// source materializes every listed file from the provider.
76+
const resolved = resolveStaticAssetsSource(distSource, host.getStorageDir('project'))
77+
if (typeof resolved === 'string') {
78+
console.log(c.cyan`[devframe] copying SPA from ${resolved} -> ${outDir}`)
79+
await fs.cp(resolved, outDir, { recursive: true })
8080
}
8181
else {
82-
const installed = resolveInstalledRemoteAssets(distSource)
83-
if (installed) {
84-
console.log(c.cyan`[devframe] copying SPA from ${installed} -> ${outDir}`)
85-
await fs.cp(installed, outDir, { recursive: true })
86-
}
87-
else {
88-
console.log(c.cyan`[devframe] materializing SPA from ${distSource.package}@${distSource.version} -> ${outDir}`)
89-
const cacheRoot = remoteAssetsCacheRoot(host.getStorageDir('project'))
90-
const store = createRemoteAssetsStore(distSource, {
91-
cacheDir: remoteAssetsCacheDir(cacheRoot, distSource),
92-
})
93-
await store.materialize(outDir)
94-
}
82+
console.log(c.cyan`[devframe] materializing SPA from ${resolved.assets.package}@${resolved.assets.version} -> ${outDir}`)
83+
await resolved.materialize(outDir)
9584
}
9685

9786
const ctx = await createHostContext({

packages/devframe/src/adapters/initiate.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { InstanceShellInternals, StartedServer } from '../node/instance-she
99
import type { DevframeDefinition, DevframeSetupInfo, DevframeSseOptions, DevframeWsOptions, McpRouteOptions } from '../types/devframe'
1010
import type { StaticAssetsSource } from '../types/remote-assets'
1111
import process from 'node:process'
12-
import { remoteAssetsCacheRoot, resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
12+
import { resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
1313
import { mountStaticHandler } from 'devframe/utils/serve-static'
1414
import { H3 } from 'h3'
1515
import { resolve } from 'pathe'
@@ -332,9 +332,7 @@ export function initDevframe(
332332
app.use(joinURL(base, DEVFRAME_CONNECTION_META_FILENAME), () => meta)
333333

334334
if (distDir) {
335-
const source = resolveStaticAssetsSource(distDir, {
336-
cacheRoot: remoteAssetsCacheRoot(context.host.getStorageDir('project')),
337-
})
335+
const source = resolveStaticAssetsSource(distDir, context.host.getStorageDir('project'))
338336
mountStaticHandler(app, base, typeof source === 'string' ? resolve(source) : source)
339337
}
340338
},

packages/devframe/src/node/host-views.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DevframeNodeContext, DevframeViewHost as DevframeViewHostType, StaticAssetsSource } from 'devframe/types'
22
import { existsSync } from 'node:fs'
3-
import { remoteAssetsCacheRoot, resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
3+
import { resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
44
import { diagnostics } from './diagnostics'
55

66
export class DevframeViewHost implements DevframeViewHostType {
@@ -18,9 +18,7 @@ export class DevframeViewHost implements DevframeViewHostType {
1818
// Local directories must exist up front; remote declarations resolve to
1919
// a locally installed package when present, otherwise to a lazy CDN
2020
// back-proxy store — nothing to check on disk yet.
21-
const resolved = resolveStaticAssetsSource(source, {
22-
cacheRoot: remoteAssetsCacheRoot(this.context.host.getStorageDir('project')),
23-
})
21+
const resolved = resolveStaticAssetsSource(source, this.context.host.getStorageDir('project'))
2422
if (typeof resolved === 'string' && !existsSync(resolved)) {
2523
throw diagnostics.DF0008({ distDir: resolved })
2624
}

packages/devframe/src/types/remote-assets.ts

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -84,46 +84,22 @@ export type StaticAssetsSource = string | RemoteAssets
8484

8585
/**
8686
* A resolved, servable handle over a {@link RemoteAssets} declaration —
87-
* created by `createRemoteAssetsStore()` (`devframe/utils/remote-assets`)
87+
* produced by `resolveStaticAssetsSource()` (`devframe/utils/remote-assets`)
8888
* and consumed by the static-serving engine (`devframe/utils/serve-static`).
8989
*/
9090
export interface RemoteAssetsStore {
91-
readonly kind: 'remote-assets-store'
9291
/** The declaration this store serves (with defaults applied). */
9392
readonly assets: RemoteAssets & { path: string }
94-
/** Version-locked cache directory files are persisted under. */
95-
readonly cacheDir: string
9693
/**
97-
* Resolve a request path (relative to the mount base) and open the file:
98-
* from the cache when present, otherwise streamed through the provider
99-
* while being written into the cache. Returns `null` for a miss (404)
100-
* and throws on provider/network failure.
94+
* Resolve a request path (relative to the mount base, SPA fallback to
95+
* `index.html`) and return a `Response`: streamed from the cache when
96+
* present, otherwise through the provider while being written into the
97+
* cache. `null` on a miss (404); throws on provider/network failure.
10198
*/
102-
serve: (urlPath: string, options?: RemoteAssetsServeOptions) => Promise<RemoteAssetsServedFile | null>
99+
serve: (urlPath: string) => Promise<Response | null>
103100
/**
104101
* Download every listed file under `assets.path` into `targetDir`
105102
* (paths relative to `assets.path`). Requires a provider file listing.
106103
*/
107104
materialize: (targetDir: string) => Promise<void>
108105
}
109-
110-
/** Request-resolution options for {@link RemoteAssetsStore.serve}. */
111-
export interface RemoteAssetsServeOptions {
112-
/** Default: `['index.html']`. */
113-
indexNames?: string[]
114-
/** SPA fallback to `indexNames[0]` on miss. Default: `true`. */
115-
single?: boolean
116-
}
117-
118-
/** An opened file ready to respond with. */
119-
export interface RemoteAssetsServedFile {
120-
/** Response headers (`Content-Type`, `Content-Length` when known, …). */
121-
headers: Record<string, string>
122-
/** Response body. Call at most once. */
123-
stream: () => ReadableStream<Uint8Array>
124-
/**
125-
* Release the file when the body will never be read (HEAD requests) —
126-
* an in-flight provider download keeps filling the cache.
127-
*/
128-
cancel: () => void
129-
}

0 commit comments

Comments
 (0)