@bleedingdev/modern-js-plugin-tanstack 3.9.0-ultramodern.11 → 3.9.0-ultramodern.12
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/cli/artifacts.js +2 -1
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +7 -7
- package/dist/cjs/cli/tanstackTypes/shared.js +0 -14
- package/dist/cjs/cli/tanstackTypes/source.js +28 -63
- package/dist/cjs/runtime/lifecycle.js +0 -3
- package/dist/cjs/runtime/loaderBridge.js +10 -4
- package/dist/cjs/runtime/navigation.js +102 -0
- package/dist/cjs/runtime/plugin.js +6 -1
- package/dist/cjs/runtime/plugin.node.js +82 -64
- package/dist/cjs/runtime/routeTree/construction.js +19 -61
- package/dist/cjs/runtime/routeTree/loaders.js +1 -1
- package/dist/cjs/runtime/routeTree/paths.js +0 -6
- package/dist/cjs/runtime/utils.js +1 -0
- package/dist/cjs/shared/routeDescriptor.js +60 -0
- package/dist/esm/cli/artifacts.mjs +2 -1
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm/runtime/lifecycle.mjs +1 -1
- package/dist/esm/runtime/loaderBridge.mjs +8 -5
- package/dist/esm/runtime/navigation.mjs +64 -0
- package/dist/esm/runtime/plugin.mjs +6 -1
- package/dist/esm/runtime/plugin.node.mjs +83 -65
- package/dist/esm/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm/runtime/utils.mjs +1 -0
- package/dist/esm/shared/routeDescriptor.mjs +22 -0
- package/dist/esm-node/cli/artifacts.mjs +2 -1
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +7 -7
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +1 -9
- package/dist/esm-node/cli/tanstackTypes/source.mjs +29 -64
- package/dist/esm-node/runtime/lifecycle.mjs +1 -1
- package/dist/esm-node/runtime/loaderBridge.mjs +8 -5
- package/dist/esm-node/runtime/navigation.mjs +65 -0
- package/dist/esm-node/runtime/plugin.mjs +6 -1
- package/dist/esm-node/runtime/plugin.node.mjs +83 -65
- package/dist/esm-node/runtime/routeTree/construction.mjs +19 -61
- package/dist/esm-node/runtime/routeTree/loaders.mjs +2 -2
- package/dist/esm-node/runtime/routeTree/paths.mjs +1 -4
- package/dist/esm-node/runtime/utils.mjs +1 -0
- package/dist/esm-node/shared/routeDescriptor.mjs +23 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +0 -2
- package/dist/types/runtime/lifecycle.d.ts +1 -1
- package/dist/types/runtime/loaderBridge.d.ts +1 -0
- package/dist/types/runtime/navigation.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +0 -2
- package/dist/types/shared/routeDescriptor.d.ts +26 -0
- package/package.json +12 -12
- package/src/cli/artifacts.ts +6 -1
- package/src/cli/tanstackTypes/canonicalRoutes.ts +17 -12
- package/src/cli/tanstackTypes/shared.ts +0 -14
- package/src/cli/tanstackTypes/source.ts +43 -119
- package/src/runtime/lifecycle.ts +0 -1
- package/src/runtime/loaderBridge.ts +9 -9
- package/src/runtime/navigation.ts +78 -0
- package/src/runtime/plugin.node.tsx +111 -89
- package/src/runtime/plugin.tsx +6 -0
- package/src/runtime/routeTree/construction.ts +32 -112
- package/src/runtime/routeTree/loaders.ts +2 -4
- package/src/runtime/routeTree/paths.ts +0 -6
- package/src/runtime/utils.tsx +1 -0
- package/src/shared/routeDescriptor.ts +46 -0
- package/tests/router/generateRouteArtifacts.test.ts +36 -2
- package/tests/router/localisedIdentity.test.tsx +1 -0
- package/tests/router/prefetchLink.test.tsx +29 -0
- package/tests/router/serverPlugin.test.ts +145 -0
- package/tests/router/tanstackTypes.test.ts +120 -2
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { mkdir, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
5
6
|
import { promisify } from 'node:util';
|
|
6
|
-
|
|
7
|
+
import { applyLocalisedUrlsToRoutes } from '@modern-js/i18n-runtime-extensions';
|
|
8
|
+
import { createMemoryHistory, createRouter } from '@tanstack/react-router';
|
|
7
9
|
import { writeTanstackRegisterFile } from '../../src/cli/artifacts';
|
|
8
10
|
import {
|
|
9
11
|
collectCanonicalRoutesForEntry,
|
|
10
12
|
generateTanstackRouterTypesSourceForEntry,
|
|
11
13
|
} from '../../src/cli/tanstackTypes';
|
|
14
|
+
import { createModernBasepathRewrite } from '../../src/runtime/basepathRewrite';
|
|
15
|
+
import { createRouteTreeFromRouteObjects } from '../../src/runtime/routeTree';
|
|
16
|
+
import { createTanstackRouteObjectsFromConfig } from '../../src/runtime/utils';
|
|
12
17
|
|
|
13
18
|
const execFileAsync = promisify(execFile);
|
|
14
19
|
const strictestTsconfigPath = path.resolve(
|
|
@@ -261,6 +266,119 @@ describe('tanstack router type generation', () => {
|
|
|
261
266
|
});
|
|
262
267
|
});
|
|
263
268
|
|
|
269
|
+
test('generated and runtime trees agree on localized splats, root siblings, layouts and params', async () => {
|
|
270
|
+
tempDir = await mkdtemp(path.join(tmpdir(), 'modern-tanstack-parity-'));
|
|
271
|
+
const localized = applyLocalisedUrlsToRoutes(
|
|
272
|
+
[
|
|
273
|
+
{
|
|
274
|
+
type: 'nested',
|
|
275
|
+
id: 'lang',
|
|
276
|
+
path: ':lang',
|
|
277
|
+
children: [
|
|
278
|
+
{
|
|
279
|
+
type: 'nested',
|
|
280
|
+
id: 'products',
|
|
281
|
+
path: 'products',
|
|
282
|
+
children: [{ type: 'nested', id: 'product-files', path: '*' }],
|
|
283
|
+
},
|
|
284
|
+
{ type: 'nested', id: 'fallback', path: '*' },
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
['en', 'cs'],
|
|
289
|
+
{ '/products': { en: '/products', cs: '/produkty' } },
|
|
290
|
+
'canonical',
|
|
291
|
+
);
|
|
292
|
+
const routes = [
|
|
293
|
+
{
|
|
294
|
+
type: 'nested',
|
|
295
|
+
id: 'layout',
|
|
296
|
+
isRoot: true,
|
|
297
|
+
children: [
|
|
298
|
+
...localized,
|
|
299
|
+
{
|
|
300
|
+
type: 'nested',
|
|
301
|
+
children: [{ type: 'nested', path: 'one/:id?', index: false }],
|
|
302
|
+
},
|
|
303
|
+
{ type: 'nested', children: [{ type: 'nested', path: 'two/*' }] },
|
|
304
|
+
{ type: 'nested', id: 'index', index: true },
|
|
305
|
+
],
|
|
306
|
+
},
|
|
307
|
+
{ type: 'nested', id: 'sibling', path: 'outside/:lang' },
|
|
308
|
+
] as any;
|
|
309
|
+
const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
|
|
310
|
+
appContext: {
|
|
311
|
+
srcDirectory: path.join(tempDir, 'src'),
|
|
312
|
+
internalSrcAlias: '@/_',
|
|
313
|
+
} as any,
|
|
314
|
+
entryName: 'parity',
|
|
315
|
+
routes,
|
|
316
|
+
});
|
|
317
|
+
const generated = path.join(tempDir, 'router.gen.ts');
|
|
318
|
+
await writeFile(generated, routerGenTs);
|
|
319
|
+
const modules = path.join(tempDir, 'node_modules', '@modern-js');
|
|
320
|
+
await mkdir(modules, { recursive: true });
|
|
321
|
+
await symlink(
|
|
322
|
+
path.resolve(__dirname, '../..'),
|
|
323
|
+
path.join(modules, 'plugin-tanstack'),
|
|
324
|
+
'junction',
|
|
325
|
+
);
|
|
326
|
+
const { stdout } = await execFileAsync(process.execPath, [
|
|
327
|
+
'--input-type=module',
|
|
328
|
+
'--eval',
|
|
329
|
+
`
|
|
330
|
+
import { router } from ${JSON.stringify(pathToFileURL(generated).href)};
|
|
331
|
+
import { createModernBasepathRewrite } from ${JSON.stringify(pathToFileURL(path.resolve(__dirname, '../../dist/esm/runtime/basepathRewrite.mjs')).href)};
|
|
332
|
+
router.update({ rewrite: createModernBasepathRewrite('/base', false, ${JSON.stringify(routes)}) });
|
|
333
|
+
await router.navigate({ to: '/cs/produkty/a/b', search: { q: 'tractor' }, hash: 'files' });
|
|
334
|
+
console.log(JSON.stringify({ ids: Object.keys(router.routesById).sort(), match: router.state.matches.at(-1).routeId, params: router.state.matches.at(-1).params, href: router.history.location.href }));
|
|
335
|
+
`,
|
|
336
|
+
]);
|
|
337
|
+
const routeObjects = createTanstackRouteObjectsFromConfig({
|
|
338
|
+
routesConfig: { routes },
|
|
339
|
+
})!;
|
|
340
|
+
const runtime = createRouter({
|
|
341
|
+
routeTree: createRouteTreeFromRouteObjects(routeObjects),
|
|
342
|
+
history: createMemoryHistory({
|
|
343
|
+
initialEntries: ['/base/cs/produkty/a/b?q=tractor#files'],
|
|
344
|
+
}),
|
|
345
|
+
rewrite: createModernBasepathRewrite('/base', false, routeObjects),
|
|
346
|
+
});
|
|
347
|
+
await runtime.load();
|
|
348
|
+
expect(JSON.parse(stdout)).toEqual({
|
|
349
|
+
ids: Object.keys(runtime.routesById).sort(),
|
|
350
|
+
match: runtime.state.matches.at(-1)?.routeId,
|
|
351
|
+
params: runtime.state.matches.at(-1)?.params,
|
|
352
|
+
href: runtime.history.location.href,
|
|
353
|
+
});
|
|
354
|
+
expect(runtime.state.matches.at(-1)?.routeId).toBe('/$lang/products/$');
|
|
355
|
+
expect(runtime.state.matches.at(-1)?.params).toMatchObject({
|
|
356
|
+
lang: 'cs',
|
|
357
|
+
_splat: 'a/b',
|
|
358
|
+
});
|
|
359
|
+
await runtime.navigate({ to: '/cs/missing/path' });
|
|
360
|
+
expect(runtime.state.matches.at(-1)?.routeId).toBe('/$lang/$');
|
|
361
|
+
expect(runtime.state.matches.at(-1)?.params).toMatchObject({
|
|
362
|
+
lang: 'cs',
|
|
363
|
+
_splat: 'missing/path',
|
|
364
|
+
});
|
|
365
|
+
await runtime.navigate({ to: '/outside/cs' });
|
|
366
|
+
expect(runtime.state.matches.at(-1)?.params).toEqual({ lang: 'cs' });
|
|
367
|
+
const canonicalRoutes = collectCanonicalRoutesForEntry(localized as any)!;
|
|
368
|
+
expect(Object.keys(canonicalRoutes)).toEqual(['/$', '/products/$']);
|
|
369
|
+
await typecheckCanonicalRegisterContract({
|
|
370
|
+
projectDirectory: tempDir,
|
|
371
|
+
canonicalRoutes,
|
|
372
|
+
contractLines: [
|
|
373
|
+
"const product: UltramodernCanonicalRoutes['/products/$'] = { _splat: 'a/b' };",
|
|
374
|
+
"const fallback: UltramodernCanonicalRoutes['/$'] = { _splat: 'unknown/path' };",
|
|
375
|
+
'// @ts-expect-error splat remains a string',
|
|
376
|
+
"const invalid: UltramodernCanonicalRoutes['/products/$'] = { _splat: 42 };",
|
|
377
|
+
'void product; void fallback; void invalid;',
|
|
378
|
+
],
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
|
|
264
382
|
test('maps a locale-prefixed route tree to the canonical paths consumers navigate to', () => {
|
|
265
383
|
const routes = [
|
|
266
384
|
{
|