react-on-rails-pro-node-renderer 16.4.0-rc.5 → 16.4.0-rc.7
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/README.md +172 -0
- package/lib/shared/licenseValidator.js +2 -2
- package/lib/shared/licenseValidator.js.map +1 -1
- package/lib/shared/utils.d.ts +15 -2
- package/lib/shared/utils.d.ts.map +1 -1
- package/lib/shared/utils.js +33 -8
- package/lib/shared/utils.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/worker/handleRenderRequest.d.ts +3 -1
- package/lib/worker/handleRenderRequest.d.ts.map +1 -1
- package/lib/worker/handleRenderRequest.js +2 -37
- package/lib/worker/handleRenderRequest.js.map +1 -1
- package/lib/worker/vm.d.ts.map +1 -1
- package/lib/worker/vm.js +30 -7
- package/lib/worker/vm.js.map +1 -1
- package/lib/worker.d.ts.map +1 -1
- package/lib/worker.js +3 -5
- package/lib/worker.js.map +1 -1
- package/package.json +3 -3
- package/src/shared/licenseValidator.ts +2 -2
- package/src/shared/utils.ts +39 -8
- package/src/worker/handleRenderRequest.ts +4 -3
- package/src/worker/vm.ts +31 -6
- package/src/worker.ts +3 -5
- package/tests/fixtures/stream-test-bundle.js +3 -0
- package/tests/handleStreamError.test.ts +188 -0
- package/tests/licenseValidator.test.ts +2 -2
- package/tests/streamErrorHang.test.ts +185 -0
- package/tests/vm.test.ts +31 -0
- package/tests/worker.test.ts +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# react-on-rails-pro-node-renderer
|
|
2
|
+
|
|
3
|
+
A high-performance standalone Node.js server for server-side rendering (SSR) of React components in [React on Rails Pro](https://github.com/shakacode/react_on_rails) applications. Built on [Fastify](https://fastify.dev/) with worker pool management.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install react-on-rails-pro-node-renderer
|
|
9
|
+
# or
|
|
10
|
+
yarn add react-on-rails-pro-node-renderer
|
|
11
|
+
# or
|
|
12
|
+
pnpm add react-on-rails-pro-node-renderer
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Prerequisites:** This package is used with the `react_on_rails_pro` Ruby gem and the `react-on-rails-pro` npm package. See the [full installation guide](https://www.shakacode.com/react-on-rails-pro/docs/installation/).
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### 1. Create the Node Renderer entry file
|
|
20
|
+
|
|
21
|
+
Create `node-renderer.js` in your project root:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
const path = require('path');
|
|
25
|
+
const { reactOnRailsProNodeRenderer } = require('react-on-rails-pro-node-renderer');
|
|
26
|
+
|
|
27
|
+
reactOnRailsProNodeRenderer({
|
|
28
|
+
// Directory where the renderer caches uploaded server bundles
|
|
29
|
+
serverBundleCachePath: path.resolve(__dirname, '.node-renderer-bundles'),
|
|
30
|
+
|
|
31
|
+
// Port the renderer listens on (must match Rails config)
|
|
32
|
+
port: Number(process.env.RENDERER_PORT) || 3800,
|
|
33
|
+
|
|
34
|
+
// Enable Node.js globals in the rendering VM context
|
|
35
|
+
supportModules: true,
|
|
36
|
+
|
|
37
|
+
// Log level: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'
|
|
38
|
+
logLevel: process.env.RENDERER_LOG_LEVEL || 'info',
|
|
39
|
+
|
|
40
|
+
// Password for Rails <-> Node renderer authentication (must match Rails config)
|
|
41
|
+
password: process.env.RENDERER_PASSWORD,
|
|
42
|
+
|
|
43
|
+
// Number of worker processes (defaults to CPU count - 1)
|
|
44
|
+
workersCount: Number(process.env.RENDERER_WORKERS_COUNT) || 3,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Configure Rails
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# config/initializers/react_on_rails_pro.rb
|
|
52
|
+
ReactOnRailsPro.configure do |config|
|
|
53
|
+
config.server_renderer = "NodeRenderer"
|
|
54
|
+
config.renderer_url = ENV.fetch("REACT_RENDERER_URL", "http://localhost:3800")
|
|
55
|
+
config.renderer_password = ENV.fetch("RENDERER_PASSWORD", "devPassword")
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. Configure Webpack
|
|
60
|
+
|
|
61
|
+
Set your server bundle webpack configuration to target Node.js:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
// In serverWebpackConfig.js
|
|
65
|
+
serverWebpackConfig.target = 'node';
|
|
66
|
+
|
|
67
|
+
// In output config
|
|
68
|
+
libraryTarget: 'commonjs2',
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 4. Start the renderer
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
node node-renderer.js
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or add to your `Procfile.dev`:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
node-renderer: node node-renderer.js
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Generator (Recommended)
|
|
84
|
+
|
|
85
|
+
The `react_on_rails:install --pro` generator automates all of the above setup:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
bundle add react_on_rails_pro
|
|
89
|
+
rails generate react_on_rails:install --pro
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Configuration Options
|
|
93
|
+
|
|
94
|
+
All options can be set via the config object or environment variables. Config object values take precedence over environment variables.
|
|
95
|
+
|
|
96
|
+
| Option | Env Variable | Default | Description |
|
|
97
|
+
| -------------------------------------- | --------------------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `port` | `RENDERER_PORT` | `3800` | Port the renderer listens on |
|
|
99
|
+
| `logLevel` | `RENDERER_LOG_LEVEL` | `'info'` | Log level (`fatal`, `error`, `warn`, `info`, `debug`, `trace`, `silent`) |
|
|
100
|
+
| `logHttpLevel` | `RENDERER_LOG_HTTP_LEVEL` | `'error'` | HTTP server log level |
|
|
101
|
+
| `serverBundleCachePath` | `RENDERER_SERVER_BUNDLE_CACHE_PATH` | Auto-detected or `/tmp/...` | Directory for cached server bundles |
|
|
102
|
+
| `supportModules` | `RENDERER_SUPPORT_MODULES` | `false` | Enable Node.js globals in VM context (`Buffer`, `process`, `setTimeout`, etc.) |
|
|
103
|
+
| `workersCount` | `RENDERER_WORKERS_COUNT` | CPU count - 1 | Number of worker processes. The `--pro` generator uses `NODE_RENDERER_CONCURRENCY` instead. |
|
|
104
|
+
| `password` | `RENDERER_PASSWORD` | (none) | Shared secret for Rails authentication |
|
|
105
|
+
| `stubTimers` | `RENDERER_STUB_TIMERS` | `true` | Stub timer functions during SSR |
|
|
106
|
+
| `allWorkersRestartInterval` | `RENDERER_ALL_WORKERS_RESTART_INTERVAL` | (disabled) | Minutes between restarting all workers |
|
|
107
|
+
| `delayBetweenIndividualWorkerRestarts` | `RENDERER_DELAY_BETWEEN_INDIVIDUAL_WORKER_RESTARTS` | (disabled) | Minutes between each worker restart |
|
|
108
|
+
| `fastifyServerOptions` | — | `{}` | Additional [Fastify server options](https://fastify.dev/docs/latest/Reference/Server/#factory) |
|
|
109
|
+
|
|
110
|
+
## Advanced: Custom Fastify Configuration
|
|
111
|
+
|
|
112
|
+
For custom routes (e.g., health checks) or plugins, import the master/worker modules directly. The example below uses ES Modules — use a `.mjs` extension, add `"type": "module"` to your `package.json`, or convert to `require()` calls:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import masterRun from 'react-on-rails-pro-node-renderer/master';
|
|
116
|
+
import run, { configureFastify } from 'react-on-rails-pro-node-renderer/worker';
|
|
117
|
+
import cluster from 'cluster';
|
|
118
|
+
|
|
119
|
+
const config = {
|
|
120
|
+
/* your config */
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
configureFastify((app) => {
|
|
124
|
+
app.get('/health', (request, reply) => {
|
|
125
|
+
reply.send({ status: 'ok' });
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (cluster.isPrimary) {
|
|
130
|
+
masterRun(config);
|
|
131
|
+
} else {
|
|
132
|
+
run(config);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Error Reporting
|
|
137
|
+
|
|
138
|
+
Integrate with Sentry or Honeybadger:
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { addNotifier } from 'react-on-rails-pro-node-renderer/integrations/api';
|
|
142
|
+
|
|
143
|
+
addNotifier((error) => {
|
|
144
|
+
Sentry.captureException(error);
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
See [Error Reporting and Tracing docs](https://www.shakacode.com/react-on-rails-pro/docs/node-renderer/error-reporting-and-tracing/).
|
|
149
|
+
|
|
150
|
+
## Documentation
|
|
151
|
+
|
|
152
|
+
- [Node Renderer Basics](https://www.shakacode.com/react-on-rails-pro/docs/node-renderer/basics/)
|
|
153
|
+
- [JavaScript Configuration](https://www.shakacode.com/react-on-rails-pro/docs/node-renderer/js-configuration/)
|
|
154
|
+
- [Rails Configuration](https://www.shakacode.com/react-on-rails-pro/docs/configuration/)
|
|
155
|
+
- [Debugging](https://www.shakacode.com/react-on-rails-pro/docs/node-renderer/debugging/)
|
|
156
|
+
- [Troubleshooting](https://www.shakacode.com/react-on-rails-pro/docs/node-renderer/troubleshooting/)
|
|
157
|
+
|
|
158
|
+
## Package Relationships
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
Rails App
|
|
162
|
+
├── react_on_rails gem (base Rails integration)
|
|
163
|
+
├── react_on_rails_pro gem (Pro server rendering features)
|
|
164
|
+
├── react-on-rails-pro npm (client JS - replaces react-on-rails)
|
|
165
|
+
└── react-on-rails-pro-node-renderer npm (this package - standalone SSR server)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Important:** When using `react_on_rails_pro` gem, you must use `react-on-rails-pro` npm package (not `react-on-rails`).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
Commercial software. No license required for evaluation, development, testing, or CI/CD. A paid license is required for production deployments. Contact [justin@shakacode.com](mailto:justin@shakacode.com) for licensing.
|
|
@@ -109,7 +109,7 @@ function decodeLicense(licenseString) {
|
|
|
109
109
|
*/
|
|
110
110
|
function checkPlan(decodedData) {
|
|
111
111
|
const { plan } = decodedData;
|
|
112
|
-
if (
|
|
112
|
+
if (plan == null) {
|
|
113
113
|
return 'valid'; // No plan field = valid (backwards compat with old paid licenses)
|
|
114
114
|
}
|
|
115
115
|
if (VALID_PLANS.includes(plan)) {
|
|
@@ -244,7 +244,7 @@ function determineLicensePlan() {
|
|
|
244
244
|
return undefined;
|
|
245
245
|
}
|
|
246
246
|
const { plan } = decodedData;
|
|
247
|
-
if (
|
|
247
|
+
if (plan == null || !VALID_PLANS.includes(plan)) {
|
|
248
248
|
return undefined;
|
|
249
249
|
}
|
|
250
250
|
return plan;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"licenseValidator.js","sourceRoot":"","sources":["../../src/shared/licenseValidator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsMA,4CAOC;AA8BD,wDAOC;AA+BD,wCAOC;AAKD,sBAIC;AAjSD,kDAAoC;AACpC,+DAAmD;AAEnD;;;GAGG;AACH,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,CAAU,CAAC;AA6B7F,6DAA6D;AAC7D,EAAE;AACF,iCAAiC;AACjC,0FAA0F;AAC1F,mFAAmF;AACnF,EAAE;AACF,sFAAsF;AACtF,sFAAsF;AACtF,4EAA4E;AAC5E,EAAE;AACF,mFAAmF;AACnF,wFAAwF;AACxF,EAAE;AACF,oFAAoF;AACpF,kFAAkF;AAClF,kFAAkF;AAClF,kEAAkE;AAClE,EAAE;AACF,uFAAuF;AACvF,mFAAmF;AACnF,kFAAkF;AAClF,IAAI,mBAA8C,CAAC;AACnD,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC9C,IAAI,yBAAyB,GAA8C,aAAa,CAAC;AACzF,IAAI,iBAAiB,GAAiD,aAAa,CAAC;AAEpF;;;;GAIG;AACH,SAAS,iBAAiB;IACxB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,EAAE,CAAC;IAClE,yEAAyE;IACzE,wDAAwD;IACxD,OAAO,UAAU,IAAI,SAAS,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,aAAqB;IAC1C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,gCAAU,EAAE;YACpD,4EAA4E;YAC5E,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,yEAAyE;YACzE,gBAAgB,EAAE,IAAI;SACvB,CAAgB,CAAC;QAElB,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,WAAwB;IACzC,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC;IAC7B,IAAI,
|
|
1
|
+
{"version":3,"file":"licenseValidator.js","sourceRoot":"","sources":["../../src/shared/licenseValidator.ts"],"names":[],"mappings":"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"}
|
package/lib/shared/utils.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MultipartFile } from '@fastify/multipart';
|
|
2
2
|
import { MoveOptions, CopyOptions } from 'fs-extra';
|
|
3
|
-
import { Readable, PassThrough } from 'stream';
|
|
3
|
+
import { Readable, Writable, PassThrough } from 'stream';
|
|
4
|
+
import type { TracingContext } from './tracing.js';
|
|
4
5
|
import type { RenderResult } from '../worker/vm.js';
|
|
5
6
|
export declare const TRUNCATION_FILLER = "\n... TRUNCATED ...\n";
|
|
6
7
|
export declare const SHUTDOWN_WORKER_MESSAGE = "NODE_RENDERER_SHUTDOWN_WORKER";
|
|
@@ -14,7 +15,7 @@ export interface ResponseResult {
|
|
|
14
15
|
data?: unknown;
|
|
15
16
|
stream?: Readable;
|
|
16
17
|
}
|
|
17
|
-
export declare function errorResponseResult(msg: string): ResponseResult;
|
|
18
|
+
export declare function errorResponseResult(msg: string, tracingContext?: TracingContext): ResponseResult;
|
|
18
19
|
/**
|
|
19
20
|
* @param renderingRequest The JavaScript code which threw an error
|
|
20
21
|
* @param error The error that was thrown (typed as `unknown` to minimize casts in `catch`)
|
|
@@ -32,6 +33,18 @@ export declare function copyUploadedAsset(asset: Asset, destinationPath: string,
|
|
|
32
33
|
export declare function copyUploadedAssets(uploadedAssets: Asset[], targetDirectory: string): Promise<void>;
|
|
33
34
|
export declare function isPromise<T>(value: T | Promise<T>): value is Promise<T>;
|
|
34
35
|
export declare const isReadableStream: (stream: unknown) => stream is Readable;
|
|
36
|
+
/**
|
|
37
|
+
* Pipes source to destination with proper 'close' event handling.
|
|
38
|
+
*
|
|
39
|
+
* Node.js `pipe()` does NOT end the destination when the source is destroyed —
|
|
40
|
+
* it silently unpipes, leaving the destination open forever. This function fills
|
|
41
|
+
* that gap by listening for the 'close' event (which fires after both normal
|
|
42
|
+
* 'end' and `destroy()`) and ending the destination if needed.
|
|
43
|
+
*
|
|
44
|
+
* An optional `onError` callback provides observability for source stream errors
|
|
45
|
+
* without forwarding them to the destination (which would break the pipe).
|
|
46
|
+
*/
|
|
47
|
+
export declare const safePipe: <T extends Writable>(source: Readable, destination: T, onError?: (err: Error) => void) => T;
|
|
35
48
|
export declare const handleStreamError: (stream: Readable, onError: (error: Error) => void) => PassThrough;
|
|
36
49
|
export declare const isErrorRenderResult: (result: RenderResult) => result is {
|
|
37
50
|
exceptionMessage: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAsC,WAAW,EAAQ,WAAW,EAAE,MAAM,UAAU,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAY,WAAW,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"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"}
|
package/lib/shared/utils.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.delay = exports.majorVersion = exports.isErrorRenderResult = exports.handleStreamError = exports.isReadableStream = exports.SHUTDOWN_WORKER_MESSAGE = exports.TRUNCATION_FILLER = void 0;
|
|
39
|
+
exports.delay = exports.majorVersion = exports.isErrorRenderResult = exports.handleStreamError = exports.safePipe = exports.isReadableStream = exports.SHUTDOWN_WORKER_MESSAGE = exports.TRUNCATION_FILLER = void 0;
|
|
40
40
|
exports.workerIdLabel = workerIdLabel;
|
|
41
41
|
exports.smartTrim = smartTrim;
|
|
42
42
|
exports.errorResponseResult = errorResponseResult;
|
|
@@ -88,8 +88,8 @@ function smartTrim(value, maxLength = (0, configBuilder_js_1.getConfig)().maxDeb
|
|
|
88
88
|
const rstrip = toRemove - lstrip;
|
|
89
89
|
return string.substring(0, midpoint - lstrip) + exports.TRUNCATION_FILLER + string.substring(midpoint + rstrip);
|
|
90
90
|
}
|
|
91
|
-
function errorResponseResult(msg) {
|
|
92
|
-
errorReporter.message(msg);
|
|
91
|
+
function errorResponseResult(msg, tracingContext) {
|
|
92
|
+
errorReporter.message(msg, tracingContext);
|
|
93
93
|
return {
|
|
94
94
|
headers: { 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate' },
|
|
95
95
|
status: 400,
|
|
@@ -140,12 +140,37 @@ const isReadableStream = (stream) => typeof stream === 'object' &&
|
|
|
140
140
|
typeof stream.pipe === 'function' &&
|
|
141
141
|
typeof stream.read === 'function';
|
|
142
142
|
exports.isReadableStream = isReadableStream;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Pipes source to destination with proper 'close' event handling.
|
|
145
|
+
*
|
|
146
|
+
* Node.js `pipe()` does NOT end the destination when the source is destroyed —
|
|
147
|
+
* it silently unpipes, leaving the destination open forever. This function fills
|
|
148
|
+
* that gap by listening for the 'close' event (which fires after both normal
|
|
149
|
+
* 'end' and `destroy()`) and ending the destination if needed.
|
|
150
|
+
*
|
|
151
|
+
* An optional `onError` callback provides observability for source stream errors
|
|
152
|
+
* without forwarding them to the destination (which would break the pipe).
|
|
153
|
+
*/
|
|
154
|
+
const safePipe = (source, destination, onError) => {
|
|
155
|
+
if (onError) {
|
|
156
|
+
// Propagate errors for logging/reporting, but don't terminate — error is not the
|
|
157
|
+
// end of the stream. Non-fatal errors (e.g., emitError for throwJsErrors) emit
|
|
158
|
+
// 'error' without destroying the stream, and React may continue rendering.
|
|
159
|
+
source.on('error', onError);
|
|
160
|
+
}
|
|
161
|
+
// 'close' fires after both normal 'end' and destroy().
|
|
162
|
+
// On normal end, pipe() already forwards 'end' to the destination — this is a no-op.
|
|
163
|
+
// On destroy, pipe() unpipes but does NOT end the destination — we do it here.
|
|
164
|
+
source.once('close', () => {
|
|
165
|
+
if (!destination.writableEnded) {
|
|
166
|
+
destination.end();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
source.pipe(destination);
|
|
170
|
+
return destination;
|
|
148
171
|
};
|
|
172
|
+
exports.safePipe = safePipe;
|
|
173
|
+
const handleStreamError = (stream, onError) => (0, exports.safePipe)(stream, new stream_1.PassThrough(), onError);
|
|
149
174
|
exports.handleStreamError = handleStreamError;
|
|
150
175
|
const isErrorRenderResult = (result) => typeof result === 'object' && !(0, exports.isReadableStream)(result) && 'exceptionMessage' in result;
|
|
151
176
|
exports.isErrorRenderResult = isErrorRenderResult;
|
package/lib/shared/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"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"}
|