@rainfw/core 0.1.2 → 0.2.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.
- package/dist/client/dom.d.ts +4 -0
- package/dist/client/dom.d.ts.map +1 -0
- package/dist/client/dom.js +130 -0
- package/dist/client/dom.js.map +1 -0
- package/dist/client/hooks.d.ts +58 -0
- package/dist/client/hooks.d.ts.map +1 -0
- package/dist/client/hooks.js +173 -0
- package/dist/client/hooks.js.map +1 -0
- package/dist/client/hydrate.d.ts +14 -0
- package/dist/client/hydrate.d.ts.map +1 -0
- package/dist/client/hydrate.js +167 -0
- package/dist/client/hydrate.js.map +1 -0
- package/dist/client/jsx-runtime.d.ts +6 -0
- package/dist/client/jsx-runtime.d.ts.map +1 -0
- package/dist/client/jsx-runtime.js +20 -0
- package/dist/client/jsx-runtime.js.map +1 -0
- package/dist/client/reconciler.d.ts +4 -0
- package/dist/client/reconciler.d.ts.map +1 -0
- package/dist/client/reconciler.js +238 -0
- package/dist/client/reconciler.js.map +1 -0
- package/dist/client/runtime.d.ts +6 -0
- package/dist/client/runtime.d.ts.map +1 -0
- package/dist/client/runtime.js +17 -0
- package/dist/client/runtime.js.map +1 -0
- package/dist/client/scheduler.d.ts +4 -0
- package/dist/client/scheduler.d.ts.map +1 -0
- package/dist/client/scheduler.js +44 -0
- package/dist/client/scheduler.js.map +1 -0
- package/dist/compiler/inject.d.ts +6 -0
- package/dist/compiler/inject.d.ts.map +1 -0
- package/dist/compiler/inject.js +19 -0
- package/dist/compiler/inject.js.map +1 -0
- package/dist/compiler/server-action.d.ts +9 -0
- package/dist/compiler/server-action.d.ts.map +1 -0
- package/dist/compiler/server-action.js +98 -0
- package/dist/compiler/server-action.js.map +1 -0
- package/dist/context.js +1 -1
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/jsx/index.d.ts +3 -2
- package/dist/jsx/index.d.ts.map +1 -1
- package/dist/jsx/index.js +2 -2
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/render.d.ts +7 -1
- package/dist/jsx/render.d.ts.map +1 -1
- package/dist/jsx/render.js +96 -14
- package/dist/jsx/render.js.map +1 -1
- package/dist/jsx/types.d.ts +4 -0
- package/dist/jsx/types.d.ts.map +1 -1
- package/dist/jsx/types.js +10 -0
- package/dist/jsx/types.js.map +1 -1
- package/dist/router.d.ts +7 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +84 -3
- package/dist/router.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -1
- package/scripts/dev.js +28 -1
- package/scripts/generate.js +150 -10
package/scripts/generate.js
CHANGED
|
@@ -3,6 +3,13 @@ const path = require("node:path");
|
|
|
3
3
|
const { execSync } = require("node:child_process");
|
|
4
4
|
const ts = require("typescript");
|
|
5
5
|
|
|
6
|
+
let esbuild;
|
|
7
|
+
try {
|
|
8
|
+
esbuild = require("esbuild");
|
|
9
|
+
} catch (_esbuildOptional) {
|
|
10
|
+
esbuild = null;
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
const PROJECT_ROOT = process.cwd();
|
|
7
14
|
|
|
8
15
|
function unwrapExpression(node) {
|
|
@@ -166,6 +173,104 @@ function middlewarePathToDir(filePath) {
|
|
|
166
173
|
.replace(/\/$/, "");
|
|
167
174
|
}
|
|
168
175
|
|
|
176
|
+
function detectUseClientDirective(content) {
|
|
177
|
+
const sourceFile = ts.createSourceFile(
|
|
178
|
+
"file.tsx",
|
|
179
|
+
content,
|
|
180
|
+
ts.ScriptTarget.Latest,
|
|
181
|
+
true,
|
|
182
|
+
);
|
|
183
|
+
const firstStatement = sourceFile.statements[0];
|
|
184
|
+
if (!firstStatement) return false;
|
|
185
|
+
return (
|
|
186
|
+
ts.isExpressionStatement(firstStatement) &&
|
|
187
|
+
ts.isStringLiteral(firstStatement.expression) &&
|
|
188
|
+
firstStatement.expression.text === "use client"
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function getClientFiles(dir, base = "") {
|
|
193
|
+
if (!fs.existsSync(dir)) return [];
|
|
194
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
195
|
+
const files = [];
|
|
196
|
+
|
|
197
|
+
for (const entry of entries) {
|
|
198
|
+
const fullPath = path.join(dir, entry.name);
|
|
199
|
+
const relativePath = path.join(base, entry.name);
|
|
200
|
+
|
|
201
|
+
if (entry.isDirectory()) {
|
|
202
|
+
if (entry.name === "node_modules" || entry.name === ".rainjs") continue;
|
|
203
|
+
files.push(...getClientFiles(fullPath, relativePath));
|
|
204
|
+
} else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
|
|
205
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
206
|
+
if (detectUseClientDirective(content)) {
|
|
207
|
+
files.push(relativePath);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return files;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function bundleClientFilesSync(clientFiles, srcDir) {
|
|
216
|
+
if (clientFiles.length === 0) return [];
|
|
217
|
+
if (!esbuild) {
|
|
218
|
+
console.warn(
|
|
219
|
+
"[Rain] Warning: esbuild not found.\n" +
|
|
220
|
+
" → Install esbuild to enable client bundling: npm install -D esbuild\n" +
|
|
221
|
+
" → Client-side components will not be bundled.",
|
|
222
|
+
);
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const outDir = path.join(PROJECT_ROOT, "public", "_rain");
|
|
227
|
+
if (!fs.existsSync(outDir)) {
|
|
228
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
for (const file of fs.readdirSync(outDir)) {
|
|
232
|
+
if (file.startsWith("island-")) {
|
|
233
|
+
fs.unlinkSync(path.join(outDir, file));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const entryPoints = clientFiles.map((f) => path.join(srcDir, f));
|
|
238
|
+
|
|
239
|
+
const result = esbuild.buildSync({
|
|
240
|
+
entryPoints,
|
|
241
|
+
outdir: outDir,
|
|
242
|
+
bundle: true,
|
|
243
|
+
minify: true,
|
|
244
|
+
format: "esm",
|
|
245
|
+
metafile: true,
|
|
246
|
+
entryNames: "island-[hash]",
|
|
247
|
+
write: true,
|
|
248
|
+
treeShaking: true,
|
|
249
|
+
platform: "browser",
|
|
250
|
+
target: ["es2022"],
|
|
251
|
+
jsx: "automatic",
|
|
252
|
+
jsxImportSource: "@rainfw/core",
|
|
253
|
+
alias: {
|
|
254
|
+
"@rainfw/core/jsx-runtime": path.resolve(
|
|
255
|
+
PROJECT_ROOT,
|
|
256
|
+
"src/framework/client/jsx-runtime.ts",
|
|
257
|
+
),
|
|
258
|
+
},
|
|
259
|
+
loader: { ".ts": "ts", ".tsx": "tsx" },
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const publicDir = path.join(PROJECT_ROOT, "public");
|
|
263
|
+
const scripts = [];
|
|
264
|
+
for (const [outPath, meta] of Object.entries(result.metafile.outputs)) {
|
|
265
|
+
if (meta.entryPoint) {
|
|
266
|
+
const relPath = path.relative(publicDir, outPath);
|
|
267
|
+
scripts.push(`/${relPath.replace(/\\/g, "/")}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return scripts;
|
|
272
|
+
}
|
|
273
|
+
|
|
169
274
|
function routePathToDir(filePath) {
|
|
170
275
|
return filePath
|
|
171
276
|
.replace(/\\/g, "/")
|
|
@@ -546,13 +651,9 @@ function validateCompatibilityFlags() {
|
|
|
546
651
|
if (!fs.existsSync(wranglerPath)) return;
|
|
547
652
|
|
|
548
653
|
const content = fs.readFileSync(wranglerPath, "utf-8");
|
|
549
|
-
const flagsMatch = content.match(
|
|
550
|
-
/compatibility_flags\s*=\s*\[([^\]]*)\]/,
|
|
551
|
-
);
|
|
654
|
+
const flagsMatch = content.match(/compatibility_flags\s*=\s*\[([^\]]*)\]/);
|
|
552
655
|
const flags = flagsMatch
|
|
553
|
-
? (flagsMatch[1].match(/"([^"]+)"/g) || []).map((s) =>
|
|
554
|
-
s.replace(/"/g, ""),
|
|
555
|
-
)
|
|
656
|
+
? (flagsMatch[1].match(/"([^"]+)"/g) || []).map((s) => s.replace(/"/g, ""))
|
|
556
657
|
: [];
|
|
557
658
|
|
|
558
659
|
if (!(flags.includes("nodejs_compat") || flags.includes("nodejs_als"))) {
|
|
@@ -571,6 +672,37 @@ function validateCompatibilityFlags() {
|
|
|
571
672
|
}
|
|
572
673
|
}
|
|
573
674
|
|
|
675
|
+
function buildAppInitLine(clientScripts, hasConfig) {
|
|
676
|
+
if (hasConfig) {
|
|
677
|
+
return clientScripts.length > 0
|
|
678
|
+
? `const app = new Rain({ ...config, clientScripts: ${JSON.stringify(clientScripts)} });`
|
|
679
|
+
: "const app = new Rain(config);";
|
|
680
|
+
}
|
|
681
|
+
return clientScripts.length > 0
|
|
682
|
+
? `const app = new Rain({ clientScripts: ${JSON.stringify(clientScripts)} });`
|
|
683
|
+
: "const app = new Rain();";
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function regenerateClient() {
|
|
687
|
+
const srcDir = path.join(PROJECT_ROOT, "src");
|
|
688
|
+
const clientFiles = getClientFiles(srcDir);
|
|
689
|
+
const clientScripts = bundleClientFilesSync(clientFiles, srcDir);
|
|
690
|
+
|
|
691
|
+
if (!fs.existsSync(ENTRY_FILE)) return;
|
|
692
|
+
|
|
693
|
+
const content = fs.readFileSync(ENTRY_FILE, "utf-8");
|
|
694
|
+
const hasConfig = fs.existsSync(CONFIG_FILE);
|
|
695
|
+
const appInit = buildAppInitLine(clientScripts, hasConfig);
|
|
696
|
+
const updated = content.replace(/^const app = new Rain\(.*\);$/m, appInit);
|
|
697
|
+
if (updated !== content) {
|
|
698
|
+
fs.writeFileSync(ENTRY_FILE, updated);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const clientMsg =
|
|
702
|
+
clientFiles.length > 0 ? `${clientFiles.length} client` : "0 client";
|
|
703
|
+
console.log(`[gen:client] ${clientMsg} -> .rainjs/entry.ts`);
|
|
704
|
+
}
|
|
705
|
+
|
|
574
706
|
function generate() {
|
|
575
707
|
if (!fs.existsSync(ROUTES_DIR)) {
|
|
576
708
|
console.error(
|
|
@@ -632,6 +764,10 @@ function generate() {
|
|
|
632
764
|
registrations,
|
|
633
765
|
);
|
|
634
766
|
|
|
767
|
+
const srcDir = path.join(PROJECT_ROOT, "src");
|
|
768
|
+
const clientFiles = getClientFiles(srcDir);
|
|
769
|
+
const clientScripts = bundleClientFilesSync(clientFiles, srcDir);
|
|
770
|
+
|
|
635
771
|
const hasConfig = fs.existsSync(CONFIG_FILE);
|
|
636
772
|
const fwPkg = BUILD_CONFIG.frameworkPackage;
|
|
637
773
|
const frameworkImport =
|
|
@@ -647,9 +783,7 @@ function generate() {
|
|
|
647
783
|
headerImports.push(`import config from "${configPath}";`);
|
|
648
784
|
}
|
|
649
785
|
|
|
650
|
-
const appInit = hasConfig
|
|
651
|
-
? "const app = new Rain(config);"
|
|
652
|
-
: "const app = new Rain();";
|
|
786
|
+
const appInit = buildAppInitLine(clientScripts, hasConfig);
|
|
653
787
|
|
|
654
788
|
const content = [
|
|
655
789
|
...headerImports,
|
|
@@ -665,18 +799,22 @@ function generate() {
|
|
|
665
799
|
|
|
666
800
|
fs.writeFileSync(ENTRY_FILE, content);
|
|
667
801
|
const total = files.length + pageFiles.length;
|
|
802
|
+
const clientMsg =
|
|
803
|
+
clientFiles.length > 0 ? `, ${clientFiles.length} client` : "";
|
|
668
804
|
console.log(
|
|
669
|
-
`[gen] ${total} route(s) (${files.length} api, ${pageFiles.length} page, ${layoutFiles.length} layout) -> .rainjs/entry.ts`,
|
|
805
|
+
`[gen] ${total} route(s) (${files.length} api, ${pageFiles.length} page, ${layoutFiles.length} layout${clientMsg}) -> .rainjs/entry.ts`,
|
|
670
806
|
);
|
|
671
807
|
}
|
|
672
808
|
|
|
673
809
|
module.exports = {
|
|
674
810
|
generate,
|
|
811
|
+
regenerateClient,
|
|
675
812
|
loadBuildConfig,
|
|
676
813
|
getRouteFiles,
|
|
677
814
|
getMiddlewareFiles,
|
|
678
815
|
getPageFiles,
|
|
679
816
|
getLayoutFiles,
|
|
817
|
+
getClientFiles,
|
|
680
818
|
getMiddlewaresForRoute,
|
|
681
819
|
getLayoutsForPage,
|
|
682
820
|
filePathToUrlPath,
|
|
@@ -691,6 +829,8 @@ module.exports = {
|
|
|
691
829
|
detectMiddlewareExportFromContent,
|
|
692
830
|
detectDefaultExport,
|
|
693
831
|
detectDefaultExportFromContent,
|
|
832
|
+
detectUseClientDirective,
|
|
833
|
+
bundleClientFilesSync,
|
|
694
834
|
validateNoPageRouteColocation,
|
|
695
835
|
ROUTES_DIR,
|
|
696
836
|
ENTRY_FILE,
|