@taujs/server 0.5.3 → 0.5.5
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 +576 -617
- 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,30 +2160,6 @@ var handleNotFound = async (req, reply, processedConfigs, maps, opts = {}) => {
|
|
|
1904
2160
|
}
|
|
1905
2161
|
};
|
|
1906
2162
|
|
|
1907
|
-
// src/utils/ResolveRouteData.ts
|
|
1908
|
-
async function resolveRouteData(url, opts) {
|
|
1909
|
-
const { req, reply, routeMatchers, serviceRegistry, logger } = opts;
|
|
1910
|
-
const match2 = matchRoute(url, routeMatchers);
|
|
1911
|
-
if (!match2) {
|
|
1912
|
-
throw AppError.notFound("route_not_found", {
|
|
1913
|
-
details: { url }
|
|
1914
|
-
});
|
|
1915
|
-
}
|
|
1916
|
-
const { route, params } = match2;
|
|
1917
|
-
const attr = route.attr;
|
|
1918
|
-
if (!attr?.data) {
|
|
1919
|
-
throw AppError.notFound("no_data_handler", {
|
|
1920
|
-
details: {
|
|
1921
|
-
url,
|
|
1922
|
-
path: route.path,
|
|
1923
|
-
appId: route.appId
|
|
1924
|
-
}
|
|
1925
|
-
});
|
|
1926
|
-
}
|
|
1927
|
-
const ctx = createRequestContext(req, reply, logger);
|
|
1928
|
-
return fetchInitialData(attr, params, serviceRegistry, ctx);
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
2163
|
// src/utils/StaticAssets.ts
|
|
1932
2164
|
function normaliseStaticAssets(reg) {
|
|
1933
2165
|
if (!reg) return [];
|
|
@@ -2000,10 +2232,7 @@ var SSRServer = fp3(
|
|
|
2000
2232
|
maps.renderModules,
|
|
2001
2233
|
maps.ssrManifests,
|
|
2002
2234
|
maps.templates,
|
|
2003
|
-
{
|
|
2004
|
-
debug: opts.debug,
|
|
2005
|
-
logger
|
|
2006
|
-
}
|
|
2235
|
+
{ logger }
|
|
2007
2236
|
);
|
|
2008
2237
|
if (!isDevelopment && !opts.staticAssets) {
|
|
2009
2238
|
const fastifyStatic = await import("@fastify/static");
|
|
@@ -2040,23 +2269,6 @@ var SSRServer = fp3(
|
|
|
2040
2269
|
viteDevServer = await setupDevServer(app, clientRoot, alias, opts.debug, opts.devNet, plugins);
|
|
2041
2270
|
}
|
|
2042
2271
|
app.addHook("onRequest", createAuthHook(routeMatchers, logger));
|
|
2043
|
-
app.get("/__taujs/route", async (req, reply) => {
|
|
2044
|
-
const query = req.query;
|
|
2045
|
-
const url = typeof query.url === "string" ? query.url : "";
|
|
2046
|
-
if (!url) {
|
|
2047
|
-
throw AppError.badRequest("url query param required", {
|
|
2048
|
-
details: { query }
|
|
2049
|
-
});
|
|
2050
|
-
}
|
|
2051
|
-
const data = await resolveRouteData(url, {
|
|
2052
|
-
req,
|
|
2053
|
-
reply,
|
|
2054
|
-
routeMatchers,
|
|
2055
|
-
serviceRegistry,
|
|
2056
|
-
logger
|
|
2057
|
-
});
|
|
2058
|
-
return reply.status(200).send({ data });
|
|
2059
|
-
});
|
|
2060
2272
|
app.get("/*", async (req, reply) => {
|
|
2061
2273
|
await handleRender(req, reply, routeMatchers, processedConfigs, serviceRegistry, maps, {
|
|
2062
2274
|
debug: opts.debug,
|
|
@@ -2111,13 +2323,13 @@ var SSRServer = fp3(
|
|
|
2111
2323
|
|
|
2112
2324
|
// src/CreateServer.ts
|
|
2113
2325
|
var resolveClientRoot = (userClientRoot) => {
|
|
2114
|
-
if (userClientRoot) return
|
|
2326
|
+
if (userClientRoot) return path6.isAbsolute(userClientRoot) ? userClientRoot : path6.resolve(process.cwd(), userClientRoot);
|
|
2115
2327
|
const cwd = process.cwd();
|
|
2116
|
-
if (process.env.NODE_ENV === "production") return
|
|
2117
|
-
return
|
|
2328
|
+
if (process.env.NODE_ENV === "production") return path6.resolve(cwd, "dist/client");
|
|
2329
|
+
return path6.resolve(cwd, "src/client");
|
|
2118
2330
|
};
|
|
2119
2331
|
var createServer = async (opts) => {
|
|
2120
|
-
const t0 =
|
|
2332
|
+
const t0 = performance.now();
|
|
2121
2333
|
const clientRoot = resolveClientRoot(opts.clientRoot);
|
|
2122
2334
|
const app = opts.fastify ?? Fastify({ logger: false });
|
|
2123
2335
|
const fastifyLogger = app.log && app.log.level && app.log.level !== "silent" ? app.log : void 0;
|
|
@@ -2178,7 +2390,7 @@ var createServer = async (opts) => {
|
|
|
2178
2390
|
"Failed to register SSRServer"
|
|
2179
2391
|
);
|
|
2180
2392
|
}
|
|
2181
|
-
const t1 =
|
|
2393
|
+
const t1 = performance.now();
|
|
2182
2394
|
console.log(`
|
|
2183
2395
|
${import_picocolors4.default.bgGreen(import_picocolors4.default.black(` ${CONTENT.TAG} `))} configured in ${(t1 - t0).toFixed(0)}ms
|
|
2184
2396
|
`);
|
|
@@ -2186,264 +2398,11 @@ ${import_picocolors4.default.bgGreen(import_picocolors4.default.black(` ${CONTEN
|
|
|
2186
2398
|
return { app, net };
|
|
2187
2399
|
};
|
|
2188
2400
|
|
|
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
2401
|
// src/logging/Adapters.ts
|
|
2446
|
-
var cleanMeta = (
|
|
2402
|
+
var cleanMeta = (meta) => {
|
|
2403
|
+
if (meta && typeof meta === "object" && !Array.isArray(meta)) return Object.keys(meta).length ? meta : void 0;
|
|
2404
|
+
return void 0;
|
|
2405
|
+
};
|
|
2447
2406
|
function messageMetaAdapter(sink) {
|
|
2448
2407
|
return {
|
|
2449
2408
|
debug: (meta, message) => sink.debug?.(message, cleanMeta(meta)),
|