@devlusoft/devix 0.2.0 → 0.2.2
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/cli/build.js +31 -308
- package/dist/cli/build.js.map +3 -3
- package/dist/cli/dev.js +33 -395
- package/dist/cli/dev.js.map +3 -3
- package/dist/cli/generate.js +31 -434
- package/dist/cli/generate.js.map +3 -3
- package/dist/cli/index.js +34 -698
- package/dist/cli/index.js.map +3 -3
- package/dist/cli/start.js +1 -89
- package/dist/cli/start.js.map +2 -2
- package/dist/config.js +1 -16
- package/dist/config.js.map +2 -2
- package/dist/runtime/api-context.js +1 -17
- package/dist/runtime/api-context.js.map +2 -2
- package/dist/runtime/client-router.js +1 -58
- package/dist/runtime/client-router.js.map +2 -2
- package/dist/runtime/context.js +1 -14
- package/dist/runtime/context.js.map +2 -2
- package/dist/runtime/error-boundary.js +1 -36
- package/dist/runtime/error-boundary.js.map +2 -2
- package/dist/runtime/fetch.js +1 -34
- package/dist/runtime/fetch.js.map +2 -2
- package/dist/runtime/head.js +1 -68
- package/dist/runtime/head.js.map +2 -2
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -367
- package/dist/runtime/index.js.map +3 -3
- package/dist/runtime/link.js +1 -42
- package/dist/runtime/link.js.map +2 -2
- package/dist/runtime/metadata.js +1 -21
- package/dist/runtime/metadata.js.map +2 -2
- package/dist/runtime/router-provider.js +1 -258
- package/dist/runtime/router-provider.js.map +2 -2
- package/dist/server/api-router.js +1 -64
- package/dist/server/api-router.js.map +2 -2
- package/dist/server/api.js +1 -123
- package/dist/server/api.js.map +2 -2
- package/dist/server/collect-css.js +1 -14
- package/dist/server/collect-css.js.map +2 -2
- package/dist/server/index.js +1 -132
- package/dist/server/index.js.map +2 -2
- package/dist/server/pages-router.js +1 -63
- package/dist/server/pages-router.js.map +2 -2
- package/dist/server/render.js +1 -305
- package/dist/server/render.js.map +2 -2
- package/dist/server/routes.js +1 -41
- package/dist/server/routes.js.map +2 -2
- package/dist/utils/async.js +1 -13
- package/dist/utils/async.js.map +2 -2
- package/dist/utils/banner.js +1 -33
- package/dist/utils/banner.js.map +2 -2
- package/dist/utils/cookies.js +1 -28
- package/dist/utils/cookies.js.map +2 -2
- package/dist/utils/duration.js +1 -21
- package/dist/utils/duration.js.map +2 -2
- package/dist/utils/env.js +1 -13
- package/dist/utils/env.js.map +2 -2
- package/dist/utils/html.js +1 -11
- package/dist/utils/html.js.map +2 -2
- package/dist/utils/patterns.js +1 -7
- package/dist/utils/patterns.js.map +2 -2
- package/dist/utils/response.d.ts +4 -1
- package/dist/utils/response.js +1 -9
- package/dist/utils/response.js.map +3 -3
- package/dist/vite/codegen/api.js +6 -12
- package/dist/vite/codegen/api.js.map +2 -2
- package/dist/vite/codegen/client-routes.js +6 -12
- package/dist/vite/codegen/client-routes.js.map +2 -2
- package/dist/vite/codegen/context.js +2 -8
- package/dist/vite/codegen/context.js.map +2 -2
- package/dist/vite/codegen/entry-client.js +4 -10
- package/dist/vite/codegen/entry-client.js.map +2 -2
- package/dist/vite/codegen/extract-methods.js +1 -15
- package/dist/vite/codegen/extract-methods.js.map +2 -2
- package/dist/vite/codegen/render.js +6 -12
- package/dist/vite/codegen/render.js.map +2 -2
- package/dist/vite/codegen/routes-dts.js +12 -49
- package/dist/vite/codegen/routes-dts.js.map +3 -3
- package/dist/vite/codegen/scan-api.js +1 -77
- package/dist/vite/codegen/scan-api.js.map +3 -3
- package/dist/vite/codegen/write-routes-dts.js +1 -16
- package/dist/vite/codegen/write-routes-dts.js.map +2 -2
- package/dist/vite/index.js +31 -247
- package/dist/vite/index.js.map +3 -3
- package/package.json +2 -2
package/dist/vite/index.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { dirname, resolve } from "node:path";
|
|
6
|
-
|
|
7
|
-
// src/vite/codegen/entry-client.ts
|
|
8
|
-
function generateEntryClient({ cssUrls }) {
|
|
9
|
-
const cssImports = cssUrls.map((u) => `import '${u}'`).join("\n");
|
|
10
|
-
return `
|
|
11
|
-
${cssImports}
|
|
1
|
+
import{mergeConfig as B}from"vite";import Z from"@vitejs/plugin-react";import{fileURLToPath as K}from"node:url";import{dirname as Q,resolve as c}from"node:path";function T({cssUrls:t}){return`
|
|
2
|
+
${t.map(r=>`import '${r}'`).join(`
|
|
3
|
+
`)}
|
|
12
4
|
import "@vitejs/plugin-react/preamble"
|
|
13
5
|
import React from "react"
|
|
14
6
|
import {hydrateRoot, createRoot} from 'react-dom/client'
|
|
@@ -62,17 +54,12 @@ if (!window.__DEVIX__) {
|
|
|
62
54
|
)
|
|
63
55
|
}
|
|
64
56
|
}
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/vite/codegen/client-routes.ts
|
|
69
|
-
function generateClientRoutes({ pagesDir, matcherPath }) {
|
|
70
|
-
return `
|
|
57
|
+
`}function A({pagesDir:t,matcherPath:e}){return`
|
|
71
58
|
import React from 'react'
|
|
72
|
-
import { createMatcher } from '${
|
|
73
|
-
const pageFiles = import.meta.glob(['/${
|
|
74
|
-
const layoutFiles = import.meta.glob('/${
|
|
75
|
-
const errorFiles = import.meta.glob('/${
|
|
59
|
+
import { createMatcher } from '${e}'
|
|
60
|
+
const pageFiles = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
61
|
+
const layoutFiles = import.meta.glob('/${t}/**/layout.tsx')
|
|
62
|
+
const errorFiles = import.meta.glob('/${t}/**/error.tsx')
|
|
76
63
|
|
|
77
64
|
export const matchClientRoute = createMatcher(pageFiles, layoutFiles)
|
|
78
65
|
|
|
@@ -95,21 +82,16 @@ export function getDefaultErrorPage() {
|
|
|
95
82
|
)
|
|
96
83
|
}
|
|
97
84
|
}
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// src/vite/codegen/render.ts
|
|
102
|
-
function generateRender({ pagesDir, renderPath }) {
|
|
103
|
-
return `
|
|
104
|
-
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${renderPath}'
|
|
85
|
+
`}function w({pagesDir:t,renderPath:e}){return`
|
|
86
|
+
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${e}'
|
|
105
87
|
|
|
106
|
-
const _pages = import.meta.glob(['/${
|
|
107
|
-
const _layouts = import.meta.glob('/${
|
|
88
|
+
const _pages = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
89
|
+
const _layouts = import.meta.glob('/${t}/**/layout.tsx')
|
|
108
90
|
|
|
109
91
|
const _glob = {
|
|
110
92
|
pages: _pages,
|
|
111
93
|
layouts: _layouts,
|
|
112
|
-
pagesDir: '/${
|
|
94
|
+
pagesDir: '/${t}',
|
|
113
95
|
}
|
|
114
96
|
|
|
115
97
|
export function render(url, request, options) {
|
|
@@ -123,242 +105,44 @@ export function runLoader(url, request, options) {
|
|
|
123
105
|
export function getStaticRoutes() {
|
|
124
106
|
return _getStaticRoutes(_glob)
|
|
125
107
|
}
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// src/vite/codegen/api.ts
|
|
130
|
-
function generateApi({ apiPath, appDir }) {
|
|
131
|
-
return `
|
|
132
|
-
import { handleApiRequest as _handleApiRequest } from '${apiPath}'
|
|
108
|
+
`}function D({apiPath:t,appDir:e}){return`
|
|
109
|
+
import { handleApiRequest as _handleApiRequest } from '${t}'
|
|
133
110
|
|
|
134
|
-
const _routes = import.meta.glob(['/${
|
|
135
|
-
const _middlewares = import.meta.glob('/${
|
|
111
|
+
const _routes = import.meta.glob(['/${e}/api/**/*.ts', '!**/middleware.ts'])
|
|
112
|
+
const _middlewares = import.meta.glob('/${e}/api/**/middleware.ts')
|
|
136
113
|
|
|
137
114
|
const _glob = {
|
|
138
115
|
routes: _routes,
|
|
139
116
|
middlewares: _middlewares,
|
|
140
|
-
apiDir: '/${
|
|
117
|
+
apiDir: '/${e}/api',
|
|
141
118
|
}
|
|
142
119
|
|
|
143
120
|
export function handleApiRequest(url, request) {
|
|
144
121
|
return _handleApiRequest(url, request, _glob)
|
|
145
122
|
}
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// src/utils/patterns.ts
|
|
150
|
-
function routePattern(rel) {
|
|
151
|
-
return rel.replace(/\.(tsx|ts|jsx|js)$/, "").replace(/\(.*?\)\//g, "").replace(/^index$|\/index$/, "").replace(/\[([^\]]+)]/g, ":$1") || "/";
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// src/server/pages-router.ts
|
|
155
|
-
var cache = null;
|
|
156
|
-
function invalidatePagesCache() {
|
|
157
|
-
cache = null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// src/server/api-router.ts
|
|
161
|
-
function keyToRoutePattern(key, apiDir) {
|
|
162
|
-
const rel = key.slice(apiDir.length + 1).replace(/\\/g, "/");
|
|
163
|
-
const pattern = routePattern(rel);
|
|
164
|
-
return pattern === "/" ? "/api" : `/api/${pattern}`.replace("/api//", "/api/");
|
|
165
|
-
}
|
|
166
|
-
var cache2 = null;
|
|
167
|
-
function invalidateApiCache() {
|
|
168
|
-
cache2 = null;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// src/vite/codegen/context.ts
|
|
172
|
-
function generateContext() {
|
|
173
|
-
return `
|
|
123
|
+
`}function g(t){return t.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}var H=null;function d(){H=null}function C(t,e){let r=t.slice(e.length+1).replace(/\\/g,"/"),i=g(r);return i==="/"?"/api":`/api/${i}`.replace("/api//","/api/")}var k=null;function m(){k=null}function S(){return`
|
|
174
124
|
export {RouterContext} from '@devlusoft/devix/runtime/context'
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// src/vite/codegen/scan-api.ts
|
|
179
|
-
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
180
|
-
import { join, relative } from "node:path";
|
|
181
|
-
|
|
182
|
-
// src/vite/codegen/extract-methods.ts
|
|
183
|
-
var METHOD_EXPORT_RE = /export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;
|
|
184
|
-
function stripComments(content) {
|
|
185
|
-
return content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
186
|
-
}
|
|
187
|
-
function extractHttpMethods(content) {
|
|
188
|
-
const found = /* @__PURE__ */ new Set();
|
|
189
|
-
for (const match of stripComments(content).matchAll(METHOD_EXPORT_RE)) {
|
|
190
|
-
found.add(match[1]);
|
|
191
|
-
}
|
|
192
|
-
return [...found];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// src/vite/codegen/routes-dts.ts
|
|
196
|
-
function filePathToIdentifier(filePath, apiDir) {
|
|
197
|
-
return "_api_" + filePath.slice(`${apiDir}/`.length).replace(/\.(ts|tsx)$/, "").replace(/[^a-zA-Z0-9]/g, "_");
|
|
198
|
-
}
|
|
199
|
-
function buildRouteEntry(filePath, apiDir, methods) {
|
|
200
|
-
return {
|
|
201
|
-
filePath,
|
|
202
|
-
urlPattern: keyToRoutePattern(filePath, apiDir),
|
|
203
|
-
identifier: filePathToIdentifier(filePath, apiDir),
|
|
204
|
-
methods
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
function generateRoutesDts(entries, apiDir) {
|
|
208
|
-
if (entries.length === 0) {
|
|
209
|
-
return `// auto-generado por devix \u2014 no editar
|
|
125
|
+
`}import{readFileSync as W,readdirSync as N,statSync as V}from"node:fs";import{join as h,relative as J}from"node:path";var F=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;function j(t){return t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function L(t){let e=new Set;for(let r of j(t).matchAll(F))e.add(r[1]);return[...e]}function q(t,e){return"_api_"+t.slice(`${e}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function M(t,e,r){return{filePath:t,urlPattern:C(t,e),identifier:q(t,e),methods:r}}function f(t,e){if(t.length===0)return`// auto-generado por devix \u2014 no editar
|
|
210
126
|
declare module '@devlusoft/devix' {
|
|
211
127
|
interface ApiRoutes {}
|
|
212
128
|
}
|
|
213
|
-
`;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return `import type * as ${e.identifier} from '${importPath}'`;
|
|
218
|
-
}).join("\n");
|
|
219
|
-
const routeLines = entries.flatMap(
|
|
220
|
-
(e) => e.methods.map(
|
|
221
|
-
(m) => ` '${m} ${e.urlPattern}': InferRoute<(typeof ${e.identifier})['${m}']>`
|
|
222
|
-
)
|
|
223
|
-
).join("\n");
|
|
224
|
-
return `// auto-generado por devix \u2014 no editar
|
|
225
|
-
${imports}
|
|
129
|
+
`;let r=t.map(o=>{let s="../"+o.filePath.replace(/\.(ts|tsx)$/,"");return`import type * as ${o.identifier} from '${s}'`}).join(`
|
|
130
|
+
`),i=t.flatMap(o=>o.methods.map(s=>` '${s} ${o.urlPattern}': InferRoute<(typeof ${o.identifier})['${s}']>`)).join(`
|
|
131
|
+
`);return`// auto-generado por devix \u2014 no editar
|
|
132
|
+
${r}
|
|
226
133
|
|
|
134
|
+
type JsonResponse<T> = Response & { readonly __body: T }
|
|
135
|
+
type UnwrapJson<T> = T extends JsonResponse<infer U> ? U : never
|
|
227
136
|
type InferRoute<T> = T extends (...args: any[]) => any
|
|
228
|
-
?
|
|
137
|
+
? [UnwrapJson<Awaited<ReturnType<T>>>] extends [never]
|
|
138
|
+
? Exclude<Awaited<ReturnType<T>>, Response | null | void>
|
|
139
|
+
: UnwrapJson<Awaited<ReturnType<T>>>
|
|
229
140
|
: never
|
|
230
141
|
|
|
231
142
|
declare module '@devlusoft/devix' {
|
|
232
143
|
interface ApiRoutes {
|
|
233
|
-
${
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
`;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// src/vite/codegen/scan-api.ts
|
|
240
|
-
function walkDir(dir, root) {
|
|
241
|
-
const entries = [];
|
|
242
|
-
for (const name of readdirSync(dir)) {
|
|
243
|
-
const full = join(dir, name);
|
|
244
|
-
if (statSync(full).isDirectory()) {
|
|
245
|
-
entries.push(...walkDir(full, root));
|
|
246
|
-
} else if (/\.(ts|tsx)$/.test(name)) {
|
|
247
|
-
entries.push(relative(root, full).replace(/\\/g, "/"));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return entries;
|
|
251
|
-
}
|
|
252
|
-
function scanApiFiles(appDir, projectRoot) {
|
|
253
|
-
const apiDir = join(projectRoot, appDir, "api");
|
|
254
|
-
let files;
|
|
255
|
-
try {
|
|
256
|
-
files = walkDir(apiDir, projectRoot);
|
|
257
|
-
} catch {
|
|
258
|
-
return [];
|
|
259
|
-
}
|
|
260
|
-
return files.filter((f) => !f.endsWith("middleware.ts") && !f.endsWith("middleware.tsx")).flatMap((filePath) => {
|
|
261
|
-
try {
|
|
262
|
-
const content = readFileSync(join(projectRoot, filePath), "utf-8");
|
|
263
|
-
const methods = extractHttpMethods(content);
|
|
264
|
-
if (methods.length === 0) return [];
|
|
265
|
-
return [buildRouteEntry(filePath, `${appDir}/api`, methods)];
|
|
266
|
-
} catch {
|
|
267
|
-
return [];
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// src/vite/codegen/write-routes-dts.ts
|
|
273
|
-
import { mkdirSync, readFileSync as readFileSync2, writeFileSync, existsSync } from "node:fs";
|
|
274
|
-
import { join as join2 } from "node:path";
|
|
275
|
-
function writeRoutesDts(content, projectRoot) {
|
|
276
|
-
const devixDir = join2(projectRoot, ".devix");
|
|
277
|
-
const outPath = join2(devixDir, "routes.d.ts");
|
|
278
|
-
mkdirSync(devixDir, { recursive: true });
|
|
279
|
-
if (existsSync(outPath) && readFileSync2(outPath, "utf-8") === content) {
|
|
280
|
-
return false;
|
|
144
|
+
${i}
|
|
281
145
|
}
|
|
282
|
-
writeFileSync(outPath, content, "utf-8");
|
|
283
|
-
return true;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// src/vite/index.ts
|
|
287
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
288
|
-
var VIRTUAL_ENTRY_CLIENT = "virtual:devix/entry-client";
|
|
289
|
-
var VIRTUAL_CLIENT_ROUTES = "virtual:devix/client-routes";
|
|
290
|
-
var VIRTUAL_RENDER = "virtual:devix/render";
|
|
291
|
-
var VIRTUAL_API = "virtual:devix/api";
|
|
292
|
-
var VIRTUAL_CONTEXT = "virtual:devix/context";
|
|
293
|
-
function devix(config) {
|
|
294
|
-
const appDir = config.appDir ?? "app";
|
|
295
|
-
const pagesDir = `${appDir}/pages`;
|
|
296
|
-
const cssUrls = (config.css ?? []).map((u) => u.startsWith("/") ? u : `/${u.replace(/^\.\//, "")}`);
|
|
297
|
-
const renderPath = resolve(__dirname, "../server/render.js").replace(/\\/g, "/");
|
|
298
|
-
const apiPath = resolve(__dirname, "../server/api.js").replace(/\\/g, "/");
|
|
299
|
-
const matcherPath = resolve(__dirname, "../runtime/client-router.js").replace(/\\/g, "/");
|
|
300
|
-
const virtualPlugin = {
|
|
301
|
-
name: "devix",
|
|
302
|
-
enforce: "pre",
|
|
303
|
-
resolveId(id) {
|
|
304
|
-
if (id === VIRTUAL_ENTRY_CLIENT) return `\0${VIRTUAL_ENTRY_CLIENT}`;
|
|
305
|
-
if (id === VIRTUAL_CLIENT_ROUTES) return `\0${VIRTUAL_CLIENT_ROUTES}`;
|
|
306
|
-
if (id === VIRTUAL_RENDER) return `\0${VIRTUAL_RENDER}`;
|
|
307
|
-
if (id === VIRTUAL_API) return `\0${VIRTUAL_API}`;
|
|
308
|
-
if (id === VIRTUAL_CONTEXT) return `\0${VIRTUAL_CONTEXT}`;
|
|
309
|
-
},
|
|
310
|
-
load(id) {
|
|
311
|
-
if (id === `\0${VIRTUAL_ENTRY_CLIENT}`)
|
|
312
|
-
return generateEntryClient({ cssUrls });
|
|
313
|
-
if (id === `\0${VIRTUAL_CLIENT_ROUTES}`)
|
|
314
|
-
return generateClientRoutes({ pagesDir, matcherPath });
|
|
315
|
-
if (id === `\0${VIRTUAL_RENDER}`)
|
|
316
|
-
return generateRender({ pagesDir, renderPath });
|
|
317
|
-
if (id === `\0${VIRTUAL_API}`)
|
|
318
|
-
return generateApi({ apiPath, appDir });
|
|
319
|
-
if (id === `\0${VIRTUAL_CONTEXT}`)
|
|
320
|
-
return generateContext();
|
|
321
|
-
},
|
|
322
|
-
buildStart() {
|
|
323
|
-
const root = process.cwd();
|
|
324
|
-
const entries = scanApiFiles(appDir, root);
|
|
325
|
-
writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root);
|
|
326
|
-
},
|
|
327
|
-
configureServer(server) {
|
|
328
|
-
const root = process.cwd();
|
|
329
|
-
const regenerateDts = () => {
|
|
330
|
-
const entries = scanApiFiles(appDir, root);
|
|
331
|
-
writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root);
|
|
332
|
-
};
|
|
333
|
-
server.watcher.on("add", (file) => {
|
|
334
|
-
if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache();
|
|
335
|
-
if (file.includes(`${appDir}/api`)) {
|
|
336
|
-
invalidateApiCache();
|
|
337
|
-
regenerateDts();
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
server.watcher.on("unlink", (file) => {
|
|
341
|
-
if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache();
|
|
342
|
-
if (file.includes(`${appDir}/api`)) {
|
|
343
|
-
invalidateApiCache();
|
|
344
|
-
regenerateDts();
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
server.watcher.on("change", (file) => {
|
|
348
|
-
if (file.includes(`${appDir}/api`) && !file.endsWith("middleware.ts")) {
|
|
349
|
-
regenerateDts();
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
const base = {
|
|
355
|
-
plugins: [react(), virtualPlugin],
|
|
356
|
-
ssr: { noExternal: ["@devlusoft/devix"] },
|
|
357
|
-
...config.envPrefix ? { envPrefix: config.envPrefix } : {}
|
|
358
|
-
};
|
|
359
|
-
return mergeConfig(base, config.vite ?? {});
|
|
360
146
|
}
|
|
361
|
-
export
|
|
362
|
-
devix
|
|
363
|
-
};
|
|
147
|
+
`}function b(t,e){let r=[];for(let i of N(t)){let o=h(t,i);V(o).isDirectory()?r.push(...b(o,e)):/\.(ts|tsx)$/.test(i)&&r.push(J(e,o).replace(/\\/g,"/"))}return r}function x(t,e){let r=h(e,t,"api"),i;try{i=b(r,e)}catch{return[]}return i.filter(o=>!o.endsWith("middleware.ts")&&!o.endsWith("middleware.tsx")).flatMap(o=>{try{let s=W(h(e,o),"utf-8"),u=L(s);return u.length===0?[]:[M(o,`${t}/api`,u)]}catch{return[]}})}import{mkdirSync as X,readFileSync as z,writeFileSync as G,existsSync as Y}from"node:fs";import{join as O}from"node:path";function y(t,e){let r=O(e,".devix"),i=O(r,"routes.d.ts");return X(r,{recursive:!0}),Y(i)&&z(i,"utf-8")===t?!1:(G(i,t,"utf-8"),!0)}var R=Q(K(import.meta.url)),E="virtual:devix/entry-client",P="virtual:devix/client-routes",_="virtual:devix/render",v="virtual:devix/api",$="virtual:devix/context";function Ht(t){let e=t.appDir??"app",r=`${e}/pages`,i=(t.css??[]).map(n=>n.startsWith("/")?n:`/${n.replace(/^\.\//,"")}`),o=c(R,"../server/render.js").replace(/\\/g,"/"),s=c(R,"../server/api.js").replace(/\\/g,"/"),u=c(R,"../runtime/client-router.js").replace(/\\/g,"/"),I={name:"devix",enforce:"pre",resolveId(n){if(n===E)return`\0${E}`;if(n===P)return`\0${P}`;if(n===_)return`\0${_}`;if(n===v)return`\0${v}`;if(n===$)return`\0${$}`},load(n){if(n===`\0${E}`)return T({cssUrls:i});if(n===`\0${P}`)return A({pagesDir:r,matcherPath:u});if(n===`\0${_}`)return w({pagesDir:r,renderPath:o});if(n===`\0${v}`)return D({apiPath:s,appDir:e});if(n===`\0${$}`)return S()},buildStart(){let n=process.cwd(),l=x(e,n);y(f(l,`${e}/api`),n)},configureServer(n){let l=process.cwd(),p=()=>{let a=x(e,l);y(f(a,`${e}/api`),l)};n.watcher.on("add",a=>{a.startsWith(c(l,r))&&d(),a.includes(`${e}/api`)&&(m(),p())}),n.watcher.on("unlink",a=>{a.startsWith(c(l,r))&&d(),a.includes(`${e}/api`)&&(m(),p())}),n.watcher.on("change",a=>{a.includes(`${e}/api`)&&!a.endsWith("middleware.ts")&&p()})}},U={plugins:[Z(),I],ssr:{noExternal:["@devlusoft/devix"]},...t.envPrefix?{envPrefix:t.envPrefix}:{}};return B(U,t.vite??{})}export{Ht as devix};
|
|
364
148
|
//# sourceMappingURL=index.js.map
|
package/dist/vite/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/vite/index.ts", "../../src/vite/codegen/entry-client.ts", "../../src/vite/codegen/client-routes.ts", "../../src/vite/codegen/render.ts", "../../src/vite/codegen/api.ts", "../../src/utils/patterns.ts", "../../src/server/pages-router.ts", "../../src/server/api-router.ts", "../../src/vite/codegen/context.ts", "../../src/vite/codegen/scan-api.ts", "../../src/vite/codegen/extract-methods.ts", "../../src/vite/codegen/routes-dts.ts", "../../src/vite/codegen/write-routes-dts.ts"],
|
|
4
|
-
"sourcesContent": ["import {UserConfig, Plugin, mergeConfig} from 'vite'\nimport type {DevixConfig} from '../config'\nimport react from '@vitejs/plugin-react'\nimport {fileURLToPath} from 'node:url'\nimport {dirname, resolve} from 'node:path'\nimport {generateEntryClient} from './codegen/entry-client'\nimport {generateClientRoutes} from './codegen/client-routes'\nimport {generateRender} from './codegen/render'\nimport {generateApi} from './codegen/api'\nimport {invalidatePagesCache} from \"../server/pages-router\";\nimport {invalidateApiCache} from \"../server/api-router\";\nimport {generateContext} from \"./codegen/context\";\nimport {scanApiFiles} from \"./codegen/scan-api\";\nimport {generateRoutesDts} from \"./codegen/routes-dts\";\nimport {writeRoutesDts} from \"./codegen/write-routes-dts\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst VIRTUAL_ENTRY_CLIENT = 'virtual:devix/entry-client'\nconst VIRTUAL_CLIENT_ROUTES = 'virtual:devix/client-routes'\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\nconst VIRTUAL_CONTEXT = 'virtual:devix/context'\n\nexport function devix(config: DevixConfig): UserConfig {\n const appDir = config.appDir ?? 'app'\n const pagesDir = `${appDir}/pages`\n const cssUrls = (config.css ?? []).map(u => u.startsWith('/') ? u : `/${u.replace(/^\\.\\//, '')}`)\n\n const renderPath = resolve(__dirname, '../server/render.js').replace(/\\\\/g, '/')\n const apiPath = resolve(__dirname, '../server/api.js').replace(/\\\\/g, '/')\n const matcherPath = resolve(__dirname, '../runtime/client-router.js').replace(/\\\\/g, '/')\n\n const virtualPlugin: Plugin = {\n name: 'devix',\n enforce: 'pre',\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_CLIENT) return `\\0${VIRTUAL_ENTRY_CLIENT}`\n if (id === VIRTUAL_CLIENT_ROUTES) return `\\0${VIRTUAL_CLIENT_ROUTES}`\n if (id === VIRTUAL_RENDER) return `\\0${VIRTUAL_RENDER}`\n if (id === VIRTUAL_API) return `\\0${VIRTUAL_API}`\n if (id === VIRTUAL_CONTEXT) return `\\0${VIRTUAL_CONTEXT}`\n },\n\n load(id) {\n if (id === `\\0${VIRTUAL_ENTRY_CLIENT}`)\n return generateEntryClient({cssUrls})\n if (id === `\\0${VIRTUAL_CLIENT_ROUTES}`)\n return generateClientRoutes({pagesDir, matcherPath})\n if (id === `\\0${VIRTUAL_RENDER}`)\n return generateRender({pagesDir, renderPath})\n if (id === `\\0${VIRTUAL_API}`)\n return generateApi({apiPath, appDir})\n if (id === `\\0${VIRTUAL_CONTEXT}`)\n return generateContext()\n },\n\n buildStart() {\n const root = process.cwd()\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n },\n\n configureServer(server) {\n const root = process.cwd()\n\n const regenerateDts = () => {\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n }\n\n server.watcher.on('add', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('unlink', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('change', (file) => {\n if (file.includes(`${appDir}/api`) && !file.endsWith('middleware.ts')) {\n regenerateDts()\n }\n })\n },\n }\n\n const base: UserConfig = {\n plugins: [react(), virtualPlugin],\n ssr: {noExternal: ['@devlusoft/devix']},\n ...(config.envPrefix ? {envPrefix: config.envPrefix} : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({cssUrls}: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}", "interface ClientRoutesOptions {\n pagesDir: string\n matcherPath: string\n}\n\nexport function generateClientRoutes({pagesDir, matcherPath}: ClientRoutesOptions) {\n return `\nimport React from 'react'\nimport { createMatcher } from '${matcherPath}'\nconst pageFiles = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst layoutFiles = import.meta.glob('/${pagesDir}/**/layout.tsx')\nconst errorFiles = import.meta.glob('/${pagesDir}/**/error.tsx')\n\nexport const matchClientRoute = createMatcher(pageFiles, layoutFiles)\n\nexport async function loadErrorPage() {\n const key = Object.keys(errorFiles)[0]\n if (!key) return null\n const mod = await errorFiles[key]()\n return mod?.default ?? null\n}\n\nexport function getDefaultErrorPage() {\n return function DefaultError({ statusCode, message }) {\n return React.createElement('main', {\n style: { minHeight: '100dvh', display: 'flex', flexDirection: 'column', \n alignItems: 'center', justifyContent: 'center', gap: '8px',\n fontFamily: 'system-ui, sans-serif' }\n },\n React.createElement('h1', {style: {fontSize: '4rem', fontWeight: 700}}, statusCode),\n React.createElement('p', {style: {color: '#666'}}, message ?? 'An unexpected error occurred'),\n )\n }\n}\n`\n}", "interface RenderOptions {\n pagesDir: string\n renderPath: string\n}\n\nexport function generateRender({pagesDir, renderPath}: RenderOptions): string {\n return `\nimport { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${renderPath}'\n\nconst _pages = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst _layouts = import.meta.glob('/${pagesDir}/**/layout.tsx')\n\nconst _glob = {\n pages: _pages,\n layouts: _layouts,\n pagesDir: '/${pagesDir}',\n}\n\nexport function render(url, request, options) {\n return _render(url, request, _glob, options)\n}\n\nexport function runLoader(url, request, options) {\n return _runLoader(url, request, _glob, options)\n}\n\nexport function getStaticRoutes() {\n return _getStaticRoutes(_glob)\n}\n`\n}\n", "interface ApiOptions {\n apiPath: string\n appDir: string\n}\n\nexport function generateApi({apiPath, appDir}: ApiOptions): string {\n return `\nimport { handleApiRequest as _handleApiRequest } from '${apiPath}'\n\nconst _routes = import.meta.glob(['/${appDir}/api/**/*.ts', '!**/middleware.ts'])\nconst _middlewares = import.meta.glob('/${appDir}/api/**/middleware.ts')\n\nconst _glob = {\n routes: _routes,\n middlewares: _middlewares,\n apiDir: '/${appDir}/api',\n}\n\nexport function handleApiRequest(url, request) {\n return _handleApiRequest(url, request, _glob)\n}\n`\n}\n", "export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\n const pages: Page[] = []\n const layouts: Layout[] = []\n\n for (const key of layoutKeys) {\n layouts.push({dir: keyToDir(key), key})\n }\n\n for (const key of pageKeys) {\n const pattern = keyToRoutePattern(key, pagesDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n pages.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n\n pages.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {pages, layouts}\n return cache\n}\n\nexport function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[] {\n const pageDir = keyToDir(pageKey)\n\n return layouts\n .filter(layout => pageDir.startsWith(layout.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchPage(pathname: string, pages: Page[]): {\n page: Page\n params: Record<string, string>\n} | null {\n for (const page of pages) {\n const match = pathname.match(page.regex)\n if (match) {\n const params: Record<string, string> = {}\n page.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {page, params}\n }\n }\n return null\n}\n", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: ApiResult | null = null\n\nexport function invalidateApiCache() {\n cache = null\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n if (cache) return cache\n\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {routes, middlewares}\n return cache\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): {route: ApiRoute; params: Record<string, string>} | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "export function generateContext(): string {\n return `\nexport {RouterContext} from '@devlusoft/devix/runtime/context'\n`\n}", "import {readFileSync, readdirSync, statSync} from 'node:fs'\nimport {join, relative} from 'node:path'\nimport {extractHttpMethods} from './extract-methods'\nimport {buildRouteEntry} from './routes-dts'\nimport type {RouteEntry} from './routes-dts'\n\nfunction walkDir(dir: string, root: string): string[] {\n const entries: string[] = []\n for (const name of readdirSync(dir)) {\n const full = join(dir, name)\n if (statSync(full).isDirectory()) {\n entries.push(...walkDir(full, root))\n } else if (/\\.(ts|tsx)$/.test(name)) {\n entries.push(relative(root, full).replace(/\\\\/g, '/'))\n }\n }\n return entries\n}\n\nexport function scanApiFiles(appDir: string, projectRoot: string): RouteEntry[] {\n const apiDir = join(projectRoot, appDir, 'api')\n\n let files: string[]\n try {\n files = walkDir(apiDir, projectRoot)\n } catch {\n return []\n }\n\n return files\n .filter(f => !f.endsWith('middleware.ts') && !f.endsWith('middleware.tsx'))\n .flatMap(filePath => {\n try {\n const content = readFileSync(join(projectRoot, filePath), 'utf-8')\n const methods = extractHttpMethods(content)\n if (methods.length === 0) return []\n return [buildRouteEntry(filePath, `${appDir}/api`, methods)]\n } catch {\n return []\n }\n })\n}\n", "const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const\nexport type HttpMethod = (typeof HTTP_METHODS)[number]\n\nconst METHOD_EXPORT_RE = /export\\s+(?:const|async\\s+function|function)\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b/g\n\nfunction stripComments(content: string): string {\n return content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '')\n}\n\nexport function extractHttpMethods(content: string): HttpMethod[] {\n const found = new Set<HttpMethod>()\n for (const match of stripComments(content).matchAll(METHOD_EXPORT_RE)) {\n found.add(match[1] as HttpMethod)\n }\n return [...found]\n}\n", "import { keyToRoutePattern } from '../../server/api-router'\nimport type { HttpMethod } from './extract-methods'\n\nexport interface RouteEntry {\n filePath: string\n urlPattern: string\n identifier: string\n methods: HttpMethod[]\n}\n\nexport function filePathToIdentifier(filePath: string, apiDir: string): string {\n return '_api_' + filePath\n .slice(`${apiDir}/`.length)\n .replace(/\\.(ts|tsx)$/, '')\n .replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nexport function buildRouteEntry(filePath: string, apiDir: string, methods: HttpMethod[]): RouteEntry {\n return {\n filePath,\n urlPattern: keyToRoutePattern(filePath, apiDir),\n identifier: filePathToIdentifier(filePath, apiDir),\n methods,\n }\n}\n\nexport function generateRoutesDts(entries: RouteEntry[], apiDir: string): string {\n if (entries.length === 0) {\n return `// auto-generado por devix \u2014 no editar\\ndeclare module '@devlusoft/devix' {\\n interface ApiRoutes {}\\n}\\n`\n }\n\n const imports = entries\n .map(e => {\n const importPath = '../' + e.filePath.replace(/\\.(ts|tsx)$/, '')\n return `import type * as ${e.identifier} from '${importPath}'`\n })\n .join('\\n')\n\n const routeLines = entries.flatMap(e =>\n e.methods.map(m =>\n ` '${m} ${e.urlPattern}': InferRoute<(typeof ${e.identifier})['${m}']>`\n )\n ).join('\\n')\n\n return `// auto-generado por devix \u2014 no editar\n${imports}\n\ntype InferRoute<T> = T extends (...args: any[]) => any\n ? Exclude<Awaited<ReturnType<T>>, Response | null | void>\n : never\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n", "import {mkdirSync, readFileSync, writeFileSync, existsSync} from 'node:fs'\nimport {join} from 'node:path'\n\nexport function writeRoutesDts(content: string, projectRoot: string): boolean {\n const devixDir = join(projectRoot, '.devix')\n const outPath = join(devixDir, 'routes.d.ts')\n\n mkdirSync(devixDir, {recursive: true})\n\n if (existsSync(outPath) && readFileSync(outPath, 'utf-8') === content) {\n return false\n }\n\n writeFileSync(outPath, content, 'utf-8')\n return true\n}\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["cache", "readFileSync", "join"]
|
|
4
|
+
"sourcesContent": ["import {UserConfig, Plugin, mergeConfig} from 'vite'\nimport type {DevixConfig} from '../config'\nimport react from '@vitejs/plugin-react'\nimport {fileURLToPath} from 'node:url'\nimport {dirname, resolve} from 'node:path'\nimport {generateEntryClient} from './codegen/entry-client'\nimport {generateClientRoutes} from './codegen/client-routes'\nimport {generateRender} from './codegen/render'\nimport {generateApi} from './codegen/api'\nimport {invalidatePagesCache} from \"../server/pages-router\";\nimport {invalidateApiCache} from \"../server/api-router\";\nimport {generateContext} from \"./codegen/context\";\nimport {scanApiFiles} from \"./codegen/scan-api\";\nimport {generateRoutesDts} from \"./codegen/routes-dts\";\nimport {writeRoutesDts} from \"./codegen/write-routes-dts\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst VIRTUAL_ENTRY_CLIENT = 'virtual:devix/entry-client'\nconst VIRTUAL_CLIENT_ROUTES = 'virtual:devix/client-routes'\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\nconst VIRTUAL_CONTEXT = 'virtual:devix/context'\n\nexport function devix(config: DevixConfig): UserConfig {\n const appDir = config.appDir ?? 'app'\n const pagesDir = `${appDir}/pages`\n const cssUrls = (config.css ?? []).map(u => u.startsWith('/') ? u : `/${u.replace(/^\\.\\//, '')}`)\n\n const renderPath = resolve(__dirname, '../server/render.js').replace(/\\\\/g, '/')\n const apiPath = resolve(__dirname, '../server/api.js').replace(/\\\\/g, '/')\n const matcherPath = resolve(__dirname, '../runtime/client-router.js').replace(/\\\\/g, '/')\n\n const virtualPlugin: Plugin = {\n name: 'devix',\n enforce: 'pre',\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_CLIENT) return `\\0${VIRTUAL_ENTRY_CLIENT}`\n if (id === VIRTUAL_CLIENT_ROUTES) return `\\0${VIRTUAL_CLIENT_ROUTES}`\n if (id === VIRTUAL_RENDER) return `\\0${VIRTUAL_RENDER}`\n if (id === VIRTUAL_API) return `\\0${VIRTUAL_API}`\n if (id === VIRTUAL_CONTEXT) return `\\0${VIRTUAL_CONTEXT}`\n },\n\n load(id) {\n if (id === `\\0${VIRTUAL_ENTRY_CLIENT}`)\n return generateEntryClient({cssUrls})\n if (id === `\\0${VIRTUAL_CLIENT_ROUTES}`)\n return generateClientRoutes({pagesDir, matcherPath})\n if (id === `\\0${VIRTUAL_RENDER}`)\n return generateRender({pagesDir, renderPath})\n if (id === `\\0${VIRTUAL_API}`)\n return generateApi({apiPath, appDir})\n if (id === `\\0${VIRTUAL_CONTEXT}`)\n return generateContext()\n },\n\n buildStart() {\n const root = process.cwd()\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n },\n\n configureServer(server) {\n const root = process.cwd()\n\n const regenerateDts = () => {\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n }\n\n server.watcher.on('add', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('unlink', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('change', (file) => {\n if (file.includes(`${appDir}/api`) && !file.endsWith('middleware.ts')) {\n regenerateDts()\n }\n })\n },\n }\n\n const base: UserConfig = {\n plugins: [react(), virtualPlugin],\n ssr: {noExternal: ['@devlusoft/devix']},\n ...(config.envPrefix ? {envPrefix: config.envPrefix} : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({cssUrls}: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}", "interface ClientRoutesOptions {\n pagesDir: string\n matcherPath: string\n}\n\nexport function generateClientRoutes({pagesDir, matcherPath}: ClientRoutesOptions) {\n return `\nimport React from 'react'\nimport { createMatcher } from '${matcherPath}'\nconst pageFiles = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst layoutFiles = import.meta.glob('/${pagesDir}/**/layout.tsx')\nconst errorFiles = import.meta.glob('/${pagesDir}/**/error.tsx')\n\nexport const matchClientRoute = createMatcher(pageFiles, layoutFiles)\n\nexport async function loadErrorPage() {\n const key = Object.keys(errorFiles)[0]\n if (!key) return null\n const mod = await errorFiles[key]()\n return mod?.default ?? null\n}\n\nexport function getDefaultErrorPage() {\n return function DefaultError({ statusCode, message }) {\n return React.createElement('main', {\n style: { minHeight: '100dvh', display: 'flex', flexDirection: 'column', \n alignItems: 'center', justifyContent: 'center', gap: '8px',\n fontFamily: 'system-ui, sans-serif' }\n },\n React.createElement('h1', {style: {fontSize: '4rem', fontWeight: 700}}, statusCode),\n React.createElement('p', {style: {color: '#666'}}, message ?? 'An unexpected error occurred'),\n )\n }\n}\n`\n}", "interface RenderOptions {\n pagesDir: string\n renderPath: string\n}\n\nexport function generateRender({pagesDir, renderPath}: RenderOptions): string {\n return `\nimport { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${renderPath}'\n\nconst _pages = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst _layouts = import.meta.glob('/${pagesDir}/**/layout.tsx')\n\nconst _glob = {\n pages: _pages,\n layouts: _layouts,\n pagesDir: '/${pagesDir}',\n}\n\nexport function render(url, request, options) {\n return _render(url, request, _glob, options)\n}\n\nexport function runLoader(url, request, options) {\n return _runLoader(url, request, _glob, options)\n}\n\nexport function getStaticRoutes() {\n return _getStaticRoutes(_glob)\n}\n`\n}\n", "interface ApiOptions {\n apiPath: string\n appDir: string\n}\n\nexport function generateApi({apiPath, appDir}: ApiOptions): string {\n return `\nimport { handleApiRequest as _handleApiRequest } from '${apiPath}'\n\nconst _routes = import.meta.glob(['/${appDir}/api/**/*.ts', '!**/middleware.ts'])\nconst _middlewares = import.meta.glob('/${appDir}/api/**/middleware.ts')\n\nconst _glob = {\n routes: _routes,\n middlewares: _middlewares,\n apiDir: '/${appDir}/api',\n}\n\nexport function handleApiRequest(url, request) {\n return _handleApiRequest(url, request, _glob)\n}\n`\n}\n", "export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\n const pages: Page[] = []\n const layouts: Layout[] = []\n\n for (const key of layoutKeys) {\n layouts.push({dir: keyToDir(key), key})\n }\n\n for (const key of pageKeys) {\n const pattern = keyToRoutePattern(key, pagesDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n pages.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n\n pages.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {pages, layouts}\n return cache\n}\n\nexport function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[] {\n const pageDir = keyToDir(pageKey)\n\n return layouts\n .filter(layout => pageDir.startsWith(layout.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchPage(pathname: string, pages: Page[]): {\n page: Page\n params: Record<string, string>\n} | null {\n for (const page of pages) {\n const match = pathname.match(page.regex)\n if (match) {\n const params: Record<string, string> = {}\n page.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {page, params}\n }\n }\n return null\n}\n", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: ApiResult | null = null\n\nexport function invalidateApiCache() {\n cache = null\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n if (cache) return cache\n\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {routes, middlewares}\n return cache\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): {route: ApiRoute; params: Record<string, string>} | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "export function generateContext(): string {\n return `\nexport {RouterContext} from '@devlusoft/devix/runtime/context'\n`\n}", "import {readFileSync, readdirSync, statSync} from 'node:fs'\nimport {join, relative} from 'node:path'\nimport {extractHttpMethods} from './extract-methods'\nimport {buildRouteEntry} from './routes-dts'\nimport type {RouteEntry} from './routes-dts'\n\nfunction walkDir(dir: string, root: string): string[] {\n const entries: string[] = []\n for (const name of readdirSync(dir)) {\n const full = join(dir, name)\n if (statSync(full).isDirectory()) {\n entries.push(...walkDir(full, root))\n } else if (/\\.(ts|tsx)$/.test(name)) {\n entries.push(relative(root, full).replace(/\\\\/g, '/'))\n }\n }\n return entries\n}\n\nexport function scanApiFiles(appDir: string, projectRoot: string): RouteEntry[] {\n const apiDir = join(projectRoot, appDir, 'api')\n\n let files: string[]\n try {\n files = walkDir(apiDir, projectRoot)\n } catch {\n return []\n }\n\n return files\n .filter(f => !f.endsWith('middleware.ts') && !f.endsWith('middleware.tsx'))\n .flatMap(filePath => {\n try {\n const content = readFileSync(join(projectRoot, filePath), 'utf-8')\n const methods = extractHttpMethods(content)\n if (methods.length === 0) return []\n return [buildRouteEntry(filePath, `${appDir}/api`, methods)]\n } catch {\n return []\n }\n })\n}\n", "const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const\nexport type HttpMethod = (typeof HTTP_METHODS)[number]\n\nconst METHOD_EXPORT_RE = /export\\s+(?:const|async\\s+function|function)\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b/g\n\nfunction stripComments(content: string): string {\n return content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '')\n}\n\nexport function extractHttpMethods(content: string): HttpMethod[] {\n const found = new Set<HttpMethod>()\n for (const match of stripComments(content).matchAll(METHOD_EXPORT_RE)) {\n found.add(match[1] as HttpMethod)\n }\n return [...found]\n}\n", "import { keyToRoutePattern } from '../../server/api-router'\nimport type { HttpMethod } from './extract-methods'\n\nexport interface RouteEntry {\n filePath: string\n urlPattern: string\n identifier: string\n methods: HttpMethod[]\n}\n\nexport function filePathToIdentifier(filePath: string, apiDir: string): string {\n return '_api_' + filePath\n .slice(`${apiDir}/`.length)\n .replace(/\\.(ts|tsx)$/, '')\n .replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nexport function buildRouteEntry(filePath: string, apiDir: string, methods: HttpMethod[]): RouteEntry {\n return {\n filePath,\n urlPattern: keyToRoutePattern(filePath, apiDir),\n identifier: filePathToIdentifier(filePath, apiDir),\n methods,\n }\n}\n\nexport function generateRoutesDts(entries: RouteEntry[], apiDir: string): string {\n if (entries.length === 0) {\n return `// auto-generado por devix \u2014 no editar\\ndeclare module '@devlusoft/devix' {\\n interface ApiRoutes {}\\n}\\n`\n }\n\n const imports = entries\n .map(e => {\n const importPath = '../' + e.filePath.replace(/\\.(ts|tsx)$/, '')\n return `import type * as ${e.identifier} from '${importPath}'`\n })\n .join('\\n')\n\n const routeLines = entries.flatMap(e =>\n e.methods.map(m =>\n ` '${m} ${e.urlPattern}': InferRoute<(typeof ${e.identifier})['${m}']>`\n )\n ).join('\\n')\n\n return `// auto-generado por devix \u2014 no editar\n${imports}\n\ntype JsonResponse<T> = Response & { readonly __body: T }\ntype UnwrapJson<T> = T extends JsonResponse<infer U> ? U : never\ntype InferRoute<T> = T extends (...args: any[]) => any\n ? [UnwrapJson<Awaited<ReturnType<T>>>] extends [never]\n ? Exclude<Awaited<ReturnType<T>>, Response | null | void>\n : UnwrapJson<Awaited<ReturnType<T>>>\n : never\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n", "import {mkdirSync, readFileSync, writeFileSync, existsSync} from 'node:fs'\nimport {join} from 'node:path'\n\nexport function writeRoutesDts(content: string, projectRoot: string): boolean {\n const devixDir = join(projectRoot, '.devix')\n const outPath = join(devixDir, 'routes.d.ts')\n\n mkdirSync(devixDir, {recursive: true})\n\n if (existsSync(outPath) && readFileSync(outPath, 'utf-8') === content) {\n return false\n }\n\n writeFileSync(outPath, content, 'utf-8')\n return true\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["mergeConfig", "react", "fileURLToPath", "dirname", "resolve", "generateEntryClient", "cssUrls", "u", "generateClientRoutes", "pagesDir", "matcherPath", "generateRender", "pagesDir", "renderPath", "generateApi", "apiPath", "appDir", "routePattern", "rel", "cache", "invalidatePagesCache", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "cache", "invalidateApiCache", "generateContext", "readFileSync", "readdirSync", "statSync", "join", "relative", "METHOD_EXPORT_RE", "stripComments", "content", "extractHttpMethods", "found", "match", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "generateRoutesDts", "entries", "imports", "e", "importPath", "routeLines", "m", "walkDir", "dir", "root", "entries", "name", "readdirSync", "full", "join", "statSync", "relative", "scanApiFiles", "appDir", "projectRoot", "apiDir", "files", "f", "filePath", "content", "readFileSync", "methods", "extractHttpMethods", "buildRouteEntry", "mkdirSync", "readFileSync", "writeFileSync", "existsSync", "join", "writeRoutesDts", "content", "projectRoot", "devixDir", "outPath", "__dirname", "dirname", "fileURLToPath", "VIRTUAL_ENTRY_CLIENT", "VIRTUAL_CLIENT_ROUTES", "VIRTUAL_RENDER", "VIRTUAL_API", "VIRTUAL_CONTEXT", "devix", "config", "appDir", "pagesDir", "cssUrls", "u", "renderPath", "resolve", "apiPath", "matcherPath", "virtualPlugin", "id", "generateEntryClient", "generateClientRoutes", "generateRender", "generateApi", "generateContext", "root", "entries", "scanApiFiles", "writeRoutesDts", "generateRoutesDts", "server", "regenerateDts", "file", "invalidatePagesCache", "invalidateApiCache", "base", "react", "mergeConfig"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devlusoft/devix",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A lightweight React SSR meta-framework — devix",
|
|
6
6
|
"author": "devlusoft",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"devlusoft"
|
|
22
22
|
],
|
|
23
23
|
"bin": {
|
|
24
|
-
"devix": "
|
|
24
|
+
"devix": "bin/devix.js"
|
|
25
25
|
},
|
|
26
26
|
"types": "./dist/runtime/index.d.ts",
|
|
27
27
|
"exports": {
|