diff --git a/package-lock.json b/package-lock.json index ed14f4df..5b8671ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oc", - "version": "0.49.66", + "version": "0.49.67", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oc", - "version": "0.49.66", + "version": "0.49.67", "license": "MIT", "dependencies": { "@types/lodash.isequal": "^4.5.8", @@ -51,6 +51,7 @@ "serialize-error": "^8.1.0", "targz": "^1.0.1", "try-require": "^1.2.1", + "turbo-stream": "^2.4.1", "undici": "^6.19.8", "universalify": "^2.0.0", "yargs": "^17.7.2" @@ -9214,6 +9215,12 @@ "node": ">=0.6.x" } }, + "node_modules/turbo-stream": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.1.tgz", + "integrity": "sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw==", + "license": "ISC" + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", diff --git a/package.json b/package.json index 9ac47cef..c78ff7d7 100644 --- a/package.json +++ b/package.json @@ -116,8 +116,9 @@ "serialize-error": "^8.1.0", "targz": "^1.0.1", "try-require": "^1.2.1", + "turbo-stream": "^2.4.1", "undici": "^6.19.8", "universalify": "^2.0.0", "yargs": "^17.7.2" } -} +} \ No newline at end of file diff --git a/src/registry/domain/require-wrapper.ts b/src/registry/domain/require-wrapper.ts index 42e2ae33..dd8a5b06 100644 --- a/src/registry/domain/require-wrapper.ts +++ b/src/registry/domain/require-wrapper.ts @@ -5,7 +5,9 @@ import tryRequire from 'try-require'; import strings from '../../resources'; -const isCoreDependency = (x: string) => coreModules.includes(x); +const allCoreModules = [...coreModules, ...coreModules.map((m) => `node:${m}`)]; + +const isCoreDependency = (x: string) => allCoreModules.includes(x); const requireCoreDependency = (x: string) => (isCoreDependency(x) && tryRequire(x)) || undefined; diff --git a/src/registry/routes/component.ts b/src/registry/routes/component.ts index 9faa558b..15197ef7 100644 --- a/src/registry/routes/component.ts +++ b/src/registry/routes/component.ts @@ -1,10 +1,12 @@ import { serializeError } from 'serialize-error'; +import { Readable } from 'node:stream'; import type { Request, RequestHandler, Response } from 'express'; +import { encode } from 'turbo-stream'; import strings from '../../resources'; import type { Config } from '../../types'; import type { Repository } from '../domain/repository'; -import GetComponentHelper from './helpers/get-component'; +import GetComponentHelper, { stream } from './helpers/get-component'; export default function component( conf: Config, @@ -48,7 +50,27 @@ export default function component( res.set(result.headers); } - res.status(result.status).json(result.response); + const streamEnabled = + !!result.response.data?.component?.props?.[stream]; + if (streamEnabled) { + delete result.response.data.component.props[stream]; + const webStream = encode({ ...result.response }); + + const nodeStream = Readable.from(webStream); + + res.status(result.status); + nodeStream.on('error', (err) => { + res.status(500).end(String(err)); + }); + + res.setHeader('Content-Type', 'x-text/stream'); + + nodeStream.pipe(res).on('finish', () => { + res.end(); + }); + } else { + res.status(result.status).json(result.response); + } } catch (e) { res.status(500).json({ code: 'RENDER_ERROR', diff --git a/src/registry/routes/helpers/get-component.ts b/src/registry/routes/helpers/get-component.ts index 651a21ff..9bc58d92 100644 --- a/src/registry/routes/helpers/get-component.ts +++ b/src/registry/routes/helpers/get-component.ts @@ -56,6 +56,7 @@ export interface GetComponentResult { }; } +export const stream = Symbol('stream'); const noop = () => {}; const noopConsole = Object.fromEntries( Object.keys(console).map((key) => [key, noop]) @@ -520,7 +521,8 @@ export default function getComponent(conf: Config, repository: Repository) { responseHeaders[header.toLowerCase()] = value; } }, - templates: repository.getTemplatesInfo() + templates: repository.getTemplatesInfo(), + streamSymbol: stream }; const setCallbackTimeout = () => { @@ -573,6 +575,9 @@ export default function getComponent(conf: Config, repository: Repository) { Buffer, AbortController: globalThis?.AbortController, AbortSignal: globalThis?.AbortSignal, + Promise, + Date, + Symbol, eval: undefined, fetch: globalThis?.fetch };