@lolyjs/core 0.2.0-alpha.23 → 0.2.0-alpha.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/cli.cjs +58 -41
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +58 -41
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +58 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -6
- package/dist/index.d.ts +1 -6
- package/dist/index.js +58 -41
- package/dist/index.js.map +1 -1
- package/dist/react/sockets.cjs +0 -8
- package/dist/react/sockets.cjs.map +1 -1
- package/dist/react/sockets.js +0 -8
- package/dist/react/sockets.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
export { a as ApiContext, A as ApiMiddleware, G as GenerateStaticParams, L as LoaderResult, M as MetadataLoader, R as RouteMiddleware, S as ServerContext, b as ServerLoader, W as WssActions } from './index.types-DMOO-uvF.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import { Socket } from 'socket.io';
|
|
4
4
|
export { c as bootstrapClient } from './bootstrap-BfGTMUkj.mjs';
|
|
5
5
|
import { ZodSchema, z } from 'zod';
|
|
6
6
|
import * as express_rate_limit from 'express-rate-limit';
|
|
@@ -153,7 +153,6 @@ interface RateLimitCfg {
|
|
|
153
153
|
type GuardFn<TUser = any> = (ctx: {
|
|
154
154
|
user: TUser | null;
|
|
155
155
|
req: AuthContext["req"];
|
|
156
|
-
socket: Socket;
|
|
157
156
|
namespace: string;
|
|
158
157
|
}) => boolean | Promise<boolean>;
|
|
159
158
|
/**
|
|
@@ -279,10 +278,6 @@ interface WssActions {
|
|
|
279
278
|
* Extended WssContext with full RFC support.
|
|
280
279
|
*/
|
|
281
280
|
interface WssContext<TData = any, TUser = any> {
|
|
282
|
-
/** Socket.IO server instance */
|
|
283
|
-
io: Server;
|
|
284
|
-
/** Socket.IO socket instance */
|
|
285
|
-
socket: Socket;
|
|
286
281
|
/** Request metadata */
|
|
287
282
|
req: {
|
|
288
283
|
headers: Record<string, string | string[] | undefined>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
export { a as ApiContext, A as ApiMiddleware, G as GenerateStaticParams, L as LoaderResult, M as MetadataLoader, R as RouteMiddleware, S as ServerContext, b as ServerLoader, W as WssActions } from './index.types-DMOO-uvF.js';
|
|
3
|
-
import {
|
|
3
|
+
import { Socket } from 'socket.io';
|
|
4
4
|
export { c as bootstrapClient } from './bootstrap-BfGTMUkj.js';
|
|
5
5
|
import { ZodSchema, z } from 'zod';
|
|
6
6
|
import * as express_rate_limit from 'express-rate-limit';
|
|
@@ -153,7 +153,6 @@ interface RateLimitCfg {
|
|
|
153
153
|
type GuardFn<TUser = any> = (ctx: {
|
|
154
154
|
user: TUser | null;
|
|
155
155
|
req: AuthContext["req"];
|
|
156
|
-
socket: Socket;
|
|
157
156
|
namespace: string;
|
|
158
157
|
}) => boolean | Promise<boolean>;
|
|
159
158
|
/**
|
|
@@ -279,10 +278,6 @@ interface WssActions {
|
|
|
279
278
|
* Extended WssContext with full RFC support.
|
|
280
279
|
*/
|
|
281
280
|
interface WssContext<TData = any, TUser = any> {
|
|
282
|
-
/** Socket.IO server instance */
|
|
283
|
-
io: Server;
|
|
284
|
-
/** Socket.IO socket instance */
|
|
285
|
-
socket: Socket;
|
|
286
281
|
/** Request metadata */
|
|
287
282
|
req: {
|
|
288
283
|
headers: Record<string, string | string[] | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -11505,22 +11505,36 @@ function copyStaticAssets(projectRoot, outDir) {
|
|
|
11505
11505
|
const assetsSrc = path11.join(projectRoot, "assets");
|
|
11506
11506
|
const assetsDest = path11.join(outDir, "assets");
|
|
11507
11507
|
copyDirRecursive(assetsSrc, assetsDest);
|
|
11508
|
-
const
|
|
11508
|
+
const publicDir = path11.join(projectRoot, "public");
|
|
11509
11509
|
const candidates = ["favicon.ico", "favicon.png"];
|
|
11510
11510
|
for (const name of candidates) {
|
|
11511
|
-
const
|
|
11512
|
-
|
|
11513
|
-
let src = null;
|
|
11514
|
-
if (fs11.existsSync(fromApp)) src = fromApp;
|
|
11515
|
-
else if (fs11.existsSync(fromRoot)) src = fromRoot;
|
|
11516
|
-
if (src) {
|
|
11511
|
+
const fromPublic = path11.join(publicDir, name);
|
|
11512
|
+
if (fs11.existsSync(fromPublic)) {
|
|
11517
11513
|
const dest = path11.join(outDir, name);
|
|
11518
11514
|
ensureDir(path11.dirname(dest));
|
|
11519
|
-
fs11.copyFileSync(
|
|
11515
|
+
fs11.copyFileSync(fromPublic, dest);
|
|
11520
11516
|
break;
|
|
11521
11517
|
}
|
|
11522
11518
|
}
|
|
11523
11519
|
}
|
|
11520
|
+
function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
|
|
11521
|
+
const candidates = [
|
|
11522
|
+
{ name: "favicon.ico", type: "image/x-icon" },
|
|
11523
|
+
{ name: "favicon.png", type: "image/png" }
|
|
11524
|
+
];
|
|
11525
|
+
const publicDir = path11.join(projectRoot, staticDir);
|
|
11526
|
+
for (const candidate of candidates) {
|
|
11527
|
+
const publicPath = path11.join(publicDir, candidate.name);
|
|
11528
|
+
if (fs11.existsSync(publicPath)) {
|
|
11529
|
+
return {
|
|
11530
|
+
path: `/${candidate.name}`,
|
|
11531
|
+
// Served at root from public/
|
|
11532
|
+
type: candidate.type
|
|
11533
|
+
};
|
|
11534
|
+
}
|
|
11535
|
+
}
|
|
11536
|
+
return null;
|
|
11537
|
+
}
|
|
11524
11538
|
function generateAssetManifest(outDir, stats) {
|
|
11525
11539
|
const manifest = {
|
|
11526
11540
|
client: {
|
|
@@ -14619,8 +14633,12 @@ function createDocumentTree(options) {
|
|
|
14619
14633
|
clientJsPath = "/static/client.js",
|
|
14620
14634
|
clientCssPath = "/static/client.css",
|
|
14621
14635
|
nonce,
|
|
14622
|
-
includeInlineScripts = true
|
|
14636
|
+
includeInlineScripts = true,
|
|
14623
14637
|
// Default true - scripts inline in body for both SSR and SSG
|
|
14638
|
+
faviconPath = FAVICON_PATH,
|
|
14639
|
+
// Default to /static/favicon.png for backward compatibility
|
|
14640
|
+
faviconType = "image/png"
|
|
14641
|
+
// Default to PNG for backward compatibility
|
|
14624
14642
|
} = options;
|
|
14625
14643
|
const metaObj = meta ?? null;
|
|
14626
14644
|
const title = metaObj?.title ?? titleFallback ?? "My Framework Dev";
|
|
@@ -14927,10 +14945,11 @@ function createDocumentTree(options) {
|
|
|
14927
14945
|
href: chunkHref,
|
|
14928
14946
|
as: "script"
|
|
14929
14947
|
}),
|
|
14930
|
-
React.createElement("link", {
|
|
14948
|
+
faviconPath && React.createElement("link", {
|
|
14949
|
+
key: "favicon",
|
|
14931
14950
|
rel: "icon",
|
|
14932
|
-
href:
|
|
14933
|
-
type: "image/png"
|
|
14951
|
+
href: faviconPath,
|
|
14952
|
+
type: faviconType || (faviconPath.endsWith(".ico") ? "image/x-icon" : "image/png")
|
|
14934
14953
|
}),
|
|
14935
14954
|
React.createElement("link", {
|
|
14936
14955
|
rel: "stylesheet",
|
|
@@ -15212,7 +15231,7 @@ async function handlePageRequest(options) {
|
|
|
15212
15231
|
const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
|
|
15213
15232
|
const reqLogger = getRequestLogger(req);
|
|
15214
15233
|
if (errorPage) {
|
|
15215
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
|
|
15234
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env, options.config);
|
|
15216
15235
|
} else {
|
|
15217
15236
|
reqLogger.error("Unhandled error in page request", error, {
|
|
15218
15237
|
urlPath: options.urlPath,
|
|
@@ -15238,11 +15257,13 @@ async function handlePageRequestInternal(options) {
|
|
|
15238
15257
|
env = "dev",
|
|
15239
15258
|
ssgOutDir,
|
|
15240
15259
|
theme,
|
|
15241
|
-
projectRoot
|
|
15260
|
+
projectRoot,
|
|
15261
|
+
config
|
|
15242
15262
|
} = options;
|
|
15243
15263
|
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
15244
15264
|
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
15245
15265
|
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
15266
|
+
const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
|
|
15246
15267
|
const isDataReq = isDataRequest(req);
|
|
15247
15268
|
const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
|
|
15248
15269
|
if (env === "prod" && ssgOutDir) {
|
|
@@ -15357,7 +15378,9 @@ async function handlePageRequestInternal(options) {
|
|
|
15357
15378
|
theme,
|
|
15358
15379
|
clientJsPath,
|
|
15359
15380
|
clientCssPath,
|
|
15360
|
-
nonce: nonce2
|
|
15381
|
+
nonce: nonce2,
|
|
15382
|
+
faviconPath: faviconInfo?.path || null,
|
|
15383
|
+
faviconType: faviconInfo?.type || null
|
|
15361
15384
|
});
|
|
15362
15385
|
let didError2 = false;
|
|
15363
15386
|
const { pipe: pipe2, abort: abort2 } = renderToPipeableStream(documentTree2, {
|
|
@@ -15372,7 +15395,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15372
15395
|
const reqLogger2 = getRequestLogger(req);
|
|
15373
15396
|
reqLogger2.error("SSR shell error", err, { route: "not-found" });
|
|
15374
15397
|
if (!res.headersSent && errorPage) {
|
|
15375
|
-
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
15398
|
+
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env, config);
|
|
15376
15399
|
} else if (!res.headersSent) {
|
|
15377
15400
|
res.statusCode = 500;
|
|
15378
15401
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -15487,7 +15510,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15487
15510
|
return;
|
|
15488
15511
|
} else {
|
|
15489
15512
|
if (errorPage) {
|
|
15490
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
|
|
15513
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env, config);
|
|
15491
15514
|
return;
|
|
15492
15515
|
} else {
|
|
15493
15516
|
throw error;
|
|
@@ -15565,7 +15588,9 @@ async function handlePageRequestInternal(options) {
|
|
|
15565
15588
|
theme,
|
|
15566
15589
|
clientJsPath,
|
|
15567
15590
|
clientCssPath,
|
|
15568
|
-
nonce
|
|
15591
|
+
nonce,
|
|
15592
|
+
faviconPath: faviconInfo?.path || null,
|
|
15593
|
+
faviconType: faviconInfo?.type || null
|
|
15569
15594
|
});
|
|
15570
15595
|
let didError = false;
|
|
15571
15596
|
const { pipe, abort } = renderToPipeableStream(documentTree, {
|
|
@@ -15613,7 +15638,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15613
15638
|
abort();
|
|
15614
15639
|
});
|
|
15615
15640
|
}
|
|
15616
|
-
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
|
|
15641
|
+
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev", config) {
|
|
15617
15642
|
try {
|
|
15618
15643
|
const isDataReq = isDataRequest(req);
|
|
15619
15644
|
const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
|
|
@@ -15624,6 +15649,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
15624
15649
|
pathname: req.path,
|
|
15625
15650
|
locals: { error }
|
|
15626
15651
|
};
|
|
15652
|
+
const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
|
|
15627
15653
|
const layoutProps = {};
|
|
15628
15654
|
const reqLogger = getRequestLogger(req);
|
|
15629
15655
|
if (!skipLayoutHooks && errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
|
|
@@ -15729,7 +15755,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
15729
15755
|
theme,
|
|
15730
15756
|
clientJsPath,
|
|
15731
15757
|
clientCssPath,
|
|
15732
|
-
nonce
|
|
15758
|
+
nonce,
|
|
15759
|
+
faviconPath: faviconInfo?.path || null,
|
|
15760
|
+
faviconType: faviconInfo?.type || null
|
|
15733
15761
|
});
|
|
15734
15762
|
let didError = false;
|
|
15735
15763
|
const { pipe, abort } = renderToPipeableStream(documentTree, {
|
|
@@ -15986,7 +16014,8 @@ function setupRoutes(options) {
|
|
|
15986
16014
|
env: isDev ? "dev" : "prod",
|
|
15987
16015
|
ssgOutDir,
|
|
15988
16016
|
theme: req.cookies?.theme || "light",
|
|
15989
|
-
projectRoot
|
|
16017
|
+
projectRoot,
|
|
16018
|
+
config
|
|
15990
16019
|
});
|
|
15991
16020
|
});
|
|
15992
16021
|
}
|
|
@@ -16600,7 +16629,6 @@ async function executeGuard(guardFn, ctx) {
|
|
|
16600
16629
|
const guardCtx = {
|
|
16601
16630
|
user: ctx.user,
|
|
16602
16631
|
req: ctx.req,
|
|
16603
|
-
socket: ctx.socket,
|
|
16604
16632
|
namespace: ctx.pathname
|
|
16605
16633
|
};
|
|
16606
16634
|
const result = await guardFn(guardCtx);
|
|
@@ -16707,9 +16735,6 @@ var generateActions = (socket, namespace, presence) => {
|
|
|
16707
16735
|
return {
|
|
16708
16736
|
emit: async (event, payload) => {
|
|
16709
16737
|
if (!presence) {
|
|
16710
|
-
console.warn(
|
|
16711
|
-
"[loly:realtime] toUser() requires presence manager. Make sure realtime is properly configured."
|
|
16712
|
-
);
|
|
16713
16738
|
return;
|
|
16714
16739
|
}
|
|
16715
16740
|
const socketIds = await presence.getSocketsForUser(userId);
|
|
@@ -16812,19 +16837,12 @@ async function setupWssEvents(options) {
|
|
|
16812
16837
|
const subClient = pubClient.duplicate();
|
|
16813
16838
|
io.adapter(createAdapter(pubClient, subClient));
|
|
16814
16839
|
} catch (error) {
|
|
16815
|
-
console.error(
|
|
16816
|
-
"[loly:realtime] Failed to setup Redis adapter:",
|
|
16817
|
-
error instanceof Error ? error.message : String(error)
|
|
16818
|
-
);
|
|
16819
16840
|
throw error;
|
|
16820
16841
|
}
|
|
16821
16842
|
}
|
|
16822
16843
|
for (const wssRoute of wssRoutes) {
|
|
16823
16844
|
const normalized = wssRoute.normalized;
|
|
16824
16845
|
if (!normalized) {
|
|
16825
|
-
console.warn(
|
|
16826
|
-
`[loly:realtime] Skipping route ${wssRoute.pattern}: No normalized route definition`
|
|
16827
|
-
);
|
|
16828
16846
|
continue;
|
|
16829
16847
|
}
|
|
16830
16848
|
let namespacePath = normalized.namespace || wssRoute.pattern.replace(/^\/wss/, "");
|
|
@@ -16835,9 +16853,7 @@ async function setupWssEvents(options) {
|
|
|
16835
16853
|
namespacePath = "/";
|
|
16836
16854
|
}
|
|
16837
16855
|
const namespace = io.of(namespacePath);
|
|
16838
|
-
console.log(`[loly:realtime] Registered namespace: ${namespacePath} (from pattern: ${wssRoute.pattern})`);
|
|
16839
16856
|
namespace.on("connection", async (socket) => {
|
|
16840
|
-
console.log(`[loly:realtime] Client connected to namespace ${namespacePath}, socket: ${socket.id}`);
|
|
16841
16857
|
const requestId = generateRequestId();
|
|
16842
16858
|
socket.requestId = requestId;
|
|
16843
16859
|
const log = createWssLogger(namespacePath, socket);
|
|
@@ -16849,8 +16865,6 @@ async function setupWssEvents(options) {
|
|
|
16849
16865
|
await presence.addSocketForUser(String(user.id), socket.id);
|
|
16850
16866
|
}
|
|
16851
16867
|
const baseCtx = {
|
|
16852
|
-
socket,
|
|
16853
|
-
io: namespace.server,
|
|
16854
16868
|
req: {
|
|
16855
16869
|
headers: socket.handshake.headers,
|
|
16856
16870
|
ip: socket.handshake.address,
|
|
@@ -17309,11 +17323,12 @@ import fs18 from "fs";
|
|
|
17309
17323
|
import path25 from "path";
|
|
17310
17324
|
import { renderToString } from "react-dom/server";
|
|
17311
17325
|
init_globals();
|
|
17312
|
-
async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params) {
|
|
17326
|
+
async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
|
|
17313
17327
|
const routeChunks = loadChunksFromManifest(projectRoot);
|
|
17314
17328
|
const assetManifest = loadAssetManifest(projectRoot);
|
|
17315
17329
|
const clientJsPath = getClientJsPath(projectRoot);
|
|
17316
17330
|
const clientCssPath = getClientCssPath(projectRoot);
|
|
17331
|
+
const faviconInfo = config ? getFaviconInfo(projectRoot, config.directories.static, false) : null;
|
|
17317
17332
|
const chunkName = routeChunks[route.pattern];
|
|
17318
17333
|
let chunkHref = null;
|
|
17319
17334
|
if (chunkName != null) {
|
|
@@ -17421,8 +17436,10 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
|
|
|
17421
17436
|
entrypointFiles,
|
|
17422
17437
|
clientJsPath,
|
|
17423
17438
|
clientCssPath,
|
|
17424
|
-
includeInlineScripts: true
|
|
17439
|
+
includeInlineScripts: true,
|
|
17425
17440
|
// SSG needs inline scripts (renderToString doesn't support bootstrapScripts)
|
|
17441
|
+
faviconPath: faviconInfo?.path || null,
|
|
17442
|
+
faviconType: faviconInfo?.type || null
|
|
17426
17443
|
});
|
|
17427
17444
|
const html = "<!DOCTYPE html>" + renderToString(documentTree);
|
|
17428
17445
|
const dir = pathToOutDir(ssgOutDir, urlPath);
|
|
@@ -17435,7 +17452,7 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
|
|
|
17435
17452
|
|
|
17436
17453
|
// modules/build/ssg/builder.ts
|
|
17437
17454
|
init_globals();
|
|
17438
|
-
async function buildStaticPages(projectRoot, routes) {
|
|
17455
|
+
async function buildStaticPages(projectRoot, routes, config) {
|
|
17439
17456
|
const ssgOutDir = path26.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
|
|
17440
17457
|
ensureDir(ssgOutDir);
|
|
17441
17458
|
for (const route of routes) {
|
|
@@ -17484,7 +17501,7 @@ async function buildStaticPages(projectRoot, routes) {
|
|
|
17484
17501
|
}
|
|
17485
17502
|
for (const params of allParams) {
|
|
17486
17503
|
const urlPath = buildPathFromPattern(route.pattern, params);
|
|
17487
|
-
await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);
|
|
17504
|
+
await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config);
|
|
17488
17505
|
}
|
|
17489
17506
|
}
|
|
17490
17507
|
console.log(`\u2705 [framework][ssg] Finished building all static pages`);
|
|
@@ -17705,7 +17722,7 @@ async function buildApp(options = {}) {
|
|
|
17705
17722
|
writeClientBoostrapManifest(projectRoot);
|
|
17706
17723
|
writeClientRoutesManifest(routes, projectRoot);
|
|
17707
17724
|
await buildClientBundle(projectRoot);
|
|
17708
|
-
await buildStaticPages(projectRoot, routes);
|
|
17725
|
+
await buildStaticPages(projectRoot, routes, config);
|
|
17709
17726
|
delete process.env.LOLY_BUILD;
|
|
17710
17727
|
console.log(`[framework][build] Build completed successfully`);
|
|
17711
17728
|
}
|