@nuraly/lumenjs 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,6 +27,13 @@ export async function buildServer(opts) {
27
27
  break;
28
28
  }
29
29
  }
30
+ for (const ext of ['.ts', '.js']) {
31
+ const subscribeFile = path.join(dir, `_subscribe${ext}`);
32
+ if (fs.existsSync(subscribeFile)) {
33
+ serverEntries[`pages/${entryDir}/_subscribe`] = subscribeFile;
34
+ break;
35
+ }
36
+ }
30
37
  }
31
38
  }
32
39
  for (const entry of layoutEntries) {
@@ -20,9 +20,11 @@ function analyzePageFile(filePath) {
20
20
  (fs.existsSync(path.join(dir, '_loader.ts')) || fs.existsSync(path.join(dir, '_loader.js')));
21
21
  const hasColocatedSocket = isIndex &&
22
22
  (fs.existsSync(path.join(dir, '_socket.ts')) || fs.existsSync(path.join(dir, '_socket.js')));
23
+ const hasColocatedSubscribe = isIndex &&
24
+ (fs.existsSync(path.join(dir, '_subscribe.ts')) || fs.existsSync(path.join(dir, '_subscribe.js')));
23
25
  return {
24
26
  hasLoader: hasExportBefore(/export\s+(async\s+)?function\s+loader\s*\(/) || hasColocatedLoader,
25
- hasSubscribe: hasExportBefore(/export\s+(async\s+)?function\s+subscribe\s*\(/),
27
+ hasSubscribe: hasExportBefore(/export\s+(async\s+)?function\s+subscribe\s*\(/) || hasColocatedSubscribe,
26
28
  hasSocket: /export\s+(function|const)\s+socket[\s(=]/.test(content) || hasColocatedSocket,
27
29
  hasAuth: hasExportBefore(/export\s+const\s+auth\s*=/),
28
30
  hasMeta: hasExportBefore(/export\s+(const\s+meta\s*=|(async\s+)?function\s+meta\s*\()/),
@@ -146,7 +146,17 @@ export async function handleSubscribeRequest(manifest, serverDir, pagesDir, path
146
146
  }
147
147
  try {
148
148
  const mod = await import(modulePath);
149
- if (!mod.subscribe || typeof mod.subscribe !== 'function') {
149
+ let subscribeFn = mod.subscribe && typeof mod.subscribe === 'function' ? mod.subscribe : null;
150
+ // Fallback: co-located _subscribe.js for folder index pages
151
+ if (!subscribeFn && path.basename(modulePath, '.js') === 'index') {
152
+ const colocated = path.join(path.dirname(modulePath), '_subscribe.js');
153
+ if (fs.existsSync(colocated)) {
154
+ const subMod = await import(colocated);
155
+ if (subMod.subscribe && typeof subMod.subscribe === 'function')
156
+ subscribeFn = subMod.subscribe;
157
+ }
158
+ }
159
+ if (!subscribeFn) {
150
160
  res.writeHead(204);
151
161
  res.end();
152
162
  return;
@@ -160,7 +170,7 @@ export async function handleSubscribeRequest(manifest, serverDir, pagesDir, path
160
170
  const push = (data) => {
161
171
  res.write(`data: ${JSON.stringify(data)}\n\n`);
162
172
  };
163
- const cleanup = mod.subscribe({ params: matched.params, push, headers, locale, user: user ?? null });
173
+ const cleanup = subscribeFn({ params: matched.params, push, headers, locale, user: user ?? null });
164
174
  res.on('close', () => {
165
175
  if (typeof cleanup === 'function')
166
176
  cleanup();
@@ -78,7 +78,20 @@ export function lumenLoadersPlugin(pagesDir) {
78
78
  try {
79
79
  installDomShims();
80
80
  const mod = await server.ssrLoadModule(filePath);
81
- if (!mod.subscribe || typeof mod.subscribe !== 'function') {
81
+ let subscribeFn = mod.subscribe && typeof mod.subscribe === 'function' ? mod.subscribe : null;
82
+ // Fallback: co-located _subscribe.ts for folder index pages
83
+ if (!subscribeFn && path.basename(filePath).replace(/\.(ts|js)$/, '') === 'index') {
84
+ for (const ext of ['.ts', '.js']) {
85
+ const colocated = path.join(path.dirname(filePath), `_subscribe${ext}`);
86
+ if (fs.existsSync(colocated)) {
87
+ const subMod = await server.ssrLoadModule(colocated);
88
+ if (subMod.subscribe && typeof subMod.subscribe === 'function')
89
+ subscribeFn = subMod.subscribe;
90
+ break;
91
+ }
92
+ }
93
+ }
94
+ if (!subscribeFn) {
82
95
  res.statusCode = 204;
83
96
  res.end();
84
97
  return;
@@ -93,7 +106,7 @@ export function lumenLoadersPlugin(pagesDir) {
93
106
  const push = (data) => {
94
107
  res.write(`data: ${JSON.stringify(data)}\n\n`);
95
108
  };
96
- const cleanup = mod.subscribe({ params, push, headers: req.headers, locale, user: req.nkAuth?.user ?? null });
109
+ const cleanup = subscribeFn({ params, push, headers: req.headers, locale, user: req.nkAuth?.user ?? null });
97
110
  res.on('close', () => {
98
111
  if (typeof cleanup === 'function')
99
112
  cleanup();
@@ -178,6 +178,13 @@ export function fileHasLoader(filePath) {
178
178
  */
179
179
  export function fileHasSubscribe(filePath) {
180
180
  try {
181
+ // Check for co-located _subscribe.ts (folder route convention: index.ts + _subscribe.ts)
182
+ if (path.basename(filePath).replace(/\.(ts|js)$/, '') === 'index') {
183
+ const dir = path.dirname(filePath);
184
+ if (fs.existsSync(path.join(dir, '_subscribe.ts')) || fs.existsSync(path.join(dir, '_subscribe.js'))) {
185
+ return true;
186
+ }
187
+ }
181
188
  const content = fs.readFileSync(filePath, 'utf-8');
182
189
  return hasTopLevelExport(content, 'subscribe');
183
190
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuraly/lumenjs",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Full-stack Lit web component framework with file-based routing, server loaders, SSR, and API routes",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",