@farm.js/plugin 0.1.0-beta.24 → 0.1.0-beta.26
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/rsc/index.d.ts.map +1 -1
- package/dist/rsc/index.js +19 -0
- package/dist/rsc/route-action-transform.d.ts +11 -0
- package/dist/rsc/route-action-transform.d.ts.map +1 -0
- package/dist/rsc/route-action-transform.js +369 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/rsc/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rsc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAA4B,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAE9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rsc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAA4B,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAE9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA8B9E,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAExF,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QACb;;;WAGG;QACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B;;;WAGG;QACH,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB;;;;;;;WAOG;QACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,CAAC;IACF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,gHAAgH;IAChH,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,aAAkB,GAAG,UAAU,CAiDnE;AA8TD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,EAAE,CAgqC5E"}
|
package/dist/rsc/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import { farmEnvironmentFunctionsPlugin } from "@farm.js/core/environment/vite";
|
|
|
27
27
|
import { generateRscEntry } from "./entries/rsc.js";
|
|
28
28
|
import { generateSsrEntry } from "./entries/ssr.js";
|
|
29
29
|
import { generateClientEntry, serverFnTransportErrorClientRuntime } from "./entries/client.js";
|
|
30
|
+
import { transformFarmRouteActionClients } from "./route-action-transform.js";
|
|
30
31
|
import { transformFarmServerFns } from "./server-fn-transform.js";
|
|
31
32
|
import { transformAutomaticOptimizedBoundaries } from "./automatic-optimized-boundary.js";
|
|
32
33
|
import { resolveRscBuildOutputPath } from "./build-paths.js";
|
|
@@ -730,6 +731,24 @@ export default function farmRsc(options = {}) {
|
|
|
730
731
|
return { code: result.code, map: null };
|
|
731
732
|
},
|
|
732
733
|
},
|
|
734
|
+
{
|
|
735
|
+
name: "@farm.js/plugin/rsc:route-action-clients",
|
|
736
|
+
enforce: "pre",
|
|
737
|
+
transform(code, id) {
|
|
738
|
+
if (!rscEnabled || !actionsEnabled)
|
|
739
|
+
return null;
|
|
740
|
+
const environmentName = this.environment?.name;
|
|
741
|
+
if (environmentName !== "client")
|
|
742
|
+
return null;
|
|
743
|
+
const result = transformFarmRouteActionClients(code, id);
|
|
744
|
+
if (!result)
|
|
745
|
+
return null;
|
|
746
|
+
return {
|
|
747
|
+
code: result.code,
|
|
748
|
+
map: null,
|
|
749
|
+
};
|
|
750
|
+
},
|
|
751
|
+
},
|
|
733
752
|
{
|
|
734
753
|
name: "@farm.js/plugin/rsc:server-fn-actions",
|
|
735
754
|
enforce: "pre",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type FarmRouteActionClientTransformResult = {
|
|
2
|
+
code: string;
|
|
3
|
+
routes: string[];
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Replace a programmatic route imported by the browser with a small action-only
|
|
7
|
+
* proxy. Route loaders, components, database imports, and other server code do
|
|
8
|
+
* not enter the client graph.
|
|
9
|
+
*/
|
|
10
|
+
export declare function transformFarmRouteActionClients(code: string, id: string): FarmRouteActionClientTransformResult | null;
|
|
11
|
+
//# sourceMappingURL=route-action-transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-action-transform.d.ts","sourceRoot":"","sources":["../../src/rsc/route-action-transform.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,oCAAoC,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,oCAAoC,GAAG,IAAI,CAqC7C"}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
const ROUTE_FACTORY_IMPORT_RE = /\bimport\s+(?:type\s+)?(?:[A-Za-z_$][\w$]*\s*,\s*)?(\{[^}]*\})\s+from\s*["']@farm.js\/core(?:\/routes)?["']\s*;?/g;
|
|
2
|
+
const EXPORTED_ROUTE_RE = /\bexport\s+(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*([A-Za-z_$][\w$]*)\s*\(/g;
|
|
3
|
+
const IMPORT_RE = /\bimport\s+(?!type\b)([\s\S]*?)\s+from\s*(["'][^"']+["'])\s*;?/g;
|
|
4
|
+
const IDENTIFIER_RE = /^[A-Za-z_$][\w$]*$/;
|
|
5
|
+
const MODULE_EXT_RE = /\.[cm]?[jt]sx?$/;
|
|
6
|
+
/**
|
|
7
|
+
* Replace a programmatic route imported by the browser with a small action-only
|
|
8
|
+
* proxy. Route loaders, components, database imports, and other server code do
|
|
9
|
+
* not enter the client graph.
|
|
10
|
+
*/
|
|
11
|
+
export function transformFarmRouteActionClients(code, id) {
|
|
12
|
+
if (!isTransformableModule(id) || !code.includes("createRoute") || !code.includes("actions")) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const routeFactories = findRouteFactoryImportNames(code);
|
|
16
|
+
if (routeFactories.size === 0)
|
|
17
|
+
return null;
|
|
18
|
+
const routes = findActionRoutes(code, routeFactories, id);
|
|
19
|
+
if (routes.length === 0)
|
|
20
|
+
return null;
|
|
21
|
+
const importStatements = findRuntimeImports(code);
|
|
22
|
+
const requiredImports = new Set();
|
|
23
|
+
for (const route of routes) {
|
|
24
|
+
for (const action of route.actions) {
|
|
25
|
+
const statement = importStatements.get(action.local);
|
|
26
|
+
if (!statement) {
|
|
27
|
+
throw new Error(`[Farm.js] Route "${route.exportName}" action "${action.name}" in ${id} must reference ` +
|
|
28
|
+
"a server function imported from another module. Define and export createServerFn in an actions module, then import it into the route.");
|
|
29
|
+
}
|
|
30
|
+
requiredImports.add(statement);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const output = [
|
|
34
|
+
...requiredImports,
|
|
35
|
+
...routes.map((route) => generateRouteActionProxy(route)),
|
|
36
|
+
...findRouteDefaultExports(code, routes),
|
|
37
|
+
].join("\n");
|
|
38
|
+
return {
|
|
39
|
+
code: `${output}\n`,
|
|
40
|
+
routes: routes.map((route) => route.exportName),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function findRouteFactoryImportNames(code) {
|
|
44
|
+
const names = new Set();
|
|
45
|
+
for (const match of code.matchAll(ROUTE_FACTORY_IMPORT_RE)) {
|
|
46
|
+
const namedImports = (match[1] ?? "").slice(1, -1).split(",");
|
|
47
|
+
for (const specifier of namedImports) {
|
|
48
|
+
const normalized = specifier.trim().replace(/^type\s+/, "");
|
|
49
|
+
const specifierMatch = normalized.match(/^createRoute(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
50
|
+
if (specifierMatch)
|
|
51
|
+
names.add(specifierMatch[1] ?? "createRoute");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return names;
|
|
55
|
+
}
|
|
56
|
+
function findActionRoutes(code, factories, id) {
|
|
57
|
+
const routes = [];
|
|
58
|
+
for (const match of code.matchAll(EXPORTED_ROUTE_RE)) {
|
|
59
|
+
const exportName = match[1];
|
|
60
|
+
const calleeName = match[2];
|
|
61
|
+
if (!exportName || !calleeName || !factories.has(calleeName))
|
|
62
|
+
continue;
|
|
63
|
+
const openParen = (match.index ?? 0) + match[0].length - 1;
|
|
64
|
+
const closeParen = findMatchingDelimiter(code, openParen, "(", ")");
|
|
65
|
+
if (closeParen === -1)
|
|
66
|
+
continue;
|
|
67
|
+
const args = splitTopLevel(code, openParen + 1, closeParen);
|
|
68
|
+
if (args.length < 2)
|
|
69
|
+
continue;
|
|
70
|
+
const pathSource = readSegment(code, args[0]);
|
|
71
|
+
if (!isQuotedString(pathSource)) {
|
|
72
|
+
throw new Error(`[Farm.js] Route "${exportName}" in ${id} must use a static string path before its actions can be imported by a Client Component.`);
|
|
73
|
+
}
|
|
74
|
+
const options = readSegment(code, args[1]);
|
|
75
|
+
if (!options.startsWith("{") || !options.endsWith("}"))
|
|
76
|
+
continue;
|
|
77
|
+
const properties = parseObjectProperties(options.slice(1, -1));
|
|
78
|
+
const actionsSource = properties.get("actions");
|
|
79
|
+
if (!actionsSource)
|
|
80
|
+
continue;
|
|
81
|
+
if (!actionsSource.startsWith("{") || !actionsSource.endsWith("}")) {
|
|
82
|
+
throw new Error(`[Farm.js] Route "${exportName}" actions in ${id} must be an object literal so Farm can generate its client proxy.`);
|
|
83
|
+
}
|
|
84
|
+
const actions = parseActionProperties(actionsSource.slice(1, -1), exportName, id);
|
|
85
|
+
if (actions.length === 0)
|
|
86
|
+
continue;
|
|
87
|
+
const defaultSource = properties.get("defaultAction");
|
|
88
|
+
const defaultAction = defaultSource
|
|
89
|
+
? parseStringValue(defaultSource, exportName, id)
|
|
90
|
+
: actions[0].name;
|
|
91
|
+
if (!actions.some((action) => action.name === defaultAction)) {
|
|
92
|
+
throw new Error(`[Farm.js] Route "${exportName}" defaultAction "${defaultAction}" in ${id} does not match a declared action.`);
|
|
93
|
+
}
|
|
94
|
+
routes.push({ exportName, pathSource, actions, defaultAction });
|
|
95
|
+
}
|
|
96
|
+
return routes;
|
|
97
|
+
}
|
|
98
|
+
function parseActionProperties(source, routeName, id) {
|
|
99
|
+
const properties = parseObjectProperties(source, true);
|
|
100
|
+
const actions = [];
|
|
101
|
+
for (const [name, value] of properties) {
|
|
102
|
+
const local = value || name;
|
|
103
|
+
if (!IDENTIFIER_RE.test(name) || !IDENTIFIER_RE.test(local)) {
|
|
104
|
+
throw new Error(`[Farm.js] Route "${routeName}" actions in ${id} must use identifier entries such as { update } or { update: updateProduct }.`);
|
|
105
|
+
}
|
|
106
|
+
actions.push({ name, local });
|
|
107
|
+
}
|
|
108
|
+
return actions;
|
|
109
|
+
}
|
|
110
|
+
function parseObjectProperties(source, allowShorthand = false) {
|
|
111
|
+
const properties = new Map();
|
|
112
|
+
for (const segment of splitTopLevel(source, 0, source.length)) {
|
|
113
|
+
const entry = readSegment(source, segment);
|
|
114
|
+
if (!entry)
|
|
115
|
+
continue;
|
|
116
|
+
if (entry.startsWith("...")) {
|
|
117
|
+
properties.set(entry, "");
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const colon = findTopLevelColon(entry);
|
|
121
|
+
if (colon === -1) {
|
|
122
|
+
if (allowShorthand)
|
|
123
|
+
properties.set(entry, "");
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const keySource = entry.slice(0, colon).trim();
|
|
127
|
+
const value = entry.slice(colon + 1).trim();
|
|
128
|
+
const key = isQuotedString(keySource) ? unquote(keySource) : keySource;
|
|
129
|
+
properties.set(key, value);
|
|
130
|
+
}
|
|
131
|
+
return properties;
|
|
132
|
+
}
|
|
133
|
+
function findRuntimeImports(code) {
|
|
134
|
+
const imports = new Map();
|
|
135
|
+
for (const match of code.matchAll(IMPORT_RE)) {
|
|
136
|
+
const clause = (match[1] ?? "").trim();
|
|
137
|
+
const statement = match[0];
|
|
138
|
+
const namedStart = clause.indexOf("{");
|
|
139
|
+
const namedEnd = clause.lastIndexOf("}");
|
|
140
|
+
if (namedStart > -1 && namedEnd > namedStart) {
|
|
141
|
+
for (const specifier of clause.slice(namedStart + 1, namedEnd).split(",")) {
|
|
142
|
+
const normalized = specifier.trim().replace(/^type\s+/, "");
|
|
143
|
+
if (!normalized || specifier.trim().startsWith("type "))
|
|
144
|
+
continue;
|
|
145
|
+
const parts = normalized.split(/\s+as\s+/);
|
|
146
|
+
const local = parts[1] ?? parts[0];
|
|
147
|
+
if (local && IDENTIFIER_RE.test(local))
|
|
148
|
+
imports.set(local, statement);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const defaultImport = clause
|
|
152
|
+
.slice(0, namedStart === -1 ? clause.length : namedStart)
|
|
153
|
+
.replace(/,$/, "")
|
|
154
|
+
.trim();
|
|
155
|
+
if (IDENTIFIER_RE.test(defaultImport))
|
|
156
|
+
imports.set(defaultImport, statement);
|
|
157
|
+
}
|
|
158
|
+
return imports;
|
|
159
|
+
}
|
|
160
|
+
function generateRouteActionProxy(route) {
|
|
161
|
+
const actions = route.actions
|
|
162
|
+
.map((action) => `${JSON.stringify(action.name)}: ${action.local}`)
|
|
163
|
+
.join(", ");
|
|
164
|
+
const defaultAction = route.actions.find((action) => action.name === route.defaultAction);
|
|
165
|
+
return `export const ${route.exportName} = Object.freeze({
|
|
166
|
+
__farmRouteActionTarget: true,
|
|
167
|
+
path: ${route.pathSource},
|
|
168
|
+
actions: Object.freeze({ ${actions} }),
|
|
169
|
+
defaultAction: ${JSON.stringify(route.defaultAction)},
|
|
170
|
+
action: ${defaultAction.local},
|
|
171
|
+
});`;
|
|
172
|
+
}
|
|
173
|
+
function findRouteDefaultExports(code, routes) {
|
|
174
|
+
const exports = [];
|
|
175
|
+
for (const route of routes) {
|
|
176
|
+
const defaultExport = new RegExp(`\\bexport\\s+default\\s+${escapeRegExp(route.exportName)}\\s*;?`);
|
|
177
|
+
if (defaultExport.test(code))
|
|
178
|
+
exports.push(`export default ${route.exportName};`);
|
|
179
|
+
}
|
|
180
|
+
return exports;
|
|
181
|
+
}
|
|
182
|
+
function splitTopLevel(source, start, end) {
|
|
183
|
+
const segments = [];
|
|
184
|
+
let segmentStart = start;
|
|
185
|
+
let parens = 0;
|
|
186
|
+
let braces = 0;
|
|
187
|
+
let brackets = 0;
|
|
188
|
+
let quote = null;
|
|
189
|
+
let escaped = false;
|
|
190
|
+
let lineComment = false;
|
|
191
|
+
let blockComment = false;
|
|
192
|
+
for (let index = start; index < end; index++) {
|
|
193
|
+
const char = source[index];
|
|
194
|
+
const next = source[index + 1];
|
|
195
|
+
if (lineComment) {
|
|
196
|
+
if (char === "\n" || char === "\r")
|
|
197
|
+
lineComment = false;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (blockComment) {
|
|
201
|
+
if (char === "*" && next === "/") {
|
|
202
|
+
blockComment = false;
|
|
203
|
+
index++;
|
|
204
|
+
}
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (quote) {
|
|
208
|
+
if (escaped)
|
|
209
|
+
escaped = false;
|
|
210
|
+
else if (char === "\\")
|
|
211
|
+
escaped = true;
|
|
212
|
+
else if (char === quote)
|
|
213
|
+
quote = null;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (char === "/" && next === "/") {
|
|
217
|
+
lineComment = true;
|
|
218
|
+
index++;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (char === "/" && next === "*") {
|
|
222
|
+
blockComment = true;
|
|
223
|
+
index++;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (char === "'" || char === '"' || char === "`") {
|
|
227
|
+
quote = char;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (char === "(")
|
|
231
|
+
parens++;
|
|
232
|
+
else if (char === ")")
|
|
233
|
+
parens--;
|
|
234
|
+
else if (char === "{")
|
|
235
|
+
braces++;
|
|
236
|
+
else if (char === "}")
|
|
237
|
+
braces--;
|
|
238
|
+
else if (char === "[")
|
|
239
|
+
brackets++;
|
|
240
|
+
else if (char === "]")
|
|
241
|
+
brackets--;
|
|
242
|
+
else if (char === "," && parens === 0 && braces === 0 && brackets === 0) {
|
|
243
|
+
segments.push([segmentStart, index]);
|
|
244
|
+
segmentStart = index + 1;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
segments.push([segmentStart, end]);
|
|
248
|
+
return segments;
|
|
249
|
+
}
|
|
250
|
+
function findTopLevelColon(source) {
|
|
251
|
+
const segments = splitTopLevel(source, 0, source.length);
|
|
252
|
+
if (segments.length !== 1)
|
|
253
|
+
return -1;
|
|
254
|
+
let parens = 0;
|
|
255
|
+
let braces = 0;
|
|
256
|
+
let brackets = 0;
|
|
257
|
+
let quote = null;
|
|
258
|
+
let escaped = false;
|
|
259
|
+
for (let index = 0; index < source.length; index++) {
|
|
260
|
+
const char = source[index];
|
|
261
|
+
if (quote) {
|
|
262
|
+
if (escaped)
|
|
263
|
+
escaped = false;
|
|
264
|
+
else if (char === "\\")
|
|
265
|
+
escaped = true;
|
|
266
|
+
else if (char === quote)
|
|
267
|
+
quote = null;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (char === "'" || char === '"' || char === "`") {
|
|
271
|
+
quote = char;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (char === "(")
|
|
275
|
+
parens++;
|
|
276
|
+
else if (char === ")")
|
|
277
|
+
parens--;
|
|
278
|
+
else if (char === "{")
|
|
279
|
+
braces++;
|
|
280
|
+
else if (char === "}")
|
|
281
|
+
braces--;
|
|
282
|
+
else if (char === "[")
|
|
283
|
+
brackets++;
|
|
284
|
+
else if (char === "]")
|
|
285
|
+
brackets--;
|
|
286
|
+
else if (char === ":" && parens === 0 && braces === 0 && brackets === 0)
|
|
287
|
+
return index;
|
|
288
|
+
}
|
|
289
|
+
return -1;
|
|
290
|
+
}
|
|
291
|
+
function findMatchingDelimiter(source, openIndex, open, close) {
|
|
292
|
+
let depth = 0;
|
|
293
|
+
let quote = null;
|
|
294
|
+
let lineComment = false;
|
|
295
|
+
let blockComment = false;
|
|
296
|
+
let escaped = false;
|
|
297
|
+
for (let index = openIndex; index < source.length; index++) {
|
|
298
|
+
const char = source[index];
|
|
299
|
+
const next = source[index + 1];
|
|
300
|
+
if (lineComment) {
|
|
301
|
+
if (char === "\n" || char === "\r")
|
|
302
|
+
lineComment = false;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (blockComment) {
|
|
306
|
+
if (char === "*" && next === "/") {
|
|
307
|
+
blockComment = false;
|
|
308
|
+
index++;
|
|
309
|
+
}
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (quote) {
|
|
313
|
+
if (escaped)
|
|
314
|
+
escaped = false;
|
|
315
|
+
else if (char === "\\")
|
|
316
|
+
escaped = true;
|
|
317
|
+
else if (char === quote)
|
|
318
|
+
quote = null;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (char === "/" && next === "/") {
|
|
322
|
+
lineComment = true;
|
|
323
|
+
index++;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (char === "/" && next === "*") {
|
|
327
|
+
blockComment = true;
|
|
328
|
+
index++;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (char === "'" || char === '"' || char === "`") {
|
|
332
|
+
quote = char;
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (char === open)
|
|
336
|
+
depth++;
|
|
337
|
+
else if (char === close && --depth === 0)
|
|
338
|
+
return index;
|
|
339
|
+
}
|
|
340
|
+
return -1;
|
|
341
|
+
}
|
|
342
|
+
function readSegment(source, segment) {
|
|
343
|
+
return source.slice(segment[0], segment[1]).trim();
|
|
344
|
+
}
|
|
345
|
+
function parseStringValue(source, routeName, id) {
|
|
346
|
+
if (!isQuotedString(source)) {
|
|
347
|
+
throw new Error(`[Farm.js] Route "${routeName}" defaultAction in ${id} must be a static string.`);
|
|
348
|
+
}
|
|
349
|
+
return unquote(source);
|
|
350
|
+
}
|
|
351
|
+
function isQuotedString(value) {
|
|
352
|
+
return (value.length >= 2 &&
|
|
353
|
+
((value.startsWith('"') && value.endsWith('"')) ||
|
|
354
|
+
(value.startsWith("'") && value.endsWith("'"))));
|
|
355
|
+
}
|
|
356
|
+
function unquote(value) {
|
|
357
|
+
const quote = value[0];
|
|
358
|
+
const body = value.slice(1, -1);
|
|
359
|
+
if (quote === '"')
|
|
360
|
+
return JSON.parse(value);
|
|
361
|
+
return body.replace(/\\'/g, "'").replace(/\\\\/g, "\\");
|
|
362
|
+
}
|
|
363
|
+
function isTransformableModule(id) {
|
|
364
|
+
const cleanId = id.split("?", 1)[0];
|
|
365
|
+
return MODULE_EXT_RE.test(cleanId) && !/\.d\.[cm]?ts$/.test(cleanId);
|
|
366
|
+
}
|
|
367
|
+
function escapeRegExp(value) {
|
|
368
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
369
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farm.js/plugin",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.26",
|
|
4
4
|
"description": "Official plugins for Farm.js framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Farm.js Team",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"nitro": "3.0.1-alpha.0",
|
|
62
62
|
"picocolors": "^1.0.0",
|
|
63
63
|
"rsc-html-stream": "^0.0.4",
|
|
64
|
-
"@farm.js/core": "0.1.0-beta.
|
|
64
|
+
"@farm.js/core": "0.1.0-beta.26"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "^20.19.21",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"react-dom": "19.2.8",
|
|
83
83
|
"react-server-dom-webpack": "19.2.8",
|
|
84
84
|
"vite": ">=6.0.0",
|
|
85
|
-
"@farm.js/core": "0.1.0-beta.
|
|
85
|
+
"@farm.js/core": "0.1.0-beta.26"
|
|
86
86
|
},
|
|
87
87
|
"peerDependenciesMeta": {
|
|
88
88
|
"@vitejs/plugin-rsc": {
|