@taujs/server 0.4.2 → 0.4.4
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/{Config-BuUuMjmO.d.ts → Config-CEhfq8Mm.d.ts} +41 -39
- package/dist/Config.d.ts +1 -1
- package/dist/Config.js +164 -1
- package/dist/index.d.ts +76 -5
- package/dist/index.js +352 -105
- package/package.json +1 -1
|
@@ -6,7 +6,6 @@ type DebugCategory = (typeof DEBUG_CATEGORIES)[number];
|
|
|
6
6
|
type DebugConfig = boolean | DebugCategory[] | ({
|
|
7
7
|
all?: boolean;
|
|
8
8
|
} & Partial<Record<DebugCategory, boolean>>);
|
|
9
|
-
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
10
9
|
interface BaseLogger {
|
|
11
10
|
debug?(meta?: Record<string, unknown>, message?: string): void;
|
|
12
11
|
info?(meta?: Record<string, unknown>, message?: string): void;
|
|
@@ -23,41 +22,8 @@ interface Logs extends BaseLogger {
|
|
|
23
22
|
child(context: Record<string, unknown>): Logs;
|
|
24
23
|
isDebugEnabled(category: DebugCategory): boolean;
|
|
25
24
|
}
|
|
26
|
-
declare class Logger implements Logs {
|
|
27
|
-
private config;
|
|
28
|
-
private debugEnabled;
|
|
29
|
-
private context;
|
|
30
|
-
constructor(config?: {
|
|
31
|
-
custom?: BaseLogger;
|
|
32
|
-
context?: Record<string, unknown>;
|
|
33
|
-
minLevel?: LogLevel;
|
|
34
|
-
includeStack?: boolean | ((level: LogLevel) => boolean);
|
|
35
|
-
includeContext?: boolean | ((level: LogLevel) => boolean);
|
|
36
|
-
singleLine?: boolean;
|
|
37
|
-
});
|
|
38
|
-
child(context: Record<string, unknown>): Logger;
|
|
39
|
-
configure(debug?: DebugConfig): void;
|
|
40
|
-
isDebugEnabled(category: DebugCategory): boolean;
|
|
41
|
-
private shouldEmit;
|
|
42
|
-
private shouldIncludeStack;
|
|
43
|
-
private stripStacks;
|
|
44
|
-
private formatTimestamp;
|
|
45
|
-
private emit;
|
|
46
|
-
info(meta?: unknown, message?: string): void;
|
|
47
|
-
warn(meta?: unknown, message?: string): void;
|
|
48
|
-
error(meta?: unknown, message?: string): void;
|
|
49
|
-
debug(category: DebugCategory, meta?: unknown, message?: string): void;
|
|
50
|
-
}
|
|
51
|
-
declare function createLogger(opts?: {
|
|
52
|
-
debug?: DebugConfig | string | boolean;
|
|
53
|
-
custom?: BaseLogger;
|
|
54
|
-
context?: Record<string, unknown>;
|
|
55
|
-
minLevel?: LogLevel;
|
|
56
|
-
includeStack?: boolean | ((level: LogLevel) => boolean);
|
|
57
|
-
includeContext?: boolean | ((level: LogLevel) => boolean);
|
|
58
|
-
singleLine?: boolean;
|
|
59
|
-
}): Logger;
|
|
60
25
|
|
|
26
|
+
type RegistryCaller<R extends ServiceRegistry = ServiceRegistry> = (serviceName: keyof R & string, methodName: string, args?: JsonObject) => Promise<JsonObject>;
|
|
61
27
|
type JsonPrimitive = string | number | boolean | null;
|
|
62
28
|
type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
63
29
|
[k: string]: JsonValue;
|
|
@@ -77,7 +43,9 @@ type ServiceContext = {
|
|
|
77
43
|
id: string;
|
|
78
44
|
roles: string[];
|
|
79
45
|
} | null;
|
|
46
|
+
call?: (service: string, method: string, args?: JsonObject) => Promise<JsonObject>;
|
|
80
47
|
};
|
|
48
|
+
declare function withDeadline(signal: AbortSignal | undefined, ms?: number): AbortSignal | undefined;
|
|
81
49
|
type ServiceMethod<P, R extends JsonObject = JsonObject> = (params: P, ctx: ServiceContext) => Promise<R>;
|
|
82
50
|
type ServiceDefinition = Readonly<Record<string, ServiceMethod<any, JsonObject>>>;
|
|
83
51
|
type ServiceRegistry = Readonly<Record<string, ServiceDefinition>>;
|
|
@@ -94,6 +62,7 @@ declare function defineService<T extends Record<string, ServiceMethod<any, JsonO
|
|
|
94
62
|
handler: ServiceMethod<infer P, infer R_1>;
|
|
95
63
|
} ? ServiceMethod<P, R_1> : never; };
|
|
96
64
|
declare const defineServiceRegistry: <R extends ServiceRegistry>(registry: R) => R;
|
|
65
|
+
declare function callServiceMethod(registry: ServiceRegistry, serviceName: string, methodName: string, params: JsonObject | undefined, ctx: ServiceContext): Promise<JsonObject>;
|
|
97
66
|
|
|
98
67
|
type RequestContext<L extends Logs = Logs> = {
|
|
99
68
|
traceId: string;
|
|
@@ -122,7 +91,11 @@ type BaseMiddleware = {
|
|
|
122
91
|
csp?: RouteCSPConfig | false;
|
|
123
92
|
};
|
|
124
93
|
type DataResult = Record<string, unknown> | ServiceDescriptor;
|
|
125
|
-
type
|
|
94
|
+
type RequestServiceContext<L extends Logs = Logs> = RequestContext<L> & {
|
|
95
|
+
call: RegistryCaller<ServiceRegistry>;
|
|
96
|
+
headers?: Record<string, string>;
|
|
97
|
+
};
|
|
98
|
+
type DataHandler<Params extends PathToRegExpParams, L extends Logs = Logs> = (params: Params, ctx: RequestServiceContext<L> & {
|
|
126
99
|
[key: string]: unknown;
|
|
127
100
|
}) => Promise<DataResult>;
|
|
128
101
|
type PathToRegExpParams = Partial<Record<string, string | string[]>>;
|
|
@@ -163,6 +136,35 @@ type CSPViolationReport = {
|
|
|
163
136
|
disposition?: 'enforce' | 'report';
|
|
164
137
|
};
|
|
165
138
|
|
|
139
|
+
type ErrorKind = 'infra' | 'upstream' | 'domain' | 'validation' | 'auth' | 'canceled' | 'timeout';
|
|
140
|
+
declare class AppError extends Error {
|
|
141
|
+
readonly kind: ErrorKind;
|
|
142
|
+
readonly httpStatus: number;
|
|
143
|
+
readonly details?: unknown;
|
|
144
|
+
readonly safeMessage: string;
|
|
145
|
+
readonly code?: string;
|
|
146
|
+
constructor(message: string, kind: ErrorKind, options?: {
|
|
147
|
+
httpStatus?: number;
|
|
148
|
+
details?: unknown;
|
|
149
|
+
cause?: unknown;
|
|
150
|
+
safeMessage?: string;
|
|
151
|
+
code?: string;
|
|
152
|
+
});
|
|
153
|
+
private getSafeMessage;
|
|
154
|
+
private serialiseValue;
|
|
155
|
+
toJSON(): any;
|
|
156
|
+
static notFound(message: string, details?: unknown, code?: string): AppError;
|
|
157
|
+
static forbidden(message: string, details?: unknown, code?: string): AppError;
|
|
158
|
+
static badRequest(message: string, details?: unknown, code?: string): AppError;
|
|
159
|
+
static unprocessable(message: string, details?: unknown, code?: string): AppError;
|
|
160
|
+
static timeout(message: string, details?: unknown, code?: string): AppError;
|
|
161
|
+
static canceled(message: string, details?: unknown, code?: string): AppError;
|
|
162
|
+
static internal(message: string, cause?: unknown, details?: unknown, code?: string): AppError;
|
|
163
|
+
static upstream(message: string, cause?: unknown, details?: unknown, code?: string): AppError;
|
|
164
|
+
static serviceUnavailable(message: string, cause?: unknown, details?: unknown, code?: string): AppError;
|
|
165
|
+
static from(err: unknown, fallback?: string): AppError;
|
|
166
|
+
}
|
|
167
|
+
|
|
166
168
|
/**
|
|
167
169
|
* τjs [ taujs ] Orchestration System
|
|
168
170
|
* (c) 2024-present Aoede Ltd
|
|
@@ -195,15 +197,15 @@ type AppConfig = {
|
|
|
195
197
|
routes?: AppRoute[];
|
|
196
198
|
};
|
|
197
199
|
type TaujsConfig = {
|
|
200
|
+
apps: AppConfig[];
|
|
201
|
+
security?: SecurityConfig;
|
|
198
202
|
server?: {
|
|
199
203
|
host?: string;
|
|
200
204
|
port?: number;
|
|
201
205
|
hmrPort?: number;
|
|
202
206
|
};
|
|
203
|
-
security?: SecurityConfig;
|
|
204
|
-
apps: AppConfig[];
|
|
205
207
|
};
|
|
206
208
|
|
|
207
209
|
declare function defineConfig<T extends TaujsConfig>(config: T): T;
|
|
208
210
|
|
|
209
|
-
export { type AppConfig as A, type BaseLogger as B, type DebugConfig as D, type InitialRouteParams as I, type ServiceRegistry as S, type TaujsConfig as T, type SecurityConfig as a, type AppRoute as b,
|
|
211
|
+
export { type AppConfig as A, type BaseLogger as B, type DebugConfig as D, type InitialRouteParams as I, type RegistryCaller as R, type ServiceRegistry as S, type TaujsConfig as T, type SecurityConfig as a, type AppRoute as b, callServiceMethod as c, defineConfig as d, defineService as e, defineServiceRegistry as f, type ServiceContext as g, AppError as h, withDeadline as w };
|
package/dist/Config.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import 'fastify';
|
|
2
2
|
import 'vite';
|
|
3
|
-
export { A as AppConfig, b as AppRoute, a as SecurityConfig, g as ServiceContext, T as TaujsConfig, d as defineConfig,
|
|
3
|
+
export { A as AppConfig, h as AppError, b as AppRoute, R as RegistryCaller, a as SecurityConfig, g as ServiceContext, T as TaujsConfig, c as callServiceMethod, d as defineConfig, e as defineService, f as defineServiceRegistry, w as withDeadline } from './Config-CEhfq8Mm.js';
|
package/dist/Config.js
CHANGED
|
@@ -1,9 +1,137 @@
|
|
|
1
1
|
// src/utils/DataServices.ts
|
|
2
2
|
import { performance } from "perf_hooks";
|
|
3
|
+
|
|
4
|
+
// src/logging/AppError.ts
|
|
5
|
+
var HTTP_STATUS = {
|
|
6
|
+
infra: 500,
|
|
7
|
+
upstream: 502,
|
|
8
|
+
domain: 404,
|
|
9
|
+
validation: 400,
|
|
10
|
+
auth: 403,
|
|
11
|
+
canceled: 499,
|
|
12
|
+
// Client Closed Request (nginx convention)
|
|
13
|
+
timeout: 504
|
|
14
|
+
};
|
|
15
|
+
var AppError = class _AppError extends Error {
|
|
16
|
+
kind;
|
|
17
|
+
httpStatus;
|
|
18
|
+
details;
|
|
19
|
+
safeMessage;
|
|
20
|
+
code;
|
|
21
|
+
constructor(message, kind, options = {}) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "AppError";
|
|
24
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
25
|
+
if (options.cause !== void 0) {
|
|
26
|
+
Object.defineProperty(this, "cause", {
|
|
27
|
+
value: options.cause,
|
|
28
|
+
enumerable: false,
|
|
29
|
+
writable: false,
|
|
30
|
+
configurable: true
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
this.kind = kind;
|
|
34
|
+
this.httpStatus = options.httpStatus ?? HTTP_STATUS[kind];
|
|
35
|
+
this.details = options.details;
|
|
36
|
+
this.safeMessage = options.safeMessage ?? this.getSafeMessage(kind, message);
|
|
37
|
+
this.code = options.code;
|
|
38
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
39
|
+
}
|
|
40
|
+
getSafeMessage(kind, message) {
|
|
41
|
+
return kind === "domain" || kind === "validation" || kind === "auth" ? message : "Internal Server Error";
|
|
42
|
+
}
|
|
43
|
+
serialiseValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
44
|
+
if (value === null || value === void 0) return value;
|
|
45
|
+
if (typeof value !== "object") return value;
|
|
46
|
+
if (seen.has(value)) return "[circular]";
|
|
47
|
+
seen.add(value);
|
|
48
|
+
if (value instanceof Error) {
|
|
49
|
+
return {
|
|
50
|
+
name: value.name,
|
|
51
|
+
message: value.message,
|
|
52
|
+
stack: value.stack,
|
|
53
|
+
...value instanceof _AppError && {
|
|
54
|
+
kind: value.kind,
|
|
55
|
+
httpStatus: value.httpStatus,
|
|
56
|
+
code: value.code
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(value)) return value.map((item) => this.serialiseValue(item, seen));
|
|
61
|
+
const result = {};
|
|
62
|
+
for (const [key, val] of Object.entries(value)) {
|
|
63
|
+
result[key] = this.serialiseValue(val, seen);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
toJSON() {
|
|
68
|
+
return {
|
|
69
|
+
name: this.name,
|
|
70
|
+
kind: this.kind,
|
|
71
|
+
message: this.message,
|
|
72
|
+
safeMessage: this.safeMessage,
|
|
73
|
+
httpStatus: this.httpStatus,
|
|
74
|
+
...this.code && { code: this.code },
|
|
75
|
+
details: this.serialiseValue(this.details),
|
|
76
|
+
stack: this.stack,
|
|
77
|
+
...this.cause && {
|
|
78
|
+
cause: this.serialiseValue(this.cause)
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
static notFound(message, details, code) {
|
|
83
|
+
return new _AppError(message, "domain", { httpStatus: 404, details, code });
|
|
84
|
+
}
|
|
85
|
+
static forbidden(message, details, code) {
|
|
86
|
+
return new _AppError(message, "auth", { httpStatus: 403, details, code });
|
|
87
|
+
}
|
|
88
|
+
static badRequest(message, details, code) {
|
|
89
|
+
return new _AppError(message, "validation", { httpStatus: 400, details, code });
|
|
90
|
+
}
|
|
91
|
+
static unprocessable(message, details, code) {
|
|
92
|
+
return new _AppError(message, "validation", { httpStatus: 422, details, code });
|
|
93
|
+
}
|
|
94
|
+
static timeout(message, details, code) {
|
|
95
|
+
return new _AppError(message, "timeout", { details, code });
|
|
96
|
+
}
|
|
97
|
+
static canceled(message, details, code) {
|
|
98
|
+
return new _AppError(message, "canceled", { details, code });
|
|
99
|
+
}
|
|
100
|
+
static internal(message, cause, details, code) {
|
|
101
|
+
return new _AppError(message, "infra", { cause, details, code });
|
|
102
|
+
}
|
|
103
|
+
static upstream(message, cause, details, code) {
|
|
104
|
+
return new _AppError(message, "upstream", { cause, details, code });
|
|
105
|
+
}
|
|
106
|
+
static serviceUnavailable(message, cause, details, code) {
|
|
107
|
+
return new _AppError(message, "infra", { httpStatus: 503, cause, details, code });
|
|
108
|
+
}
|
|
109
|
+
static from(err, fallback = "Internal error") {
|
|
110
|
+
return err instanceof _AppError ? err : _AppError.internal(err?.message ?? fallback, err);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/utils/DataServices.ts
|
|
3
115
|
var runSchema = (schema, input) => {
|
|
4
116
|
if (!schema) return input;
|
|
5
117
|
return typeof schema.parse === "function" ? schema.parse(input) : schema(input);
|
|
6
118
|
};
|
|
119
|
+
function withDeadline(signal, ms) {
|
|
120
|
+
if (!ms) return signal;
|
|
121
|
+
const ctrl = new AbortController();
|
|
122
|
+
const onAbort = () => ctrl.abort(signal?.reason ?? new Error("Aborted"));
|
|
123
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
124
|
+
const t = setTimeout(() => ctrl.abort(new Error("DeadlineExceeded")), ms);
|
|
125
|
+
ctrl.signal.addEventListener(
|
|
126
|
+
"abort",
|
|
127
|
+
() => {
|
|
128
|
+
clearTimeout(t);
|
|
129
|
+
signal?.removeEventListener("abort", onAbort);
|
|
130
|
+
},
|
|
131
|
+
{ once: true }
|
|
132
|
+
);
|
|
133
|
+
return ctrl.signal;
|
|
134
|
+
}
|
|
7
135
|
function defineService(spec) {
|
|
8
136
|
const out = {};
|
|
9
137
|
for (const [name, v] of Object.entries(spec)) {
|
|
@@ -21,6 +149,38 @@ function defineService(spec) {
|
|
|
21
149
|
return Object.freeze(out);
|
|
22
150
|
}
|
|
23
151
|
var defineServiceRegistry = (registry) => Object.freeze(Object.fromEntries(Object.entries(registry).map(([k, v]) => [k, Object.freeze(v)])));
|
|
152
|
+
async function callServiceMethod(registry, serviceName, methodName, params, ctx) {
|
|
153
|
+
if (ctx.signal?.aborted) throw AppError.timeout("Request canceled");
|
|
154
|
+
const service = registry[serviceName];
|
|
155
|
+
if (!service) throw AppError.notFound(`Unknown service: ${serviceName}`);
|
|
156
|
+
const method = service[methodName];
|
|
157
|
+
if (!method) throw AppError.notFound(`Unknown method: ${serviceName}.${methodName}`);
|
|
158
|
+
const logger = ctx.logger?.child?.({
|
|
159
|
+
component: "service-call",
|
|
160
|
+
service: serviceName,
|
|
161
|
+
method: methodName,
|
|
162
|
+
traceId: ctx.traceId
|
|
163
|
+
});
|
|
164
|
+
const t0 = performance.now();
|
|
165
|
+
try {
|
|
166
|
+
const result = await method(params ?? {}, ctx);
|
|
167
|
+
if (typeof result !== "object" || result === null) {
|
|
168
|
+
throw AppError.internal(`Non-object result from ${serviceName}.${methodName}`);
|
|
169
|
+
}
|
|
170
|
+
logger?.debug?.({ ms: +(performance.now() - t0).toFixed(1) }, "Service method ok");
|
|
171
|
+
return result;
|
|
172
|
+
} catch (err) {
|
|
173
|
+
logger?.error?.(
|
|
174
|
+
{
|
|
175
|
+
params,
|
|
176
|
+
error: err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : String(err),
|
|
177
|
+
ms: +(performance.now() - t0).toFixed(1)
|
|
178
|
+
},
|
|
179
|
+
"Service method failed"
|
|
180
|
+
);
|
|
181
|
+
throw err instanceof AppError ? err : err instanceof Error ? AppError.internal(err.message, { cause: err }) : AppError.internal("Unknown error", { details: { err } });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
24
184
|
|
|
25
185
|
// src/Config.ts
|
|
26
186
|
function defineConfig(config) {
|
|
@@ -28,7 +188,10 @@ function defineConfig(config) {
|
|
|
28
188
|
return config;
|
|
29
189
|
}
|
|
30
190
|
export {
|
|
191
|
+
AppError,
|
|
192
|
+
callServiceMethod,
|
|
31
193
|
defineConfig,
|
|
32
194
|
defineService,
|
|
33
|
-
defineServiceRegistry
|
|
195
|
+
defineServiceRegistry,
|
|
196
|
+
withDeadline
|
|
34
197
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FastifyPluginCallback, FastifyPluginAsync, FastifyInstance } from 'fastify';
|
|
2
|
-
import { T as TaujsConfig, S as ServiceRegistry, D as DebugConfig, B as BaseLogger, A as AppConfig } from './Config-
|
|
3
|
-
export { I as InitialRouteParams
|
|
4
|
-
import 'vite';
|
|
2
|
+
import { T as TaujsConfig, S as ServiceRegistry, D as DebugConfig, B as BaseLogger, A as AppConfig } from './Config-CEhfq8Mm.js';
|
|
3
|
+
export { I as InitialRouteParams } from './Config-CEhfq8Mm.js';
|
|
4
|
+
import { InlineConfig } from 'vite';
|
|
5
5
|
|
|
6
6
|
type StaticMountEntry = {
|
|
7
7
|
plugin: FastifyPluginCallback<any> | FastifyPluginAsync<any>;
|
|
@@ -42,13 +42,84 @@ declare const createServer: (opts: CreateServerOptions) => Promise<CreateServerR
|
|
|
42
42
|
* including CSR, SSR, streaming, and middleware composition.
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
type ViteBuildContext = {
|
|
46
|
+
appId: string;
|
|
47
|
+
entryPoint: string;
|
|
48
|
+
isSSRBuild: boolean;
|
|
49
|
+
clientRoot: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* User-supplied vite config override.
|
|
53
|
+
* Can be a static config object or a function that receives build context.
|
|
54
|
+
*
|
|
55
|
+
* **Plugin order**: Framework applies plugins in this sequence:
|
|
56
|
+
* 1. `appConfig.plugins` (from taujs.config.ts)
|
|
57
|
+
* 2. `nodePolyfills({ include: ['stream'] })` (client builds only)
|
|
58
|
+
* 3. `userViteConfig.plugins` (from this option)
|
|
59
|
+
*
|
|
60
|
+
* If you need plugins before nodePolyfills, add them to `appConfig.plugins` instead.
|
|
61
|
+
*
|
|
62
|
+
* **Allowed customisations:**
|
|
63
|
+
* - `plugins`: Appended to framework plugin list
|
|
64
|
+
* - `define`: Shallow-merged with framework defines
|
|
65
|
+
* - `css.preprocessorOptions`: Deep-merged by preprocessor engine (scss, less, etc.)
|
|
66
|
+
* - `build.sourcemap`, `minify`, `terserOptions`: Direct overrides
|
|
67
|
+
* - `build.rollupOptions.external`: Direct override
|
|
68
|
+
* - `build.rollupOptions.output.manualChunks`: Merged into output config
|
|
69
|
+
* - `resolve.*` (except `alias`): Merged with framework resolve config
|
|
70
|
+
* - `esbuild`, `logLevel`, `optimizeDeps`: Direct overrides
|
|
71
|
+
*
|
|
72
|
+
* **Protected fields (cannot override):**
|
|
73
|
+
* - `root`, `base`, `publicDir`: Framework-controlled per-app paths
|
|
74
|
+
* - `build.outDir`: Framework manages `dist/client` vs `dist/ssr` separation
|
|
75
|
+
* - `build.ssr`, `ssrManifest`, `format`, `target`: Framework-controlled for SSR integrity
|
|
76
|
+
* - `build.rollupOptions.input`: Framework manages entry points
|
|
77
|
+
* - `resolve.alias`: Use top-level `alias` option in taujsBuild() instead
|
|
78
|
+
* - `server.*`: Ignored in builds (dev-mode only; configure in DevServer.ts)
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* // Static config
|
|
83
|
+
* vite: {
|
|
84
|
+
* plugins: [visualizer()],
|
|
85
|
+
* build: { sourcemap: 'inline' }
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* // Function-based (conditional per app/mode)
|
|
89
|
+
* vite: ({ isSSRBuild, entryPoint }) => ({
|
|
90
|
+
* plugins: isSSRBuild ? [] : [visualizer()],
|
|
91
|
+
* logLevel: entryPoint === 'admin' ? 'info' : 'warn'
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
type ViteConfigOverride = Partial<InlineConfig> | ((ctx: ViteBuildContext) => Partial<InlineConfig>);
|
|
96
|
+
declare function taujsBuild({ config, projectRoot, clientBaseDir, isSSRBuild, alias: userAlias, vite: userViteConfig, }: {
|
|
46
97
|
config: {
|
|
47
98
|
apps: AppConfig[];
|
|
48
99
|
};
|
|
49
100
|
projectRoot: string;
|
|
50
101
|
clientBaseDir: string;
|
|
51
102
|
isSSRBuild?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Top-level alias overrides. Use this instead of `vite.resolve.alias`.
|
|
105
|
+
* User aliases are merged with framework defaults; user values win on conflicts.
|
|
106
|
+
*
|
|
107
|
+
* Framework provides:
|
|
108
|
+
* - `@client`: Resolves to current app's root
|
|
109
|
+
* - `@server`: Resolves to `src/server`
|
|
110
|
+
* - `@shared`: Resolves to `src/shared`
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* alias: {
|
|
115
|
+
* '@utils': './src/utils',
|
|
116
|
+
* '@server': './custom-server', // overrides framework default
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
alias?: Record<string, string>;
|
|
121
|
+
/** User-supplied Vite config overrides (plugins, tuning, etc.) */
|
|
122
|
+
vite?: ViteConfigOverride;
|
|
52
123
|
}): Promise<void>;
|
|
53
124
|
|
|
54
125
|
interface MessageMetaLogger {
|
|
@@ -60,4 +131,4 @@ interface MessageMetaLogger {
|
|
|
60
131
|
}
|
|
61
132
|
declare function winstonAdapter(winston: MessageMetaLogger): BaseLogger;
|
|
62
133
|
|
|
63
|
-
export { createServer, taujsBuild, winstonAdapter };
|
|
134
|
+
export { BaseLogger, createServer, taujsBuild, winstonAdapter };
|
package/dist/index.js
CHANGED
|
@@ -189,7 +189,7 @@ var require_plugin = __commonJS({
|
|
|
189
189
|
|
|
190
190
|
// src/CreateServer.ts
|
|
191
191
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
192
|
-
import
|
|
192
|
+
import path7 from "path";
|
|
193
193
|
import { performance as performance3 } from "perf_hooks";
|
|
194
194
|
import fastifyStatic from "@fastify/static";
|
|
195
195
|
import Fastify from "fastify";
|
|
@@ -259,8 +259,8 @@ var extractRoutes = (taujsConfig) => {
|
|
|
259
259
|
apps.push({ appId: app.appId, routeCount: appRoutes.length });
|
|
260
260
|
allRoutes.push(...appRoutes);
|
|
261
261
|
}
|
|
262
|
-
for (const [
|
|
263
|
-
if (appIds.length > 1) warnings.push(`Route path "${
|
|
262
|
+
for (const [path9, appIds] of pathTracker.entries()) {
|
|
263
|
+
if (appIds.length > 1) warnings.push(`Route path "${path9}" is declared in multiple apps: ${appIds.join(", ")}`);
|
|
264
264
|
}
|
|
265
265
|
const sortedRoutes = allRoutes.sort((a, b) => computeScore(b.path) - computeScore(a.path));
|
|
266
266
|
const durationMs = performance.now() - t0;
|
|
@@ -344,8 +344,8 @@ function printContractReport(logger, report) {
|
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
|
-
var computeScore = (
|
|
348
|
-
return
|
|
347
|
+
var computeScore = (path9) => {
|
|
348
|
+
return path9.split("/").filter(Boolean).reduce((score, segment) => score + (segment.startsWith(":") ? 1 : 10), 0);
|
|
349
349
|
};
|
|
350
350
|
|
|
351
351
|
// src/logging/AppError.ts
|
|
@@ -609,11 +609,20 @@ var Logger = class _Logger {
|
|
|
609
609
|
if (!this.shouldEmit(level)) return;
|
|
610
610
|
const timestamp = this.formatTimestamp();
|
|
611
611
|
const wantCtx = this.config.includeContext === void 0 ? false : typeof this.config.includeContext === "function" ? this.config.includeContext(level) : this.config.includeContext;
|
|
612
|
-
const
|
|
612
|
+
const owner = this.config.custom;
|
|
613
|
+
const rawSink = owner && typeof owner[level] === "function" ? owner[level] : void 0;
|
|
614
|
+
const boundSink = rawSink ? rawSink.bind(owner) : void 0;
|
|
613
615
|
const consoleFallback = level === "error" ? console.error : level === "warn" ? console.warn : console.log;
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
616
|
+
const hasCustom = !!boundSink;
|
|
617
|
+
let baseMeta;
|
|
618
|
+
if (meta && typeof meta === "object" && !Array.isArray(meta)) {
|
|
619
|
+
baseMeta = meta;
|
|
620
|
+
} else if (meta === void 0) {
|
|
621
|
+
baseMeta = {};
|
|
622
|
+
} else {
|
|
623
|
+
baseMeta = { value: meta };
|
|
624
|
+
}
|
|
625
|
+
const withCtx = wantCtx && Object.keys(this.context).length > 0 ? { context: this.context, ...baseMeta } : baseMeta;
|
|
617
626
|
const finalMeta = this.shouldIncludeStack(level) ? withCtx : this.stripStacks(withCtx);
|
|
618
627
|
const hasMeta = finalMeta && typeof finalMeta === "object" ? Object.keys(finalMeta).length > 0 : false;
|
|
619
628
|
const levelText = level.toLowerCase() + (category ? `:${category.toLowerCase()}` : "");
|
|
@@ -632,16 +641,20 @@ var Logger = class _Logger {
|
|
|
632
641
|
return plainTag;
|
|
633
642
|
}
|
|
634
643
|
})();
|
|
635
|
-
const tagForOutput =
|
|
644
|
+
const tagForOutput = hasCustom ? plainTag : coloredTag;
|
|
636
645
|
const formatted = `${timestamp} ${tagForOutput} ${message}`;
|
|
637
|
-
if (this.config.singleLine && hasMeta && !
|
|
646
|
+
if (this.config.singleLine && hasMeta && !hasCustom) {
|
|
638
647
|
const metaStr = JSON.stringify(finalMeta).replace(/\n/g, "\\n");
|
|
639
648
|
consoleFallback(`${formatted} ${metaStr}`);
|
|
640
649
|
return;
|
|
641
650
|
}
|
|
642
|
-
if (
|
|
651
|
+
if (hasCustom) {
|
|
643
652
|
const obj = hasMeta ? finalMeta : {};
|
|
644
|
-
|
|
653
|
+
try {
|
|
654
|
+
boundSink(obj, formatted);
|
|
655
|
+
} catch {
|
|
656
|
+
hasMeta ? consoleFallback(formatted, finalMeta) : consoleFallback(formatted);
|
|
657
|
+
}
|
|
645
658
|
} else {
|
|
646
659
|
hasMeta ? consoleFallback(formatted, finalMeta) : consoleFallback(formatted);
|
|
647
660
|
}
|
|
@@ -839,6 +852,7 @@ var verifyContracts = (app, routes, contracts, security) => {
|
|
|
839
852
|
|
|
840
853
|
// src/SSRServer.ts
|
|
841
854
|
var import_fastify_plugin3 = __toESM(require_plugin(), 1);
|
|
855
|
+
import path6 from "path";
|
|
842
856
|
|
|
843
857
|
// src/logging/utils/index.ts
|
|
844
858
|
var httpStatusFrom = (err, fallback = 500) => err instanceof AppError ? err.httpStatus : fallback;
|
|
@@ -879,6 +893,12 @@ import { match } from "path-to-regexp";
|
|
|
879
893
|
|
|
880
894
|
// src/utils/DataServices.ts
|
|
881
895
|
import { performance as performance2 } from "perf_hooks";
|
|
896
|
+
function createCaller(registry, ctx) {
|
|
897
|
+
return (serviceName, methodName, args) => callServiceMethod(registry, serviceName, methodName, args ?? {}, ctx);
|
|
898
|
+
}
|
|
899
|
+
function ensureServiceCaller(registry, ctx) {
|
|
900
|
+
if (!ctx.call) ctx.call = createCaller(registry, ctx);
|
|
901
|
+
}
|
|
882
902
|
async function callServiceMethod(registry, serviceName, methodName, params, ctx) {
|
|
883
903
|
if (ctx.signal?.aborted) throw AppError.timeout("Request canceled");
|
|
884
904
|
const service = registry[serviceName];
|
|
@@ -929,15 +949,15 @@ var safeDecode = (value) => {
|
|
|
929
949
|
return value;
|
|
930
950
|
}
|
|
931
951
|
};
|
|
932
|
-
var cleanPath = (
|
|
933
|
-
if (!
|
|
934
|
-
const basePart =
|
|
952
|
+
var cleanPath = (path9) => {
|
|
953
|
+
if (!path9) return "/";
|
|
954
|
+
const basePart = path9.split("?")[0];
|
|
935
955
|
const base = basePart ? basePart.split("#")[0] : "/";
|
|
936
956
|
return base || "/";
|
|
937
957
|
};
|
|
938
|
-
var calculateSpecificity = (
|
|
958
|
+
var calculateSpecificity = (path9) => {
|
|
939
959
|
let score = 0;
|
|
940
|
-
const segments =
|
|
960
|
+
const segments = path9.split("/").filter(Boolean);
|
|
941
961
|
for (const segment of segments) {
|
|
942
962
|
if (segment.startsWith(":")) {
|
|
943
963
|
score += 1;
|
|
@@ -962,9 +982,9 @@ var createRouteMatchers = (routes) => {
|
|
|
962
982
|
});
|
|
963
983
|
};
|
|
964
984
|
var matchRoute = (url, routeMatchers) => {
|
|
965
|
-
const
|
|
985
|
+
const path9 = cleanPath(url);
|
|
966
986
|
for (const { route, matcher, keys } of routeMatchers) {
|
|
967
|
-
const match2 = matcher(
|
|
987
|
+
const match2 = matcher(path9);
|
|
968
988
|
if (match2) {
|
|
969
989
|
return {
|
|
970
990
|
route,
|
|
@@ -978,14 +998,16 @@ var matchRoute = (url, routeMatchers) => {
|
|
|
978
998
|
var fetchInitialData = async (attr, params, serviceRegistry, ctx, callServiceMethodImpl = callServiceMethod) => {
|
|
979
999
|
const dataHandler = attr?.data;
|
|
980
1000
|
if (!dataHandler || typeof dataHandler !== "function") return {};
|
|
1001
|
+
const ctxForData = {
|
|
1002
|
+
...ctx,
|
|
1003
|
+
headers: ctx.headers ?? {}
|
|
1004
|
+
};
|
|
1005
|
+
ensureServiceCaller(serviceRegistry, ctxForData);
|
|
981
1006
|
try {
|
|
982
|
-
const result = await dataHandler(params,
|
|
983
|
-
...ctx,
|
|
984
|
-
headers: ctx.headers ?? {}
|
|
985
|
-
});
|
|
1007
|
+
const result = await dataHandler(params, ctxForData);
|
|
986
1008
|
if (isServiceDescriptor(result)) {
|
|
987
1009
|
const { serviceName, serviceMethod, args } = result;
|
|
988
|
-
return callServiceMethodImpl(serviceRegistry, serviceName, serviceMethod, args ?? {},
|
|
1010
|
+
return callServiceMethodImpl(serviceRegistry, serviceName, serviceMethod, args ?? {}, ctxForData);
|
|
989
1011
|
}
|
|
990
1012
|
if (isPlainObject(result)) return result;
|
|
991
1013
|
throw AppError.badRequest("attr.data must return a plain object or a ServiceDescriptor");
|
|
@@ -1102,9 +1124,9 @@ var mergeDirectives = (base, override) => {
|
|
|
1102
1124
|
}
|
|
1103
1125
|
return merged;
|
|
1104
1126
|
};
|
|
1105
|
-
var findMatchingRoute = (routeMatchers,
|
|
1127
|
+
var findMatchingRoute = (routeMatchers, path9) => {
|
|
1106
1128
|
if (!routeMatchers) return null;
|
|
1107
|
-
const match2 = matchRoute(
|
|
1129
|
+
const match2 = matchRoute(path9, routeMatchers);
|
|
1108
1130
|
return match2 ? { route: match2.route, params: match2.params } : null;
|
|
1109
1131
|
};
|
|
1110
1132
|
var cspPlugin = (0, import_fastify_plugin.default)(
|
|
@@ -1434,8 +1456,9 @@ var loadAssets = async (processedConfigs, baseClientRoot, bootstrapModules, cssL
|
|
|
1434
1456
|
debug: opts.debug,
|
|
1435
1457
|
includeContext: true
|
|
1436
1458
|
});
|
|
1459
|
+
const projectRoot = opts.projectRoot ?? path2.resolve(process.cwd());
|
|
1437
1460
|
for (const config of processedConfigs) {
|
|
1438
|
-
const { clientRoot, entryClient, entryServer, htmlTemplate } = config;
|
|
1461
|
+
const { clientRoot, entryClient, entryServer, htmlTemplate, entryPoint } = config;
|
|
1439
1462
|
try {
|
|
1440
1463
|
const templateHtmlPath = path2.join(clientRoot, htmlTemplate);
|
|
1441
1464
|
const templateHtml = await readFile(templateHtmlPath, "utf-8");
|
|
@@ -1444,11 +1467,13 @@ var loadAssets = async (processedConfigs, baseClientRoot, bootstrapModules, cssL
|
|
|
1444
1467
|
const adjustedRelativePath = relativeBasePath ? `/${relativeBasePath}` : "";
|
|
1445
1468
|
if (!isDevelopment) {
|
|
1446
1469
|
try {
|
|
1447
|
-
const
|
|
1470
|
+
const clientDistPath = path2.resolve(projectRoot, "client", entryPoint);
|
|
1471
|
+
const manifestPath = path2.join(clientDistPath, ".vite/manifest.json");
|
|
1448
1472
|
const manifestContent = await readFile(manifestPath, "utf-8");
|
|
1449
1473
|
const manifest = JSON.parse(manifestContent);
|
|
1450
1474
|
manifests.set(clientRoot, manifest);
|
|
1451
|
-
const
|
|
1475
|
+
const ssrDistPath = path2.resolve(projectRoot, "ssr", entryPoint);
|
|
1476
|
+
const ssrManifestPath = path2.join(ssrDistPath, ".vite/ssr-manifest.json");
|
|
1452
1477
|
const ssrManifestContent = await readFile(ssrManifestPath, "utf-8");
|
|
1453
1478
|
const ssrManifest = JSON.parse(ssrManifestContent);
|
|
1454
1479
|
ssrManifests.set(clientRoot, ssrManifest);
|
|
@@ -1468,7 +1493,7 @@ var loadAssets = async (processedConfigs, baseClientRoot, bootstrapModules, cssL
|
|
|
1468
1493
|
preloadLinks.set(clientRoot, preloadLink);
|
|
1469
1494
|
const cssLink = getCssLinks(manifest, adjustedRelativePath);
|
|
1470
1495
|
cssLinks.set(clientRoot, cssLink);
|
|
1471
|
-
const renderModulePath = path2.join(
|
|
1496
|
+
const renderModulePath = path2.join(ssrDistPath, `${entryServer}.js`);
|
|
1472
1497
|
const moduleUrl = pathToFileURL(renderModulePath).href;
|
|
1473
1498
|
try {
|
|
1474
1499
|
const importedModule = await import(moduleUrl);
|
|
@@ -1476,7 +1501,7 @@ var loadAssets = async (processedConfigs, baseClientRoot, bootstrapModules, cssL
|
|
|
1476
1501
|
} catch (err) {
|
|
1477
1502
|
throw AppError.internal(`Failed to load render module ${renderModulePath}`, {
|
|
1478
1503
|
cause: err,
|
|
1479
|
-
details: { moduleUrl, clientRoot, entryServer }
|
|
1504
|
+
details: { moduleUrl, clientRoot, entryServer, ssrDistPath }
|
|
1480
1505
|
});
|
|
1481
1506
|
}
|
|
1482
1507
|
} catch (err) {
|
|
@@ -1687,10 +1712,15 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1687
1712
|
if (renderType === RENDERTYPE.ssr) {
|
|
1688
1713
|
const { renderSSR } = renderModule;
|
|
1689
1714
|
if (!renderSSR) {
|
|
1690
|
-
throw AppError.internal(
|
|
1691
|
-
|
|
1692
|
-
|
|
1715
|
+
throw AppError.internal(
|
|
1716
|
+
"ssr",
|
|
1717
|
+
{
|
|
1718
|
+
details: { clientRoot, availableFunctions: Object.keys(renderModule) }
|
|
1719
|
+
},
|
|
1720
|
+
"renderSSR function not found in module"
|
|
1721
|
+
);
|
|
1693
1722
|
}
|
|
1723
|
+
logger.debug?.("ssr", {}, "ssr requested");
|
|
1694
1724
|
const ac = new AbortController();
|
|
1695
1725
|
const onAborted = () => ac.abort("client_aborted");
|
|
1696
1726
|
req.raw.on("aborted", onAborted);
|
|
@@ -1699,7 +1729,7 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1699
1729
|
});
|
|
1700
1730
|
reply.raw.on("finish", () => req.raw.off("aborted", onAborted));
|
|
1701
1731
|
if (ac.signal.aborted) {
|
|
1702
|
-
logger.warn("SSR skipped; already aborted"
|
|
1732
|
+
logger.warn({ url: req.url }, "SSR skipped; already aborted");
|
|
1703
1733
|
return;
|
|
1704
1734
|
}
|
|
1705
1735
|
const initialDataResolved = await initialDataInput();
|
|
@@ -1709,14 +1739,31 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1709
1739
|
const res = await renderSSR(initialDataResolved, req.url, attr?.meta, ac.signal, { logger: reqLogger });
|
|
1710
1740
|
headContent = res.headContent;
|
|
1711
1741
|
appHtml = res.appHtml;
|
|
1742
|
+
logger.debug?.("ssr", {}, "ssr data resolved");
|
|
1743
|
+
if (ac.signal.aborted) {
|
|
1744
|
+
logger.warn({}, "SSR completed but client disconnected");
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1712
1747
|
} catch (err) {
|
|
1713
1748
|
const msg = String(err?.message ?? err ?? "");
|
|
1714
1749
|
const benign = REGEX.BENIGN_NET_ERR.test(msg);
|
|
1715
1750
|
if (ac.signal.aborted || benign) {
|
|
1716
|
-
logger.warn(
|
|
1751
|
+
logger.warn(
|
|
1752
|
+
{
|
|
1753
|
+
url: req.url,
|
|
1754
|
+
reason: msg
|
|
1755
|
+
},
|
|
1756
|
+
"SSR aborted mid-render (benign)"
|
|
1757
|
+
);
|
|
1717
1758
|
return;
|
|
1718
1759
|
}
|
|
1719
|
-
logger.error(
|
|
1760
|
+
logger.error(
|
|
1761
|
+
{
|
|
1762
|
+
url: req.url,
|
|
1763
|
+
error: normaliseError(err)
|
|
1764
|
+
},
|
|
1765
|
+
"SSR render failed"
|
|
1766
|
+
);
|
|
1720
1767
|
throw err;
|
|
1721
1768
|
}
|
|
1722
1769
|
let aggregateHeadContent = headContent;
|
|
@@ -1728,13 +1775,14 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1728
1775
|
const bootstrapScriptTag = shouldHydrate && bootstrapModule ? `<script${nonceAttr} type="module" src="${bootstrapModule}" defer></script>` : "";
|
|
1729
1776
|
const safeAppHtml = appHtml.trim();
|
|
1730
1777
|
const fullHtml = rebuildTemplate(templateParts, aggregateHeadContent, `${safeAppHtml}${initialDataScript}${bootstrapScriptTag}`);
|
|
1778
|
+
logger.debug?.("ssr", {}, "ssr template rebuilt and sending response");
|
|
1731
1779
|
try {
|
|
1732
1780
|
return reply.status(200).header("Content-Type", "text/html").send(fullHtml);
|
|
1733
1781
|
} catch (err) {
|
|
1734
1782
|
const msg = String(err?.message ?? err ?? "");
|
|
1735
1783
|
const benign = REGEX.BENIGN_NET_ERR.test(msg);
|
|
1736
|
-
if (!benign) logger.error(
|
|
1737
|
-
else logger.warn(
|
|
1784
|
+
if (!benign) logger.error({ url: req.url, error: normaliseError(err) }, "SSR send failed");
|
|
1785
|
+
else logger.warn({ url: req.url, reason: msg }, "SSR send aborted (benign)");
|
|
1738
1786
|
return;
|
|
1739
1787
|
}
|
|
1740
1788
|
} else {
|
|
@@ -1744,30 +1792,44 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1744
1792
|
details: { clientRoot, availableFunctions: Object.keys(renderModule) }
|
|
1745
1793
|
});
|
|
1746
1794
|
}
|
|
1795
|
+
const headers2 = reply.getHeaders();
|
|
1796
|
+
headers2["Content-Type"] = "text/html; charset=utf-8";
|
|
1747
1797
|
const cspHeader = reply.getHeader("Content-Security-Policy");
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
});
|
|
1798
|
+
if (cspHeader) headers2["Content-Security-Policy"] = cspHeader;
|
|
1799
|
+
reply.raw.writeHead(200, headers2);
|
|
1800
|
+
const abortedState = { aborted: false };
|
|
1752
1801
|
const ac = new AbortController();
|
|
1753
|
-
const onAborted = () =>
|
|
1802
|
+
const onAborted = () => {
|
|
1803
|
+
if (!abortedState.aborted) {
|
|
1804
|
+
logger.warn({}, "Client disconnected before stream finished");
|
|
1805
|
+
abortedState.aborted = true;
|
|
1806
|
+
}
|
|
1807
|
+
ac.abort();
|
|
1808
|
+
};
|
|
1754
1809
|
req.raw.on("aborted", onAborted);
|
|
1755
1810
|
reply.raw.on("close", () => {
|
|
1756
|
-
if (!reply.raw.writableEnded)
|
|
1811
|
+
if (!reply.raw.writableEnded) {
|
|
1812
|
+
if (!abortedState.aborted) {
|
|
1813
|
+
logger.warn({}, "Client disconnected before stream finished");
|
|
1814
|
+
abortedState.aborted = true;
|
|
1815
|
+
}
|
|
1816
|
+
ac.abort();
|
|
1817
|
+
}
|
|
1818
|
+
});
|
|
1819
|
+
reply.raw.on("finish", () => {
|
|
1820
|
+
req.raw.off("aborted", onAborted);
|
|
1757
1821
|
});
|
|
1758
|
-
reply.raw.on("finish", () => req.raw.off("aborted", onAborted));
|
|
1759
1822
|
const shouldHydrate = attr?.hydrate !== false;
|
|
1760
|
-
const abortedState = { aborted: false };
|
|
1761
1823
|
const isBenignSocketAbort = (e) => {
|
|
1762
1824
|
const msg = String(e?.message ?? e ?? "");
|
|
1763
1825
|
return REGEX.BENIGN_NET_ERR.test(msg);
|
|
1764
1826
|
};
|
|
1765
1827
|
const writable = new PassThrough();
|
|
1766
1828
|
writable.on("error", (err) => {
|
|
1767
|
-
if (!isBenignSocketAbort(err)) logger.error(
|
|
1829
|
+
if (!isBenignSocketAbort(err)) logger.error({ error: err }, "PassThrough error:");
|
|
1768
1830
|
});
|
|
1769
1831
|
reply.raw.on("error", (err) => {
|
|
1770
|
-
if (!isBenignSocketAbort(err)) logger.error("HTTP socket error:"
|
|
1832
|
+
if (!isBenignSocketAbort(err)) logger.error({ error: err }, "HTTP socket error:");
|
|
1771
1833
|
});
|
|
1772
1834
|
writable.pipe(reply.raw, { end: false });
|
|
1773
1835
|
let finalData = void 0;
|
|
@@ -1787,30 +1849,33 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1787
1849
|
},
|
|
1788
1850
|
onError: (err) => {
|
|
1789
1851
|
if (abortedState.aborted || isBenignSocketAbort(err)) {
|
|
1790
|
-
logger.warn("Client disconnected before stream finished");
|
|
1852
|
+
logger.warn({}, "Client disconnected before stream finished");
|
|
1791
1853
|
try {
|
|
1792
1854
|
if (!reply.raw.writableEnded && !reply.raw.destroyed) reply.raw.destroy();
|
|
1793
1855
|
} catch (e) {
|
|
1794
|
-
logger.debug?.("
|
|
1856
|
+
logger.debug?.("ssr", { error: normaliseError(e) }, "stream teardown: destroy() failed");
|
|
1795
1857
|
}
|
|
1796
1858
|
return;
|
|
1797
1859
|
}
|
|
1798
1860
|
abortedState.aborted = true;
|
|
1799
|
-
logger.error(
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1861
|
+
logger.error(
|
|
1862
|
+
{
|
|
1863
|
+
error: normaliseError(err),
|
|
1864
|
+
clientRoot,
|
|
1865
|
+
url: req.url
|
|
1866
|
+
},
|
|
1867
|
+
"Critical rendering error during stream"
|
|
1868
|
+
);
|
|
1804
1869
|
try {
|
|
1805
1870
|
ac?.abort?.();
|
|
1806
1871
|
} catch (e) {
|
|
1807
|
-
logger.debug?.("
|
|
1872
|
+
logger.debug?.("ssr", { error: normaliseError(e) }, "stream teardown: abort() failed");
|
|
1808
1873
|
}
|
|
1809
1874
|
const reason = toReason(err);
|
|
1810
1875
|
try {
|
|
1811
1876
|
if (!reply.raw.writableEnded && !reply.raw.destroyed) reply.raw.destroy(reason);
|
|
1812
1877
|
} catch (e) {
|
|
1813
|
-
logger.debug?.("
|
|
1878
|
+
logger.debug?.("ssr", { error: normaliseError(e) }, "stream teardown: destroy() failed");
|
|
1814
1879
|
}
|
|
1815
1880
|
}
|
|
1816
1881
|
},
|
|
@@ -1897,8 +1962,33 @@ var handleNotFound = async (req, reply, processedConfigs, maps, opts = {}) => {
|
|
|
1897
1962
|
}
|
|
1898
1963
|
};
|
|
1899
1964
|
|
|
1965
|
+
// src/utils/ResolveRouteData.ts
|
|
1966
|
+
async function resolveRouteData(url, opts) {
|
|
1967
|
+
const { req, reply, routeMatchers, serviceRegistry, logger } = opts;
|
|
1968
|
+
const match2 = matchRoute(url, routeMatchers);
|
|
1969
|
+
if (!match2) {
|
|
1970
|
+
throw AppError.notFound("route_not_found", {
|
|
1971
|
+
details: { url }
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
const { route, params } = match2;
|
|
1975
|
+
const attr = route.attr;
|
|
1976
|
+
if (!attr?.data) {
|
|
1977
|
+
throw AppError.notFound("no_data_handler", {
|
|
1978
|
+
details: {
|
|
1979
|
+
url,
|
|
1980
|
+
path: route.path,
|
|
1981
|
+
appId: route.appId
|
|
1982
|
+
}
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
const ctx = createRequestContext(req, reply, logger);
|
|
1986
|
+
return fetchInitialData(attr, params, serviceRegistry, ctx);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1900
1989
|
// src/utils/StaticAssets.ts
|
|
1901
|
-
|
|
1990
|
+
import path5 from "path";
|
|
1991
|
+
function normaliseStaticAssets(reg) {
|
|
1902
1992
|
if (!reg) return [];
|
|
1903
1993
|
return Array.isArray(reg) ? reg : [reg];
|
|
1904
1994
|
}
|
|
@@ -1906,11 +1996,14 @@ function prefixWeight(prefix) {
|
|
|
1906
1996
|
if (typeof prefix !== "string" || prefix === "/" || prefix.length === 0) return 0;
|
|
1907
1997
|
return prefix.split("/").filter(Boolean).length;
|
|
1908
1998
|
}
|
|
1909
|
-
async function registerStaticAssets(app, baseClientRoot, reg, defaults) {
|
|
1910
|
-
const
|
|
1999
|
+
async function registerStaticAssets(app, baseClientRoot, reg, defaults, projectRoot) {
|
|
2000
|
+
const isDevelopment2 = process.env.NODE_ENV === "development";
|
|
2001
|
+
const effectiveProjectRoot = projectRoot ?? path5.resolve(process.cwd());
|
|
2002
|
+
const staticRoot = isDevelopment2 ? baseClientRoot : path5.resolve(effectiveProjectRoot, "client");
|
|
2003
|
+
const entries = normaliseStaticAssets(reg).map(({ plugin, options }) => ({
|
|
1911
2004
|
plugin,
|
|
1912
2005
|
options: {
|
|
1913
|
-
root:
|
|
2006
|
+
root: staticRoot,
|
|
1914
2007
|
prefix: "/",
|
|
1915
2008
|
index: false,
|
|
1916
2009
|
wildcard: false,
|
|
@@ -1939,6 +2032,7 @@ var SSRServer = (0, import_fastify_plugin3.default)(
|
|
|
1939
2032
|
const processedConfigs = processConfigs(configs, baseClientRoot, TEMPLATE);
|
|
1940
2033
|
const routeMatchers = createRouteMatchers(routes);
|
|
1941
2034
|
let viteDevServer;
|
|
2035
|
+
const projectRoot = path6.resolve(baseClientRoot, "..");
|
|
1942
2036
|
await loadAssets(
|
|
1943
2037
|
processedConfigs,
|
|
1944
2038
|
baseClientRoot,
|
|
@@ -1951,10 +2045,11 @@ var SSRServer = (0, import_fastify_plugin3.default)(
|
|
|
1951
2045
|
maps.templates,
|
|
1952
2046
|
{
|
|
1953
2047
|
debug: opts.debug,
|
|
1954
|
-
logger
|
|
2048
|
+
logger,
|
|
2049
|
+
projectRoot
|
|
1955
2050
|
}
|
|
1956
2051
|
);
|
|
1957
|
-
if (opts.staticAssets) await registerStaticAssets(app, baseClientRoot, opts.staticAssets);
|
|
2052
|
+
if (opts.staticAssets) await registerStaticAssets(app, baseClientRoot, opts.staticAssets, void 0, projectRoot);
|
|
1958
2053
|
if (security?.csp?.reporting) {
|
|
1959
2054
|
app.register(cspReportPlugin, {
|
|
1960
2055
|
path: security.csp.reporting.endpoint,
|
|
@@ -1971,6 +2066,23 @@ var SSRServer = (0, import_fastify_plugin3.default)(
|
|
|
1971
2066
|
});
|
|
1972
2067
|
if (isDevelopment) viteDevServer = await setupDevServer(app, baseClientRoot, alias, opts.debug, opts.devNet);
|
|
1973
2068
|
app.addHook("onRequest", createAuthHook(routeMatchers, logger));
|
|
2069
|
+
app.get("/__taujs/data", async (req, reply) => {
|
|
2070
|
+
const query = req.query;
|
|
2071
|
+
const url = typeof query.url === "string" ? query.url : "";
|
|
2072
|
+
if (!url) {
|
|
2073
|
+
throw AppError.badRequest("url query param required", {
|
|
2074
|
+
details: { query }
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
const data = await resolveRouteData(url, {
|
|
2078
|
+
req,
|
|
2079
|
+
reply,
|
|
2080
|
+
routeMatchers,
|
|
2081
|
+
serviceRegistry,
|
|
2082
|
+
logger
|
|
2083
|
+
});
|
|
2084
|
+
return reply.status(200).send({ data });
|
|
2085
|
+
});
|
|
1974
2086
|
app.get("/*", async (req, reply) => {
|
|
1975
2087
|
await handleRender(req, reply, routeMatchers, processedConfigs, serviceRegistry, maps, {
|
|
1976
2088
|
debug: opts.debug,
|
|
@@ -2026,9 +2138,9 @@ var SSRServer = (0, import_fastify_plugin3.default)(
|
|
|
2026
2138
|
// src/CreateServer.ts
|
|
2027
2139
|
var createServer = async (opts) => {
|
|
2028
2140
|
const t0 = performance3.now();
|
|
2029
|
-
const clientRoot = opts.clientRoot ??
|
|
2141
|
+
const clientRoot = opts.clientRoot ?? path7.resolve(process.cwd(), "client");
|
|
2030
2142
|
const app = opts.fastify ?? Fastify({ logger: false });
|
|
2031
|
-
const fastifyLogger = app.log && app.log.level !== "silent" ? app.log : void 0;
|
|
2143
|
+
const fastifyLogger = app.log && app.log.level && app.log.level !== "silent" ? app.log : void 0;
|
|
2032
2144
|
const logger = createLogger({
|
|
2033
2145
|
debug: opts.debug,
|
|
2034
2146
|
custom: opts.logger ?? fastifyLogger,
|
|
@@ -2095,18 +2207,149 @@ ${import_picocolors4.default.bgGreen(import_picocolors4.default.black(` ${CONTEN
|
|
|
2095
2207
|
};
|
|
2096
2208
|
|
|
2097
2209
|
// src/Build.ts
|
|
2098
|
-
import
|
|
2210
|
+
import { existsSync } from "fs";
|
|
2211
|
+
import path8 from "path";
|
|
2099
2212
|
import { build } from "vite";
|
|
2100
|
-
|
|
2213
|
+
function resolveInputs(isSSRBuild, mainExists, paths) {
|
|
2214
|
+
if (isSSRBuild) return { server: paths.server };
|
|
2215
|
+
if (mainExists) return { client: paths.client, main: paths.main };
|
|
2216
|
+
return { client: paths.client };
|
|
2217
|
+
}
|
|
2218
|
+
function getFrameworkInvariants(config) {
|
|
2219
|
+
return {
|
|
2220
|
+
root: config.root || "",
|
|
2221
|
+
base: config.base || "/",
|
|
2222
|
+
publicDir: config.publicDir === void 0 ? "public" : config.publicDir,
|
|
2223
|
+
build: {
|
|
2224
|
+
outDir: config.build?.outDir || "",
|
|
2225
|
+
manifest: config.build?.manifest ?? false,
|
|
2226
|
+
ssr: config.build?.ssr ?? void 0,
|
|
2227
|
+
// Preserve exact type
|
|
2228
|
+
ssrManifest: config.build?.ssrManifest ?? false,
|
|
2229
|
+
format: config.build?.format,
|
|
2230
|
+
target: config.build?.target,
|
|
2231
|
+
rollupOptions: {
|
|
2232
|
+
input: config.build?.rollupOptions?.input || {}
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
function mergeViteConfig(framework, userOverride, context) {
|
|
2238
|
+
if (!userOverride) return framework;
|
|
2239
|
+
const userConfig = typeof userOverride === "function" && context ? userOverride(context) : userOverride;
|
|
2240
|
+
const invariants = getFrameworkInvariants(framework);
|
|
2241
|
+
const merged = {
|
|
2242
|
+
...framework,
|
|
2243
|
+
build: { ...framework.build ?? {} },
|
|
2244
|
+
css: { ...framework.css ?? {} },
|
|
2245
|
+
resolve: { ...framework.resolve ?? {} },
|
|
2246
|
+
plugins: [...framework.plugins ?? []],
|
|
2247
|
+
define: { ...framework.define ?? {} }
|
|
2248
|
+
};
|
|
2249
|
+
const ignoredKeys = [];
|
|
2250
|
+
if (userConfig.plugins) {
|
|
2251
|
+
const frameworkPlugins = merged.plugins;
|
|
2252
|
+
merged.plugins = [...frameworkPlugins, ...userConfig.plugins];
|
|
2253
|
+
}
|
|
2254
|
+
if (userConfig.define && typeof userConfig.define === "object") {
|
|
2255
|
+
merged.define = {
|
|
2256
|
+
...merged.define,
|
|
2257
|
+
...userConfig.define
|
|
2258
|
+
};
|
|
2259
|
+
}
|
|
2260
|
+
if (userConfig.css?.preprocessorOptions && typeof userConfig.css.preprocessorOptions === "object") {
|
|
2261
|
+
const fpp = merged.css.preprocessorOptions ?? {};
|
|
2262
|
+
const upp = userConfig.css.preprocessorOptions;
|
|
2263
|
+
merged.css.preprocessorOptions = Object.keys({ ...fpp, ...upp }).reduce((acc, engine) => {
|
|
2264
|
+
const fppEngine = fpp[engine];
|
|
2265
|
+
const uppEngine = upp[engine];
|
|
2266
|
+
acc[engine] = { ...fppEngine ?? {}, ...uppEngine ?? {} };
|
|
2267
|
+
return acc;
|
|
2268
|
+
}, {});
|
|
2269
|
+
}
|
|
2270
|
+
if (userConfig.build) {
|
|
2271
|
+
const protectedBuildFields = ["outDir", "ssr", "ssrManifest", "format", "target"];
|
|
2272
|
+
for (const field of protectedBuildFields) {
|
|
2273
|
+
if (field in userConfig.build) {
|
|
2274
|
+
ignoredKeys.push(`build.${field}`);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
if ("sourcemap" in userConfig.build) merged.build.sourcemap = userConfig.build.sourcemap;
|
|
2278
|
+
if ("minify" in userConfig.build) merged.build.minify = userConfig.build.minify;
|
|
2279
|
+
if (userConfig.build.terserOptions && typeof userConfig.build.terserOptions === "object") {
|
|
2280
|
+
merged.build.terserOptions = {
|
|
2281
|
+
...merged.build.terserOptions ?? {},
|
|
2282
|
+
...userConfig.build.terserOptions
|
|
2283
|
+
};
|
|
2284
|
+
}
|
|
2285
|
+
if (userConfig.build.rollupOptions) {
|
|
2286
|
+
if (!merged.build.rollupOptions) {
|
|
2287
|
+
merged.build.rollupOptions = {};
|
|
2288
|
+
}
|
|
2289
|
+
const userRollup = userConfig.build.rollupOptions;
|
|
2290
|
+
if ("input" in userRollup) ignoredKeys.push("build.rollupOptions.input");
|
|
2291
|
+
if ("external" in userRollup) merged.build.rollupOptions.external = userRollup.external;
|
|
2292
|
+
if (userRollup.output) {
|
|
2293
|
+
const mro = merged.build.rollupOptions ??= {};
|
|
2294
|
+
const uo = Array.isArray(userRollup.output) ? userRollup.output[0] : userRollup.output;
|
|
2295
|
+
const baseOut = Array.isArray(mro.output) ? mro.output[0] ?? {} : mro.output ?? {};
|
|
2296
|
+
mro.output = { ...baseOut, ...uo?.manualChunks ? { manualChunks: uo.manualChunks } : {} };
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
if (userConfig.resolve) {
|
|
2301
|
+
const userResolve = userConfig.resolve;
|
|
2302
|
+
const { alias: _ignore, ...resolveRest } = userResolve;
|
|
2303
|
+
if (_ignore) ignoredKeys.push("resolve.alias");
|
|
2304
|
+
merged.resolve = {
|
|
2305
|
+
...merged.resolve,
|
|
2306
|
+
...resolveRest
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
if (userConfig.server) ignoredKeys.push("server (ignored in build; dev-only)");
|
|
2310
|
+
if ("root" in userConfig) ignoredKeys.push("root");
|
|
2311
|
+
if ("base" in userConfig) ignoredKeys.push("base");
|
|
2312
|
+
if ("publicDir" in userConfig) ignoredKeys.push("publicDir");
|
|
2313
|
+
const safeTopLevelKeys = /* @__PURE__ */ new Set([
|
|
2314
|
+
"esbuild",
|
|
2315
|
+
"logLevel",
|
|
2316
|
+
"envPrefix",
|
|
2317
|
+
"optimizeDeps",
|
|
2318
|
+
"ssr"
|
|
2319
|
+
// NOTE: NOT 'server' (build-time irrelevant; dev-server only)
|
|
2320
|
+
]);
|
|
2321
|
+
for (const [key, value] of Object.entries(userConfig)) {
|
|
2322
|
+
if (safeTopLevelKeys.has(key)) merged[key] = value;
|
|
2323
|
+
}
|
|
2324
|
+
merged.root = invariants.root;
|
|
2325
|
+
merged.base = invariants.base;
|
|
2326
|
+
merged.publicDir = invariants.publicDir;
|
|
2327
|
+
merged.build.outDir = invariants.build.outDir;
|
|
2328
|
+
merged.build.manifest = invariants.build.manifest;
|
|
2329
|
+
if (invariants.build.ssr !== void 0) merged.build.ssr = invariants.build.ssr;
|
|
2330
|
+
merged.build.ssrManifest = invariants.build.ssrManifest;
|
|
2331
|
+
if (invariants.build.format) merged.build.format = invariants.build.format;
|
|
2332
|
+
if (invariants.build.target) merged.build.target = invariants.build.target;
|
|
2333
|
+
if (!merged.build.rollupOptions) merged.build.rollupOptions = {};
|
|
2334
|
+
merged.build.rollupOptions.input = invariants.build.rollupOptions.input;
|
|
2335
|
+
if (ignoredKeys.length > 0) {
|
|
2336
|
+
const uniqueKeys = [...new Set(ignoredKeys)];
|
|
2337
|
+
const prefix = context ? `[taujs:build:${context.entryPoint}]` : "[taujs:build]";
|
|
2338
|
+
console.warn(`${prefix} Ignored Vite config overrides: ${uniqueKeys.join(", ")}`);
|
|
2339
|
+
}
|
|
2340
|
+
return merged;
|
|
2341
|
+
}
|
|
2101
2342
|
async function taujsBuild({
|
|
2102
2343
|
config,
|
|
2103
2344
|
projectRoot,
|
|
2104
2345
|
clientBaseDir,
|
|
2105
|
-
isSSRBuild = process.env.BUILD_MODE === "ssr"
|
|
2346
|
+
isSSRBuild = process.env.BUILD_MODE === "ssr",
|
|
2347
|
+
alias: userAlias,
|
|
2348
|
+
vite: userViteConfig
|
|
2106
2349
|
}) {
|
|
2107
2350
|
const deleteDist = async () => {
|
|
2108
2351
|
const { rm } = await import("fs/promises");
|
|
2109
|
-
const distPath =
|
|
2352
|
+
const distPath = path8.resolve(projectRoot, "dist");
|
|
2110
2353
|
try {
|
|
2111
2354
|
await rm(distPath, { recursive: true, force: true });
|
|
2112
2355
|
console.log("Deleted the dist directory\n");
|
|
@@ -2117,26 +2360,36 @@ async function taujsBuild({
|
|
|
2117
2360
|
const extractedConfigs = extractBuildConfigs(config);
|
|
2118
2361
|
const processedConfigs = processConfigs(extractedConfigs, clientBaseDir, TEMPLATE);
|
|
2119
2362
|
if (!isSSRBuild) await deleteDist();
|
|
2120
|
-
for (const
|
|
2121
|
-
const { appId, entryPoint, clientRoot, entryClient, entryServer, htmlTemplate, plugins = [] } =
|
|
2122
|
-
const outDir =
|
|
2123
|
-
const root = entryPoint ?
|
|
2124
|
-
const
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2363
|
+
for (const appConfig of processedConfigs) {
|
|
2364
|
+
const { appId, entryPoint, clientRoot, entryClient, entryServer, htmlTemplate, plugins = [] } = appConfig;
|
|
2365
|
+
const outDir = path8.resolve(projectRoot, isSSRBuild ? `dist/ssr/${entryPoint}` : `dist/client/${entryPoint}`);
|
|
2366
|
+
const root = entryPoint ? path8.resolve(clientBaseDir, entryPoint) : clientBaseDir;
|
|
2367
|
+
const defaultAlias = {
|
|
2368
|
+
"@client": root,
|
|
2369
|
+
"@server": path8.resolve(projectRoot, "src/server"),
|
|
2370
|
+
"@shared": path8.resolve(projectRoot, "src/shared")
|
|
2371
|
+
};
|
|
2372
|
+
const resolvedAlias = { ...defaultAlias, ...userAlias ?? {} };
|
|
2373
|
+
const server = path8.resolve(clientRoot, `${entryServer}.tsx`);
|
|
2374
|
+
const client = path8.resolve(clientRoot, `${entryClient}.tsx`);
|
|
2375
|
+
const main = path8.resolve(clientRoot, htmlTemplate);
|
|
2376
|
+
const inputs = resolveInputs(isSSRBuild, !isSSRBuild && existsSync(main), { server, client, main });
|
|
2377
|
+
const nodeVersion = process.versions.node.split(".")[0];
|
|
2378
|
+
const frameworkConfig = {
|
|
2128
2379
|
base: entryPoint ? `/${entryPoint}/` : "/",
|
|
2129
2380
|
build: {
|
|
2130
2381
|
outDir,
|
|
2382
|
+
emptyOutDir: true,
|
|
2131
2383
|
manifest: !isSSRBuild,
|
|
2132
2384
|
rollupOptions: {
|
|
2133
|
-
input:
|
|
2385
|
+
input: inputs
|
|
2134
2386
|
},
|
|
2135
2387
|
ssr: isSSRBuild ? server : void 0,
|
|
2136
2388
|
ssrManifest: isSSRBuild,
|
|
2137
2389
|
...isSSRBuild && {
|
|
2138
2390
|
format: "esm",
|
|
2139
|
-
target: `node${
|
|
2391
|
+
target: `node${nodeVersion}`,
|
|
2392
|
+
copyPublicDir: false
|
|
2140
2393
|
}
|
|
2141
2394
|
},
|
|
2142
2395
|
css: {
|
|
@@ -2144,33 +2397,28 @@ async function taujsBuild({
|
|
|
2144
2397
|
scss: { api: "modern-compiler" }
|
|
2145
2398
|
}
|
|
2146
2399
|
},
|
|
2147
|
-
plugins
|
|
2148
|
-
publicDir: "public",
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
"/api": {
|
|
2160
|
-
target: "http://localhost:3000",
|
|
2161
|
-
changeOrigin: true,
|
|
2162
|
-
rewrite: (path7) => path7.replace(/^\/api/, "")
|
|
2163
|
-
}
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2400
|
+
plugins,
|
|
2401
|
+
publicDir: isSSRBuild ? false : "public",
|
|
2402
|
+
// single shared public
|
|
2403
|
+
// publicDir: isSSRBuild ? false : path.join(root, 'public'), // per-app. no public dir for SSR builds
|
|
2404
|
+
resolve: { alias: resolvedAlias },
|
|
2405
|
+
root
|
|
2406
|
+
};
|
|
2407
|
+
const buildContext = {
|
|
2408
|
+
appId,
|
|
2409
|
+
entryPoint,
|
|
2410
|
+
isSSRBuild,
|
|
2411
|
+
clientRoot
|
|
2166
2412
|
};
|
|
2413
|
+
const finalConfig = mergeViteConfig(frameworkConfig, userViteConfig, buildContext);
|
|
2167
2414
|
try {
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2415
|
+
const mode = isSSRBuild ? "SSR" : "Client";
|
|
2416
|
+
console.log(`[taujs:build:${entryPoint}] Building \u2192 ${mode}`);
|
|
2417
|
+
await build(finalConfig);
|
|
2418
|
+
console.log(`[taujs:build:${entryPoint}] \u2713 Complete
|
|
2171
2419
|
`);
|
|
2172
2420
|
} catch (error) {
|
|
2173
|
-
console.error(`
|
|
2421
|
+
console.error(`[taujs:build:${entryPoint}] \u2717 Failed
|
|
2174
2422
|
`, error);
|
|
2175
2423
|
process.exit(1);
|
|
2176
2424
|
}
|
|
@@ -2192,7 +2440,6 @@ function winstonAdapter(winston) {
|
|
|
2192
2440
|
return messageMetaAdapter(winston);
|
|
2193
2441
|
}
|
|
2194
2442
|
export {
|
|
2195
|
-
createLogger,
|
|
2196
2443
|
createServer,
|
|
2197
2444
|
taujsBuild,
|
|
2198
2445
|
winstonAdapter
|