@taujs/server 0.5.2 → 0.5.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-DHz6Lax2.d.ts → Config-2Loymxo2.d.ts} +58 -47
- package/dist/Config.d.ts +1 -1
- package/dist/Config.js +28 -10
- package/dist/index.d.ts +14 -10
- package/dist/index.js +595 -593
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99,62 +99,19 @@ var require_picocolors = __commonJS({
|
|
|
99
99
|
|
|
100
100
|
// src/CreateServer.ts
|
|
101
101
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
102
|
-
import
|
|
103
|
-
import { performance as performance3 } from "perf_hooks";
|
|
104
|
-
import Fastify from "fastify";
|
|
105
|
-
|
|
106
|
-
// src/Setup.ts
|
|
102
|
+
import path6 from "path";
|
|
107
103
|
import { performance } from "perf_hooks";
|
|
104
|
+
import Fastify from "fastify";
|
|
108
105
|
|
|
109
|
-
// src/
|
|
110
|
-
var
|
|
111
|
-
var RENDERTYPE = {
|
|
112
|
-
ssr: "ssr",
|
|
113
|
-
streaming: "streaming"
|
|
114
|
-
};
|
|
115
|
-
var SSRTAG = {
|
|
116
|
-
ssrHead: "<!--ssr-head-->",
|
|
117
|
-
ssrHtml: "<!--ssr-html-->"
|
|
118
|
-
};
|
|
119
|
-
var TEMPLATE = {
|
|
120
|
-
defaultEntryClient: "entry-client",
|
|
121
|
-
defaultEntryServer: "entry-server",
|
|
122
|
-
defaultHtmlTemplate: "index.html"
|
|
123
|
-
};
|
|
124
|
-
var DEV_CSP_DIRECTIVES = {
|
|
125
|
-
"default-src": ["'self'"],
|
|
126
|
-
"connect-src": ["'self'", "ws:", "http:"],
|
|
127
|
-
"style-src": ["'self'", "'unsafe-inline'"],
|
|
128
|
-
"img-src": ["'self'", "data:"]
|
|
129
|
-
};
|
|
130
|
-
var CONTENT = {
|
|
131
|
-
TAG: "\u03C4js"
|
|
132
|
-
};
|
|
133
|
-
var DEBUG = {
|
|
134
|
-
auth: { label: "auth", colour: import_picocolors.default.blue },
|
|
135
|
-
csp: { label: "csp", colour: import_picocolors.default.yellow },
|
|
136
|
-
errors: { label: "errors", colour: import_picocolors.default.red },
|
|
137
|
-
routes: { label: "routes", colour: import_picocolors.default.cyan },
|
|
138
|
-
security: { label: "security", colour: import_picocolors.default.yellow },
|
|
139
|
-
trx: { label: "trx", colour: import_picocolors.default.magenta },
|
|
140
|
-
vite: { label: "vite", colour: import_picocolors.default.yellow }
|
|
141
|
-
};
|
|
142
|
-
var REGEX = {
|
|
143
|
-
BENIGN_NET_ERR: /\b(?:ECONNRESET|EPIPE|ECONNABORTED)\b|socket hang up|aborted|premature(?: close)?/i,
|
|
144
|
-
SAFE_TRACE: /^[a-zA-Z0-9-_:.]{1,128}$/
|
|
145
|
-
};
|
|
146
|
-
var ENTRY_EXTENSIONS = [".ts", ".tsx"];
|
|
106
|
+
// src/core/telemetry/Telemetry.ts
|
|
107
|
+
var now = () => globalThis.performance?.now?.() ?? Date.now();
|
|
147
108
|
|
|
148
|
-
// src/Setup.ts
|
|
109
|
+
// src/core/config/Setup.ts
|
|
149
110
|
var extractBuildConfigs = (config) => {
|
|
150
|
-
return config.apps.map(({ appId, entryPoint, plugins }) => ({
|
|
151
|
-
appId,
|
|
152
|
-
entryPoint,
|
|
153
|
-
plugins
|
|
154
|
-
}));
|
|
111
|
+
return config.apps.map(({ appId, entryPoint, plugins }) => ({ appId, entryPoint, plugins }));
|
|
155
112
|
};
|
|
156
113
|
var extractRoutes = (taujsConfig) => {
|
|
157
|
-
const t0 =
|
|
114
|
+
const t0 = now();
|
|
158
115
|
const allRoutes = [];
|
|
159
116
|
const apps = [];
|
|
160
117
|
const warnings = [];
|
|
@@ -173,7 +130,7 @@ var extractRoutes = (taujsConfig) => {
|
|
|
173
130
|
if (appIds.length > 1) warnings.push(`Route path "${path7}" is declared in multiple apps: ${appIds.join(", ")}`);
|
|
174
131
|
}
|
|
175
132
|
const sortedRoutes = allRoutes.sort((a, b) => computeScore(b.path) - computeScore(a.path));
|
|
176
|
-
const durationMs =
|
|
133
|
+
const durationMs = now() - t0;
|
|
177
134
|
return {
|
|
178
135
|
routes: sortedRoutes,
|
|
179
136
|
apps,
|
|
@@ -183,7 +140,7 @@ var extractRoutes = (taujsConfig) => {
|
|
|
183
140
|
};
|
|
184
141
|
};
|
|
185
142
|
var extractSecurity = (taujsConfig) => {
|
|
186
|
-
const t0 =
|
|
143
|
+
const t0 = now();
|
|
187
144
|
const user = taujsConfig.security ?? {};
|
|
188
145
|
const userCsp = user.csp;
|
|
189
146
|
const hasExplicitCSP = !!userCsp;
|
|
@@ -204,7 +161,7 @@ var extractSecurity = (taujsConfig) => {
|
|
|
204
161
|
hasReporting: !!normalisedCsp?.reporting?.endpoint,
|
|
205
162
|
reportOnly: !!normalisedCsp?.reporting?.reportOnly
|
|
206
163
|
};
|
|
207
|
-
const durationMs =
|
|
164
|
+
const durationMs = now() - t0;
|
|
208
165
|
return {
|
|
209
166
|
security,
|
|
210
167
|
durationMs,
|
|
@@ -212,58 +169,11 @@ var extractSecurity = (taujsConfig) => {
|
|
|
212
169
|
summary
|
|
213
170
|
};
|
|
214
171
|
};
|
|
215
|
-
function printConfigSummary(logger, apps, configsCount, totalRoutes, durationMs, warnings) {
|
|
216
|
-
logger.info({}, `${CONTENT.TAG} [config] Loaded ${configsCount} app(s), ${totalRoutes} route(s) in ${durationMs.toFixed(1)}ms`);
|
|
217
|
-
apps.forEach((a) => logger.debug("routes", {}, `\u2022 ${a.appId}: ${a.routeCount} route(s)`));
|
|
218
|
-
warnings.forEach((w) => logger.warn({}, `${CONTENT.TAG} [warn] ${w}`));
|
|
219
|
-
}
|
|
220
|
-
function printSecuritySummary(logger, routes, security, hasExplicitCSP, securityDurationMs) {
|
|
221
|
-
const total = routes.length;
|
|
222
|
-
const disabled = routes.filter((r) => r.attr?.middleware?.csp === false).length;
|
|
223
|
-
const custom = routes.filter((r) => {
|
|
224
|
-
const v = r.attr?.middleware?.csp;
|
|
225
|
-
return v !== void 0 && v !== false;
|
|
226
|
-
}).length;
|
|
227
|
-
const enabled = total - disabled;
|
|
228
|
-
const hasReporting = !!security.csp?.reporting?.endpoint;
|
|
229
|
-
const mode = security.csp?.defaultMode ?? "merge";
|
|
230
|
-
let status = "configured";
|
|
231
|
-
let detail = "";
|
|
232
|
-
if (hasExplicitCSP) {
|
|
233
|
-
detail = `explicit, mode=${mode}`;
|
|
234
|
-
if (hasReporting) detail += ", reporting";
|
|
235
|
-
if (custom > 0) detail += `, ${custom} route override(s)`;
|
|
236
|
-
} else {
|
|
237
|
-
if (process.env.NODE_ENV === "production") {
|
|
238
|
-
logger.warn({}, "(consider explicit config for production)");
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
logger.info({}, `${CONTENT.TAG} [security] CSP ${status} (${enabled}/${total} routes) in ${securityDurationMs.toFixed(1)}ms`);
|
|
242
|
-
}
|
|
243
|
-
function printContractReport(logger, report) {
|
|
244
|
-
for (const r of report.items) {
|
|
245
|
-
const line = `${CONTENT.TAG} [security][${r.key}] ${r.message}`;
|
|
246
|
-
if (r.status === "error") {
|
|
247
|
-
logger.error({}, line);
|
|
248
|
-
} else if (r.status === "warning") {
|
|
249
|
-
logger.warn({}, line);
|
|
250
|
-
} else if (r.status === "skipped") {
|
|
251
|
-
logger.debug(r.key, {}, line);
|
|
252
|
-
} else {
|
|
253
|
-
logger.info({}, line);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
172
|
var computeScore = (path7) => {
|
|
258
173
|
return path7.split("/").filter(Boolean).reduce((score, segment) => score + (segment.startsWith(":") ? 1 : 10), 0);
|
|
259
174
|
};
|
|
260
|
-
function printVitePluginSummary(logger, appPlugins, merged) {
|
|
261
|
-
const mergedNames = merged.map((p) => p?.name).filter((n) => typeof n === "string" && n.length > 0);
|
|
262
|
-
const appsLine = appPlugins.length === 0 ? "no app plugins" : appPlugins.map((a) => `${a.appId}=[${a.plugins.join(", ") || "none"}]`).join(" ");
|
|
263
|
-
logger.info(void 0, `${CONTENT.TAG} [vite] Plugins ${appsLine} merged=[${mergedNames.join(", ") || "none"}]`);
|
|
264
|
-
}
|
|
265
175
|
|
|
266
|
-
// src/
|
|
176
|
+
// src/core/errors/AppError.ts
|
|
267
177
|
var HTTP_STATUS = {
|
|
268
178
|
infra: 500,
|
|
269
179
|
upstream: 502,
|
|
@@ -387,6 +297,40 @@ function toReason(e) {
|
|
|
387
297
|
return new Error(String(e));
|
|
388
298
|
}
|
|
389
299
|
|
|
300
|
+
// src/constants.ts
|
|
301
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
302
|
+
var SSRTAG = {
|
|
303
|
+
ssrHead: "<!--ssr-head-->",
|
|
304
|
+
ssrHtml: "<!--ssr-html-->"
|
|
305
|
+
};
|
|
306
|
+
var TEMPLATE = {
|
|
307
|
+
defaultEntryClient: "entry-client",
|
|
308
|
+
defaultEntryServer: "entry-server",
|
|
309
|
+
defaultHtmlTemplate: "index.html"
|
|
310
|
+
};
|
|
311
|
+
var ENTRY_EXTENSIONS = [".ts", ".tsx"];
|
|
312
|
+
var DEV_CSP_DIRECTIVES = {
|
|
313
|
+
"default-src": ["'self'"],
|
|
314
|
+
"connect-src": ["'self'", "ws:", "http:"],
|
|
315
|
+
"style-src": ["'self'", "'unsafe-inline'"],
|
|
316
|
+
"img-src": ["'self'", "data:"]
|
|
317
|
+
};
|
|
318
|
+
var CONTENT = {
|
|
319
|
+
TAG: "\u03C4js"
|
|
320
|
+
};
|
|
321
|
+
var DEBUG = {
|
|
322
|
+
auth: { label: "auth", colour: import_picocolors.default.blue },
|
|
323
|
+
csp: { label: "csp", colour: import_picocolors.default.yellow },
|
|
324
|
+
errors: { label: "errors", colour: import_picocolors.default.red },
|
|
325
|
+
routes: { label: "routes", colour: import_picocolors.default.cyan },
|
|
326
|
+
security: { label: "security", colour: import_picocolors.default.yellow },
|
|
327
|
+
trx: { label: "trx", colour: import_picocolors.default.magenta },
|
|
328
|
+
vite: { label: "vite", colour: import_picocolors.default.yellow }
|
|
329
|
+
};
|
|
330
|
+
var REGEX = {
|
|
331
|
+
BENIGN_NET_ERR: /\b(?:ECONNRESET|EPIPE|ECONNABORTED)\b|socket hang up|aborted|premature(?: close)?/i
|
|
332
|
+
};
|
|
333
|
+
|
|
390
334
|
// src/logging/Logger.ts
|
|
391
335
|
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
392
336
|
|
|
@@ -451,8 +395,10 @@ function parseDebugInput(input) {
|
|
|
451
395
|
return input;
|
|
452
396
|
}
|
|
453
397
|
|
|
454
|
-
// src/logging/
|
|
398
|
+
// src/core/logging/types.ts
|
|
455
399
|
var DEBUG_CATEGORIES = ["auth", "routes", "errors", "vite", "network", "ssr"];
|
|
400
|
+
|
|
401
|
+
// src/logging/Logger.ts
|
|
456
402
|
var Logger = class _Logger {
|
|
457
403
|
constructor(config = {}) {
|
|
458
404
|
this.config = config;
|
|
@@ -512,12 +458,12 @@ var Logger = class _Logger {
|
|
|
512
458
|
return copy;
|
|
513
459
|
}
|
|
514
460
|
formatTimestamp() {
|
|
515
|
-
const
|
|
516
|
-
if (process.env.NODE_ENV === "production") return
|
|
517
|
-
const hours = String(
|
|
518
|
-
const minutes = String(
|
|
519
|
-
const seconds = String(
|
|
520
|
-
const millis = String(
|
|
461
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
462
|
+
if (process.env.NODE_ENV === "production") return now2.toISOString();
|
|
463
|
+
const hours = String(now2.getHours()).padStart(2, "0");
|
|
464
|
+
const minutes = String(now2.getMinutes()).padStart(2, "0");
|
|
465
|
+
const seconds = String(now2.getSeconds()).padStart(2, "0");
|
|
466
|
+
const millis = String(now2.getMilliseconds()).padStart(3, "0");
|
|
521
467
|
return `${hours}:${minutes}:${seconds}.${millis}`;
|
|
522
468
|
}
|
|
523
469
|
emit(level, message, meta, category) {
|
|
@@ -765,48 +711,79 @@ var verifyContracts = (app, routes, contracts, security) => {
|
|
|
765
711
|
return { items };
|
|
766
712
|
};
|
|
767
713
|
|
|
714
|
+
// src/Setup.ts
|
|
715
|
+
function printConfigSummary(logger, apps, configsCount, totalRoutes, durationMs, warnings) {
|
|
716
|
+
logger.info({}, `${CONTENT.TAG} [config] Loaded ${configsCount} app(s), ${totalRoutes} route(s) in ${durationMs.toFixed(1)}ms`);
|
|
717
|
+
apps.forEach((a) => logger.debug("routes", {}, `\u2022 ${a.appId}: ${a.routeCount} route(s)`));
|
|
718
|
+
warnings.forEach((w) => logger.warn({}, `${CONTENT.TAG} [warn] ${w}`));
|
|
719
|
+
}
|
|
720
|
+
function printSecuritySummary(logger, routes, security, hasExplicitCSP, securityDurationMs) {
|
|
721
|
+
const total = routes.length;
|
|
722
|
+
const disabled = routes.filter((r) => r.attr?.middleware?.csp === false).length;
|
|
723
|
+
const custom = routes.filter((r) => {
|
|
724
|
+
const v = r.attr?.middleware?.csp;
|
|
725
|
+
return v !== void 0 && v !== false;
|
|
726
|
+
}).length;
|
|
727
|
+
const enabled = total - disabled;
|
|
728
|
+
const hasReporting = !!security.csp?.reporting?.endpoint;
|
|
729
|
+
const mode = security.csp?.defaultMode ?? "merge";
|
|
730
|
+
let status = "configured";
|
|
731
|
+
let detail = "";
|
|
732
|
+
if (hasExplicitCSP) {
|
|
733
|
+
detail = `explicit, mode=${mode}`;
|
|
734
|
+
if (hasReporting) detail += ", reporting";
|
|
735
|
+
if (custom > 0) detail += `, ${custom} route override(s)`;
|
|
736
|
+
} else {
|
|
737
|
+
if (process.env.NODE_ENV === "production") {
|
|
738
|
+
logger.warn({}, "(consider explicit config for production)");
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
logger.info({}, `${CONTENT.TAG} [security] CSP ${status} (${enabled}/${total} routes) in ${securityDurationMs.toFixed(1)}ms`);
|
|
742
|
+
}
|
|
743
|
+
function printContractReport(logger, report) {
|
|
744
|
+
for (const r of report.items) {
|
|
745
|
+
const line = `${CONTENT.TAG} [security][${r.key}] ${r.message}`;
|
|
746
|
+
if (r.status === "error") {
|
|
747
|
+
logger.error({}, line);
|
|
748
|
+
} else if (r.status === "warning") {
|
|
749
|
+
logger.warn({}, line);
|
|
750
|
+
} else if (r.status === "skipped") {
|
|
751
|
+
logger.debug(r.key, {}, line);
|
|
752
|
+
} else {
|
|
753
|
+
logger.info({}, line);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
function printVitePluginSummary(logger, appPlugins, merged) {
|
|
758
|
+
const mergedNames = merged.map((p) => p?.name).filter((n) => typeof n === "string" && n.length > 0);
|
|
759
|
+
const appsLine = appPlugins.length === 0 ? "no app plugins" : appPlugins.map((a) => `${a.appId}=[${a.plugins.join(", ") || "none"}]`).join(" ");
|
|
760
|
+
logger.info(void 0, `${CONTENT.TAG} [vite] Plugins ${appsLine} merged=[${mergedNames.join(", ") || "none"}]`);
|
|
761
|
+
}
|
|
762
|
+
|
|
768
763
|
// src/SSRServer.ts
|
|
769
764
|
import fp3 from "fastify-plugin";
|
|
770
765
|
|
|
771
|
-
// src/
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
var statusText = (status) => {
|
|
787
|
-
const map = {
|
|
788
|
-
400: "Bad Request",
|
|
789
|
-
401: "Unauthorized",
|
|
790
|
-
403: "Forbidden",
|
|
791
|
-
404: "Not Found",
|
|
792
|
-
405: "Method Not Allowed",
|
|
793
|
-
408: "Request Timeout",
|
|
794
|
-
422: "Unprocessable Entity",
|
|
795
|
-
429: "Too Many Requests",
|
|
796
|
-
499: "Client Closed Request",
|
|
797
|
-
500: "Internal Server Error",
|
|
798
|
-
502: "Bad Gateway",
|
|
799
|
-
503: "Service Unavailable",
|
|
800
|
-
504: "Gateway Timeout"
|
|
801
|
-
};
|
|
802
|
-
return map[status] ?? "Error";
|
|
766
|
+
// src/core/routes/DataRoutes.ts
|
|
767
|
+
import { match } from "path-to-regexp";
|
|
768
|
+
|
|
769
|
+
// src/core/logging/noop.ts
|
|
770
|
+
var noopLogger = {
|
|
771
|
+
debug: () => {
|
|
772
|
+
},
|
|
773
|
+
info: () => {
|
|
774
|
+
},
|
|
775
|
+
warn: () => {
|
|
776
|
+
},
|
|
777
|
+
error: () => {
|
|
778
|
+
},
|
|
779
|
+
child: () => noopLogger,
|
|
780
|
+
isDebugEnabled: () => false
|
|
803
781
|
};
|
|
804
782
|
|
|
805
|
-
// src/
|
|
806
|
-
|
|
783
|
+
// src/core/logging/resolve.ts
|
|
784
|
+
var resolveLogs = (logger) => logger ?? noopLogger;
|
|
807
785
|
|
|
808
|
-
// src/
|
|
809
|
-
import { performance as performance2 } from "perf_hooks";
|
|
786
|
+
// src/core/services/DataServices.ts
|
|
810
787
|
function createCaller(registry, ctx) {
|
|
811
788
|
return (serviceName, methodName, args) => callServiceMethod(registry, serviceName, methodName, args ?? {}, ctx);
|
|
812
789
|
}
|
|
@@ -819,26 +796,27 @@ async function callServiceMethod(registry, serviceName, methodName, params, ctx)
|
|
|
819
796
|
if (!service) throw AppError.notFound(`Unknown service: ${serviceName}`);
|
|
820
797
|
const method = service[methodName];
|
|
821
798
|
if (!method) throw AppError.notFound(`Unknown method: ${serviceName}.${methodName}`);
|
|
822
|
-
const
|
|
799
|
+
const baseLogger = resolveLogs(ctx.logger);
|
|
800
|
+
const logger = baseLogger.child({
|
|
823
801
|
component: "service-call",
|
|
824
802
|
service: serviceName,
|
|
825
803
|
method: methodName,
|
|
826
804
|
traceId: ctx.traceId
|
|
827
805
|
});
|
|
828
|
-
const t0 =
|
|
806
|
+
const t0 = now();
|
|
829
807
|
try {
|
|
830
808
|
const result = await method(params ?? {}, ctx);
|
|
831
809
|
if (typeof result !== "object" || result === null) {
|
|
832
810
|
throw AppError.internal(`Non-object result from ${serviceName}.${methodName}`);
|
|
833
811
|
}
|
|
834
|
-
logger
|
|
812
|
+
logger.debug({ ms: +(now() - t0).toFixed(1) }, "Service method ok");
|
|
835
813
|
return result;
|
|
836
814
|
} catch (err) {
|
|
837
|
-
logger
|
|
815
|
+
logger.error(
|
|
838
816
|
{
|
|
839
817
|
params,
|
|
840
818
|
error: err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : String(err),
|
|
841
|
-
ms: +(
|
|
819
|
+
ms: +(now() - t0).toFixed(1)
|
|
842
820
|
},
|
|
843
821
|
"Service method failed"
|
|
844
822
|
);
|
|
@@ -855,7 +833,7 @@ var isServiceDescriptor = (obj) => {
|
|
|
855
833
|
return true;
|
|
856
834
|
};
|
|
857
835
|
|
|
858
|
-
// src/
|
|
836
|
+
// src/core/routes/DataRoutes.ts
|
|
859
837
|
var safeDecode = (value) => {
|
|
860
838
|
try {
|
|
861
839
|
return decodeURIComponent(value);
|
|
@@ -953,43 +931,86 @@ var fetchInitialData = async (attr, params, serviceRegistry, ctx, callServiceMet
|
|
|
953
931
|
}
|
|
954
932
|
};
|
|
955
933
|
|
|
956
|
-
// src/
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
934
|
+
// src/System.ts
|
|
935
|
+
import { dirname, join } from "path";
|
|
936
|
+
import "path";
|
|
937
|
+
import { fileURLToPath } from "url";
|
|
938
|
+
var isDevelopment = process.env.NODE_ENV === "development";
|
|
939
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
940
|
+
var DIR_SUFFIX = isDevelopment ? ".." : "./";
|
|
941
|
+
var __dirname = join(dirname(__filename), DIR_SUFFIX);
|
|
942
|
+
|
|
943
|
+
// src/logging/utils/index.ts
|
|
944
|
+
var httpStatusFrom = (err, fallback = 500) => err instanceof AppError ? err.httpStatus : fallback;
|
|
945
|
+
var toHttp = (err) => {
|
|
946
|
+
const app = AppError.from(err);
|
|
947
|
+
const status = httpStatusFrom(app);
|
|
948
|
+
const errorMessage = app.safeMessage;
|
|
949
|
+
return {
|
|
950
|
+
status,
|
|
951
|
+
body: {
|
|
952
|
+
error: errorMessage,
|
|
953
|
+
...app.code && { code: app.code },
|
|
954
|
+
statusText: statusText(status)
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
};
|
|
958
|
+
var statusText = (status) => {
|
|
959
|
+
const map = {
|
|
960
|
+
400: "Bad Request",
|
|
961
|
+
401: "Unauthorized",
|
|
962
|
+
403: "Forbidden",
|
|
963
|
+
404: "Not Found",
|
|
964
|
+
405: "Method Not Allowed",
|
|
965
|
+
408: "Request Timeout",
|
|
966
|
+
422: "Unprocessable Entity",
|
|
967
|
+
429: "Too Many Requests",
|
|
968
|
+
499: "Client Closed Request",
|
|
969
|
+
500: "Internal Server Error",
|
|
970
|
+
502: "Bad Gateway",
|
|
971
|
+
503: "Service Unavailable",
|
|
972
|
+
504: "Gateway Timeout"
|
|
973
|
+
};
|
|
974
|
+
return map[status] ?? "Error";
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
// src/security/Auth.ts
|
|
978
|
+
var createAuthHook = (routeMatchers, logger) => {
|
|
979
|
+
return async function authHook(req, reply) {
|
|
980
|
+
const url = new URL(req.url, `http://${req.headers.host}`).pathname;
|
|
981
|
+
const match2 = matchRoute(url, routeMatchers);
|
|
982
|
+
if (!match2) return;
|
|
983
|
+
const { route } = match2;
|
|
984
|
+
const authConfig = route.attr?.middleware?.auth;
|
|
985
|
+
req.routeMeta = {
|
|
986
|
+
path: route.path,
|
|
987
|
+
appId: route.appId,
|
|
988
|
+
attr: {
|
|
989
|
+
middleware: {
|
|
990
|
+
auth: route.attr?.middleware?.auth
|
|
991
|
+
},
|
|
992
|
+
render: route.attr?.render
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
if (!authConfig) {
|
|
996
|
+
logger.debug("auth", { method: req.method, url: req.url }, "(none)");
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
if (typeof req.server.authenticate !== "function") {
|
|
1000
|
+
logger.warn(
|
|
1001
|
+
{
|
|
1002
|
+
path: url,
|
|
1003
|
+
appId: route.appId
|
|
1004
|
+
},
|
|
1005
|
+
"Route requires auth but Fastify authenticate decorator is missing"
|
|
1006
|
+
);
|
|
1007
|
+
return reply.status(500).send("Server misconfiguration: auth decorator missing.");
|
|
1008
|
+
}
|
|
1009
|
+
try {
|
|
1010
|
+
logger.debug("auth", { method: req.method, url: req.url }, "Invoking authenticate(...)");
|
|
1011
|
+
await req.server.authenticate(req, reply);
|
|
1012
|
+
logger.debug("auth", { method: req.method, url: req.url }, "Authentication successful");
|
|
1013
|
+
} catch (err) {
|
|
993
1014
|
logger.debug("auth", { method: req.method, url: req.url }, "Authentication failed");
|
|
994
1015
|
return reply.send(err);
|
|
995
1016
|
}
|
|
@@ -999,16 +1020,6 @@ var createAuthHook = (routeMatchers, logger) => {
|
|
|
999
1020
|
// src/security/CSP.ts
|
|
1000
1021
|
import fp from "fastify-plugin";
|
|
1001
1022
|
import crypto from "crypto";
|
|
1002
|
-
|
|
1003
|
-
// src/utils/System.ts
|
|
1004
|
-
import { dirname, join } from "path";
|
|
1005
|
-
import "path";
|
|
1006
|
-
import { fileURLToPath } from "url";
|
|
1007
|
-
var isDevelopment = process.env.NODE_ENV === "development";
|
|
1008
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
1009
|
-
var __dirname = join(dirname(__filename), !isDevelopment ? "./" : "..");
|
|
1010
|
-
|
|
1011
|
-
// src/security/CSP.ts
|
|
1012
1023
|
var defaultGenerateCSP = (directives, nonce, req) => {
|
|
1013
1024
|
const merged = { ...directives };
|
|
1014
1025
|
merged["script-src"] = merged["script-src"] || ["'self'"];
|
|
@@ -1232,7 +1243,6 @@ var cspReportPlugin = fp2(
|
|
|
1232
1243
|
);
|
|
1233
1244
|
|
|
1234
1245
|
// src/utils/AssetManager.ts
|
|
1235
|
-
import { existsSync } from "fs";
|
|
1236
1246
|
import { readFile } from "fs/promises";
|
|
1237
1247
|
import path2 from "path";
|
|
1238
1248
|
import { pathToFileURL } from "url";
|
|
@@ -1344,14 +1354,6 @@ var rebuildTemplate = (parts, headContent, bodyContent) => {
|
|
|
1344
1354
|
};
|
|
1345
1355
|
|
|
1346
1356
|
// src/utils/AssetManager.ts
|
|
1347
|
-
function resolveEntryFile(clientRoot, stem) {
|
|
1348
|
-
for (const ext of ENTRY_EXTENSIONS) {
|
|
1349
|
-
const filename = `${stem}${ext}`;
|
|
1350
|
-
const absPath = path2.join(clientRoot, filename);
|
|
1351
|
-
if (existsSync(absPath)) return filename;
|
|
1352
|
-
}
|
|
1353
|
-
throw new Error(`Entry file "${stem}" not found in ${clientRoot}. Tried: ${ENTRY_EXTENSIONS.map((e) => stem + e).join(", ")}`);
|
|
1354
|
-
}
|
|
1355
1357
|
var createMaps = () => ({
|
|
1356
1358
|
bootstrapModules: /* @__PURE__ */ new Map(),
|
|
1357
1359
|
cssLinks: /* @__PURE__ */ new Map(),
|
|
@@ -1364,108 +1366,104 @@ var createMaps = () => ({
|
|
|
1364
1366
|
var processConfigs = (configs, baseClientRoot, templateDefaults) => {
|
|
1365
1367
|
return configs.map((config) => {
|
|
1366
1368
|
const clientRoot = path2.resolve(baseClientRoot, config.entryPoint);
|
|
1367
|
-
const entryClient = config.entryClient || templateDefaults.defaultEntryClient;
|
|
1368
|
-
const entryServer = config.entryServer || templateDefaults.defaultEntryServer;
|
|
1369
|
-
const entryClientFile = resolveEntryFile(clientRoot, entryClient);
|
|
1370
|
-
const entryServerFile = resolveEntryFile(clientRoot, entryServer);
|
|
1371
1369
|
return {
|
|
1372
1370
|
clientRoot,
|
|
1373
1371
|
entryPoint: config.entryPoint,
|
|
1374
|
-
entryClient,
|
|
1375
|
-
|
|
1372
|
+
entryClient: config.entryClient || templateDefaults.defaultEntryClient,
|
|
1373
|
+
// stem
|
|
1374
|
+
entryServer: config.entryServer || templateDefaults.defaultEntryServer,
|
|
1375
|
+
// stem
|
|
1376
1376
|
htmlTemplate: config.htmlTemplate || templateDefaults.defaultHtmlTemplate,
|
|
1377
1377
|
appId: config.appId,
|
|
1378
|
-
plugins: config.plugins ?? []
|
|
1379
|
-
entryClientFile,
|
|
1380
|
-
entryServerFile
|
|
1378
|
+
plugins: config.plugins ?? []
|
|
1381
1379
|
};
|
|
1382
1380
|
});
|
|
1383
1381
|
};
|
|
1382
|
+
var logAssetError = (logger, stage, err) => {
|
|
1383
|
+
if (err instanceof AppError) {
|
|
1384
|
+
logger.error(
|
|
1385
|
+
{
|
|
1386
|
+
error: {
|
|
1387
|
+
name: err.name,
|
|
1388
|
+
message: err.message,
|
|
1389
|
+
stack: err.stack,
|
|
1390
|
+
code: err.code
|
|
1391
|
+
},
|
|
1392
|
+
stage
|
|
1393
|
+
},
|
|
1394
|
+
"Asset load failed"
|
|
1395
|
+
);
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
logger.error(
|
|
1399
|
+
{
|
|
1400
|
+
error: err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : String(err),
|
|
1401
|
+
stage
|
|
1402
|
+
},
|
|
1403
|
+
"Asset load failed"
|
|
1404
|
+
);
|
|
1405
|
+
};
|
|
1406
|
+
var findManifestEntry = (manifest, stem) => {
|
|
1407
|
+
for (const ext of ENTRY_EXTENSIONS) {
|
|
1408
|
+
const entry = manifest[`${stem}${ext}`];
|
|
1409
|
+
if (entry?.file) return entry;
|
|
1410
|
+
}
|
|
1411
|
+
return null;
|
|
1412
|
+
};
|
|
1384
1413
|
var loadAssets = async (processedConfigs, baseClientRoot, bootstrapModules, cssLinks, manifests, preloadLinks, renderModules, ssrManifests, templates, opts = {}) => {
|
|
1385
|
-
const logger = opts.logger
|
|
1386
|
-
debug: opts.debug,
|
|
1387
|
-
includeContext: true
|
|
1388
|
-
});
|
|
1414
|
+
const logger = resolveLogs(opts.logger);
|
|
1389
1415
|
for (const config of processedConfigs) {
|
|
1390
|
-
const { clientRoot,
|
|
1416
|
+
const { clientRoot, entryServer, entryClient, htmlTemplate, entryPoint } = config;
|
|
1391
1417
|
try {
|
|
1392
1418
|
const templateHtmlPath = path2.join(clientRoot, htmlTemplate);
|
|
1393
|
-
|
|
1394
|
-
templates.set(clientRoot, templateHtml);
|
|
1419
|
+
templates.set(clientRoot, await readFile(templateHtmlPath, "utf-8"));
|
|
1395
1420
|
const relativeBasePath = path2.relative(baseClientRoot, clientRoot).replace(/\\/g, "/");
|
|
1396
1421
|
const adjustedRelativePath = relativeBasePath ? `/${relativeBasePath}` : "";
|
|
1397
|
-
if (
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
const bootstrapModule = `/${adjustedRelativePath}/${manifestEntry.file}`.replace(/\/{2,}/g, "/");
|
|
1422
|
-
bootstrapModules.set(clientRoot, bootstrapModule);
|
|
1423
|
-
const preloadLink = renderPreloadLinks(ssrManifest, adjustedRelativePath);
|
|
1424
|
-
preloadLinks.set(clientRoot, preloadLink);
|
|
1425
|
-
const cssLink = getCssLinks(manifest, adjustedRelativePath);
|
|
1426
|
-
cssLinks.set(clientRoot, cssLink);
|
|
1427
|
-
const renderModulePath = path2.join(ssrDistPath, `${entryServer}.js`);
|
|
1428
|
-
const moduleUrl = pathToFileURL(renderModulePath).href;
|
|
1429
|
-
try {
|
|
1430
|
-
const importedModule = await import(moduleUrl);
|
|
1431
|
-
renderModules.set(clientRoot, importedModule);
|
|
1432
|
-
} catch (err) {
|
|
1433
|
-
throw AppError.internal(`Failed to load render module ${renderModulePath}`, {
|
|
1434
|
-
cause: err,
|
|
1435
|
-
details: { moduleUrl, clientRoot, entryServer, ssrDistPath }
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
} catch (err) {
|
|
1439
|
-
if (err instanceof AppError) {
|
|
1440
|
-
logger.error(
|
|
1441
|
-
{
|
|
1442
|
-
error: { name: err.name, message: err.message, stack: err.stack, code: err.code },
|
|
1443
|
-
stage: "loadAssets:production"
|
|
1444
|
-
},
|
|
1445
|
-
"Asset load failed"
|
|
1446
|
-
);
|
|
1447
|
-
} else {
|
|
1448
|
-
logger.error(
|
|
1449
|
-
{
|
|
1450
|
-
error: err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : String(err),
|
|
1451
|
-
stage: "loadAssets:production"
|
|
1452
|
-
},
|
|
1453
|
-
"Asset load failed"
|
|
1454
|
-
);
|
|
1422
|
+
if (isDevelopment) {
|
|
1423
|
+
const bootstrapModule2 = `/${adjustedRelativePath}/${entryClient}`.replace(/\/{2,}/g, "/");
|
|
1424
|
+
bootstrapModules.set(clientRoot, bootstrapModule2);
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
const distRoot = path2.dirname(baseClientRoot);
|
|
1428
|
+
const ssrRoot = path2.join(distRoot, "ssr");
|
|
1429
|
+
const clientDistPath = path2.join(baseClientRoot, entryPoint);
|
|
1430
|
+
const manifestPath = path2.join(clientDistPath, ".vite/manifest.json");
|
|
1431
|
+
const manifest = JSON.parse(await readFile(manifestPath, "utf-8"));
|
|
1432
|
+
manifests.set(clientRoot, manifest);
|
|
1433
|
+
const ssrDistPath = path2.join(ssrRoot, entryPoint);
|
|
1434
|
+
const ssrManifestPath = path2.join(ssrDistPath, ".vite/ssr-manifest.json");
|
|
1435
|
+
const ssrManifest = JSON.parse(await readFile(ssrManifestPath, "utf-8"));
|
|
1436
|
+
ssrManifests.set(clientRoot, ssrManifest);
|
|
1437
|
+
const manifestEntry = findManifestEntry(manifest, entryClient);
|
|
1438
|
+
if (!manifestEntry?.file) {
|
|
1439
|
+
throw AppError.internal(`Entry "${entryClient}" not found in manifest`, {
|
|
1440
|
+
details: {
|
|
1441
|
+
tried: ENTRY_EXTENSIONS.map((e) => `${entryClient}${e}`),
|
|
1442
|
+
availableKeys: Object.keys(manifest),
|
|
1443
|
+
clientRoot,
|
|
1444
|
+
entryPoint,
|
|
1445
|
+
manifestPath
|
|
1455
1446
|
}
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
const bootstrapModule = `/${adjustedRelativePath}/${manifestEntry.file}`.replace(/\/{2,}/g, "/");
|
|
1450
|
+
bootstrapModules.set(clientRoot, bootstrapModule);
|
|
1451
|
+
preloadLinks.set(clientRoot, renderPreloadLinks(ssrManifest, adjustedRelativePath));
|
|
1452
|
+
cssLinks.set(clientRoot, getCssLinks(manifest, adjustedRelativePath));
|
|
1453
|
+
const renderModulePath = path2.join(ssrDistPath, `${entryServer}.js`);
|
|
1454
|
+
const moduleUrl = pathToFileURL(renderModulePath).href;
|
|
1455
|
+
try {
|
|
1456
|
+
const importedModule = await import(moduleUrl);
|
|
1457
|
+
renderModules.set(clientRoot, importedModule);
|
|
1458
|
+
} catch (err) {
|
|
1459
|
+
throw AppError.internal(`Failed to load render module ${renderModulePath}`, {
|
|
1460
|
+
cause: err,
|
|
1461
|
+
details: { moduleUrl, clientRoot, entryServer, ssrDistPath }
|
|
1462
|
+
});
|
|
1460
1463
|
}
|
|
1461
1464
|
} catch (err) {
|
|
1462
|
-
logger
|
|
1463
|
-
|
|
1464
|
-
error: err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : String(err),
|
|
1465
|
-
stage: "loadAssets:config"
|
|
1466
|
-
},
|
|
1467
|
-
"Failed to process config"
|
|
1468
|
-
);
|
|
1465
|
+
logAssetError(logger, isDevelopment ? "loadAssets:development" : "loadAssets:production", err);
|
|
1466
|
+
if (!isDevelopment) throw err;
|
|
1469
1467
|
}
|
|
1470
1468
|
}
|
|
1471
1469
|
};
|
|
@@ -1544,27 +1542,284 @@ var setupDevServer = async (app, baseClientRoot, alias, debug, devNet, plugins =
|
|
|
1544
1542
|
protocol: "ws"
|
|
1545
1543
|
}
|
|
1546
1544
|
}
|
|
1547
|
-
});
|
|
1548
|
-
overrideCSSHMRConsoleError();
|
|
1549
|
-
app.addHook("onRequest", async (request, reply) => {
|
|
1550
|
-
await new Promise((resolve) => {
|
|
1551
|
-
viteDevServer.middlewares(request.raw, reply.raw, () => {
|
|
1552
|
-
if (!reply.sent) resolve();
|
|
1553
|
-
});
|
|
1554
|
-
});
|
|
1555
|
-
});
|
|
1556
|
-
return viteDevServer;
|
|
1557
|
-
};
|
|
1558
|
-
|
|
1559
|
-
// src/utils/HandleRender.ts
|
|
1560
|
-
import
|
|
1561
|
-
import { PassThrough } from "stream";
|
|
1545
|
+
});
|
|
1546
|
+
overrideCSSHMRConsoleError();
|
|
1547
|
+
app.addHook("onRequest", async (request, reply) => {
|
|
1548
|
+
await new Promise((resolve) => {
|
|
1549
|
+
viteDevServer.middlewares(request.raw, reply.raw, () => {
|
|
1550
|
+
if (!reply.sent) resolve();
|
|
1551
|
+
});
|
|
1552
|
+
});
|
|
1553
|
+
});
|
|
1554
|
+
return viteDevServer;
|
|
1555
|
+
};
|
|
1556
|
+
|
|
1557
|
+
// src/utils/HandleRender.ts
|
|
1558
|
+
import path5 from "path";
|
|
1559
|
+
import { PassThrough } from "stream";
|
|
1560
|
+
|
|
1561
|
+
// src/core/constants.ts
|
|
1562
|
+
var RENDERTYPE = {
|
|
1563
|
+
ssr: "ssr",
|
|
1564
|
+
streaming: "streaming"
|
|
1565
|
+
};
|
|
1566
|
+
var REGEX2 = {
|
|
1567
|
+
SAFE_TRACE: /^[a-zA-Z0-9-_:.]{1,128}$/
|
|
1568
|
+
};
|
|
1569
|
+
|
|
1570
|
+
// src/Build.ts
|
|
1571
|
+
import { existsSync } from "fs";
|
|
1572
|
+
import * as fs from "fs";
|
|
1573
|
+
import path4 from "path";
|
|
1574
|
+
import { build } from "vite";
|
|
1575
|
+
function resolveInputs(isSSRBuild, mainExists, paths) {
|
|
1576
|
+
if (isSSRBuild) return { server: paths.server };
|
|
1577
|
+
if (mainExists) return { client: paths.client, main: paths.main };
|
|
1578
|
+
return { client: paths.client };
|
|
1579
|
+
}
|
|
1580
|
+
function resolveEntryFile(clientRoot, stem, exists = fs.existsSync) {
|
|
1581
|
+
for (const ext of ENTRY_EXTENSIONS) {
|
|
1582
|
+
const filename = `${stem}${ext}`;
|
|
1583
|
+
if (exists(path4.join(clientRoot, filename))) return filename;
|
|
1584
|
+
}
|
|
1585
|
+
throw new Error(`Entry file "${stem}" not found in ${clientRoot}. Tried: ${ENTRY_EXTENSIONS.map((e) => stem + e).join(", ")}`);
|
|
1586
|
+
}
|
|
1587
|
+
function getFrameworkInvariants(config) {
|
|
1588
|
+
return {
|
|
1589
|
+
root: config.root || "",
|
|
1590
|
+
base: config.base || "/",
|
|
1591
|
+
publicDir: config.publicDir === void 0 ? "public" : config.publicDir,
|
|
1592
|
+
build: {
|
|
1593
|
+
outDir: config.build?.outDir || "",
|
|
1594
|
+
manifest: config.build?.manifest ?? false,
|
|
1595
|
+
ssr: config.build?.ssr ?? void 0,
|
|
1596
|
+
// Preserve exact type
|
|
1597
|
+
ssrManifest: config.build?.ssrManifest ?? false,
|
|
1598
|
+
format: config.build?.format,
|
|
1599
|
+
target: config.build?.target,
|
|
1600
|
+
rollupOptions: {
|
|
1601
|
+
input: config.build?.rollupOptions?.input || {}
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
var normalisePlugins = (p) => Array.isArray(p) ? p : p ? [p] : [];
|
|
1607
|
+
function mergeViteConfig(framework, userOverride, context) {
|
|
1608
|
+
if (!userOverride) return framework;
|
|
1609
|
+
const userConfig = typeof userOverride === "function" && context ? userOverride(context) : userOverride;
|
|
1610
|
+
const invariants = getFrameworkInvariants(framework);
|
|
1611
|
+
const merged = {
|
|
1612
|
+
...framework,
|
|
1613
|
+
build: { ...framework.build ?? {} },
|
|
1614
|
+
css: { ...framework.css ?? {} },
|
|
1615
|
+
resolve: { ...framework.resolve ?? {} },
|
|
1616
|
+
plugins: [...framework.plugins ?? []],
|
|
1617
|
+
define: { ...framework.define ?? {} }
|
|
1618
|
+
};
|
|
1619
|
+
const ignoredKeys = [];
|
|
1620
|
+
if (userConfig.plugins) merged.plugins = [...normalisePlugins(merged.plugins), ...normalisePlugins(userConfig.plugins)];
|
|
1621
|
+
if (userConfig.define && typeof userConfig.define === "object") merged.define = { ...merged.define, ...userConfig.define };
|
|
1622
|
+
if (userConfig.css?.preprocessorOptions) {
|
|
1623
|
+
const fpp = merged.css?.preprocessorOptions ?? {};
|
|
1624
|
+
const upp = userConfig.css.preprocessorOptions;
|
|
1625
|
+
merged.css ??= {};
|
|
1626
|
+
merged.css.preprocessorOptions ??= {};
|
|
1627
|
+
merged.css.preprocessorOptions = Object.keys({ ...fpp, ...upp }).reduce((acc, engine) => {
|
|
1628
|
+
acc[engine] = {
|
|
1629
|
+
...fpp[engine],
|
|
1630
|
+
...upp[engine]
|
|
1631
|
+
};
|
|
1632
|
+
return acc;
|
|
1633
|
+
}, {});
|
|
1634
|
+
}
|
|
1635
|
+
if (userConfig.build) {
|
|
1636
|
+
const protectedBuildFields = ["outDir", "ssr", "ssrManifest", "format", "target"];
|
|
1637
|
+
for (const field of protectedBuildFields) {
|
|
1638
|
+
if (field in userConfig.build) ignoredKeys.push(`build.${field}`);
|
|
1639
|
+
}
|
|
1640
|
+
if ("sourcemap" in userConfig.build) merged.build.sourcemap = userConfig.build.sourcemap;
|
|
1641
|
+
if ("minify" in userConfig.build) merged.build.minify = userConfig.build.minify;
|
|
1642
|
+
if (userConfig.build.terserOptions) {
|
|
1643
|
+
merged.build.terserOptions = {
|
|
1644
|
+
...merged.build.terserOptions,
|
|
1645
|
+
...userConfig.build.terserOptions
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1648
|
+
if (userConfig.build.rollupOptions) {
|
|
1649
|
+
const userRollup = userConfig.build.rollupOptions;
|
|
1650
|
+
const ro = merged.build.rollupOptions ??= {};
|
|
1651
|
+
if ("input" in userRollup) ignoredKeys.push("build.rollupOptions.input");
|
|
1652
|
+
if ("external" in userRollup) ro.external = userRollup.external;
|
|
1653
|
+
if (userRollup.output) {
|
|
1654
|
+
const uo = Array.isArray(userRollup.output) ? userRollup.output[0] : userRollup.output;
|
|
1655
|
+
ro.output = {
|
|
1656
|
+
...Array.isArray(ro.output) ? ro.output[0] : ro.output,
|
|
1657
|
+
...uo?.manualChunks ? { manualChunks: uo.manualChunks } : {}
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
if (userConfig.resolve) {
|
|
1663
|
+
const { alias: _ignore, ...rest } = userConfig.resolve;
|
|
1664
|
+
if (_ignore) ignoredKeys.push("resolve.alias");
|
|
1665
|
+
merged.resolve = { ...merged.resolve, ...rest };
|
|
1666
|
+
}
|
|
1667
|
+
if (userConfig.server) ignoredKeys.push("server");
|
|
1668
|
+
if ("root" in userConfig) ignoredKeys.push("root");
|
|
1669
|
+
if ("base" in userConfig) ignoredKeys.push("base");
|
|
1670
|
+
if ("publicDir" in userConfig) ignoredKeys.push("publicDir");
|
|
1671
|
+
for (const key of ["esbuild", "logLevel", "envPrefix", "optimizeDeps", "ssr"]) {
|
|
1672
|
+
if (key in userConfig) merged[key] = userConfig[key];
|
|
1673
|
+
}
|
|
1674
|
+
merged.root = invariants.root;
|
|
1675
|
+
merged.base = invariants.base;
|
|
1676
|
+
merged.publicDir = invariants.publicDir;
|
|
1677
|
+
merged.build.outDir = invariants.build.outDir;
|
|
1678
|
+
merged.build.manifest = invariants.build.manifest;
|
|
1679
|
+
merged.build.ssr = invariants.build.ssr;
|
|
1680
|
+
merged.build.ssrManifest = invariants.build.ssrManifest;
|
|
1681
|
+
merged.build.format = invariants.build.format;
|
|
1682
|
+
merged.build.target = invariants.build.target;
|
|
1683
|
+
if (invariants.build.ssr === void 0) delete merged.build.ssr;
|
|
1684
|
+
if (invariants.build.format === void 0) delete merged.build.format;
|
|
1685
|
+
if (invariants.build.target === void 0) delete merged.build.target;
|
|
1686
|
+
(merged.build.rollupOptions ??= {}).input = invariants.build.rollupOptions.input;
|
|
1687
|
+
if (ignoredKeys.length > 0) {
|
|
1688
|
+
const prefix = context ? `[taujs:build:${context.entryPoint}]` : "[taujs:build]";
|
|
1689
|
+
console.warn(`${prefix} Ignored Vite config overrides: ${[...new Set(ignoredKeys)].join(", ")}`);
|
|
1690
|
+
}
|
|
1691
|
+
return merged;
|
|
1692
|
+
}
|
|
1693
|
+
function resolveAppFilter(argv, env) {
|
|
1694
|
+
const read = (keys) => {
|
|
1695
|
+
const end = argv.indexOf("--");
|
|
1696
|
+
const limit = end === -1 ? argv.length : end;
|
|
1697
|
+
for (let i = 0; i < limit; i++) {
|
|
1698
|
+
const arg = argv[i];
|
|
1699
|
+
if (!arg) continue;
|
|
1700
|
+
for (const key of keys) {
|
|
1701
|
+
if (arg === key) {
|
|
1702
|
+
const next = argv[i + 1];
|
|
1703
|
+
if (!next || next.startsWith("-")) return "";
|
|
1704
|
+
return next.trim();
|
|
1705
|
+
}
|
|
1706
|
+
const pref = `${key}=`;
|
|
1707
|
+
if (arg.startsWith(pref)) {
|
|
1708
|
+
const v = arg.slice(pref.length).trim();
|
|
1709
|
+
return v;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
return void 0;
|
|
1714
|
+
};
|
|
1715
|
+
const envFilter = env.TAUJS_APP || env.TAUJS_APPS;
|
|
1716
|
+
const cliFilter = read(["--app", "--apps", "-a"]);
|
|
1717
|
+
const raw = (cliFilter ?? envFilter)?.trim() || void 0;
|
|
1718
|
+
if (!raw) return { selectedIds: null, raw: void 0 };
|
|
1719
|
+
const selectedIds = new Set(
|
|
1720
|
+
raw.split(",").map((s) => s.trim()).filter(Boolean)
|
|
1721
|
+
);
|
|
1722
|
+
return { selectedIds, raw };
|
|
1723
|
+
}
|
|
1724
|
+
async function taujsBuild({
|
|
1725
|
+
config,
|
|
1726
|
+
projectRoot,
|
|
1727
|
+
clientBaseDir,
|
|
1728
|
+
isSSRBuild = process.env.BUILD_MODE === "ssr",
|
|
1729
|
+
alias: userAlias,
|
|
1730
|
+
vite: userViteConfig
|
|
1731
|
+
}) {
|
|
1732
|
+
const deleteDist = async () => {
|
|
1733
|
+
const { rm } = await import("fs/promises");
|
|
1734
|
+
const distPath = path4.resolve(projectRoot, "dist");
|
|
1735
|
+
try {
|
|
1736
|
+
await rm(distPath, { recursive: true, force: true });
|
|
1737
|
+
console.log("Deleted the dist directory\n");
|
|
1738
|
+
} catch (err) {
|
|
1739
|
+
console.error("Error deleting dist directory:", err);
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
const extractedConfigs = extractBuildConfigs(config);
|
|
1743
|
+
const processedConfigs = processConfigs(extractedConfigs, clientBaseDir, TEMPLATE);
|
|
1744
|
+
const { selectedIds, raw: appFilterRaw } = resolveAppFilter(process.argv.slice(2), process.env);
|
|
1745
|
+
const configsToBuild = selectedIds ? processedConfigs.filter(({ appId, entryPoint }) => selectedIds.has(appId) || selectedIds.has(entryPoint)) : processedConfigs;
|
|
1746
|
+
if (selectedIds && configsToBuild.length === 0) {
|
|
1747
|
+
console.error(
|
|
1748
|
+
`[taujs:build] No apps match filter "${appFilterRaw}". Known apps: ${processedConfigs.map((c) => `${c.appId}${c.entryPoint ? ` (entry: ${c.entryPoint})` : ""}`).join(", ")}`
|
|
1749
|
+
);
|
|
1750
|
+
process.exit(1);
|
|
1751
|
+
}
|
|
1752
|
+
if (!isSSRBuild) await deleteDist();
|
|
1753
|
+
for (const appConfig of configsToBuild) {
|
|
1754
|
+
const { appId, entryPoint, clientRoot, entryClient, entryServer, htmlTemplate, plugins = [] } = appConfig;
|
|
1755
|
+
const outDir = path4.resolve(projectRoot, isSSRBuild ? `dist/ssr/${entryPoint}` : `dist/client/${entryPoint}`);
|
|
1756
|
+
const root = entryPoint ? path4.resolve(clientBaseDir, entryPoint) : clientBaseDir;
|
|
1757
|
+
const defaultAlias = {
|
|
1758
|
+
"@client": root,
|
|
1759
|
+
"@server": path4.resolve(projectRoot, "src/server"),
|
|
1760
|
+
"@shared": path4.resolve(projectRoot, "src/shared")
|
|
1761
|
+
};
|
|
1762
|
+
const resolvedAlias = { ...defaultAlias, ...userAlias ?? {} };
|
|
1763
|
+
const entryClientFile = resolveEntryFile(clientRoot, entryClient);
|
|
1764
|
+
const entryServerFile = resolveEntryFile(clientRoot, entryServer);
|
|
1765
|
+
const server = path4.resolve(clientRoot, entryServerFile);
|
|
1766
|
+
const client = path4.resolve(clientRoot, entryClientFile);
|
|
1767
|
+
const main = path4.resolve(clientRoot, htmlTemplate);
|
|
1768
|
+
const inputs = resolveInputs(isSSRBuild, !isSSRBuild && existsSync(main), { server, client, main });
|
|
1769
|
+
const nodeVersion = process.versions.node.split(".")[0];
|
|
1770
|
+
const frameworkConfig = {
|
|
1771
|
+
base: entryPoint ? `/${entryPoint}/` : "/",
|
|
1772
|
+
build: {
|
|
1773
|
+
outDir,
|
|
1774
|
+
emptyOutDir: true,
|
|
1775
|
+
manifest: !isSSRBuild,
|
|
1776
|
+
rollupOptions: {
|
|
1777
|
+
input: inputs
|
|
1778
|
+
},
|
|
1779
|
+
ssr: isSSRBuild ? server : void 0,
|
|
1780
|
+
ssrManifest: isSSRBuild,
|
|
1781
|
+
...isSSRBuild && {
|
|
1782
|
+
format: "esm",
|
|
1783
|
+
target: `node${nodeVersion}`,
|
|
1784
|
+
copyPublicDir: false
|
|
1785
|
+
}
|
|
1786
|
+
},
|
|
1787
|
+
css: {
|
|
1788
|
+
preprocessorOptions: {
|
|
1789
|
+
scss: { api: "modern-compiler" }
|
|
1790
|
+
}
|
|
1791
|
+
},
|
|
1792
|
+
plugins,
|
|
1793
|
+
publicDir: isSSRBuild ? false : "public",
|
|
1794
|
+
resolve: { alias: resolvedAlias },
|
|
1795
|
+
root
|
|
1796
|
+
};
|
|
1797
|
+
const buildContext = {
|
|
1798
|
+
appId,
|
|
1799
|
+
entryPoint,
|
|
1800
|
+
isSSRBuild,
|
|
1801
|
+
clientRoot
|
|
1802
|
+
};
|
|
1803
|
+
const finalConfig = mergeViteConfig(frameworkConfig, userViteConfig, buildContext);
|
|
1804
|
+
try {
|
|
1805
|
+
const mode = isSSRBuild ? "SSR" : "Client";
|
|
1806
|
+
console.log(`[taujs:build:${entryPoint}] Building \u2192 ${mode}`);
|
|
1807
|
+
await build(finalConfig);
|
|
1808
|
+
console.log(`[taujs:build:${entryPoint}] \u2713 Complete
|
|
1809
|
+
`);
|
|
1810
|
+
} catch (error) {
|
|
1811
|
+
console.error(`[taujs:build:${entryPoint}] \u2717 Failed
|
|
1812
|
+
`, error);
|
|
1813
|
+
process.exit(1);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1562
1817
|
|
|
1563
1818
|
// src/utils/Telemetry.ts
|
|
1564
1819
|
import crypto2 from "crypto";
|
|
1565
1820
|
function createRequestContext(req, reply, baseLogger) {
|
|
1566
1821
|
const raw = typeof req.headers["x-trace-id"] === "string" ? req.headers["x-trace-id"] : "";
|
|
1567
|
-
const traceId = raw &&
|
|
1822
|
+
const traceId = raw && REGEX2.SAFE_TRACE.test(raw) ? raw : typeof req.id === "string" ? req.id : crypto2.randomUUID();
|
|
1568
1823
|
reply.header("x-trace-id", traceId);
|
|
1569
1824
|
const anyLogger = baseLogger;
|
|
1570
1825
|
const child = anyLogger.child;
|
|
@@ -1615,7 +1870,7 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1615
1870
|
}
|
|
1616
1871
|
});
|
|
1617
1872
|
}
|
|
1618
|
-
const { clientRoot,
|
|
1873
|
+
const { clientRoot, entryServer } = config;
|
|
1619
1874
|
let template = ensureNonNull(maps.templates.get(clientRoot), `Template not found for clientRoot: ${clientRoot}`);
|
|
1620
1875
|
const bootstrapModule = maps.bootstrapModules.get(clientRoot);
|
|
1621
1876
|
const cssLink = maps.cssLinks.get(clientRoot);
|
|
@@ -1627,7 +1882,8 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1627
1882
|
try {
|
|
1628
1883
|
template = template.replace(/<script type="module" src="\/@vite\/client"><\/script>/g, "");
|
|
1629
1884
|
template = template.replace(/<style type="text\/css">[\s\S]*?<\/style>/g, "");
|
|
1630
|
-
const
|
|
1885
|
+
const entryServerFile = resolveEntryFile(clientRoot, entryServer);
|
|
1886
|
+
const entryServerPath = path5.join(clientRoot, entryServerFile);
|
|
1631
1887
|
const executedModule = await viteDevServer.ssrLoadModule(entryServerPath);
|
|
1632
1888
|
renderModule = executedModule;
|
|
1633
1889
|
const styles = await collectStyle(viteDevServer, [entryServerPath]);
|
|
@@ -1635,7 +1891,7 @@ var handleRender = async (req, reply, routeMatchers, processedConfigs, serviceRe
|
|
|
1635
1891
|
template = template?.replace("</head>", `<style type="text/css"${styleNonce}>${styles}</style></head>`);
|
|
1636
1892
|
template = await viteDevServer.transformIndexHtml(url, template);
|
|
1637
1893
|
} catch (error) {
|
|
1638
|
-
throw AppError.internal("Failed to load dev assets", { cause: error, details: { clientRoot,
|
|
1894
|
+
throw AppError.internal("Failed to load dev assets", { cause: error, details: { clientRoot, entryServer, url } });
|
|
1639
1895
|
}
|
|
1640
1896
|
} else {
|
|
1641
1897
|
renderModule = maps.renderModules.get(clientRoot);
|
|
@@ -1904,28 +2160,30 @@ var handleNotFound = async (req, reply, processedConfigs, maps, opts = {}) => {
|
|
|
1904
2160
|
}
|
|
1905
2161
|
};
|
|
1906
2162
|
|
|
1907
|
-
// src/
|
|
1908
|
-
async function
|
|
1909
|
-
const
|
|
1910
|
-
const match2 = matchRoute(url, routeMatchers);
|
|
2163
|
+
// src/core/routes/ResolveRouteData.ts
|
|
2164
|
+
async function resolveRouteDataCore(url, opts) {
|
|
2165
|
+
const match2 = matchRoute(url, opts.routeMatchers);
|
|
1911
2166
|
if (!match2) {
|
|
1912
|
-
throw AppError.notFound("route_not_found", {
|
|
1913
|
-
details: { url }
|
|
1914
|
-
});
|
|
2167
|
+
throw AppError.notFound("route_not_found", { details: { url } });
|
|
1915
2168
|
}
|
|
1916
2169
|
const { route, params } = match2;
|
|
1917
|
-
|
|
1918
|
-
if (!attr?.data) {
|
|
2170
|
+
if (!route.attr?.data) {
|
|
1919
2171
|
throw AppError.notFound("no_data_handler", {
|
|
1920
|
-
details: {
|
|
1921
|
-
url,
|
|
1922
|
-
path: route.path,
|
|
1923
|
-
appId: route.appId
|
|
1924
|
-
}
|
|
2172
|
+
details: { url, path: route.path, appId: route.appId }
|
|
1925
2173
|
});
|
|
1926
2174
|
}
|
|
1927
|
-
const ctx =
|
|
1928
|
-
return fetchInitialData(attr, params, serviceRegistry, ctx);
|
|
2175
|
+
const ctx = opts.getCtx();
|
|
2176
|
+
return fetchInitialData(route.attr, params, opts.serviceRegistry, ctx);
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
// src/utils/ResolveRouteData.ts
|
|
2180
|
+
async function resolveRouteData(url, opts) {
|
|
2181
|
+
const { req, reply, routeMatchers, serviceRegistry, logger } = opts;
|
|
2182
|
+
return resolveRouteDataCore(url, {
|
|
2183
|
+
routeMatchers,
|
|
2184
|
+
serviceRegistry,
|
|
2185
|
+
getCtx: () => createRequestContext(req, reply, logger)
|
|
2186
|
+
});
|
|
1929
2187
|
}
|
|
1930
2188
|
|
|
1931
2189
|
// src/utils/StaticAssets.ts
|
|
@@ -2000,10 +2258,7 @@ var SSRServer = fp3(
|
|
|
2000
2258
|
maps.renderModules,
|
|
2001
2259
|
maps.ssrManifests,
|
|
2002
2260
|
maps.templates,
|
|
2003
|
-
{
|
|
2004
|
-
debug: opts.debug,
|
|
2005
|
-
logger
|
|
2006
|
-
}
|
|
2261
|
+
{ logger }
|
|
2007
2262
|
);
|
|
2008
2263
|
if (!isDevelopment && !opts.staticAssets) {
|
|
2009
2264
|
const fastifyStatic = await import("@fastify/static");
|
|
@@ -2040,7 +2295,7 @@ var SSRServer = fp3(
|
|
|
2040
2295
|
viteDevServer = await setupDevServer(app, clientRoot, alias, opts.debug, opts.devNet, plugins);
|
|
2041
2296
|
}
|
|
2042
2297
|
app.addHook("onRequest", createAuthHook(routeMatchers, logger));
|
|
2043
|
-
app.get("/__taujs/
|
|
2298
|
+
app.get("/__taujs/route", async (req, reply) => {
|
|
2044
2299
|
const query = req.query;
|
|
2045
2300
|
const url = typeof query.url === "string" ? query.url : "";
|
|
2046
2301
|
if (!url) {
|
|
@@ -2111,13 +2366,13 @@ var SSRServer = fp3(
|
|
|
2111
2366
|
|
|
2112
2367
|
// src/CreateServer.ts
|
|
2113
2368
|
var resolveClientRoot = (userClientRoot) => {
|
|
2114
|
-
if (userClientRoot) return
|
|
2369
|
+
if (userClientRoot) return path6.isAbsolute(userClientRoot) ? userClientRoot : path6.resolve(process.cwd(), userClientRoot);
|
|
2115
2370
|
const cwd = process.cwd();
|
|
2116
|
-
if (process.env.NODE_ENV === "production") return
|
|
2117
|
-
return
|
|
2371
|
+
if (process.env.NODE_ENV === "production") return path6.resolve(cwd, "dist/client");
|
|
2372
|
+
return path6.resolve(cwd, "src/client");
|
|
2118
2373
|
};
|
|
2119
2374
|
var createServer = async (opts) => {
|
|
2120
|
-
const t0 =
|
|
2375
|
+
const t0 = performance.now();
|
|
2121
2376
|
const clientRoot = resolveClientRoot(opts.clientRoot);
|
|
2122
2377
|
const app = opts.fastify ?? Fastify({ logger: false });
|
|
2123
2378
|
const fastifyLogger = app.log && app.log.level && app.log.level !== "silent" ? app.log : void 0;
|
|
@@ -2178,7 +2433,7 @@ var createServer = async (opts) => {
|
|
|
2178
2433
|
"Failed to register SSRServer"
|
|
2179
2434
|
);
|
|
2180
2435
|
}
|
|
2181
|
-
const t1 =
|
|
2436
|
+
const t1 = performance.now();
|
|
2182
2437
|
console.log(`
|
|
2183
2438
|
${import_picocolors4.default.bgGreen(import_picocolors4.default.black(` ${CONTENT.TAG} `))} configured in ${(t1 - t0).toFixed(0)}ms
|
|
2184
2439
|
`);
|
|
@@ -2186,264 +2441,11 @@ ${import_picocolors4.default.bgGreen(import_picocolors4.default.black(` ${CONTEN
|
|
|
2186
2441
|
return { app, net };
|
|
2187
2442
|
};
|
|
2188
2443
|
|
|
2189
|
-
// src/Build.ts
|
|
2190
|
-
import { existsSync as existsSync2 } from "fs";
|
|
2191
|
-
import path6 from "path";
|
|
2192
|
-
import { build } from "vite";
|
|
2193
|
-
function resolveInputs(isSSRBuild, mainExists, paths) {
|
|
2194
|
-
if (isSSRBuild) return { server: paths.server };
|
|
2195
|
-
if (mainExists) return { client: paths.client, main: paths.main };
|
|
2196
|
-
return { client: paths.client };
|
|
2197
|
-
}
|
|
2198
|
-
function getFrameworkInvariants(config) {
|
|
2199
|
-
return {
|
|
2200
|
-
root: config.root || "",
|
|
2201
|
-
base: config.base || "/",
|
|
2202
|
-
publicDir: config.publicDir === void 0 ? "public" : config.publicDir,
|
|
2203
|
-
build: {
|
|
2204
|
-
outDir: config.build?.outDir || "",
|
|
2205
|
-
manifest: config.build?.manifest ?? false,
|
|
2206
|
-
ssr: config.build?.ssr ?? void 0,
|
|
2207
|
-
// Preserve exact type
|
|
2208
|
-
ssrManifest: config.build?.ssrManifest ?? false,
|
|
2209
|
-
format: config.build?.format,
|
|
2210
|
-
target: config.build?.target,
|
|
2211
|
-
rollupOptions: {
|
|
2212
|
-
input: config.build?.rollupOptions?.input || {}
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
};
|
|
2216
|
-
}
|
|
2217
|
-
function mergeViteConfig(framework, userOverride, context) {
|
|
2218
|
-
if (!userOverride) return framework;
|
|
2219
|
-
const userConfig = typeof userOverride === "function" && context ? userOverride(context) : userOverride;
|
|
2220
|
-
const invariants = getFrameworkInvariants(framework);
|
|
2221
|
-
const merged = {
|
|
2222
|
-
...framework,
|
|
2223
|
-
build: { ...framework.build ?? {} },
|
|
2224
|
-
css: { ...framework.css ?? {} },
|
|
2225
|
-
resolve: { ...framework.resolve ?? {} },
|
|
2226
|
-
plugins: [...framework.plugins ?? []],
|
|
2227
|
-
define: { ...framework.define ?? {} }
|
|
2228
|
-
};
|
|
2229
|
-
const ignoredKeys = [];
|
|
2230
|
-
if (userConfig.plugins) {
|
|
2231
|
-
const frameworkPlugins = merged.plugins;
|
|
2232
|
-
merged.plugins = [...frameworkPlugins, ...userConfig.plugins];
|
|
2233
|
-
}
|
|
2234
|
-
if (userConfig.define && typeof userConfig.define === "object") {
|
|
2235
|
-
merged.define = {
|
|
2236
|
-
...merged.define,
|
|
2237
|
-
...userConfig.define
|
|
2238
|
-
};
|
|
2239
|
-
}
|
|
2240
|
-
if (userConfig.css?.preprocessorOptions && typeof userConfig.css.preprocessorOptions === "object") {
|
|
2241
|
-
const fpp = merged.css.preprocessorOptions ?? {};
|
|
2242
|
-
const upp = userConfig.css.preprocessorOptions;
|
|
2243
|
-
merged.css.preprocessorOptions = Object.keys({ ...fpp, ...upp }).reduce((acc, engine) => {
|
|
2244
|
-
const fppEngine = fpp[engine];
|
|
2245
|
-
const uppEngine = upp[engine];
|
|
2246
|
-
acc[engine] = { ...fppEngine ?? {}, ...uppEngine ?? {} };
|
|
2247
|
-
return acc;
|
|
2248
|
-
}, {});
|
|
2249
|
-
}
|
|
2250
|
-
if (userConfig.build) {
|
|
2251
|
-
const protectedBuildFields = ["outDir", "ssr", "ssrManifest", "format", "target"];
|
|
2252
|
-
for (const field of protectedBuildFields) {
|
|
2253
|
-
if (field in userConfig.build) {
|
|
2254
|
-
ignoredKeys.push(`build.${field}`);
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
if ("sourcemap" in userConfig.build) merged.build.sourcemap = userConfig.build.sourcemap;
|
|
2258
|
-
if ("minify" in userConfig.build) merged.build.minify = userConfig.build.minify;
|
|
2259
|
-
if (userConfig.build.terserOptions && typeof userConfig.build.terserOptions === "object") {
|
|
2260
|
-
merged.build.terserOptions = {
|
|
2261
|
-
...merged.build.terserOptions ?? {},
|
|
2262
|
-
...userConfig.build.terserOptions
|
|
2263
|
-
};
|
|
2264
|
-
}
|
|
2265
|
-
if (userConfig.build.rollupOptions) {
|
|
2266
|
-
if (!merged.build.rollupOptions) {
|
|
2267
|
-
merged.build.rollupOptions = {};
|
|
2268
|
-
}
|
|
2269
|
-
const userRollup = userConfig.build.rollupOptions;
|
|
2270
|
-
if ("input" in userRollup) ignoredKeys.push("build.rollupOptions.input");
|
|
2271
|
-
if ("external" in userRollup) merged.build.rollupOptions.external = userRollup.external;
|
|
2272
|
-
if (userRollup.output) {
|
|
2273
|
-
const mro = merged.build.rollupOptions ??= {};
|
|
2274
|
-
const uo = Array.isArray(userRollup.output) ? userRollup.output[0] : userRollup.output;
|
|
2275
|
-
const baseOut = Array.isArray(mro.output) ? mro.output[0] ?? {} : mro.output ?? {};
|
|
2276
|
-
mro.output = { ...baseOut, ...uo?.manualChunks ? { manualChunks: uo.manualChunks } : {} };
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
}
|
|
2280
|
-
if (userConfig.resolve) {
|
|
2281
|
-
const userResolve = userConfig.resolve;
|
|
2282
|
-
const { alias: _ignore, ...resolveRest } = userResolve;
|
|
2283
|
-
if (_ignore) ignoredKeys.push("resolve.alias");
|
|
2284
|
-
merged.resolve = {
|
|
2285
|
-
...merged.resolve,
|
|
2286
|
-
...resolveRest
|
|
2287
|
-
};
|
|
2288
|
-
}
|
|
2289
|
-
if (userConfig.server) ignoredKeys.push("server (ignored in build; dev-only)");
|
|
2290
|
-
if ("root" in userConfig) ignoredKeys.push("root");
|
|
2291
|
-
if ("base" in userConfig) ignoredKeys.push("base");
|
|
2292
|
-
if ("publicDir" in userConfig) ignoredKeys.push("publicDir");
|
|
2293
|
-
const safeTopLevelKeys = /* @__PURE__ */ new Set([
|
|
2294
|
-
"esbuild",
|
|
2295
|
-
"logLevel",
|
|
2296
|
-
"envPrefix",
|
|
2297
|
-
"optimizeDeps",
|
|
2298
|
-
"ssr"
|
|
2299
|
-
// NOTE: NOT 'server' (build-time irrelevant; dev-server only)
|
|
2300
|
-
]);
|
|
2301
|
-
for (const [key, value] of Object.entries(userConfig)) {
|
|
2302
|
-
if (safeTopLevelKeys.has(key)) merged[key] = value;
|
|
2303
|
-
}
|
|
2304
|
-
merged.root = invariants.root;
|
|
2305
|
-
merged.base = invariants.base;
|
|
2306
|
-
merged.publicDir = invariants.publicDir;
|
|
2307
|
-
merged.build.outDir = invariants.build.outDir;
|
|
2308
|
-
merged.build.manifest = invariants.build.manifest;
|
|
2309
|
-
if (invariants.build.ssr !== void 0) merged.build.ssr = invariants.build.ssr;
|
|
2310
|
-
merged.build.ssrManifest = invariants.build.ssrManifest;
|
|
2311
|
-
if (invariants.build.format) merged.build.format = invariants.build.format;
|
|
2312
|
-
if (invariants.build.target) merged.build.target = invariants.build.target;
|
|
2313
|
-
if (!merged.build.rollupOptions) merged.build.rollupOptions = {};
|
|
2314
|
-
merged.build.rollupOptions.input = invariants.build.rollupOptions.input;
|
|
2315
|
-
if (ignoredKeys.length > 0) {
|
|
2316
|
-
const uniqueKeys = [...new Set(ignoredKeys)];
|
|
2317
|
-
const prefix = context ? `[taujs:build:${context.entryPoint}]` : "[taujs:build]";
|
|
2318
|
-
console.warn(`${prefix} Ignored Vite config overrides: ${uniqueKeys.join(", ")}`);
|
|
2319
|
-
}
|
|
2320
|
-
return merged;
|
|
2321
|
-
}
|
|
2322
|
-
function resolveAppFilter(argv, env) {
|
|
2323
|
-
const read = (keys) => {
|
|
2324
|
-
const end = argv.indexOf("--");
|
|
2325
|
-
const limit = end === -1 ? argv.length : end;
|
|
2326
|
-
for (let i = 0; i < limit; i++) {
|
|
2327
|
-
const arg = argv[i];
|
|
2328
|
-
if (!arg) continue;
|
|
2329
|
-
for (const key of keys) {
|
|
2330
|
-
if (arg === key) {
|
|
2331
|
-
const next = argv[i + 1];
|
|
2332
|
-
if (!next || next.startsWith("-")) return "";
|
|
2333
|
-
return next.trim();
|
|
2334
|
-
}
|
|
2335
|
-
const pref = `${key}=`;
|
|
2336
|
-
if (arg.startsWith(pref)) {
|
|
2337
|
-
const v = arg.slice(pref.length).trim();
|
|
2338
|
-
return v;
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
return void 0;
|
|
2343
|
-
};
|
|
2344
|
-
const envFilter = env.TAUJS_APP || env.TAUJS_APPS;
|
|
2345
|
-
const cliFilter = read(["--app", "--apps", "-a"]);
|
|
2346
|
-
const raw = (cliFilter ?? envFilter)?.trim() || void 0;
|
|
2347
|
-
if (!raw) return { selectedIds: null, raw: void 0 };
|
|
2348
|
-
const selectedIds = new Set(
|
|
2349
|
-
raw.split(",").map((s) => s.trim()).filter(Boolean)
|
|
2350
|
-
);
|
|
2351
|
-
return { selectedIds, raw };
|
|
2352
|
-
}
|
|
2353
|
-
async function taujsBuild({
|
|
2354
|
-
config,
|
|
2355
|
-
projectRoot,
|
|
2356
|
-
clientBaseDir,
|
|
2357
|
-
isSSRBuild = process.env.BUILD_MODE === "ssr",
|
|
2358
|
-
alias: userAlias,
|
|
2359
|
-
vite: userViteConfig
|
|
2360
|
-
}) {
|
|
2361
|
-
const deleteDist = async () => {
|
|
2362
|
-
const { rm } = await import("fs/promises");
|
|
2363
|
-
const distPath = path6.resolve(projectRoot, "dist");
|
|
2364
|
-
try {
|
|
2365
|
-
await rm(distPath, { recursive: true, force: true });
|
|
2366
|
-
console.log("Deleted the dist directory\n");
|
|
2367
|
-
} catch (err) {
|
|
2368
|
-
console.error("Error deleting dist directory:", err);
|
|
2369
|
-
}
|
|
2370
|
-
};
|
|
2371
|
-
const extractedConfigs = extractBuildConfigs(config);
|
|
2372
|
-
const processedConfigs = processConfigs(extractedConfigs, clientBaseDir, TEMPLATE);
|
|
2373
|
-
const { selectedIds, raw: appFilterRaw } = resolveAppFilter(process.argv.slice(2), process.env);
|
|
2374
|
-
const configsToBuild = selectedIds ? processedConfigs.filter(({ appId, entryPoint }) => selectedIds.has(appId) || selectedIds.has(entryPoint)) : processedConfigs;
|
|
2375
|
-
if (selectedIds && configsToBuild.length === 0) {
|
|
2376
|
-
console.error(
|
|
2377
|
-
`[taujs:build] No apps match filter "${appFilterRaw}". Known apps: ${processedConfigs.map((c) => `${c.appId}${c.entryPoint ? ` (entry: ${c.entryPoint})` : ""}`).join(", ")}`
|
|
2378
|
-
);
|
|
2379
|
-
process.exit(1);
|
|
2380
|
-
}
|
|
2381
|
-
if (!isSSRBuild) await deleteDist();
|
|
2382
|
-
for (const appConfig of configsToBuild) {
|
|
2383
|
-
const { appId, entryPoint, clientRoot, entryClientFile, entryServerFile, htmlTemplate, plugins = [] } = appConfig;
|
|
2384
|
-
const outDir = path6.resolve(projectRoot, isSSRBuild ? `dist/ssr/${entryPoint}` : `dist/client/${entryPoint}`);
|
|
2385
|
-
const root = entryPoint ? path6.resolve(clientBaseDir, entryPoint) : clientBaseDir;
|
|
2386
|
-
const defaultAlias = {
|
|
2387
|
-
"@client": root,
|
|
2388
|
-
"@server": path6.resolve(projectRoot, "src/server"),
|
|
2389
|
-
"@shared": path6.resolve(projectRoot, "src/shared")
|
|
2390
|
-
};
|
|
2391
|
-
const resolvedAlias = { ...defaultAlias, ...userAlias ?? {} };
|
|
2392
|
-
const server = path6.resolve(clientRoot, entryServerFile);
|
|
2393
|
-
const client = path6.resolve(clientRoot, entryClientFile);
|
|
2394
|
-
const main = path6.resolve(clientRoot, htmlTemplate);
|
|
2395
|
-
const inputs = resolveInputs(isSSRBuild, !isSSRBuild && existsSync2(main), { server, client, main });
|
|
2396
|
-
const nodeVersion = process.versions.node.split(".")[0];
|
|
2397
|
-
const frameworkConfig = {
|
|
2398
|
-
base: entryPoint ? `/${entryPoint}/` : "/",
|
|
2399
|
-
build: {
|
|
2400
|
-
outDir,
|
|
2401
|
-
emptyOutDir: true,
|
|
2402
|
-
manifest: !isSSRBuild,
|
|
2403
|
-
rollupOptions: {
|
|
2404
|
-
input: inputs
|
|
2405
|
-
},
|
|
2406
|
-
ssr: isSSRBuild ? server : void 0,
|
|
2407
|
-
ssrManifest: isSSRBuild,
|
|
2408
|
-
...isSSRBuild && {
|
|
2409
|
-
format: "esm",
|
|
2410
|
-
target: `node${nodeVersion}`,
|
|
2411
|
-
copyPublicDir: false
|
|
2412
|
-
}
|
|
2413
|
-
},
|
|
2414
|
-
css: {
|
|
2415
|
-
preprocessorOptions: {
|
|
2416
|
-
scss: { api: "modern-compiler" }
|
|
2417
|
-
}
|
|
2418
|
-
},
|
|
2419
|
-
plugins,
|
|
2420
|
-
publicDir: isSSRBuild ? false : "public",
|
|
2421
|
-
resolve: { alias: resolvedAlias },
|
|
2422
|
-
root
|
|
2423
|
-
};
|
|
2424
|
-
const buildContext = {
|
|
2425
|
-
appId,
|
|
2426
|
-
entryPoint,
|
|
2427
|
-
isSSRBuild,
|
|
2428
|
-
clientRoot
|
|
2429
|
-
};
|
|
2430
|
-
const finalConfig = mergeViteConfig(frameworkConfig, userViteConfig, buildContext);
|
|
2431
|
-
try {
|
|
2432
|
-
const mode = isSSRBuild ? "SSR" : "Client";
|
|
2433
|
-
console.log(`[taujs:build:${entryPoint}] Building \u2192 ${mode}`);
|
|
2434
|
-
await build(finalConfig);
|
|
2435
|
-
console.log(`[taujs:build:${entryPoint}] \u2713 Complete
|
|
2436
|
-
`);
|
|
2437
|
-
} catch (error) {
|
|
2438
|
-
console.error(`[taujs:build:${entryPoint}] \u2717 Failed
|
|
2439
|
-
`, error);
|
|
2440
|
-
process.exit(1);
|
|
2441
|
-
}
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
|
|
2445
2444
|
// src/logging/Adapters.ts
|
|
2446
|
-
var cleanMeta = (
|
|
2445
|
+
var cleanMeta = (meta) => {
|
|
2446
|
+
if (meta && typeof meta === "object" && !Array.isArray(meta)) return Object.keys(meta).length ? meta : void 0;
|
|
2447
|
+
return void 0;
|
|
2448
|
+
};
|
|
2447
2449
|
function messageMetaAdapter(sink) {
|
|
2448
2450
|
return {
|
|
2449
2451
|
debug: (meta, message) => sink.debug?.(message, cleanMeta(meta)),
|