@octanejs/rspack-plugin 0.1.4 → 0.1.6
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/package.json +3 -3
- package/src/loader.js +6 -0
- package/src/plugin.js +10 -1
- package/src/shared.js +50 -2
- package/types/index.d.ts +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octanejs/rspack-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@rspack/core": "^2.0.0",
|
|
48
|
-
"octane": "0.1.
|
|
48
|
+
"octane": "0.1.11"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@rspack/core": "^2.1.3",
|
|
52
52
|
"@types/node": "^24.3.0",
|
|
53
53
|
"vitest": "^4.1.9",
|
|
54
|
-
"octane": "0.1.
|
|
54
|
+
"octane": "0.1.11"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"test": "vitest run --config vitest.config.js"
|
package/src/loader.js
CHANGED
|
@@ -104,6 +104,9 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
104
104
|
profile,
|
|
105
105
|
...(options.exclude === undefined ? null : { exclude: options.exclude }),
|
|
106
106
|
...(options.renderers === undefined ? null : { renderers: options.renderers }),
|
|
107
|
+
...(options.universalRuntime === undefined
|
|
108
|
+
? null
|
|
109
|
+
: { universalRuntime: options.universalRuntime }),
|
|
107
110
|
...(options.requireDirective === undefined
|
|
108
111
|
? null
|
|
109
112
|
: { requireDirective: options.requireDirective }),
|
|
@@ -138,6 +141,9 @@ export default function octaneLoader(source, inputSourceMap) {
|
|
|
138
141
|
result.kind === 'compile' &&
|
|
139
142
|
(result.code.includes('_$__serverRpc(') ||
|
|
140
143
|
result.code.includes('export const _$_server_$_')),
|
|
144
|
+
...(result.universalRuntime === undefined
|
|
145
|
+
? null
|
|
146
|
+
: { universalRuntime: result.universalRuntime }),
|
|
141
147
|
...(result.clientReference === undefined
|
|
142
148
|
? null
|
|
143
149
|
: { clientReference: { ...result.clientReference } }),
|
package/src/plugin.js
CHANGED
|
@@ -237,6 +237,8 @@ export class OctaneRspackPlugin {
|
|
|
237
237
|
profile,
|
|
238
238
|
exclude: this.options.exclude ?? [],
|
|
239
239
|
renderers: this.options.renderers?.signature,
|
|
240
|
+
runtime: this.options.runtime,
|
|
241
|
+
universalRuntime: this.options.universalRuntime,
|
|
240
242
|
// Ownership flips which modules compile vs pass through — cached
|
|
241
243
|
// transform results must not survive a requireDirective toggle.
|
|
242
244
|
requireDirective: this.options.requireDirective === true,
|
|
@@ -248,8 +250,12 @@ export class OctaneRspackPlugin {
|
|
|
248
250
|
profile,
|
|
249
251
|
...(this.options.exclude === undefined ? null : { exclude: this.options.exclude }),
|
|
250
252
|
...(this.options.renderers === undefined ? null : { renderers: this.options.renderers }),
|
|
253
|
+
...(this.options.universalRuntime === undefined
|
|
254
|
+
? null
|
|
255
|
+
: { universalRuntime: this.options.universalRuntime }),
|
|
251
256
|
});
|
|
252
|
-
const runtimeRequest =
|
|
257
|
+
const runtimeRequest =
|
|
258
|
+
this.options.runtime ?? neutralCompiler.resolveRuntimeRequest('octane', environment);
|
|
253
259
|
|
|
254
260
|
compiler.options.resolve ??= {};
|
|
255
261
|
addUniqueExtensions(compiler.options.resolve);
|
|
@@ -266,6 +272,9 @@ export class OctaneRspackPlugin {
|
|
|
266
272
|
...(this.options.dev === undefined ? null : { dev: this.options.dev }),
|
|
267
273
|
...(this.options.exclude === undefined ? null : { exclude: this.options.exclude }),
|
|
268
274
|
...(this.options.renderers === undefined ? null : { renderers: this.options.renderers }),
|
|
275
|
+
...(this.options.universalRuntime === undefined
|
|
276
|
+
? null
|
|
277
|
+
: { universalRuntime: this.options.universalRuntime }),
|
|
269
278
|
...(this.options.requireDirective === undefined
|
|
270
279
|
? null
|
|
271
280
|
: { requireDirective: this.options.requireDirective }),
|
package/src/shared.js
CHANGED
|
@@ -43,8 +43,35 @@ const LOADER_OPTION_KEYS = new Set([
|
|
|
43
43
|
'exclude',
|
|
44
44
|
'renderers',
|
|
45
45
|
'requireDirective',
|
|
46
|
+
'universalRuntime',
|
|
46
47
|
]);
|
|
47
|
-
const PLUGIN_OPTION_KEYS = new Set([...LOADER_OPTION_KEYS, 'transpile']);
|
|
48
|
+
const PLUGIN_OPTION_KEYS = new Set([...LOADER_OPTION_KEYS, 'runtime', 'transpile']);
|
|
49
|
+
|
|
50
|
+
function normalizeUniversalRuntime(value) {
|
|
51
|
+
if (value === undefined) return undefined;
|
|
52
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
53
|
+
throw new TypeError('@octanejs/rspack-plugin: `universalRuntime` must be an object.');
|
|
54
|
+
}
|
|
55
|
+
for (const key of Object.keys(value)) {
|
|
56
|
+
if (key !== 'runtime' && key !== 'thread') {
|
|
57
|
+
throw new TypeError(`@octanejs/rspack-plugin: unknown \`universalRuntime.${key}\` option.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (
|
|
61
|
+
typeof value.runtime !== 'string' ||
|
|
62
|
+
!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/.test(value.runtime)
|
|
63
|
+
) {
|
|
64
|
+
throw new TypeError(
|
|
65
|
+
'@octanejs/rspack-plugin: `universalRuntime.runtime` must be a lowercase runtime ID.',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (value.thread !== 'background' && value.thread !== 'main-thread') {
|
|
69
|
+
throw new TypeError(
|
|
70
|
+
'@octanejs/rspack-plugin: `universalRuntime.thread` must be "background" or "main-thread".',
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return Object.freeze({ runtime: value.runtime, thread: value.thread });
|
|
74
|
+
}
|
|
48
75
|
|
|
49
76
|
function assertBooleanOption(options, key) {
|
|
50
77
|
if (options[key] !== undefined && typeof options[key] !== 'boolean') {
|
|
@@ -66,6 +93,17 @@ function normalizeOptions(value, plugin) {
|
|
|
66
93
|
if (options.root !== undefined && typeof options.root !== 'string') {
|
|
67
94
|
throw new TypeError('@octanejs/rspack-plugin: `root` must be a path string.');
|
|
68
95
|
}
|
|
96
|
+
if (
|
|
97
|
+
plugin &&
|
|
98
|
+
options.runtime !== undefined &&
|
|
99
|
+
(typeof options.runtime !== 'string' ||
|
|
100
|
+
options.runtime.trim() !== options.runtime ||
|
|
101
|
+
!options.runtime)
|
|
102
|
+
) {
|
|
103
|
+
throw new TypeError(
|
|
104
|
+
'@octanejs/rspack-plugin: `runtime` must be a non-empty module request string.',
|
|
105
|
+
);
|
|
106
|
+
}
|
|
69
107
|
if (
|
|
70
108
|
options.environment !== undefined &&
|
|
71
109
|
options.environment !== 'client' &&
|
|
@@ -86,6 +124,7 @@ function normalizeOptions(value, plugin) {
|
|
|
86
124
|
if (plugin) assertBooleanOption(options, 'transpile');
|
|
87
125
|
const renderers =
|
|
88
126
|
options.renderers === undefined ? undefined : normalizeRendererConfig(options.renderers);
|
|
127
|
+
const universalRuntime = normalizeUniversalRuntime(options.universalRuntime);
|
|
89
128
|
|
|
90
129
|
const normalized = {
|
|
91
130
|
...(options.root === undefined ? null : { root: options.root }),
|
|
@@ -95,10 +134,12 @@ function normalizeOptions(value, plugin) {
|
|
|
95
134
|
...(options.profile === undefined ? null : { profile: options.profile }),
|
|
96
135
|
...(options.exclude === undefined ? null : { exclude: [...options.exclude] }),
|
|
97
136
|
...(renderers === undefined ? null : { renderers }),
|
|
137
|
+
...(universalRuntime === undefined ? null : { universalRuntime }),
|
|
98
138
|
...(options.requireDirective === undefined
|
|
99
139
|
? null
|
|
100
140
|
: { requireDirective: options.requireDirective }),
|
|
101
141
|
...(plugin && options.transpile !== undefined ? { transpile: options.transpile } : null),
|
|
142
|
+
...(plugin && options.runtime !== undefined ? { runtime: options.runtime } : null),
|
|
102
143
|
};
|
|
103
144
|
if (normalized.exclude) Object.freeze(normalized.exclude);
|
|
104
145
|
return Object.freeze(normalized);
|
|
@@ -121,6 +162,12 @@ export function getOctaneRspackBuildInfo(module) {
|
|
|
121
162
|
typeof value.clientReference.id === 'string' &&
|
|
122
163
|
typeof value.clientReference.moduleId === 'string' &&
|
|
123
164
|
typeof value.clientReference.renderer === 'string';
|
|
165
|
+
const universalRuntimeValid =
|
|
166
|
+
value?.universalRuntime !== null &&
|
|
167
|
+
typeof value?.universalRuntime === 'object' &&
|
|
168
|
+
typeof value.universalRuntime.runtime === 'string' &&
|
|
169
|
+
(value.universalRuntime.thread === 'background' ||
|
|
170
|
+
value.universalRuntime.thread === 'main-thread');
|
|
124
171
|
if (
|
|
125
172
|
value &&
|
|
126
173
|
typeof value === 'object' &&
|
|
@@ -129,7 +176,8 @@ export function getOctaneRspackBuildInfo(module) {
|
|
|
129
176
|
value.transformKind === 'slots' ||
|
|
130
177
|
value.transformKind === 'client-only-stub') &&
|
|
131
178
|
typeof value.serverRpc === 'boolean' &&
|
|
132
|
-
(value.clientReference === undefined || nestedReferenceValid)
|
|
179
|
+
(value.clientReference === undefined || nestedReferenceValid) &&
|
|
180
|
+
(value.universalRuntime === undefined || universalRuntimeValid)
|
|
133
181
|
) {
|
|
134
182
|
return value;
|
|
135
183
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ export interface OctaneRendererRuleOptions {
|
|
|
11
11
|
renderer: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/** @experimental Static source restrictions enforced for a renderer. */
|
|
15
|
+
export interface OctaneRendererValidationOptions {
|
|
16
|
+
/** Host elements that may directly contain authored primitive text. */
|
|
17
|
+
textParents?: readonly string[];
|
|
18
|
+
/** Unbound JavaScript globals that renderer-owned source may not reference. */
|
|
19
|
+
forbiddenGlobals?: readonly string[];
|
|
20
|
+
/** Package IDs whose static imports, subpaths, and CommonJS requires are forbidden. */
|
|
21
|
+
forbiddenImports?: readonly string[];
|
|
22
|
+
/** Allowed static JSX attributes by host name; `*` supplies shared patterns. */
|
|
23
|
+
hostProps?: Readonly<Record<string, readonly string[]>>;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
export type OctaneRendererRegistryEntry =
|
|
15
27
|
| string
|
|
16
28
|
| {
|
|
@@ -20,6 +32,7 @@ export type OctaneRendererRegistryEntry =
|
|
|
20
32
|
intrinsics?: string;
|
|
21
33
|
text?: 'reject' | 'ignore' | 'host';
|
|
22
34
|
capabilities?: readonly string[];
|
|
35
|
+
validation?: OctaneRendererValidationOptions;
|
|
23
36
|
};
|
|
24
37
|
|
|
25
38
|
/** Static metadata for a component prop lowered for another renderer. */
|
|
@@ -51,6 +64,7 @@ export interface OctaneResolvedRendererConfig {
|
|
|
51
64
|
readonly intrinsics?: string;
|
|
52
65
|
readonly text: 'reject' | 'ignore' | 'host';
|
|
53
66
|
readonly capabilities: readonly string[];
|
|
67
|
+
readonly validation?: Readonly<OctaneRendererValidationOptions>;
|
|
54
68
|
}
|
|
55
69
|
>
|
|
56
70
|
>;
|
|
@@ -86,6 +100,11 @@ export interface OctaneRspackLoaderOptions {
|
|
|
86
100
|
exclude?: string[];
|
|
87
101
|
/** @experimental Renderer registry and ordered per-file selection rules. */
|
|
88
102
|
renderers?: OctaneRendererConfigOptions | OctaneResolvedRendererConfig;
|
|
103
|
+
/** Compile-only host runtime/thread identity for a universal renderer graph. */
|
|
104
|
+
universalRuntime?: {
|
|
105
|
+
readonly runtime: string;
|
|
106
|
+
readonly thread: 'background' | 'main-thread';
|
|
107
|
+
};
|
|
89
108
|
/**
|
|
90
109
|
* Mixed-toolchain ownership gate: when `true`, Octane compiles only
|
|
91
110
|
* project modules that declare `'use octane'` in their directive prologue.
|
|
@@ -100,6 +119,12 @@ export interface OctaneRspackLoaderOptions {
|
|
|
100
119
|
}
|
|
101
120
|
|
|
102
121
|
export interface OctaneRspackPluginOptions extends OctaneRspackLoaderOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Override the exact module used for plain `octane` imports in this graph.
|
|
124
|
+
* Universal host integrations use this to share one hook/context runtime
|
|
125
|
+
* between compiled templates and plain TypeScript custom hooks.
|
|
126
|
+
*/
|
|
127
|
+
runtime?: string;
|
|
103
128
|
/**
|
|
104
129
|
* Add Rspack's built-in SWC loader to strip TypeScript after Octane runs.
|
|
105
130
|
* Disable this when another rule already owns TypeScript transpilation.
|
|
@@ -112,6 +137,11 @@ export interface OctaneRspackBuildInfo {
|
|
|
112
137
|
canonicalId: string;
|
|
113
138
|
transformKind: 'compile' | 'slots' | 'client-only-stub';
|
|
114
139
|
serverRpc: boolean;
|
|
140
|
+
/** Universal host runtime/thread identity, when this module was specialized. */
|
|
141
|
+
universalRuntime?: {
|
|
142
|
+
readonly runtime: string;
|
|
143
|
+
readonly thread: 'background' | 'main-thread';
|
|
144
|
+
};
|
|
115
145
|
/** Stable identity shared by the client compile and its inert server stub. */
|
|
116
146
|
clientReference?: {
|
|
117
147
|
readonly id: string;
|