react-streaming
Advanced tools
Comparing version 0.3.3 to 0.3.4
export { renderToStream, disable } from './renderToStream'; | ||
export type { InjectToStream } from './renderToStream/createBuffer'; |
export { createBuffer }; | ||
declare function createBuffer(bufferParams: { | ||
writeChunk: null | ((_chunk: string) => void); | ||
}): { | ||
injectToStream: (chunk: string) => void; | ||
export type { InjectToStream }; | ||
export type { StreamOperations }; | ||
declare type InjectToStream = (chunk: unknown, options?: { | ||
flush?: boolean; | ||
}) => void; | ||
declare type StreamOperations = { | ||
operations: null | { | ||
writeChunk: (chunk: unknown) => void; | ||
flush: null | (() => void); | ||
}; | ||
}; | ||
declare function createBuffer(streamOperations: StreamOperations): { | ||
injectToStream: InjectToStream; | ||
onBeforeWrite: (chunk: unknown) => void; | ||
onBeforeEnd: () => void; | ||
}; |
@@ -6,3 +6,3 @@ "use strict"; | ||
const debug = (0, utils_1.createDebugger)('react-streaming:buffer'); | ||
function createBuffer(bufferParams) { | ||
function createBuffer(streamOperations) { | ||
const buffer = []; | ||
@@ -12,6 +12,8 @@ let state = 'UNSTARTED'; | ||
return { injectToStream, onBeforeWrite, onBeforeEnd }; | ||
function injectToStream(chunk) { | ||
function injectToStream(chunk, options) { | ||
(0, utils_1.assertUsage)(state !== 'ENDED', `Cannot inject following chunk after stream has ended: \`${chunk}\``); | ||
debug('injectToStream:', chunk); | ||
buffer.push(chunk); | ||
if (debug.isEnabled) { | ||
debug('injectToStream()', String(chunk)); | ||
} | ||
buffer.push({ chunk, flush: options === null || options === void 0 ? void 0 : options.flush }); | ||
flushBuffer(); | ||
@@ -30,12 +32,23 @@ } | ||
} | ||
buffer.forEach((chunk) => { | ||
const { writeChunk } = bufferParams; | ||
(0, utils_1.assert)(writeChunk); | ||
writeChunk(chunk); | ||
let flushStream = false; | ||
buffer.forEach((bufferEntry) => { | ||
(0, utils_1.assert)(streamOperations.operations); | ||
const { writeChunk } = streamOperations.operations; | ||
writeChunk(bufferEntry.chunk); | ||
if (bufferEntry.flush) { | ||
flushStream = true; | ||
} | ||
}); | ||
buffer.length = 0; | ||
(0, utils_1.assert)(streamOperations.operations); | ||
if (flushStream && streamOperations.operations.flush !== null) { | ||
streamOperations.operations.flush(); | ||
debug('stream flushed'); | ||
} | ||
} | ||
function onBeforeWrite(chunk) { | ||
state === 'UNSTARTED' && debug('>>> START'); | ||
debug(`react write${!writePermission ? '' : ' (allowed)'}:`, String(chunk)); | ||
if (debug.isEnabled) { | ||
debug(`react write${!writePermission ? '' : ' (allowed)'}`, String(chunk)); | ||
} | ||
state = 'STREAMING'; | ||
@@ -42,0 +55,0 @@ if (writePermission) { |
@@ -11,3 +11,3 @@ /// <reference types="node" /> | ||
streamEnd: Promise<void>; | ||
injectToStream: (chunk: string) => void; | ||
injectToStream: import("./createBuffer").InjectToStream; | ||
}>; |
@@ -11,6 +11,6 @@ "use strict"; | ||
const { pipeForUser, streamEnd } = createPipeForUser(); | ||
const bufferParams = { | ||
writeChunk: null | ||
const streamOperations = { | ||
operations: null | ||
}; | ||
const { injectToStream, onBeforeWrite, onBeforeEnd } = (0, createBuffer_1.createBuffer)(bufferParams); | ||
const { injectToStream, onBeforeWrite, onBeforeEnd } = (0, createBuffer_1.createBuffer)(streamOperations); | ||
return { pipeForUser, streamEnd, injectToStream }; | ||
@@ -46,11 +46,16 @@ function createPipeForUser() { | ||
}); | ||
bufferParams.writeChunk = (chunk) => { | ||
writableFromUser.write(chunk); | ||
}; | ||
writableForReact.flush = () => { | ||
const flush = () => { | ||
if (typeof writableFromUser.flush === 'function') { | ||
; | ||
writableFromUser.flush(); | ||
debug('stream flushed (Node.js Writable)'); | ||
} | ||
}; | ||
streamOperations.operations = { | ||
flush, | ||
writeChunk(chunk) { | ||
writableFromUser.write(chunk); | ||
} | ||
}; | ||
writableForReact.flush = flush; | ||
pipeFromReact(writableForReact); | ||
@@ -57,0 +62,0 @@ }; |
@@ -5,3 +5,3 @@ export { createReadableWrapper }; | ||
streamEnd: Promise<void>; | ||
injectToStream: (chunk: string) => void; | ||
injectToStream: import("./createBuffer").InjectToStream; | ||
}; |
@@ -9,4 +9,4 @@ "use strict"; | ||
function createReadableWrapper(readableFromReact) { | ||
const bufferParams = { | ||
writeChunk: null | ||
const streamOperations = { | ||
operations: null | ||
}; | ||
@@ -24,8 +24,11 @@ let controllerOfUserStream; | ||
}); | ||
const { injectToStream, onBeforeWrite, onBeforeEnd } = (0, createBuffer_1.createBuffer)(bufferParams); | ||
const { injectToStream, onBeforeWrite, onBeforeEnd } = (0, createBuffer_1.createBuffer)(streamOperations); | ||
return { readableForUser, streamEnd, injectToStream }; | ||
async function onReady(onEnded) { | ||
const writeChunk = (bufferParams.writeChunk = (chunk) => { | ||
controllerOfUserStream.enqueue(encodeForWebStream(chunk)); | ||
}); | ||
streamOperations.operations = { | ||
writeChunk(chunk) { | ||
controllerOfUserStream.enqueue(encodeForWebStream(chunk)); | ||
}, | ||
flush: null | ||
}; | ||
const reader = readableFromReact.getReader(); | ||
@@ -46,3 +49,3 @@ while (true) { | ||
onBeforeWrite(value); | ||
writeChunk(value); | ||
streamOperations.operations.writeChunk(value); | ||
} | ||
@@ -49,0 +52,0 @@ // Collect `injectToStream()` calls stuck in an async call |
@@ -10,5 +10,6 @@ export { createDebugger }; | ||
}; | ||
declare function createDebugger(namespace: string, optionsGlobal?: Options): ((...msgs: unknown[]) => void) & { | ||
options: (options: Options) => (...msgs: unknown[]) => void; | ||
declare function createDebugger(namespace: string, optionsGlobal?: Options): ((msg: string, info?: unknown) => void) & { | ||
options: (options: Options) => (msg: string, info?: unknown) => void; | ||
isEnabled: boolean; | ||
}; | ||
declare function isDebugEnabled(namespace: string): boolean | undefined; | ||
declare function isDebugEnabled(namespace: string): boolean; |
@@ -14,11 +14,13 @@ "use strict"; | ||
const debugWithOptions = (options) => { | ||
return (...msgs) => { | ||
return (msg, info) => { | ||
if (!isDebugEnabled(namespace)) | ||
return; | ||
const msgsStr = msgs.map((msg) => strMsg(msg, Object.assign(Object.assign({}, optionsGlobal), options))); | ||
console.log('\x1b[1m%s\x1b[0m', namespace, ...msgsStr); | ||
if (info !== undefined) { | ||
msg += strInfo(info, Object.assign(Object.assign({}, optionsGlobal), options)); | ||
} | ||
console.log('\x1b[1m%s\x1b[0m', namespace, msg); | ||
}; | ||
}; | ||
const debug = (...msgs) => debugWithOptions({})(...msgs); | ||
(0, objectAssign_1.objectAssign)(debug, { options: debugWithOptions }); | ||
const debug = (msg, info) => debugWithOptions({})(msg, info); | ||
(0, objectAssign_1.objectAssign)(debug, { options: debugWithOptions, isEnabled: isDebugEnabled(namespace) }); | ||
return debug; | ||
@@ -28,2 +30,3 @@ } | ||
function isDebugEnabled(namespace) { | ||
var _a; | ||
let DEBUG; | ||
@@ -35,40 +38,64 @@ // - `process` can be undefined in edge workers | ||
} | ||
catch (_a) { } | ||
return DEBUG === null || DEBUG === void 0 ? void 0 : DEBUG.includes(namespace); | ||
catch (_b) { } | ||
return (_a = DEBUG === null || DEBUG === void 0 ? void 0 : DEBUG.includes(namespace)) !== null && _a !== void 0 ? _a : false; | ||
} | ||
exports.isDebugEnabled = isDebugEnabled; | ||
function strMsg(msg, options) { | ||
function strInfo(info, options) { | ||
var _a, _b; | ||
if (typeof msg === 'string') { | ||
return msg; | ||
if (info === undefined) { | ||
return undefined; | ||
} | ||
if (Array.isArray(msg)) { | ||
if (msg.length === 0) { | ||
return (_b = (_a = options.serialization) === null || _a === void 0 ? void 0 : _a.emptyArray) !== null && _b !== void 0 ? _b : '[]'; | ||
let str = '\n'; | ||
if (typeof info === 'string') { | ||
str += info; | ||
} | ||
else if (Array.isArray(info)) { | ||
if (info.length === 0) { | ||
str += (_b = (_a = options.serialization) === null || _a === void 0 ? void 0 : _a.emptyArray) !== null && _b !== void 0 ? _b : '[]'; | ||
} | ||
return '\n' + msg.map((entry) => strEntry(entry)).join('\n'); | ||
else { | ||
str += info.map(strUnknown).join('\n'); | ||
} | ||
} | ||
return strEntry(msg); | ||
} | ||
const padding1 = ' - '; | ||
const padding2 = ' '; | ||
function strEntry(entry) { | ||
return padding1 + (typeof entry === 'string' ? entry : strObj(entry)); | ||
} | ||
function strObj(obj, newLines = false) { | ||
let str; | ||
if (newLines) { | ||
str = JSON.stringify(obj, replacer, 2); | ||
str = str.split('\n').join('\n' + padding2); | ||
} | ||
else { | ||
str = JSON.stringify(obj, replacer, undefined); | ||
str += strUnknown(info); | ||
} | ||
str = pad(str); | ||
return str; | ||
function replacer(_key, value) { | ||
if ((0, isCallable_1.isCallable)(value)) { | ||
return value.toString().split(/\s+/).join(' '); | ||
} | ||
function pad(str) { | ||
const PADDING = ' '; | ||
const WIDTH = process.stdout.columns; | ||
const lines = []; | ||
str.split('\n').forEach((line) => { | ||
if (!WIDTH) { | ||
lines.push(line); | ||
} | ||
return value; | ||
else { | ||
chunk(line, WIDTH - PADDING.length).forEach((chunk) => { | ||
lines.push(chunk); | ||
}); | ||
} | ||
}); | ||
return lines.join('\n' + PADDING); | ||
} | ||
function chunk(str, size) { | ||
if (str.length <= size) { | ||
return [str]; | ||
} | ||
const chunks = str.match(new RegExp('.{1,' + size + '}', 'g')); | ||
(0, assert_1.assert)(chunks); | ||
return chunks; | ||
} | ||
function strUnknown(thing) { | ||
return typeof thing === 'string' ? thing : strObj(thing); | ||
} | ||
function strObj(obj, newLines = false) { | ||
return JSON.stringify(obj, replaceFunctionSerializer, newLines ? 2 : undefined); | ||
} | ||
function replaceFunctionSerializer(_key, value) { | ||
if ((0, isCallable_1.isCallable)(value)) { | ||
return value.toString().split(/\s+/).join(' '); | ||
} | ||
return value; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.projectInfo = void 0; | ||
const PROJECT_VERSION = '0.3.3'; | ||
const PROJECT_VERSION = '0.3.4'; | ||
exports.projectInfo = { | ||
@@ -6,0 +6,0 @@ projectName: 'react-streaming', |
@@ -1,2 +0,2 @@ | ||
const PROJECT_VERSION = '0.3.3'; | ||
const PROJECT_VERSION = '0.3.4'; | ||
export const projectInfo = { | ||
@@ -3,0 +3,0 @@ projectName: 'react-streaming', |
{ | ||
"name": "react-streaming", | ||
"description": "React 18 Streaming. Full-fledged & Easy.", | ||
"version": "0.3.3", | ||
"version": "0.3.4", | ||
"main": "./dist/cjs/server/hooks.js", | ||
@@ -51,3 +51,3 @@ "peerDependencies": { | ||
"react-dom": "18.2.0", | ||
"typescript": "^4.8.2", | ||
"typescript": "^4.8.3", | ||
"vitest": "^0.14.1" | ||
@@ -54,0 +54,0 @@ }, |
@@ -263,3 +263,3 @@ <p align="center"> | ||
`injectToStream(htmlChunk: string)` allows you to inject strings to the current stream. | ||
`injectToStream(chunk: string | Buffer | unknown, options?: { flush?: boolean })` enables you to inject chunks to the current stream. | ||
@@ -292,6 +292,6 @@ There are two ways to access `injectToStream()`: | ||
// Inject JavaScript (e.g. for progressive hydration) | ||
injectToStream('<script type="module" src="/main.js"></script>') | ||
injectToStream('<script type="module" src="/main.js"></script>', { flush: true }) | ||
// Inject CSS (e.g. for CSS-in-JS) | ||
injectToStream('<styles>.some-component { color: blue }</styles>') | ||
injectToStream('<styles>.some-component { color: blue }</styles>', { flush: true }) | ||
@@ -303,1 +303,3 @@ // Pass data to client | ||
For a full example of using `injectToStream()`, have a look at `useAsync()`'s implementation. | ||
If setting `options.flush` to `true`, then the stream will be flushed after `chunk` has been written to the stream. This is only applicable for Node.js streams and only if you are using a compression library that makes a `flush()` method available. For example, [`compression` adds a `res.flush()` method](https://www.npmjs.com/package/compression#resflush). The option is ignored if there isn't a `flush()` method available. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
84687
1751
303