@bleedingdev/modern-js-renderer-octane 3.9.3-ultramodern.7 → 3.9.3-ultramodern.8
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/dist/cjs/entry-server.js +2 -2
- package/dist/cjs/i18n/I18nProvider.js +6 -14
- package/dist/cjs/index.js +4 -4
- package/dist/cjs/manifest.js +2 -2
- package/dist/cjs/plugin/compiler.js +2 -5
- package/dist/cjs/plugin/index.js +1 -1
- package/dist/cjs/plugin/profile.js +11 -10
- package/dist/cjs/router-client.js +1 -1
- package/dist/cjs/router-handler.js +11 -8
- package/dist/cjs/router-server.js +3 -11
- package/dist/cjs/router.js +1 -1
- package/dist/cjs/routes.js +11 -17
- package/dist/cjs/server.js +14 -6
- package/dist/esm/entry-server.mjs +3 -3
- package/dist/esm/i18n/I18nProvider.mjs +7 -15
- package/dist/esm/index.mjs +4 -4
- package/dist/esm/manifest.mjs +2 -2
- package/dist/esm/router-client.mjs +1 -1
- package/dist/esm/router-handler.mjs +11 -8
- package/dist/esm/router-server.mjs +0 -1
- package/dist/esm/router.mjs +2 -2
- package/dist/esm/routes.mjs +11 -17
- package/dist/esm/server.mjs +9 -1
- package/dist/esm-node/manifest.mjs +2 -2
- package/dist/esm-node/plugin/compiler.mjs +2 -5
- package/dist/esm-node/plugin/index.mjs +1 -1
- package/dist/esm-node/plugin/profile.mjs +11 -10
- package/dist/types/index.d.ts +4 -4
- package/dist/types/manifest.d.ts +2 -2
- package/dist/types/router-server.d.ts +0 -2
- package/dist/types/server.d.ts +3 -0
- package/package.json +23 -18
- package/src/entry-server.ts +3 -3
- package/src/i18n/I18nProvider.ts +11 -20
- package/src/index.ts +4 -4
- package/src/manifest.ts +2 -2
- package/src/plugin/compiler.ts +6 -14
- package/src/plugin/index.ts +3 -1
- package/src/plugin/profile.ts +12 -10
- package/src/router-client.ts +1 -1
- package/src/router-handler.ts +11 -8
- package/src/router-server.ts +0 -2
- package/src/router.ts +2 -2
- package/src/routes.ts +28 -26
- package/src/server.ts +16 -1
- package/dist/cjs/router-injection.js +0 -139
- package/dist/esm/router-injection.mjs +0 -101
- package/dist/types/router-injection.d.ts +0 -8
- package/src/router-injection.ts +0 -145
package/dist/esm/server.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { prepareDocument } from "@modern-js/renderer-core/document";
|
|
2
2
|
import { untilAborted } from "@modern-js/renderer-core/session";
|
|
3
|
+
import { transformReadableStreamWithRouter } from "@octanejs/tanstack-router/ssr/server";
|
|
3
4
|
import { createElement, earlySignalBootstrapScript, renderToReadableStream } from "octane/server";
|
|
4
5
|
import { assertNativeHydrationBuildId, assertOctaneIdentity } from "./bootstrap.mjs";
|
|
5
6
|
import { FederationRoot, createFederationScope } from "./federation-context.mjs";
|
|
@@ -174,7 +175,14 @@ async function renderOctaneApplication(input) {
|
|
|
174
175
|
}, {
|
|
175
176
|
highWaterMark: 0
|
|
176
177
|
});
|
|
177
|
-
return session.respond(body
|
|
178
|
+
return session.respond(input.router ? transformReadableStreamWithRouter(input.router, body, {
|
|
179
|
+
signal: session.signal,
|
|
180
|
+
rendererSafePoint: "script-close",
|
|
181
|
+
timeoutMs: input.routerSerializationTimeoutMs,
|
|
182
|
+
onAbort: (reason)=>{
|
|
183
|
+
session.fail(reason);
|
|
184
|
+
}
|
|
185
|
+
}) : body);
|
|
178
186
|
} catch (error) {
|
|
179
187
|
await session.fail(error);
|
|
180
188
|
throw error;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nativeModuleManifestFilename, readRendererIdentity } from "@modern-js/renderer-core/identity";
|
|
2
2
|
import { assertNativeHydrationBuildId, assertOctaneIdentity } from "./bootstrap.mjs";
|
|
3
|
-
const OCTANE_RUNTIME_VERSION = '0.
|
|
4
|
-
const OCTANE_COMPILER_VERSION = '0.
|
|
3
|
+
const OCTANE_RUNTIME_VERSION = '0.13.8';
|
|
4
|
+
const OCTANE_COMPILER_VERSION = '0.2.4';
|
|
5
5
|
function octaneModuleManifestFileName(entryName) {
|
|
6
6
|
return nativeModuleManifestFilename('octane', entryName);
|
|
7
7
|
}
|
|
@@ -20,7 +20,8 @@ function createOctaneCompilerPlugin(options) {
|
|
|
20
20
|
const directory = pluginSourceDirectory();
|
|
21
21
|
const require = createRequire(node_path.join(directory, 'index.cjs'));
|
|
22
22
|
const { OctaneCompilerManifestPlugin } = require('./compiler-manifest.cjs');
|
|
23
|
-
const
|
|
23
|
+
const appRequire = createRequire(node_path.join(api.context.rootPath, 'package.json'));
|
|
24
|
+
const { inferRspackEnvironment, OctaneRspackPlugin } = appRequire('@octanejs/rspack-plugin');
|
|
24
25
|
api.modifyRsbuildConfig((config, { mergeRsbuildConfig })=>mergeRsbuildConfig(config, {
|
|
25
26
|
source: {
|
|
26
27
|
include: [
|
|
@@ -30,10 +31,6 @@ function createOctaneCompilerPlugin(options) {
|
|
|
30
31
|
}));
|
|
31
32
|
api.modifyRspackConfig((config, { environment: rsbuildEnvironment })=>{
|
|
32
33
|
const environment = rsbuildEnvironment.name === options.workerEnvironmentName ? 'server' : inferRspackEnvironment(config.target);
|
|
33
|
-
config.resolve ??= {};
|
|
34
|
-
const extensions = (config.resolve.extensions ?? []).filter((extension)=>'.tsrx' !== extension);
|
|
35
|
-
extensions.splice(Math.max(extensions.indexOf('.ts'), extensions.indexOf('.tsx')) + 1, 0, '.tsrx');
|
|
36
|
-
config.resolve.extensions = extensions;
|
|
37
34
|
config.plugins ??= [];
|
|
38
35
|
config.plugins.push(new OctaneRspackPlugin({
|
|
39
36
|
root: api.context.rootPath,
|
|
@@ -86,7 +86,7 @@ const rendererAdapter = defineRendererAdapter({
|
|
|
86
86
|
],
|
|
87
87
|
dependencies: nativeRendererDependencies(profile),
|
|
88
88
|
devDependencies: {
|
|
89
|
-
[profile.compiler.name]: profile.compiler.version,
|
|
89
|
+
[profile.compiler.name]: profile.dependencies[profile.compiler.name] ?? profile.compiler.version,
|
|
90
90
|
typescript: typescriptVersion
|
|
91
91
|
},
|
|
92
92
|
typecheckCommand: 'octane-tsc --noEmit --project tsconfig.json',
|
|
@@ -2,7 +2,7 @@ const octaneProfile = {
|
|
|
2
2
|
renderer: 'octane',
|
|
3
3
|
status: 'preview',
|
|
4
4
|
protocolVersion: 1,
|
|
5
|
-
minimumNode: '26.
|
|
5
|
+
minimumNode: '26.12.0',
|
|
6
6
|
hmr: {
|
|
7
7
|
editedBoundary: 'may-reset',
|
|
8
8
|
unaffectedComponents: 'preserved',
|
|
@@ -12,17 +12,17 @@ const octaneProfile = {
|
|
|
12
12
|
},
|
|
13
13
|
compiler: {
|
|
14
14
|
name: '@octanejs/rspack-plugin',
|
|
15
|
-
version: '0.
|
|
15
|
+
version: '0.2.4'
|
|
16
16
|
},
|
|
17
17
|
hydration: {
|
|
18
18
|
name: 'octane',
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.13.8'
|
|
20
20
|
},
|
|
21
21
|
router: {
|
|
22
22
|
name: '@octanejs/tanstack-router',
|
|
23
|
-
version: '0.
|
|
23
|
+
version: '0.2.10',
|
|
24
24
|
coreName: '@tanstack/router-core',
|
|
25
|
-
coreVersion: '1.171.
|
|
25
|
+
coreVersion: '1.171.34'
|
|
26
26
|
},
|
|
27
27
|
sourceExtensions: [
|
|
28
28
|
'.tsx',
|
|
@@ -32,12 +32,13 @@ const octaneProfile = {
|
|
|
32
32
|
],
|
|
33
33
|
jsxImportSource: 'octane',
|
|
34
34
|
dependencies: {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
'@octanejs/
|
|
35
|
+
'@tsrx/oxc': '0.20.0',
|
|
36
|
+
octane: 'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octane-0.13.8.tgz',
|
|
37
|
+
'@octanejs/tanstack-router': 'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-tanstack-router-0.2.10.tgz',
|
|
38
|
+
'@octanejs/rspack-plugin': 'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-rspack-plugin-0.2.4.tgz',
|
|
38
39
|
'@modern-js/renderer-octane': '3.8.3',
|
|
39
|
-
seroval: '1.6.
|
|
40
|
-
'seroval-plugins': '1.6.
|
|
40
|
+
seroval: '1.6.9',
|
|
41
|
+
'seroval-plugins': '1.6.9'
|
|
41
42
|
},
|
|
42
43
|
capabilities: {
|
|
43
44
|
worker: true,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export type { RendererIdentity } from '@modern-js/renderer-core/identity';
|
|
|
2
2
|
export type { OctaneDocumentBootstrap } from './bootstrap';
|
|
3
3
|
export declare const OCTANE_RUNTIME_PROFILE: Readonly<{
|
|
4
4
|
renderer: "octane";
|
|
5
|
-
runtime: "0.
|
|
6
|
-
router: "0.
|
|
7
|
-
routerCore: "1.171.
|
|
8
|
-
history: "1.162.
|
|
5
|
+
runtime: "0.13.8";
|
|
6
|
+
router: "0.2.10";
|
|
7
|
+
routerCore: "1.171.34";
|
|
8
|
+
history: "1.162.4";
|
|
9
9
|
}>;
|
package/dist/types/manifest.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NativeCompilerArtifacts } from '@modern-js/renderer-core/adapter';
|
|
2
2
|
import { type RendererIdentity } from '@modern-js/renderer-core/identity';
|
|
3
|
-
export declare const OCTANE_RUNTIME_VERSION = "0.
|
|
4
|
-
export declare const OCTANE_COMPILER_VERSION = "0.
|
|
3
|
+
export declare const OCTANE_RUNTIME_VERSION = "0.13.8";
|
|
4
|
+
export declare const OCTANE_COMPILER_VERSION = "0.2.4";
|
|
5
5
|
export interface OctaneCompiledSource {
|
|
6
6
|
readonly resource: string;
|
|
7
7
|
readonly canonicalId: string;
|
|
@@ -3,8 +3,6 @@ import { type ServerRenderNode } from 'octane/server';
|
|
|
3
3
|
export * from '@octanejs/tanstack-router/ssr/server';
|
|
4
4
|
export type { OctaneRequestHandlerOptions } from './router-handler';
|
|
5
5
|
export { createOctaneRequestHandler } from './router-handler';
|
|
6
|
-
export type { OctaneRouterInjectionOptions } from './router-injection';
|
|
7
|
-
export { createOctaneRouterInjection } from './router-injection';
|
|
8
6
|
export type { OctaneRouterSerializationGuard, OctaneRouterSerializationOptions, } from './router-server-snapshot';
|
|
9
7
|
export { prepareOctaneRouterSerialization } from './router-server-snapshot';
|
|
10
8
|
/** Render the native provider using the released Start server root contract. */
|
package/dist/types/server.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type DocumentAsset, type DocumentInlineData } from '@modern-js/renderer-core/document';
|
|
2
2
|
import type { NativeFederationBinding } from '@modern-js/renderer-core/federation';
|
|
3
3
|
import { type RequestSession, type ResponsePolicy } from '@modern-js/renderer-core/session';
|
|
4
|
+
import type { AnyRouter } from '@octanejs/tanstack-router';
|
|
4
5
|
import { type ServerRenderNode, type StreamOptions } from 'octane/server';
|
|
5
6
|
export interface OctaneDocumentOptions {
|
|
6
7
|
/** One identity for this response, shared with the client's signal receiver. */
|
|
@@ -27,6 +28,8 @@ export interface RenderOctaneApplicationOptions<Bindings extends object = object
|
|
|
27
28
|
readonly props?: unknown;
|
|
28
29
|
/** Native router serialization, owned by this request's router SSR context. */
|
|
29
30
|
readonly injection?: StreamOptions['injection'];
|
|
31
|
+
readonly router?: AnyRouter;
|
|
32
|
+
readonly routerSerializationTimeoutMs?: number;
|
|
30
33
|
/** This server compilation's native Module Federation runtime. */
|
|
31
34
|
readonly federation?: NativeFederationBinding;
|
|
32
35
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bleedingdev/modern-js-renderer-octane",
|
|
3
|
-
"version": "3.9.3-ultramodern.
|
|
3
|
+
"version": "3.9.3-ultramodern.8",
|
|
4
4
|
"description": "UltraModern native Octane application adapter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -149,23 +149,24 @@
|
|
|
149
149
|
"octane-tsc": "bin/octane-tsc.mjs"
|
|
150
150
|
},
|
|
151
151
|
"engines": {
|
|
152
|
-
"node": ">=26.
|
|
152
|
+
"node": ">=26.12.0"
|
|
153
153
|
},
|
|
154
154
|
"dependencies": {
|
|
155
|
-
"@modern-js/renderer-core": "npm:@bleedingdev/modern-js-renderer-core@3.9.3-ultramodern.
|
|
155
|
+
"@modern-js/renderer-core": "npm:@bleedingdev/modern-js-renderer-core@3.9.3-ultramodern.8",
|
|
156
156
|
"@volar/language-core": "2.4.28",
|
|
157
157
|
"jsonc-parser": "3.3.1",
|
|
158
|
-
"seroval": "1.6.
|
|
159
|
-
"seroval-plugins": "1.6.
|
|
158
|
+
"seroval": "1.6.9",
|
|
159
|
+
"seroval-plugins": "1.6.9",
|
|
160
160
|
"typescript": "7.0.2"
|
|
161
161
|
},
|
|
162
162
|
"peerDependencies": {
|
|
163
|
-
"@modern-js/i18n-runtime-extensions": "3.9.3-ultramodern.
|
|
164
|
-
"@octanejs/rspack-plugin": "0.
|
|
165
|
-
"@octanejs/tanstack-router": "0.
|
|
166
|
-
"@rsbuild/core": "2.2.
|
|
163
|
+
"@modern-js/i18n-runtime-extensions": "3.9.3-ultramodern.8",
|
|
164
|
+
"@octanejs/rspack-plugin": "0.2.4",
|
|
165
|
+
"@octanejs/tanstack-router": "0.2.10",
|
|
166
|
+
"@rsbuild/core": "2.2.13",
|
|
167
|
+
"@tsrx/oxc": "0.20.0",
|
|
167
168
|
"i18next": ">=25.7.4",
|
|
168
|
-
"octane": "0.
|
|
169
|
+
"octane": "0.13.8"
|
|
169
170
|
},
|
|
170
171
|
"peerDependenciesMeta": {
|
|
171
172
|
"@modern-js/i18n-runtime-extensions": {
|
|
@@ -180,6 +181,9 @@
|
|
|
180
181
|
"@rsbuild/core": {
|
|
181
182
|
"optional": true
|
|
182
183
|
},
|
|
184
|
+
"@tsrx/oxc": {
|
|
185
|
+
"optional": true
|
|
186
|
+
},
|
|
183
187
|
"i18next": {
|
|
184
188
|
"optional": true
|
|
185
189
|
},
|
|
@@ -188,16 +192,17 @@
|
|
|
188
192
|
}
|
|
189
193
|
},
|
|
190
194
|
"devDependencies": {
|
|
191
|
-
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.3-ultramodern.
|
|
192
|
-
"@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.3-ultramodern.
|
|
193
|
-
"@octanejs/rspack-plugin": "0.
|
|
194
|
-
"@octanejs/tanstack-router": "https://github.com/
|
|
195
|
-
"@rsbuild/core": "2.2.
|
|
195
|
+
"@modern-js/i18n-runtime-extensions": "npm:@bleedingdev/modern-js-i18n-runtime-extensions@3.9.3-ultramodern.8",
|
|
196
|
+
"@modern-js/tsconfig": "npm:@bleedingdev/modern-js-tsconfig@3.9.3-ultramodern.8",
|
|
197
|
+
"@octanejs/rspack-plugin": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-rspack-plugin-0.2.4.tgz",
|
|
198
|
+
"@octanejs/tanstack-router": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-tanstack-router-0.2.10.tgz",
|
|
199
|
+
"@rsbuild/core": "2.2.13",
|
|
196
200
|
"@rslib/core": "1.0.3",
|
|
197
201
|
"@scripts/rstest-config": "2.66.0",
|
|
198
|
-
"@
|
|
199
|
-
"
|
|
200
|
-
"
|
|
202
|
+
"@tsrx/oxc": "0.20.0",
|
|
203
|
+
"@types/node": "^26.6.5",
|
|
204
|
+
"happy-dom": "^21.0.3",
|
|
205
|
+
"octane": "https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octane-0.13.8.tgz",
|
|
201
206
|
"typescript": "7.0.2"
|
|
202
207
|
},
|
|
203
208
|
"sideEffects": false,
|
package/src/entry-server.ts
CHANGED
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
import { validateOctaneModuleManifest } from './manifest';
|
|
24
24
|
import {
|
|
25
25
|
createOctaneRequestHandler,
|
|
26
|
-
createOctaneRouterInjection,
|
|
27
26
|
createSsrStreamResponse,
|
|
27
|
+
getSsrStatus,
|
|
28
28
|
OctaneRouterServer,
|
|
29
29
|
} from './router-server';
|
|
30
30
|
import { renderOctaneApplication, renderOctaneCSRDocument } from './server';
|
|
@@ -100,7 +100,7 @@ export function createNativeServerEntry(
|
|
|
100
100
|
serialization: { forbiddenValues },
|
|
101
101
|
})(async ({ router, responseHeaders }) => {
|
|
102
102
|
const metadata = mergeDataResponseMetadata(outcomes, {
|
|
103
|
-
status: router
|
|
103
|
+
status: getSsrStatus(router),
|
|
104
104
|
});
|
|
105
105
|
// Route headers() take precedence over loader singleton fields; list
|
|
106
106
|
// fields keep both.
|
|
@@ -127,7 +127,7 @@ export function createNativeServerEntry(
|
|
|
127
127
|
}),
|
|
128
128
|
document,
|
|
129
129
|
federation: options.federation,
|
|
130
|
-
|
|
130
|
+
router,
|
|
131
131
|
});
|
|
132
132
|
return createSsrStreamResponse(router, rendered);
|
|
133
133
|
});
|
package/src/i18n/I18nProvider.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createElement, hookSlots,
|
|
1
|
+
import { createElement, hookSlots, useSyncExternalStore } from 'octane';
|
|
2
2
|
import { I18nContext } from './context';
|
|
3
|
-
import type { I18nContextValue
|
|
3
|
+
import type { I18nContextValue } from './types';
|
|
4
4
|
|
|
5
5
|
export interface I18nProviderProps extends Omit<I18nContextValue, 'language'> {
|
|
6
6
|
children?: unknown;
|
|
@@ -22,27 +22,18 @@ export interface I18nProviderProps extends Omit<I18nContextValue, 'language'> {
|
|
|
22
22
|
*/
|
|
23
23
|
// Plain TypeScript is not rewritten by the Octane compiler, so each hook call
|
|
24
24
|
// site carries its own stable slot, like `OctaneRouterRoot`.
|
|
25
|
-
const
|
|
26
|
-
const languageSubscriptionSlot = Symbol(hookSlots(1));
|
|
25
|
+
const languageStoreSlot = Symbol(hookSlots(1));
|
|
27
26
|
|
|
28
27
|
export function I18nProvider(props: I18nProviderProps) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
useEffect(
|
|
35
|
-
() => {
|
|
36
|
-
const instance: I18nInstanceLike = props.instance;
|
|
37
|
-
setLanguage(instance.language);
|
|
38
|
-
const handleLanguageChanged = (lng: string) => setLanguage(lng);
|
|
39
|
-
instance.on?.('languageChanged', handleLanguageChanged);
|
|
40
|
-
return () => {
|
|
41
|
-
instance.off?.('languageChanged', handleLanguageChanged);
|
|
42
|
-
};
|
|
28
|
+
const instance = props.instance;
|
|
29
|
+
const language = useSyncExternalStore(
|
|
30
|
+
notify => {
|
|
31
|
+
instance.on?.('languageChanged', notify);
|
|
32
|
+
return () => instance.off?.('languageChanged', notify);
|
|
43
33
|
},
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
() => instance.language,
|
|
35
|
+
() => instance.language,
|
|
36
|
+
languageStoreSlot,
|
|
46
37
|
);
|
|
47
38
|
|
|
48
39
|
const value: I18nContextValue = {
|
package/src/index.ts
CHANGED
|
@@ -3,8 +3,8 @@ export type { OctaneDocumentBootstrap } from './bootstrap';
|
|
|
3
3
|
|
|
4
4
|
export const OCTANE_RUNTIME_PROFILE = Object.freeze({
|
|
5
5
|
renderer: 'octane',
|
|
6
|
-
runtime: '0.
|
|
7
|
-
router: '0.
|
|
8
|
-
routerCore: '1.171.
|
|
9
|
-
history: '1.162.
|
|
6
|
+
runtime: '0.13.8',
|
|
7
|
+
router: '0.2.10',
|
|
8
|
+
routerCore: '1.171.34',
|
|
9
|
+
history: '1.162.4',
|
|
10
10
|
});
|
package/src/manifest.ts
CHANGED
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
assertOctaneIdentity,
|
|
10
10
|
} from './bootstrap';
|
|
11
11
|
|
|
12
|
-
export const OCTANE_RUNTIME_VERSION = '0.
|
|
13
|
-
export const OCTANE_COMPILER_VERSION = '0.
|
|
12
|
+
export const OCTANE_RUNTIME_VERSION = '0.13.8';
|
|
13
|
+
export const OCTANE_COMPILER_VERSION = '0.2.4';
|
|
14
14
|
|
|
15
15
|
export interface OctaneCompiledSource {
|
|
16
16
|
readonly resource: string;
|
package/src/plugin/compiler.ts
CHANGED
|
@@ -41,10 +41,15 @@ export function createOctaneCompilerPlugin(
|
|
|
41
41
|
} = require('./compiler-manifest.cjs');
|
|
42
42
|
// The application installs the Octane compiler; resolve it lazily so
|
|
43
43
|
// descriptor readers never load it.
|
|
44
|
+
const appRequire = createRequire(
|
|
45
|
+
path.join(api.context.rootPath, 'package.json'),
|
|
46
|
+
);
|
|
44
47
|
const {
|
|
45
48
|
inferRspackEnvironment,
|
|
46
49
|
OctaneRspackPlugin,
|
|
47
|
-
}: typeof import('@octanejs/rspack-plugin') =
|
|
50
|
+
}: typeof import('@octanejs/rspack-plugin') = appRequire(
|
|
51
|
+
'@octanejs/rspack-plugin',
|
|
52
|
+
);
|
|
48
53
|
api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) =>
|
|
49
54
|
mergeRsbuildConfig(config, {
|
|
50
55
|
source: {
|
|
@@ -60,19 +65,6 @@ export function createOctaneCompilerPlugin(
|
|
|
60
65
|
rsbuildEnvironment.name === options.workerEnvironmentName
|
|
61
66
|
? 'server'
|
|
62
67
|
: inferRspackEnvironment(config.target);
|
|
63
|
-
// Octane prepends '.tsrx' only when it is absent. Keep TypeScript
|
|
64
|
-
// modules first so an extensionless './link' cannot select a
|
|
65
|
-
// case-colliding Link.tsrx on case-insensitive file systems.
|
|
66
|
-
config.resolve ??= {};
|
|
67
|
-
const extensions = (config.resolve.extensions ?? []).filter(
|
|
68
|
-
extension => extension !== '.tsrx',
|
|
69
|
-
);
|
|
70
|
-
extensions.splice(
|
|
71
|
-
Math.max(extensions.indexOf('.ts'), extensions.indexOf('.tsx')) + 1,
|
|
72
|
-
0,
|
|
73
|
-
'.tsrx',
|
|
74
|
-
);
|
|
75
|
-
config.resolve.extensions = extensions;
|
|
76
68
|
config.plugins ??= [];
|
|
77
69
|
config.plugins.push(
|
|
78
70
|
new OctaneRspackPlugin({
|
package/src/plugin/index.ts
CHANGED
|
@@ -89,7 +89,9 @@ export const rendererAdapter: NativeRendererAdapter<'octane'> =
|
|
|
89
89
|
],
|
|
90
90
|
dependencies: nativeRendererDependencies(profile),
|
|
91
91
|
devDependencies: {
|
|
92
|
-
[profile.compiler.name]:
|
|
92
|
+
[profile.compiler.name]:
|
|
93
|
+
profile.dependencies[profile.compiler.name] ??
|
|
94
|
+
profile.compiler.version,
|
|
93
95
|
typescript: typescriptVersion,
|
|
94
96
|
},
|
|
95
97
|
typecheckCommand: 'octane-tsc --noEmit --project tsconfig.json',
|
package/src/plugin/profile.ts
CHANGED
|
@@ -4,7 +4,7 @@ export const octaneProfile: RendererBuildProfile<'octane'> = {
|
|
|
4
4
|
renderer: 'octane',
|
|
5
5
|
status: 'preview',
|
|
6
6
|
protocolVersion: 1,
|
|
7
|
-
minimumNode: '26.
|
|
7
|
+
minimumNode: '26.12.0',
|
|
8
8
|
hmr: {
|
|
9
9
|
editedBoundary: 'may-reset',
|
|
10
10
|
unaffectedComponents: 'preserved',
|
|
@@ -12,28 +12,30 @@ export const octaneProfile: RendererBuildProfile<'octane'> = {
|
|
|
12
12
|
roots: 'single',
|
|
13
13
|
cleanup: 'exactly-once',
|
|
14
14
|
},
|
|
15
|
-
compiler: { name: '@octanejs/rspack-plugin', version: '0.
|
|
15
|
+
compiler: { name: '@octanejs/rspack-plugin', version: '0.2.4' },
|
|
16
16
|
hydration: {
|
|
17
17
|
name: 'octane',
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.13.8',
|
|
19
19
|
},
|
|
20
20
|
router: {
|
|
21
21
|
name: '@octanejs/tanstack-router',
|
|
22
|
-
version: '0.
|
|
22
|
+
version: '0.2.10',
|
|
23
23
|
coreName: '@tanstack/router-core',
|
|
24
|
-
coreVersion: '1.171.
|
|
24
|
+
coreVersion: '1.171.34',
|
|
25
25
|
},
|
|
26
26
|
sourceExtensions: ['.tsx', '.tsrx', '.ts', '.js'],
|
|
27
27
|
jsxImportSource: 'octane',
|
|
28
28
|
dependencies: {
|
|
29
|
+
'@tsrx/oxc': '0.20.0',
|
|
29
30
|
octane:
|
|
30
|
-
'https://github.com/
|
|
31
|
+
'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octane-0.13.8.tgz',
|
|
31
32
|
'@octanejs/tanstack-router':
|
|
32
|
-
'https://github.com/
|
|
33
|
-
'@octanejs/rspack-plugin':
|
|
33
|
+
'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-tanstack-router-0.2.10.tgz',
|
|
34
|
+
'@octanejs/rspack-plugin':
|
|
35
|
+
'https://github.com/BleedingDev/octane/releases/download/ultramodern-octane-d5988dd93614/octanejs-rspack-plugin-0.2.4.tgz',
|
|
34
36
|
'@modern-js/renderer-octane': '3.8.3',
|
|
35
|
-
seroval: '1.6.
|
|
36
|
-
'seroval-plugins': '1.6.
|
|
37
|
+
seroval: '1.6.9',
|
|
38
|
+
'seroval-plugins': '1.6.9',
|
|
37
39
|
},
|
|
38
40
|
capabilities: {
|
|
39
41
|
worker: true,
|
package/src/router-client.ts
CHANGED
|
@@ -64,7 +64,7 @@ function waitForCommittedMatches(
|
|
|
64
64
|
signal?: AbortSignal,
|
|
65
65
|
): Promise<void> {
|
|
66
66
|
signal?.throwIfAborted();
|
|
67
|
-
const matchesId = router.stores.
|
|
67
|
+
const matchesId = router.stores.ids;
|
|
68
68
|
if (matchesId.get().length > 0) return Promise.resolve();
|
|
69
69
|
if (!isReactiveMatchIds(matchesId)) {
|
|
70
70
|
throw new Error(
|
package/src/router-handler.ts
CHANGED
|
@@ -91,8 +91,9 @@ function requestHeaders(router: AnyRouter): Headers {
|
|
|
91
91
|
);
|
|
92
92
|
appendHeaders(headers, field?.value);
|
|
93
93
|
}
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
94
|
+
const result = router._serverResult;
|
|
95
|
+
if (result?.type === 'redirect')
|
|
96
|
+
appendHeaders(headers, result.redirect.headers);
|
|
96
97
|
return headers;
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -117,7 +118,6 @@ export function createOctaneRequestHandler<TRouter extends AnyRouter>({
|
|
|
117
118
|
...serialization,
|
|
118
119
|
forbiddenValues: [request, ...(serialization?.forbiddenValues ?? [])],
|
|
119
120
|
});
|
|
120
|
-
session.registerCleanup(() => router.cancelMatches());
|
|
121
121
|
|
|
122
122
|
const { url } = getNormalizedURL(request.url, 'http://localhost');
|
|
123
123
|
const href = url.href.replace(url.origin, '');
|
|
@@ -126,14 +126,14 @@ export function createOctaneRequestHandler<TRouter extends AnyRouter>({
|
|
|
126
126
|
history: createMemoryHistory({ initialEntries: [href] }),
|
|
127
127
|
origin: router.options.origin ?? getOrigin(request),
|
|
128
128
|
});
|
|
129
|
-
await withAbort(router.load(), session.signal);
|
|
129
|
+
await withAbort(router.load({ _signal: session.signal }), session.signal);
|
|
130
130
|
guard.assertActive();
|
|
131
131
|
|
|
132
132
|
// A native redirect is a terminal HTTP Response. It must never enter
|
|
133
133
|
// the public serializer as a match error or document payload.
|
|
134
|
-
const
|
|
135
|
-
if (redirect) {
|
|
136
|
-
const resolved =
|
|
134
|
+
const loadResult = router._serverResult;
|
|
135
|
+
if (loadResult?.type === 'redirect') {
|
|
136
|
+
const resolved = loadResult.redirect;
|
|
137
137
|
const headers = requestHeaders(router);
|
|
138
138
|
return new Response(null, {
|
|
139
139
|
status: resolved.status,
|
|
@@ -146,7 +146,10 @@ export function createOctaneRequestHandler<TRouter extends AnyRouter>({
|
|
|
146
146
|
const serverSsr = router.serverSsr;
|
|
147
147
|
if (!serverSsr)
|
|
148
148
|
throw new Error('Native Octane router SSR state is required');
|
|
149
|
-
await withAbort(
|
|
149
|
+
await withAbort(
|
|
150
|
+
serverSsr.dehydrate({ signal: session.signal }),
|
|
151
|
+
session.signal,
|
|
152
|
+
);
|
|
150
153
|
guard.assertActive();
|
|
151
154
|
const responseHeaders = requestHeaders(router);
|
|
152
155
|
// A callback that ignores cancellation must not hold the router SSR
|
package/src/router-server.ts
CHANGED
|
@@ -5,8 +5,6 @@ import { createElement, type ServerRenderNode } from 'octane/server';
|
|
|
5
5
|
export * from '@octanejs/tanstack-router/ssr/server';
|
|
6
6
|
export type { OctaneRequestHandlerOptions } from './router-handler';
|
|
7
7
|
export { createOctaneRequestHandler } from './router-handler';
|
|
8
|
-
export type { OctaneRouterInjectionOptions } from './router-injection';
|
|
9
|
-
export { createOctaneRouterInjection } from './router-injection';
|
|
10
8
|
export type {
|
|
11
9
|
OctaneRouterSerializationGuard,
|
|
12
10
|
OctaneRouterSerializationOptions,
|
package/src/router.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
useMatch,
|
|
10
10
|
useRouter,
|
|
11
11
|
} from '@octanejs/tanstack-router';
|
|
12
|
-
import { createSubSlot, useCallback,
|
|
12
|
+
import { createSubSlot, useCallback, useLayoutEffect, useRef } from 'octane';
|
|
13
13
|
import { assertOctaneIdentity } from './bootstrap';
|
|
14
14
|
import { resolveRouteData } from './routes';
|
|
15
15
|
|
|
@@ -161,7 +161,7 @@ export function useOctaneRouteAction(...args: unknown[]) {
|
|
|
161
161
|
const identity = useApplicationIdentity();
|
|
162
162
|
const routeId = useApplicationRouteId();
|
|
163
163
|
const owner = useRef<AbortController | null>(null, actionSlot(slot, 'owner'));
|
|
164
|
-
|
|
164
|
+
useLayoutEffect(
|
|
165
165
|
() => {
|
|
166
166
|
const controller = new AbortController();
|
|
167
167
|
owner.current = controller;
|
package/src/routes.ts
CHANGED
|
@@ -59,7 +59,7 @@ export function resolveRouteData(
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
interface ReactiveNativeMatch {
|
|
62
|
-
get(): AnyRouteMatch;
|
|
62
|
+
get(): AnyRouteMatch | undefined;
|
|
63
63
|
subscribe(callback: () => void): { unsubscribe(): void };
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -75,24 +75,18 @@ function isReactiveNativeMatch(value: unknown): value is ReactiveNativeMatch {
|
|
|
75
75
|
/** A transport failure belongs to the native generation that fetched it. */
|
|
76
76
|
function observeRouteCompletion(
|
|
77
77
|
router: AnyRouter,
|
|
78
|
+
routeId: string,
|
|
78
79
|
controller: AbortController,
|
|
79
80
|
signal: AbortSignal,
|
|
80
81
|
completion: Promise<void>,
|
|
81
82
|
) {
|
|
82
83
|
void completion.catch(error => {
|
|
83
84
|
if (signal.aborted) return;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (!match) return;
|
|
90
|
-
const store = [
|
|
91
|
-
router.stores.pendingMatchStores.get(match.id),
|
|
92
|
-
router.stores.matchStores.get(match.id),
|
|
93
|
-
router.stores.cachedMatchStores.get(match.id),
|
|
94
|
-
].find(candidate => candidate?.get().abortController === controller);
|
|
95
|
-
if (!store) return;
|
|
85
|
+
const route = Object.values(router.routesById).find(
|
|
86
|
+
candidate => candidate.options.staticData?.ultramodernRouteId === routeId,
|
|
87
|
+
);
|
|
88
|
+
if (!route) return;
|
|
89
|
+
const store = router.stores.getMatchStore(route.id);
|
|
96
90
|
let subscription: { unsubscribe(): void } | undefined;
|
|
97
91
|
let settled = false;
|
|
98
92
|
const cleanup = () => {
|
|
@@ -103,9 +97,10 @@ function observeRouteCompletion(
|
|
|
103
97
|
settled = true;
|
|
104
98
|
cleanup();
|
|
105
99
|
};
|
|
106
|
-
const publish = () => {
|
|
100
|
+
const publish = async () => {
|
|
107
101
|
if (settled) return;
|
|
108
102
|
const current = store.get();
|
|
103
|
+
if (!current) return;
|
|
109
104
|
if (
|
|
110
105
|
current.abortController !== controller ||
|
|
111
106
|
signal.aborted ||
|
|
@@ -121,23 +116,29 @@ function observeRouteCompletion(
|
|
|
121
116
|
const route = router.routesById[current.routeId];
|
|
122
117
|
let failure = error;
|
|
123
118
|
try {
|
|
119
|
+
await route?.options.errorComponent?.preload?.();
|
|
120
|
+
if (signal.aborted || store.get()?.abortController !== controller)
|
|
121
|
+
return;
|
|
124
122
|
route?.options.onError?.(failure);
|
|
125
123
|
} catch (onErrorFailure) {
|
|
126
124
|
failure = onErrorFailure;
|
|
127
125
|
}
|
|
128
|
-
//
|
|
126
|
+
// The error component is ready before publishing a late transport failure.
|
|
129
127
|
if (signal.aborted) return;
|
|
130
|
-
router.
|
|
131
|
-
previous
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
128
|
+
router.stores.setMatches(
|
|
129
|
+
router.stores.matches.get().map(previous =>
|
|
130
|
+
previous.routeId === route.id &&
|
|
131
|
+
previous.abortController === controller &&
|
|
132
|
+
previous.status === 'success' &&
|
|
133
|
+
!previous.isFetching
|
|
134
|
+
? {
|
|
135
|
+
...previous,
|
|
136
|
+
error: failure,
|
|
137
|
+
status: 'error',
|
|
138
|
+
isFetching: false,
|
|
139
|
+
}
|
|
140
|
+
: previous,
|
|
141
|
+
),
|
|
141
142
|
);
|
|
142
143
|
};
|
|
143
144
|
signal.addEventListener('abort', onAbort, { once: true });
|
|
@@ -203,6 +204,7 @@ export function createFileSystemRouteTree<Context = unknown>(
|
|
|
203
204
|
if (failed) throw failure;
|
|
204
205
|
observeRouteCompletion(
|
|
205
206
|
router,
|
|
207
|
+
route.id,
|
|
206
208
|
match.abortController,
|
|
207
209
|
signal,
|
|
208
210
|
outcome.completion,
|