@adep/web-container 0.2.1 → 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/function-fetch-proxy.d.ts +9 -3
- package/dist/index.js +228 -33
- package/dist/vite-dev.d.ts +2 -0
- package/dist/web-container.esm.js +228 -33
- package/dist/web-container.iife.js +228 -33
- package/package.json +3 -3
|
@@ -28,9 +28,15 @@ export interface OfflineRunner {
|
|
|
28
28
|
/**
|
|
29
29
|
* 浏览器端 fetch 拦截器脚本(IIFE,纯 JS——必须能直接内联进 `<script>`,不能有 TS / ESM)。
|
|
30
30
|
*
|
|
31
|
-
* **同步纪律**:本字符串与 `
|
|
32
|
-
* `
|
|
33
|
-
* vite-dev
|
|
31
|
+
* **同步纪律**:本字符串与 `packages/vite-plugin/src/ide-proxy.ts` 的
|
|
32
|
+
* `FN_FETCH_INTERCEPTOR_SCRIPT`(单一真相源)必须**逐字一致**(两处复制粘贴,无共享
|
|
33
|
+
* import——预览 iframe 与浏览器内 vite-dev 是两个独立加载上下文,共享一份源码反而会引入
|
|
34
|
+
* 打包耦合)。改这里务必同步另一侧。
|
|
35
|
+
*
|
|
36
|
+
* blob base 兼容(2026-09-11 修复):浏览器内 vite-dev 预览文档的 baseURI 是 blob: URL,
|
|
37
|
+
* `new URL('/api/x', 'blob:…')` 抛 TypeError → 拦截器退化成原生 fetch 报
|
|
38
|
+
* "Failed to parse URL"。首次解析失败时用 `window.location.origin`(blob 继承创建者
|
|
39
|
+
* origin)兜底再解析一次。
|
|
34
40
|
*/
|
|
35
41
|
export declare const FN_FETCH_INTERCEPTOR_SCRIPT: string;
|
|
36
42
|
/** IDE 主线程侧的消息处理器类型:直接挂到 `window.addEventListener('message', handler)`。 */
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,27 @@ function withinPackage(pkgDirAbs, rel, context) {
|
|
|
105
105
|
}
|
|
106
106
|
return abs;
|
|
107
107
|
}
|
|
108
|
+
function pickConditionTarget(conditions, order, resolveRel, context) {
|
|
109
|
+
for (const key of order) {
|
|
110
|
+
const value = conditions[key];
|
|
111
|
+
if (value === void 0 || value === null) continue;
|
|
112
|
+
if (typeof value === "string") return resolveRel(value);
|
|
113
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
114
|
+
const nested = pickConditionTarget(
|
|
115
|
+
value,
|
|
116
|
+
order,
|
|
117
|
+
resolveRel,
|
|
118
|
+
context
|
|
119
|
+
);
|
|
120
|
+
if (nested !== null) return nested;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
throw new ResolveError(
|
|
124
|
+
`${context}\uFF1Aexports["."]["${key}"] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32 / null / \u6761\u4EF6\u5BF9\u8C61\uFF09`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
108
129
|
function resolvePackageEntry(meta, pkgDirAbs, condition) {
|
|
109
130
|
const context = `\u5305 ${meta.name ?? meta.version ?? pkgDirAbs} \u7684 exports/main \u58F0\u660E`;
|
|
110
131
|
const exp = meta.exports;
|
|
@@ -125,20 +146,11 @@ function resolvePackageEntry(meta, pkgDirAbs, condition) {
|
|
|
125
146
|
if (typeof dot !== "object" || Array.isArray(dot)) {
|
|
126
147
|
throw new ResolveError(`${context}\uFF1Aexports["."] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216\u6761\u4EF6\u5BF9\u8C61\uFF09`);
|
|
127
148
|
}
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (value !== void 0 && (typeof value !== "object" || value === null)) {
|
|
134
|
-
throw new ResolveError(
|
|
135
|
-
`${context}\uFF1Aexports["."]["${key}"] \u5F62\u6001\u4E0D\u652F\u6301\uFF08\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32\u6216 null\uFF09`
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
throw new ResolveError(
|
|
140
|
-
`${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${condition}/node/default \u5B57\u7B26\u4E32\u5165\u53E3\uFF08\u5B50\u8DEF\u5F84/\u5D4C\u5957\u6761\u4EF6\u4E0D\u652F\u6301\uFF09`
|
|
141
|
-
);
|
|
149
|
+
const order = condition === "import" ? IMPORT_CONDITION_ORDER : REQUIRE_CONDITION_ORDER;
|
|
150
|
+
const resolveRel = (rel) => withinPackage(pkgDirAbs, rel, context);
|
|
151
|
+
const hit = pickConditionTarget(dot, order, resolveRel, context);
|
|
152
|
+
if (hit !== null) return hit;
|
|
153
|
+
throw new ResolveError(`${context}\uFF1Aexports["."] \u6761\u4EF6\u5BF9\u8C61\u91CC\u6CA1\u6709 ${order.join("/")} \u5165\u53E3`);
|
|
142
154
|
}
|
|
143
155
|
if (meta.main !== void 0) {
|
|
144
156
|
if (typeof meta.main !== "string") {
|
|
@@ -236,11 +248,13 @@ function resolveImport(fs, specifier, fromFileAbs, condition = "require") {
|
|
|
236
248
|
`\u627E\u4E0D\u5230\u5305 "${specifier}"\uFF1A${dirname(fromFileAbs)} \u53CA\u5176\u5404\u7EA7\u7236\u76EE\u5F55\u4E0B\u90FD\u6CA1\u6709 node_modules/${name}\uFF08\u5148\u5728\u7EC8\u7AEF npm install ${name}\uFF09`
|
|
237
249
|
);
|
|
238
250
|
}
|
|
239
|
-
var RESOLVE_EXTENSIONS, ResolveError;
|
|
251
|
+
var IMPORT_CONDITION_ORDER, REQUIRE_CONDITION_ORDER, RESOLVE_EXTENSIONS, ResolveError;
|
|
240
252
|
var init_node_resolve = __esm({
|
|
241
253
|
"packages/web-container/src/node-resolve.ts"() {
|
|
242
254
|
"use strict";
|
|
243
255
|
init_path();
|
|
256
|
+
IMPORT_CONDITION_ORDER = ["browser", "import", "module", "default"];
|
|
257
|
+
REQUIRE_CONDITION_ORDER = ["require", "node", "default"];
|
|
244
258
|
RESOLVE_EXTENSIONS = [".js", ".mjs", ".cjs", ".json"];
|
|
245
259
|
ResolveError = class extends Error {
|
|
246
260
|
constructor(message) {
|
|
@@ -515,6 +529,7 @@ var init_strip_types = __esm({
|
|
|
515
529
|
return;
|
|
516
530
|
case "as":
|
|
517
531
|
case "satisfies": {
|
|
532
|
+
if (this.frames[this.frames.length - 1]?.specifierList === true) return;
|
|
518
533
|
if (this.tokenAt(2) === "*" || this.tokenAt(2) === "type") return;
|
|
519
534
|
const nextChar = this.skipWhitespaceFrom(this.i);
|
|
520
535
|
if (nextChar === null || "=,:]})".includes(this.src[nextChar])) return;
|
|
@@ -567,7 +582,8 @@ var init_strip_types = __esm({
|
|
|
567
582
|
const frame = {
|
|
568
583
|
kind: c === "(" ? "paren" : c === "{" ? "brace" : "bracket",
|
|
569
584
|
declare: false,
|
|
570
|
-
classBody: false
|
|
585
|
+
classBody: false,
|
|
586
|
+
specifierList: c === "{" && this.isImportSpecifierBrace()
|
|
571
587
|
};
|
|
572
588
|
if (c === "{" && this.pendingClassBody) {
|
|
573
589
|
frame.classBody = true;
|
|
@@ -653,6 +669,15 @@ var init_strip_types = __esm({
|
|
|
653
669
|
this.i = end;
|
|
654
670
|
return true;
|
|
655
671
|
}
|
|
672
|
+
/**
|
|
673
|
+
* `{` 是 import / export 的说明符列表吗——`{ a as b }` 覆盖 `import { … }`、
|
|
674
|
+
* `export { … }` 与 `import def, { … }` 三种写法(后者说明符花括号的前驱 token 是 `,`)。
|
|
675
|
+
*/
|
|
676
|
+
isImportSpecifierBrace() {
|
|
677
|
+
const back1 = this.tokenAt(1);
|
|
678
|
+
if (back1 === "import" || back1 === "export") return true;
|
|
679
|
+
return back1 === "," && this.tokenAt(3) === "import";
|
|
680
|
+
}
|
|
656
681
|
/**
|
|
657
682
|
* `(` 是否为参数列表(声明位):`function f(`、类体里的方法 `m(`、箭头 `=> (`,
|
|
658
683
|
* 以及出现在 `(` `,` `=` `>` `:` `[` `{` `}` `;` 之后(如 `map((v: T) => v)` 的内层括号)。
|
|
@@ -664,6 +689,7 @@ var init_strip_types = __esm({
|
|
|
664
689
|
if (this.afterFunctionKeyword) return true;
|
|
665
690
|
if (this.tokenAt(2) === "function" && IDENT_START.test(this.tokenAt(1))) return true;
|
|
666
691
|
if (this.afterArrow) return true;
|
|
692
|
+
if (this.tokenAt(1) === "return") return true;
|
|
667
693
|
if (this.inClassBody() && IDENT_PART.test(this.prevSignificantChar(at - 1))) return true;
|
|
668
694
|
const prev = this.prevSignificantChar(at - 1);
|
|
669
695
|
return prev === "" || "(,=>:[{};".includes(prev);
|
|
@@ -1172,7 +1198,10 @@ var init_function_fetch_proxy = __esm({
|
|
|
1172
1198
|
" }",
|
|
1173
1199
|
" var u;",
|
|
1174
1200
|
" try { u = new URL(urlStr, document.baseURI); }",
|
|
1175
|
-
" catch (
|
|
1201
|
+
" catch (e0) {",
|
|
1202
|
+
" try { u = new URL(urlStr, window.location.origin); }",
|
|
1203
|
+
" catch (e1) { return ORIGINAL_FETCH(input, init); }",
|
|
1204
|
+
" }",
|
|
1176
1205
|
' if (u.pathname.indexOf("/api/") !== 0 && u.pathname !== "/api") {',
|
|
1177
1206
|
" return ORIGINAL_FETCH(input, init);",
|
|
1178
1207
|
" }",
|
|
@@ -1311,6 +1340,18 @@ function cssModule(css) {
|
|
|
1311
1340
|
"export default css;"
|
|
1312
1341
|
].join("\n");
|
|
1313
1342
|
}
|
|
1343
|
+
function inlineStyleBlock(css, key) {
|
|
1344
|
+
return [
|
|
1345
|
+
"{",
|
|
1346
|
+
`const css = ${JSON.stringify(css)};`,
|
|
1347
|
+
'const el = document.createElement("style");',
|
|
1348
|
+
'el.setAttribute("data-adep-vite", "");',
|
|
1349
|
+
`el.setAttribute("data-adep-style", ${JSON.stringify(key)});`,
|
|
1350
|
+
"el.textContent = css;",
|
|
1351
|
+
"document.head.appendChild(el);",
|
|
1352
|
+
"}"
|
|
1353
|
+
].join("\n");
|
|
1354
|
+
}
|
|
1314
1355
|
function jsonModule(source, abs) {
|
|
1315
1356
|
try {
|
|
1316
1357
|
JSON.parse(source);
|
|
@@ -1361,6 +1402,17 @@ function createViteServer(vfs, options = {}) {
|
|
|
1361
1402
|
} catch {
|
|
1362
1403
|
}
|
|
1363
1404
|
};
|
|
1405
|
+
const DEFINES = [
|
|
1406
|
+
[/\bprocess\s*\.\s*env\s*\.\s*NODE_ENV\b/g, JSON.stringify("development")],
|
|
1407
|
+
[/\b__VUE_OPTIONS_API__\b/g, "true"],
|
|
1408
|
+
[/\b__VUE_PROD_DEVTOOLS__\b/g, "false"],
|
|
1409
|
+
[/\b__VUE_PROD_HYDRATION_MISMATCH_DETAILS__\b/g, "false"]
|
|
1410
|
+
];
|
|
1411
|
+
function applyDefines(code) {
|
|
1412
|
+
let out = code;
|
|
1413
|
+
for (const [pattern, value] of DEFINES) out = out.replace(pattern, value);
|
|
1414
|
+
return out;
|
|
1415
|
+
}
|
|
1364
1416
|
function transformModule2(abs, source) {
|
|
1365
1417
|
if (abs.endsWith(".css")) return cssModule(source);
|
|
1366
1418
|
if (abs.endsWith(".json")) return jsonModule(source, abs);
|
|
@@ -1371,21 +1423,27 @@ function createViteServer(vfs, options = {}) {
|
|
|
1371
1423
|
`${abs} \u662F Vue SFC\uFF0C\u4F46\u5F53\u524D\u73AF\u5883\u672A\u88C5\u914D SFC \u7F16\u8BD1\u5668\uFF08IDE \u4FA7\u9700\u6CE8\u5165 vue/compiler-sfc\uFF09`
|
|
1372
1424
|
);
|
|
1373
1425
|
const compiled = sfcCompiler(source, abs);
|
|
1374
|
-
return [
|
|
1426
|
+
return [
|
|
1427
|
+
...compiled.styles.map((css, index) => inlineStyleBlock(css, `${abs}#${index}`)),
|
|
1428
|
+
applyDefines(stripTypes(compiled.script))
|
|
1429
|
+
].join("\n");
|
|
1375
1430
|
}
|
|
1376
1431
|
if (abs.endsWith(".tsx") || abs.endsWith(".jsx"))
|
|
1377
1432
|
throw new ViteDevError(
|
|
1378
1433
|
"JSX_UNSUPPORTED",
|
|
1379
1434
|
`${abs} \u4F7F\u7528 JSX\uFF1A\u6D4F\u89C8\u5668\u5185 vite \u53EA\u64E6\u9664 TS \u7C7B\u578B\u6807\u6CE8\uFF0C\u4E0D\u8F6C\u8BD1 JSX\uFF08\u8BF7\u7528 h() \u6E32\u67D3\u51FD\u6570\u6216 .vue SFC\uFF09`
|
|
1380
1435
|
);
|
|
1381
|
-
if (abs.endsWith(".ts") || abs.endsWith(".mts")) return stripTypes(source);
|
|
1382
|
-
return source;
|
|
1436
|
+
if (abs.endsWith(".ts") || abs.endsWith(".mts")) return applyDefines(stripTypes(source));
|
|
1437
|
+
return applyDefines(source);
|
|
1438
|
+
}
|
|
1439
|
+
function absoluteFromRoot(spec) {
|
|
1440
|
+
return join(root, spec.replace(/^\/+/, ""));
|
|
1383
1441
|
}
|
|
1384
1442
|
async function resolveSpecifier(spec, importerAbs) {
|
|
1385
1443
|
if (EXTERNAL_SPECIFIER.test(spec) || DATA_OR_BLOB.test(spec)) return spec;
|
|
1386
1444
|
let target;
|
|
1387
1445
|
if (spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/")) {
|
|
1388
|
-
const base = spec.startsWith("/") ? spec : join(dirname(importerAbs), spec);
|
|
1446
|
+
const base = spec.startsWith("/") ? absoluteFromRoot(spec) : join(dirname(importerAbs), spec);
|
|
1389
1447
|
target = resolveWithSuffixes(vfs, base);
|
|
1390
1448
|
if (!vfs.exists(target) || vfs.isDirectory(target))
|
|
1391
1449
|
throw new ViteDevError(
|
|
@@ -1474,7 +1532,7 @@ function createViteServer(vfs, options = {}) {
|
|
|
1474
1532
|
html = html.replace(
|
|
1475
1533
|
MODULE_SCRIPT_SRC_RE,
|
|
1476
1534
|
(_whole, pre, _q1, mid, _q2, src, post) => {
|
|
1477
|
-
const base = src.startsWith("/") ?
|
|
1535
|
+
const base = src.startsWith("/") ? absoluteFromRoot(src) : join(dirname(entryAbs), src);
|
|
1478
1536
|
const abs = resolveWithSuffixes(vfs, base);
|
|
1479
1537
|
if (!vfs.exists(abs) || vfs.isDirectory(abs))
|
|
1480
1538
|
throw new ViteDevError(
|
|
@@ -1482,7 +1540,7 @@ function createViteServer(vfs, options = {}) {
|
|
|
1482
1540
|
`\u5165\u53E3 module script \u627E\u4E0D\u5230 "${src}"\uFF08root: ${root}\uFF1B\u8BD5\u8FC7\u6269\u5C55\u540D ${VITE_RESOLVE_SUFFIXES.join("/")} \u4E0E\u76EE\u5F55 index\uFF09`
|
|
1483
1541
|
);
|
|
1484
1542
|
entryModuleUrls.push(loadModuleUrl(abs));
|
|
1485
|
-
return `<script${pre}${mid}src="__adep_vite_entry_${entryModuleUrls.length - 1}__"${post}></script>`;
|
|
1543
|
+
return `<script${pre}${mid}src="__adep_vite_entry_${entryModuleUrls.length - 1}__"${post} type="module"></script>`;
|
|
1486
1544
|
}
|
|
1487
1545
|
);
|
|
1488
1546
|
html = html.replace(
|
|
@@ -1492,7 +1550,7 @@ function createViteServer(vfs, options = {}) {
|
|
|
1492
1550
|
const abs = `${INLINE_PREFIX}${inlineSeq++}.mjs`;
|
|
1493
1551
|
inlineSources.set(abs, body);
|
|
1494
1552
|
entryModuleUrls.push(loadModuleUrl(abs));
|
|
1495
|
-
return `<script${pre}${post}src="__adep_vite_entry_${entryModuleUrls.length - 1}__"></script>`;
|
|
1553
|
+
return `<script${pre}${post}src="__adep_vite_entry_${entryModuleUrls.length - 1}__" type="module"></script>`;
|
|
1496
1554
|
}
|
|
1497
1555
|
);
|
|
1498
1556
|
const urls = await Promise.all(entryModuleUrls);
|
|
@@ -4459,6 +4517,8 @@ var CHAIN_CAPABILITY_KEY = "__adepChain";
|
|
|
4459
4517
|
var DB_RPC = {
|
|
4460
4518
|
/** 直通方法(如 query):`(method=query, args=[sql, params])`。 */
|
|
4461
4519
|
query: "query",
|
|
4520
|
+
/** 写路径(CF-013):`(method=writeQuery, args=[sql, params])` → `{ changes }`。 */
|
|
4521
|
+
writeQuery: "writeQuery",
|
|
4462
4522
|
/** 读取 owned 表变更流(DB-006):`(method=changes, args=[table, query])`。 */
|
|
4463
4523
|
changes: "changes",
|
|
4464
4524
|
/** 开启事务:`begin → txId`。 */
|
|
@@ -4535,21 +4595,35 @@ function unsafeOperation(message) {
|
|
|
4535
4595
|
function stripLiterals(sql) {
|
|
4536
4596
|
return sql.replace(/'[^']*(?:''[^']*)*'/g, "").replace(/"[^"]*(?:""[^"]*)*"/g, "").replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
4537
4597
|
}
|
|
4538
|
-
function
|
|
4598
|
+
function sqlHead(sql) {
|
|
4599
|
+
return sql.trim().replace(/^\(+/, "").trim().toUpperCase();
|
|
4600
|
+
}
|
|
4601
|
+
function assertSafeStatement(sql) {
|
|
4539
4602
|
const stripped = stripLiterals(sql);
|
|
4540
4603
|
if (stripped.includes(";")) {
|
|
4541
4604
|
throw unsafeOperation("\u4EC5\u5141\u8BB8\u5355\u6761\u8BED\u53E5\uFF0C\u7981\u6B62\u591A\u8BED\u53E5\u5806\u53E0");
|
|
4542
4605
|
}
|
|
4543
|
-
const head = stripped.trim().replace(/^\(+/, "").trim().toUpperCase();
|
|
4544
|
-
if (!head.startsWith("SELECT") && !head.startsWith("WITH")) {
|
|
4545
|
-
throw unsafeOperation("cloud.db.query \u4EC5\u5141\u8BB8\u53EA\u8BFB\u67E5\u8BE2\uFF08SELECT / WITH\uFF09");
|
|
4546
|
-
}
|
|
4547
4606
|
if (/ATTACH|DETACH/.test(stripped.toUpperCase())) {
|
|
4548
4607
|
throw unsafeOperation("\u7981\u6B62\u8DE8\u5E93\u64CD\u4F5C\uFF08ATTACH / DETACH\uFF09");
|
|
4549
4608
|
}
|
|
4550
4609
|
if (/SQLITE_\w+/i.test(stripped)) {
|
|
4551
4610
|
throw unsafeOperation("\u7981\u6B62\u8BBF\u95EE\u7CFB\u7EDF\u8868\uFF08sqlite_*\uFF09");
|
|
4552
4611
|
}
|
|
4612
|
+
return sqlHead(stripped);
|
|
4613
|
+
}
|
|
4614
|
+
function assertReadOnlyQuery(sql) {
|
|
4615
|
+
const head = assertSafeStatement(sql);
|
|
4616
|
+
if (!head.startsWith("SELECT") && !head.startsWith("WITH")) {
|
|
4617
|
+
throw unsafeOperation("cloud.db.query \u4EC5\u5141\u8BB8\u53EA\u8BFB\u67E5\u8BE2\uFF08SELECT / WITH\uFF09");
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
function assertWriteQuery(sql) {
|
|
4621
|
+
const head = assertSafeStatement(sql);
|
|
4622
|
+
if (!head.startsWith("INSERT") && !head.startsWith("UPDATE") && !head.startsWith("DELETE")) {
|
|
4623
|
+
throw unsafeOperation(
|
|
4624
|
+
"cloud.db.writeQuery \u4EC5\u5141\u8BB8 DML\uFF08INSERT / UPDATE / DELETE\uFF09\uFF0CDDL \u8BF7\u8D70\u63A7\u5236\u53F0"
|
|
4625
|
+
);
|
|
4626
|
+
}
|
|
4553
4627
|
}
|
|
4554
4628
|
|
|
4555
4629
|
// packages/runtime/src/database/builder/owned.ts
|
|
@@ -5095,6 +5169,14 @@ function createCloudDb(driver, options = {}) {
|
|
|
5095
5169
|
assertReadOnlyQuery(sql);
|
|
5096
5170
|
return driver.all(sql, params);
|
|
5097
5171
|
},
|
|
5172
|
+
async writeQuery(sql, params) {
|
|
5173
|
+
if (!Array.isArray(params)) {
|
|
5174
|
+
throw unsafeOperation("writeQuery \u7684 params \u5FC5\u987B\u63D0\u4F9B\uFF08\u65E0\u53C2\u4F20 []\uFF09");
|
|
5175
|
+
}
|
|
5176
|
+
guardWrite();
|
|
5177
|
+
assertWriteQuery(sql);
|
|
5178
|
+
return driver.run(sql, params);
|
|
5179
|
+
},
|
|
5098
5180
|
async changes(table, query = {}) {
|
|
5099
5181
|
return readChanges(driver, table, query);
|
|
5100
5182
|
}
|
|
@@ -5110,7 +5192,8 @@ var CLOUD_DB_SPEC = {
|
|
|
5110
5192
|
rootMethod: "table",
|
|
5111
5193
|
stepMethods: ["select", "where", "orderBy", "limit", "offset"],
|
|
5112
5194
|
terminalMethods: ["get", "first", "count", "insert", "insertMany", "update", "delete"],
|
|
5113
|
-
|
|
5195
|
+
// CF-013:writeQuery 是 D1 shim 的写路径(INSERT/UPDATE/DELETE),与 query 并列直通方法。
|
|
5196
|
+
directMethods: ["query", "writeQuery", "changes"],
|
|
5114
5197
|
transactionMethod: "transaction"
|
|
5115
5198
|
};
|
|
5116
5199
|
var WRITE_TERMINALS = /* @__PURE__ */ new Set(["insert", "insertMany", "update", "delete"]);
|
|
@@ -5165,6 +5248,10 @@ function createDbCapability(driver, options = {}) {
|
|
|
5165
5248
|
const [sql, params] = args;
|
|
5166
5249
|
return await db.query(sql, params);
|
|
5167
5250
|
}
|
|
5251
|
+
case DB_RPC.writeQuery: {
|
|
5252
|
+
const [sql, params] = args;
|
|
5253
|
+
return await db.writeQuery(sql, params);
|
|
5254
|
+
}
|
|
5168
5255
|
case DB_RPC.changes: {
|
|
5169
5256
|
const [table, query] = args;
|
|
5170
5257
|
return await db.changes(table, query);
|
|
@@ -5894,9 +5981,12 @@ function createStorageCapability(driver, signer, projectId) {
|
|
|
5894
5981
|
const handler = async (method, args) => {
|
|
5895
5982
|
switch (method) {
|
|
5896
5983
|
case "upload": {
|
|
5897
|
-
const [path, data] = args;
|
|
5984
|
+
const [path, data, options] = args;
|
|
5898
5985
|
return toStoredFile(
|
|
5899
|
-
await driver.put(projectId, path, asBytes(data), {
|
|
5986
|
+
await driver.put(projectId, path, asBytes(data), {
|
|
5987
|
+
visibility: DEFAULT_VISIBILITY,
|
|
5988
|
+
...options?.contentType === void 0 ? {} : { contentType: options.contentType }
|
|
5989
|
+
})
|
|
5900
5990
|
);
|
|
5901
5991
|
}
|
|
5902
5992
|
case "get": {
|
|
@@ -6343,6 +6433,10 @@ var KNOWN_CAPABILITY_HINTS = {
|
|
|
6343
6433
|
realtime: {
|
|
6344
6434
|
code: "REALTIME_NOT_AVAILABLE",
|
|
6345
6435
|
message: "\u5B9E\u65F6\u901A\u9053\u672A\u88C5\u914D\uFF1Arealtime \u57DF\u672A\u88C5\u8F7D\uFF08\u68C0\u67E5\u90E8\u7F72\u5F62\u6001\u4E0E Redis \u914D\u7F6E\uFF09\uFF08REALTIME_NOT_AVAILABLE\uFF09"
|
|
6436
|
+
},
|
|
6437
|
+
kv: {
|
|
6438
|
+
code: "KV_NOT_PROVISIONED",
|
|
6439
|
+
message: "\u9879\u76EE KV \u5B58\u50A8\u672A\u53EF\u7528\uFF1Akv \u968F\u9879\u76EE\u6570\u636E\u5E93\u63D0\u4F9B\uFF0C\u8BF7\u5148\u542F\u52A8\u6570\u636E\u5E93\uFF08KV_NOT_PROVISIONED\uFF09"
|
|
6346
6440
|
}
|
|
6347
6441
|
};
|
|
6348
6442
|
var CapabilityNotRegisteredError = class extends Error {
|
|
@@ -6655,6 +6749,106 @@ function createOfflineFunctionRunner(options = {}) {
|
|
|
6655
6749
|
return { run };
|
|
6656
6750
|
}
|
|
6657
6751
|
|
|
6752
|
+
// packages/runtime/src/database/sdk/kv.ts
|
|
6753
|
+
var KV_TABLE = "_adep_kv";
|
|
6754
|
+
var KV_RPC = {
|
|
6755
|
+
get: "get",
|
|
6756
|
+
put: "put",
|
|
6757
|
+
delete: "delete",
|
|
6758
|
+
list: "list"
|
|
6759
|
+
};
|
|
6760
|
+
var KV_CAPABILITY_CODES = {
|
|
6761
|
+
invalidMethod: "KV_INVALID_METHOD"
|
|
6762
|
+
};
|
|
6763
|
+
var KV_LIST_DEFAULT_LIMIT = 100;
|
|
6764
|
+
function nowSeconds() {
|
|
6765
|
+
return Math.floor(Date.now() / 1e3);
|
|
6766
|
+
}
|
|
6767
|
+
function errorWithCode2(error) {
|
|
6768
|
+
const code = typeof error === "object" && error !== null && typeof error.code === "string" ? error.code : void 0;
|
|
6769
|
+
if (code !== void 0 && error instanceof Error) {
|
|
6770
|
+
return new Error(`[${code}] ${error.message}`);
|
|
6771
|
+
}
|
|
6772
|
+
return error;
|
|
6773
|
+
}
|
|
6774
|
+
function createKvCapability(driver) {
|
|
6775
|
+
let ensurePromise = null;
|
|
6776
|
+
const ensureTable = () => {
|
|
6777
|
+
if (ensurePromise === null) {
|
|
6778
|
+
ensurePromise = driver.run(
|
|
6779
|
+
`CREATE TABLE IF NOT EXISTS ${KV_TABLE} (key TEXT PRIMARY KEY, value TEXT, expires_at INTEGER)`
|
|
6780
|
+
).then(() => void 0);
|
|
6781
|
+
}
|
|
6782
|
+
return ensurePromise;
|
|
6783
|
+
};
|
|
6784
|
+
const handler = async (method, args) => {
|
|
6785
|
+
try {
|
|
6786
|
+
await ensureTable();
|
|
6787
|
+
switch (method) {
|
|
6788
|
+
case KV_RPC.get: {
|
|
6789
|
+
const [key] = args;
|
|
6790
|
+
const row = await driver.get(`SELECT value, expires_at FROM ${KV_TABLE} WHERE key = ?`, [
|
|
6791
|
+
key
|
|
6792
|
+
]);
|
|
6793
|
+
if (row === null || row === void 0) return null;
|
|
6794
|
+
const expiresAt = row.expires_at;
|
|
6795
|
+
if (expiresAt !== null && expiresAt !== void 0 && Number(expiresAt) <= nowSeconds()) {
|
|
6796
|
+
return null;
|
|
6797
|
+
}
|
|
6798
|
+
return row.value;
|
|
6799
|
+
}
|
|
6800
|
+
case KV_RPC.put: {
|
|
6801
|
+
const [key, value, options] = args;
|
|
6802
|
+
const ttl = options?.expirationTtlSeconds;
|
|
6803
|
+
const expiresAt = typeof ttl === "number" && ttl > 0 ? nowSeconds() + Math.floor(ttl) : null;
|
|
6804
|
+
await driver.run(`DELETE FROM ${KV_TABLE} WHERE key = ?`, [key]);
|
|
6805
|
+
await driver.run(`INSERT INTO ${KV_TABLE} (key, value, expires_at) VALUES (?, ?, ?)`, [
|
|
6806
|
+
key,
|
|
6807
|
+
value,
|
|
6808
|
+
expiresAt
|
|
6809
|
+
]);
|
|
6810
|
+
return void 0;
|
|
6811
|
+
}
|
|
6812
|
+
case KV_RPC.delete: {
|
|
6813
|
+
const [key] = args;
|
|
6814
|
+
await driver.run(`DELETE FROM ${KV_TABLE} WHERE key = ?`, [key]);
|
|
6815
|
+
return void 0;
|
|
6816
|
+
}
|
|
6817
|
+
case KV_RPC.list: {
|
|
6818
|
+
const [options] = args;
|
|
6819
|
+
const prefix = options?.prefix ?? "";
|
|
6820
|
+
const limit = options?.limit ?? KV_LIST_DEFAULT_LIMIT;
|
|
6821
|
+
const rows = prefix === "" ? await driver.all(`SELECT key, expires_at FROM ${KV_TABLE}`) : await driver.all(`SELECT key, expires_at FROM ${KV_TABLE} WHERE key LIKE ?`, [
|
|
6822
|
+
`${prefix}%`
|
|
6823
|
+
]);
|
|
6824
|
+
const now = nowSeconds();
|
|
6825
|
+
const entries = [];
|
|
6826
|
+
for (const row of rows) {
|
|
6827
|
+
const expiresAt = row.expires_at;
|
|
6828
|
+
if (expiresAt !== null && expiresAt !== void 0 && Number(expiresAt) <= now) continue;
|
|
6829
|
+
entries.push({
|
|
6830
|
+
name: String(row.key),
|
|
6831
|
+
expiration: expiresAt === null || expiresAt === void 0 ? null : Number(expiresAt)
|
|
6832
|
+
});
|
|
6833
|
+
if (entries.length >= limit) break;
|
|
6834
|
+
}
|
|
6835
|
+
return entries;
|
|
6836
|
+
}
|
|
6837
|
+
default:
|
|
6838
|
+
throw new Error(
|
|
6839
|
+
`\u672A\u77E5\u7684 cloud.kv \u65B9\u6CD5 "${String(method)}"\uFF08${KV_CAPABILITY_CODES.invalidMethod}\uFF09`
|
|
6840
|
+
);
|
|
6841
|
+
}
|
|
6842
|
+
} catch (error) {
|
|
6843
|
+
throw errorWithCode2(error);
|
|
6844
|
+
}
|
|
6845
|
+
};
|
|
6846
|
+
return {
|
|
6847
|
+
capabilities: [{ name: "kv", value: { [RPC_CAPABILITY_KEY]: true } }],
|
|
6848
|
+
rpcHandlers: { kv: handler }
|
|
6849
|
+
};
|
|
6850
|
+
}
|
|
6851
|
+
|
|
6658
6852
|
// packages/web-container/src/sim/runtime.ts
|
|
6659
6853
|
function mergeBundles(bundles) {
|
|
6660
6854
|
const capabilities = [];
|
|
@@ -6689,7 +6883,8 @@ async function createBrowserSimRuntime(options) {
|
|
|
6689
6883
|
projectId: options.projectId,
|
|
6690
6884
|
...options.realtime === void 0 ? {} : options.realtime
|
|
6691
6885
|
});
|
|
6692
|
-
const
|
|
6886
|
+
const kvBundle = createKvCapability(db.driver);
|
|
6887
|
+
const bundle = mergeBundles([db.bundle, storage.bundle, kvBundle, realtime.bundle]);
|
|
6693
6888
|
await db.engine.load();
|
|
6694
6889
|
const runner = createOfflineFunctionRunner(options.runner ?? {});
|
|
6695
6890
|
return {
|
package/dist/vite-dev.d.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* (真 live binding、真模块隔离),不是 CJS 打平;
|
|
12
12
|
* - **转换**:`.ts` 复用 stripTypes 擦类型;`.css` 变成「注入 `<style>` 的副作用模块」;
|
|
13
13
|
* `.json` 变成默认导出对象;`.vue` 经注入的 SFC 编译器(IDE 侧装 `vue/compiler-sfc`);
|
|
14
|
+
* JS 系产物统一过 define 替换(`process.env.NODE_ENV` / `__VUE_*__`),让 esm-bundler
|
|
15
|
+
* 构建(vue 等)在无打包器的浏览器里也能跑;
|
|
14
16
|
* - **依赖**:裸说明符经 node-resolve 命中 VFS `node_modules/`(终端 `npm install` 的产物),
|
|
15
17
|
* 与 CLI / 线上同一套解析规则;相对说明符支持 Vite 风格省略扩展名(.ts/.js/.vue/…);
|
|
16
18
|
* - **HMR**:订阅 VFS 变更(`vfs.onMutate`,IDE 保存 / shell 写入 / npm 解包皆触发)→
|