proteum 2.1.9-8 → 2.2.0
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 +11 -8
- package/agents/project/AGENTS.md +7 -7
- package/agents/project/CODING_STYLE.md +1 -1
- package/agents/project/client/AGENTS.md +1 -1
- package/agents/project/client/pages/AGENTS.md +10 -10
- package/agents/project/optimizations.md +5 -6
- package/agents/project/root/AGENTS.md +7 -7
- package/cli/commands/migrate.ts +51 -0
- package/cli/compiler/artifacts/manifest.ts +4 -4
- package/cli/compiler/artifacts/routing.ts +2 -2
- package/cli/compiler/common/generatedRouteModules.ts +31 -38
- package/cli/context.ts +1 -1
- package/cli/migrate/pageContract.ts +516 -0
- package/cli/presentation/commands.ts +27 -1
- package/cli/runtime/commands.ts +25 -0
- package/cli/scaffold/templates.ts +4 -2
- package/client/dev/profiler/index.tsx +1 -2
- package/client/services/router/index.tsx +6 -22
- package/common/dev/console.ts +1 -0
- package/common/dev/diagnostics.ts +4 -4
- package/common/dev/inspection.ts +1 -1
- package/common/dev/proteumManifest.ts +4 -4
- package/common/dev/requestTrace.ts +0 -1
- package/common/router/contracts.ts +8 -11
- package/common/router/index.ts +2 -2
- package/common/router/pageData.ts +72 -0
- package/common/router/register.ts +10 -46
- package/common/router/response/page.ts +28 -16
- package/package.json +5 -1
- package/server/services/router/index.ts +48 -14
- package/server/services/router/request/api.ts +1 -1
- package/server/services/router/response/index.ts +0 -27
- package/types/global/vendors.d.ts +12 -0
- package/types/vendors.d.ts +12 -0
- package/common/router/pageSetup.ts +0 -51
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Proteum combines:
|
|
|
26
26
|
|
|
27
27
|
## Core Principles
|
|
28
28
|
|
|
29
|
-
- **Server-first by default.** Put data loading in the page
|
|
29
|
+
- **Server-first by default.** Put data loading in the page data function and keep client code focused on UI.
|
|
30
30
|
- **Explicit request entrypoints.** Controllers are classes. Request access is explicit through `this.request`.
|
|
31
31
|
- **Local validation.** Validate handler input inside the handler with `this.input(schema)`.
|
|
32
32
|
- **Deterministic generation.** Proteum owns `.proteum/` and regenerates it from source.
|
|
@@ -71,7 +71,7 @@ Important files:
|
|
|
71
71
|
- `process.env` / optional `.env`: `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen variables referenced by `proteum.config.ts`, and `TRACE_*` environment variables loaded by the app
|
|
72
72
|
- `server/config/*.ts`: plain typed config exports consumed by the explicit app bootstrap
|
|
73
73
|
- `server/index.ts`: default-exported `Application` subclass that instantiates root services and router plugins
|
|
74
|
-
- `client/pages/**`: SSR page entrypoints registered through `Router.page(
|
|
74
|
+
- `client/pages/**`: SSR page entrypoints registered through `Router.page(path, options, data, render)`
|
|
75
75
|
- `server/controllers/**`: request handlers that extend `Controller`
|
|
76
76
|
- `commands/**`: dev-only internal commands that extend `Commands`
|
|
77
77
|
- `server/services/**`: business logic that extends `Service`
|
|
@@ -194,9 +194,11 @@ import Router from '@/client/router';
|
|
|
194
194
|
|
|
195
195
|
Router.page(
|
|
196
196
|
'/',
|
|
197
|
+
{
|
|
198
|
+
auth: false,
|
|
199
|
+
layout: false,
|
|
200
|
+
},
|
|
197
201
|
({ Plans, Stats }) => ({
|
|
198
|
-
_auth: false,
|
|
199
|
-
_layout: false,
|
|
200
202
|
plans: Plans.getPlans(),
|
|
201
203
|
stats: Stats.general(),
|
|
202
204
|
}),
|
|
@@ -209,9 +211,10 @@ Router.page(
|
|
|
209
211
|
What happens here:
|
|
210
212
|
|
|
211
213
|
- the first argument is the route path
|
|
212
|
-
- the
|
|
213
|
-
-
|
|
214
|
-
-
|
|
214
|
+
- the second argument is the explicit route-options object
|
|
215
|
+
- the third argument is the page data function or `null`
|
|
216
|
+
- route behavior such as `auth`, `layout`, `static`, or `redirectLogged` lives in the options object
|
|
217
|
+
- every key returned from the data function becomes page data
|
|
215
218
|
- the renderer receives the resolved data and the generated controller/service context
|
|
216
219
|
|
|
217
220
|
## Example: Controller
|
|
@@ -518,7 +521,7 @@ If you are an LLM or automation agent, start here:
|
|
|
518
521
|
4. Read `.proteum/manifest.json` or run `proteum explain --json`.
|
|
519
522
|
5. Inspect `server/controllers/**` for request entrypoints.
|
|
520
523
|
6. Inspect `server/services/**` for business logic.
|
|
521
|
-
7. Inspect `client/pages/**` for SSR routes and page
|
|
524
|
+
7. Inspect `client/pages/**` for SSR routes and page data contracts.
|
|
522
525
|
8. If the task touches a protected route or controller in dev and login UX is not the feature under test, use `proteum session <email> --role <role>` before Playwright or direct HTTP calls.
|
|
523
526
|
|
|
524
527
|
For implementation rules in a real Proteum app, treat the local `AGENTS.md` files plus `proteum explain`, `proteum doctor`, `proteum diagnose`, `proteum perf`, and `proteum trace` as the task contract. This README is the framework overview, not the project-local instruction layer.
|
package/agents/project/AGENTS.md
CHANGED
|
@@ -136,14 +136,14 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
|
|
|
136
136
|
|
|
137
137
|
- Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
|
|
138
138
|
- File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
- `
|
|
142
|
-
- Controller fetchers and promises returned from `
|
|
143
|
-
- `render` consumes resolved
|
|
144
|
-
- Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page
|
|
139
|
+
- The only supported page signature is `Router.page(path, options, data, render)`.
|
|
140
|
+
- `options` is always required. `data` is the only nullable argument and must be `null` when the page has no SSR data loader.
|
|
141
|
+
- `data` returns one flat object. Route-option keys such as `auth`, `layout`, `static`, and `_static` are forbidden in page data and must live in `options`.
|
|
142
|
+
- Controller fetchers and promises returned from `data` resolve before render.
|
|
143
|
+
- `render` consumes resolved page data and uses generated controller methods from render args or `@/client/context`.
|
|
144
|
+
- Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page data state.
|
|
145
145
|
- Error pages use `Router.error(code, options, render)` in `client/pages/_messages/**`.
|
|
146
|
-
- Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path and
|
|
146
|
+
- Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path, options object, and data payload.
|
|
147
147
|
|
|
148
148
|
### Manual Routes
|
|
149
149
|
|
|
@@ -17,7 +17,7 @@ This file is the source of truth for codex coding style instructions in Proteum-
|
|
|
17
17
|
- Keep short arrow functions and short returned object literals compact when they are easy to scan.
|
|
18
18
|
- Keep JSX multiline only when it is clearly more readable; otherwise keep short JSX compact.
|
|
19
19
|
- Avoid staircase formatting and unnecessary blank lines inside short callbacks.
|
|
20
|
-
- Keep `Router.page(...)` and `Router.error(...)` registrations in the compact inline-call shape when possible, for example `Router.page('/path',
|
|
20
|
+
- Keep `Router.page(...)` and `Router.error(...)` registrations in the compact inline-call shape when possible, for example `Router.page('/path', {}, null, render);`.
|
|
21
21
|
|
|
22
22
|
## File organization
|
|
23
23
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This is the canonical client-area contract for Proteum-based projects.
|
|
4
4
|
Role: keep only client-area rules here.
|
|
5
5
|
Keep here: client component, hook, design-system, accessibility, and client-context usage rules that apply beyond a single page.
|
|
6
|
-
Do not put here: page `
|
|
6
|
+
Do not put here: page `data` and route-registration details, server/service rules, or generic project workflow already covered by broader ancestor `AGENTS.md` files.
|
|
7
7
|
|
|
8
8
|
Optimization source of truth: root-level `optimizations.md`.
|
|
9
9
|
Diagnostics source of truth: root-level `diagnostics.md`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This is the canonical page-file contract for Proteum-based projects.
|
|
4
4
|
Role: keep only page-file rules here.
|
|
5
|
-
Keep here: `Router.page(...)` registration, SSR `
|
|
5
|
+
Keep here: `Router.page(...)` registration, SSR `data` and `render` contracts, page payload shape, and page-local typing rules.
|
|
6
6
|
Do not put here: generic component rules, server/service implementation details, or app-wide workflow already covered by broader AGENTS files.
|
|
7
7
|
|
|
8
8
|
Optimization source of truth: root-level `optimizations.md`.
|
|
@@ -13,19 +13,19 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
|
|
|
13
13
|
|
|
14
14
|
- Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
|
|
15
15
|
- File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
16
|
+
- The only supported page signature is `Router.page(path, options, data, render)`.
|
|
17
|
+
- `options` is always required and must be an object.
|
|
18
|
+
- `data` is the only nullable argument. Pass `null` when the page does not need SSR data.
|
|
19
19
|
- Keep the `Router.page(...)` call compact instead of exploding each outer argument onto its own line.
|
|
20
20
|
- Keep route registration at top level. Do not hide it behind helper abstractions.
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Data And Render
|
|
23
23
|
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
-
|
|
27
|
-
- Controller fetchers and promises returned from `
|
|
28
|
-
- If a page needs route data, return it from `
|
|
24
|
+
- Route behavior belongs in the explicit `options` object, not in page data.
|
|
25
|
+
- `data` returns one flat object or `null` is passed as the third argument when no page data is needed.
|
|
26
|
+
- Returning route-option keys such as `auth`, `layout`, `static`, `redirectLogged`, or their `_`-prefixed variants from `data` is a contract error.
|
|
27
|
+
- Controller fetchers and promises returned from `data` resolve before render.
|
|
28
|
+
- If a page needs route data, return it from `data` and read it in `render`.
|
|
29
29
|
|
|
30
30
|
## Page Rules
|
|
31
31
|
|
|
@@ -22,12 +22,11 @@ When tradeoffs exist inside optimization work, optimize in this order:
|
|
|
22
22
|
|
|
23
23
|
## SSR And Page Size
|
|
24
24
|
|
|
25
|
-
- SSR page data belongs in page `
|
|
26
|
-
-
|
|
27
|
-
- `
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
- Controller fetchers and promises returned from `setup` resolve before render.
|
|
25
|
+
- SSR page data belongs in the explicit `Router.page(path, options, data, render)` `data` function, not in `api.fetch(...)`.
|
|
26
|
+
- `options` carries route behavior. `data` returns one flat object or is `null` when the page has no SSR data loader.
|
|
27
|
+
- Route-option keys and `_`-prefixed route-option aliases are forbidden in page data and must live in `options`.
|
|
28
|
+
- If a page needs route data, return it from `data` and read it in `render`.
|
|
29
|
+
- Controller fetchers and promises returned from `data` resolve before render.
|
|
31
30
|
- Never use `api.fetch(...)` in page files for SSR loading.
|
|
32
31
|
- Synchronous or SSR data calls must return only the strictly necessary data for the current render path to minimize SSR payload size.
|
|
33
32
|
- If an existing controller or data method returns a broader shape than the SSR path needs, create a dedicated proxy controller method with a narrower typed contract instead of reusing the oversized payload.
|
|
@@ -128,14 +128,14 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
|
|
|
128
128
|
|
|
129
129
|
- Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
|
|
130
130
|
- File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
|
|
131
|
-
-
|
|
132
|
-
-
|
|
133
|
-
- `
|
|
134
|
-
- Controller fetchers and promises returned from `
|
|
135
|
-
- `render` consumes resolved
|
|
136
|
-
- Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page
|
|
131
|
+
- The only supported page signature is `Router.page(path, options, data, render)`.
|
|
132
|
+
- `options` is always required. `data` is the only nullable argument and must be `null` when the page has no SSR data loader.
|
|
133
|
+
- `data` returns one flat object. Route-option keys such as `auth`, `layout`, `static`, and `_static` are forbidden in page data and must live in `options`.
|
|
134
|
+
- Controller fetchers and promises returned from `data` resolve before render.
|
|
135
|
+
- `render` consumes resolved page data and uses generated controller methods from render args or `@/client/context`.
|
|
136
|
+
- Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page data state.
|
|
137
137
|
- Error pages use `Router.error(code, options, render)` in `client/pages/_messages/**`.
|
|
138
|
-
- Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path and
|
|
138
|
+
- Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path, options object, and data payload.
|
|
139
139
|
|
|
140
140
|
### Manual Routes
|
|
141
141
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import cli from '..';
|
|
4
|
+
import { runPageContractMigration } from '../migrate/pageContract';
|
|
5
|
+
|
|
6
|
+
const printHuman = (summary: ReturnType<typeof runPageContractMigration>) => {
|
|
7
|
+
console.log(`Proteum migrate page-contract`);
|
|
8
|
+
console.log(`App root: ${summary.appRoot}`);
|
|
9
|
+
console.log(`Scanned files: ${summary.scannedFiles}`);
|
|
10
|
+
console.log(`Changed files: ${summary.changedFiles.length}${summary.dryRun ? ' (dry run)' : ''}`);
|
|
11
|
+
|
|
12
|
+
if (summary.changedFiles.length > 0) {
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log('Rewritten files:');
|
|
15
|
+
for (const filepath of summary.changedFiles) {
|
|
16
|
+
console.log(`- ${path.relative(summary.appRoot, filepath)}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (summary.manualFixes.length > 0) {
|
|
21
|
+
console.log('');
|
|
22
|
+
console.log('Manual fixes required:');
|
|
23
|
+
for (const fix of summary.manualFixes) {
|
|
24
|
+
console.log(
|
|
25
|
+
`- ${path.relative(summary.appRoot, fix.filepath)}:${fix.line}:${fix.column} ${fix.routeLabel} :: ${fix.reason}`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const run = async (): Promise<void> => {
|
|
32
|
+
const action = String(cli.args.action || '').trim();
|
|
33
|
+
if (action !== 'page-contract') {
|
|
34
|
+
throw new Error(`Unsupported migrate action "${action}". Expected "page-contract".`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const summary = runPageContractMigration({
|
|
38
|
+
appRoot: String(cli.args.workdir || process.cwd()),
|
|
39
|
+
dryRun: cli.args.dryRun === true,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (cli.args.json === true) {
|
|
43
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
44
|
+
} else {
|
|
45
|
+
printHuman(summary);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (summary.manualFixes.length > 0) {
|
|
49
|
+
throw new Error(`Page-contract migration requires manual fixes in ${summary.manualFixes.length} location(s).`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
@@ -4,7 +4,7 @@ import path from 'path';
|
|
|
4
4
|
import app from '../../app';
|
|
5
5
|
import cli from '../..';
|
|
6
6
|
import { inspectProteumEnv } from '../../../common/env/proteumEnv';
|
|
7
|
-
import {
|
|
7
|
+
import { reservedRouteOptionKeys, routeOptionKeys } from '../../../common/router/pageData';
|
|
8
8
|
import { getProjectInstructionGitignoreEntries } from '../../utils/agents';
|
|
9
9
|
import {
|
|
10
10
|
TProteumManifest,
|
|
@@ -303,7 +303,7 @@ export const writeCurrentProteumManifest = ({
|
|
|
303
303
|
});
|
|
304
304
|
|
|
305
305
|
const manifest: TProteumManifest = {
|
|
306
|
-
version:
|
|
306
|
+
version: 10,
|
|
307
307
|
app: {
|
|
308
308
|
root: normalizeAbsolutePath(app.paths.root),
|
|
309
309
|
coreRoot: normalizeAbsolutePath(cli.paths.core.root),
|
|
@@ -338,8 +338,8 @@ export const writeCurrentProteumManifest = ({
|
|
|
338
338
|
},
|
|
339
339
|
},
|
|
340
340
|
conventions: {
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
routeOptionKeys: [...routeOptionKeys],
|
|
342
|
+
reservedRouteOptionKeys: [...reservedRouteOptionKeys],
|
|
343
343
|
},
|
|
344
344
|
env: {
|
|
345
345
|
source: 'process.env',
|
|
@@ -59,7 +59,7 @@ const buildClientRouteManifestEntry = (filepath: string): TProteumManifestRoute
|
|
|
59
59
|
invalidOptionKeys: definition.invalidOptionKeys,
|
|
60
60
|
reservedOptionKeys: definition.reservedOptionKeys,
|
|
61
61
|
optionsRaw: definition.optionsRaw,
|
|
62
|
-
|
|
62
|
+
hasData: definition.hasData,
|
|
63
63
|
chunkId: pageChunk.chunkId,
|
|
64
64
|
chunkFilepath: normalizePath(pageChunk.filepath),
|
|
65
65
|
scope: 'app',
|
|
@@ -83,7 +83,7 @@ const buildServerRouteManifestEntries = (filepath: string) =>
|
|
|
83
83
|
invalidOptionKeys: definition.invalidOptionKeys,
|
|
84
84
|
reservedOptionKeys: definition.reservedOptionKeys,
|
|
85
85
|
optionsRaw: definition.optionsRaw,
|
|
86
|
-
|
|
86
|
+
hasData: definition.hasData,
|
|
87
87
|
scope: 'app',
|
|
88
88
|
}));
|
|
89
89
|
|
|
@@ -2,7 +2,7 @@ import fs from 'fs-extra';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import ts from 'typescript';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { getRouteOptionKey } from '../../../common/router/pageData';
|
|
6
6
|
import writeIfChanged from '../writeIfChanged';
|
|
7
7
|
|
|
8
8
|
type TRouteSide = 'client' | 'server';
|
|
@@ -33,7 +33,7 @@ export type TIndexedRouteDefinition = {
|
|
|
33
33
|
invalidOptionKeys: string[];
|
|
34
34
|
reservedOptionKeys: string[];
|
|
35
35
|
optionsRaw?: string;
|
|
36
|
-
|
|
36
|
+
hasData: boolean;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
type TGeneratedClientRouteModuleOptions = { chunkId: string };
|
|
@@ -206,7 +206,7 @@ const getRouteOptionMetadata = (node: ts.ObjectLiteralExpression | undefined) =>
|
|
|
206
206
|
|
|
207
207
|
for (const optionKey of optionKeys) {
|
|
208
208
|
try {
|
|
209
|
-
const normalizedOptionKey =
|
|
209
|
+
const normalizedOptionKey = getRouteOptionKey(optionKey);
|
|
210
210
|
|
|
211
211
|
if (normalizedOptionKey) {
|
|
212
212
|
normalizedOptionKeys.push(normalizedOptionKey);
|
|
@@ -438,29 +438,33 @@ const buildDestructuring = (importedServices: TImportedService[]) => {
|
|
|
438
438
|
const getClientRouteSignature = (sourceFile: ts.SourceFile, definition: TRouteDefinition) => {
|
|
439
439
|
const [, ...routeArgs] = [...definition.args];
|
|
440
440
|
|
|
441
|
-
if (
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
441
|
+
if (definition.methodName === 'error') {
|
|
442
|
+
if (routeArgs.length === 2) {
|
|
443
|
+
return {
|
|
444
|
+
hasData: false,
|
|
445
|
+
optionsExpression: routeArgs[0],
|
|
446
|
+
optionsArg: ts.isObjectLiteralExpression(routeArgs[0]) ? routeArgs[0] : undefined,
|
|
447
|
+
renderArg: routeArgs[1],
|
|
448
|
+
};
|
|
448
449
|
}
|
|
449
450
|
|
|
450
|
-
|
|
451
|
+
throw new Error(
|
|
452
|
+
`Unsupported client error route signature in ${sourceFile.fileName}. Expected Router.error(code, options, render).`,
|
|
453
|
+
);
|
|
451
454
|
}
|
|
452
455
|
|
|
453
|
-
if (routeArgs.length === 3
|
|
456
|
+
if (routeArgs.length === 3) {
|
|
454
457
|
return {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
hasData: routeArgs[1].kind !== ts.SyntaxKind.NullKeyword,
|
|
459
|
+
optionsExpression: routeArgs[0],
|
|
460
|
+
optionsArg: ts.isObjectLiteralExpression(routeArgs[0]) ? routeArgs[0] : undefined,
|
|
461
|
+
dataArg: routeArgs[1],
|
|
458
462
|
renderArg: routeArgs[2],
|
|
459
463
|
};
|
|
460
464
|
}
|
|
461
465
|
|
|
462
466
|
throw new Error(
|
|
463
|
-
`Unsupported client route signature in ${sourceFile.fileName}. Expected Router.page
|
|
467
|
+
`Unsupported client page route signature in ${sourceFile.fileName}. Expected Router.page(path, options, data, render).`,
|
|
464
468
|
);
|
|
465
469
|
};
|
|
466
470
|
|
|
@@ -469,30 +473,23 @@ const buildClientRegisterArgs = (
|
|
|
469
473
|
definition: TRouteDefinition,
|
|
470
474
|
clientRoute: TGeneratedClientRouteModuleOptions,
|
|
471
475
|
) => {
|
|
472
|
-
const {
|
|
476
|
+
const { optionsExpression, renderArg } = getClientRouteSignature(sourceFile, definition);
|
|
473
477
|
const sourceLocation = getNodeLocation(sourceFile, definition.callExpression);
|
|
474
478
|
const injectedOptions = buildInjectedRouteMetadata(sourceFile.fileName, sourceLocation, [
|
|
475
479
|
`id: ${JSON.stringify(clientRoute.chunkId)}`,
|
|
476
480
|
]);
|
|
477
481
|
|
|
478
|
-
if (
|
|
479
|
-
return [injectedOptions, getNodeText(sourceFile, renderArg)];
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (optionsArg && !setupArg) {
|
|
482
|
+
if (definition.methodName === 'error') {
|
|
483
483
|
return [
|
|
484
|
-
`{ ...(${getNodeText(sourceFile,
|
|
484
|
+
`{ ...(${getNodeText(sourceFile, optionsExpression)}), ...${injectedOptions} }`,
|
|
485
485
|
getNodeText(sourceFile, renderArg),
|
|
486
486
|
];
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
-
|
|
490
|
-
return [injectedOptions, getNodeText(sourceFile, setupArg), getNodeText(sourceFile, renderArg)];
|
|
491
|
-
}
|
|
492
|
-
|
|
489
|
+
const { dataArg } = getClientRouteSignature(sourceFile, definition);
|
|
493
490
|
return [
|
|
494
|
-
`{ ...(${getNodeText(sourceFile,
|
|
495
|
-
getNodeText(sourceFile,
|
|
491
|
+
`{ ...(${getNodeText(sourceFile, optionsExpression)}), ...${injectedOptions} }`,
|
|
492
|
+
getNodeText(sourceFile, dataArg!),
|
|
496
493
|
getNodeText(sourceFile, renderArg),
|
|
497
494
|
];
|
|
498
495
|
};
|
|
@@ -604,10 +601,8 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
|
|
|
604
601
|
normalizedOptionKeys: optionMetadata.normalizedOptionKeys,
|
|
605
602
|
invalidOptionKeys: optionMetadata.invalidOptionKeys,
|
|
606
603
|
reservedOptionKeys: optionMetadata.reservedOptionKeys,
|
|
607
|
-
optionsRaw: clientSignature.
|
|
608
|
-
|
|
609
|
-
: undefined,
|
|
610
|
-
hasSetup: clientSignature.hasSetup,
|
|
604
|
+
optionsRaw: getNodeText(sourceFile, clientSignature.optionsExpression),
|
|
605
|
+
hasData: false,
|
|
611
606
|
}
|
|
612
607
|
: {
|
|
613
608
|
methodName: definition.methodName,
|
|
@@ -627,10 +622,8 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
|
|
|
627
622
|
normalizedOptionKeys: optionMetadata.normalizedOptionKeys,
|
|
628
623
|
invalidOptionKeys: optionMetadata.invalidOptionKeys,
|
|
629
624
|
reservedOptionKeys: optionMetadata.reservedOptionKeys,
|
|
630
|
-
optionsRaw: clientSignature.
|
|
631
|
-
|
|
632
|
-
: undefined,
|
|
633
|
-
hasSetup: clientSignature.hasSetup,
|
|
625
|
+
optionsRaw: getNodeText(sourceFile, clientSignature.optionsExpression),
|
|
626
|
+
hasData: clientSignature.hasData,
|
|
634
627
|
};
|
|
635
628
|
}
|
|
636
629
|
|
|
@@ -659,7 +652,7 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
|
|
|
659
652
|
invalidOptionKeys: optionMetadata.invalidOptionKeys,
|
|
660
653
|
reservedOptionKeys: optionMetadata.reservedOptionKeys,
|
|
661
654
|
optionsRaw: optionsArg ? getNodeText(sourceFile, optionsArg) : undefined,
|
|
662
|
-
|
|
655
|
+
hasData: false,
|
|
663
656
|
};
|
|
664
657
|
});
|
|
665
658
|
};
|
package/cli/context.ts
CHANGED
|
@@ -27,7 +27,7 @@ export class CLIContext {
|
|
|
27
27
|
const workdir =
|
|
28
28
|
typeof args.workdir === 'string' && args.workdir.trim().length > 0 ? args.workdir.trim() : process.cwd();
|
|
29
29
|
|
|
30
|
-
this.args = {
|
|
30
|
+
this.args = { ...args, workdir };
|
|
31
31
|
this.paths = new Paths(workdir, this.paths.core.root);
|
|
32
32
|
this.paths.applyAliases();
|
|
33
33
|
this.verbose = this.args.verbose === true;
|