@adep/cli 0.4.6 → 0.4.11
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/README.md +44 -3
- package/dist/index.js +797 -410
- package/dist/vite.js +180 -33
- package/package.json +4 -4
package/dist/vite.js
CHANGED
|
@@ -1090,6 +1090,20 @@ var CLOUD_DB_SPEC = {
|
|
|
1090
1090
|
};
|
|
1091
1091
|
var WRITE_TERMINALS = /* @__PURE__ */ new Set(["insert", "insertMany", "update", "delete"]);
|
|
1092
1092
|
function errorWithCode(error) {
|
|
1093
|
+
if (error instanceof Error) {
|
|
1094
|
+
const sqlite = /no such table: (\S+)/.exec(error.message);
|
|
1095
|
+
if (sqlite !== null) {
|
|
1096
|
+
return new Error(
|
|
1097
|
+
`[DB_TABLE_MISSING] \u9879\u76EE\u5E93\u5DF2\u542F\u52A8\u4F46\u7F3A\u8868 "${sqlite[1]}"\uFF1A\u8BF7\u6267\u884C adep db migrate <schema.sql> \u5EFA\u8868\uFF08\u53D1\u5E03\u4E0D\u542B\u5EFA\u8868\uFF09\u3002\u539F\u59CB\u9519\u8BEF\uFF1A${error.message}`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
const pg = /relation "([^"]+)" does not exist/.exec(error.message);
|
|
1101
|
+
if (pg !== null) {
|
|
1102
|
+
return new Error(
|
|
1103
|
+
`[DB_TABLE_MISSING] \u9879\u76EE\u5E93\u5DF2\u542F\u52A8\u4F46\u7F3A\u8868\uFF08\u6216\u5173\u7CFB\uFF09"${pg[1]}"\uFF1A\u8BF7\u6267\u884C adep db migrate <schema.sql> \u5EFA\u8868\uFF08\u53D1\u5E03\u4E0D\u542B\u5EFA\u8868\uFF09\u3002\u539F\u59CB\u9519\u8BEF\uFF1A${error.message}`
|
|
1104
|
+
);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1093
1107
|
const code = typeof error === "object" && error !== null && typeof error.code === "string" ? error.code : void 0;
|
|
1094
1108
|
if (code !== void 0 && error instanceof Error) {
|
|
1095
1109
|
return new Error(`[${code}] ${error.message}`);
|
|
@@ -2742,7 +2756,7 @@ async function createSimRuntime(options) {
|
|
|
2742
2756
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
2743
2757
|
import { join as join5, relative, resolve as resolve3 } from "node:path";
|
|
2744
2758
|
|
|
2745
|
-
// packages/
|
|
2759
|
+
// packages/runtime/src/shared/sql-split.ts
|
|
2746
2760
|
function splitSqlStatements(source) {
|
|
2747
2761
|
const statements = [];
|
|
2748
2762
|
let buffer = "";
|
|
@@ -2751,12 +2765,13 @@ function splitSqlStatements(source) {
|
|
|
2751
2765
|
for (const rawLine of lines) {
|
|
2752
2766
|
const trimmed = rawLine.trim();
|
|
2753
2767
|
if (!inQuote && (trimmed.length === 0 || trimmed.startsWith("--"))) continue;
|
|
2754
|
-
|
|
2755
|
-
|
|
2768
|
+
const scanLine = inQuote ? rawLine : trimmed;
|
|
2769
|
+
for (let i = 0; i < scanLine.length; i++) {
|
|
2770
|
+
const ch = scanLine[i];
|
|
2756
2771
|
if (inQuote) {
|
|
2757
2772
|
if (ch === "'") {
|
|
2758
|
-
if (
|
|
2759
|
-
buffer += ch +
|
|
2773
|
+
if (scanLine[i + 1] === "'") {
|
|
2774
|
+
buffer += ch + scanLine[i + 1];
|
|
2760
2775
|
i++;
|
|
2761
2776
|
continue;
|
|
2762
2777
|
}
|
|
@@ -2770,7 +2785,7 @@ function splitSqlStatements(source) {
|
|
|
2770
2785
|
buffer += ch;
|
|
2771
2786
|
continue;
|
|
2772
2787
|
}
|
|
2773
|
-
if (ch === "-" &&
|
|
2788
|
+
if (ch === "-" && scanLine[i + 1] === "-") break;
|
|
2774
2789
|
if (ch === ";") {
|
|
2775
2790
|
const statement = buffer.trim();
|
|
2776
2791
|
if (statement.length > 0) statements.push(statement);
|
|
@@ -2779,10 +2794,14 @@ function splitSqlStatements(source) {
|
|
|
2779
2794
|
}
|
|
2780
2795
|
buffer += ch;
|
|
2781
2796
|
}
|
|
2782
|
-
|
|
2797
|
+
if (inQuote) {
|
|
2798
|
+
buffer += "\n";
|
|
2799
|
+
} else if (buffer.length > 0 && !/\s$/.test(buffer)) {
|
|
2800
|
+
buffer += " ";
|
|
2801
|
+
}
|
|
2783
2802
|
}
|
|
2784
2803
|
if (inQuote) {
|
|
2785
|
-
throw new Error(`SQL \
|
|
2804
|
+
throw new Error(`SQL \u811A\u672C\u5F15\u53F7\u672A\u95ED\u5408\uFF1A${buffer.trim().slice(0, 80)}\u2026`);
|
|
2786
2805
|
}
|
|
2787
2806
|
const tail = buffer.trim();
|
|
2788
2807
|
if (tail.length > 0) statements.push(tail);
|
|
@@ -4842,12 +4861,120 @@ function mergeSharedSource(files, shared) {
|
|
|
4842
4861
|
return merged;
|
|
4843
4862
|
}
|
|
4844
4863
|
|
|
4864
|
+
// packages/runtime/src/shared/multipart.ts
|
|
4865
|
+
var MultipartParseError = class extends Error {
|
|
4866
|
+
constructor(message) {
|
|
4867
|
+
super(message);
|
|
4868
|
+
this.name = "MultipartParseError";
|
|
4869
|
+
}
|
|
4870
|
+
};
|
|
4871
|
+
function extractBoundary(contentType) {
|
|
4872
|
+
const match = /boundary\s*=\s*(?:"([^"]+)"|([^;\s]+))/i.exec(contentType);
|
|
4873
|
+
if (match === null) {
|
|
4874
|
+
throw new MultipartParseError("Content-Type \u7F3A\u5C11 boundary \u53C2\u6570\uFF0C\u65E0\u6CD5\u89E3\u6790 multipart \u8BF7\u6C42\u4F53");
|
|
4875
|
+
}
|
|
4876
|
+
const boundary = match[1] ?? match[2];
|
|
4877
|
+
if (boundary === void 0 || boundary.length === 0) {
|
|
4878
|
+
throw new MultipartParseError("Content-Type \u7684 boundary \u4E3A\u7A7A");
|
|
4879
|
+
}
|
|
4880
|
+
return boundary;
|
|
4881
|
+
}
|
|
4882
|
+
var HEADER_BODY_SEP = [13, 10, 13, 10];
|
|
4883
|
+
var encoder2 = new TextEncoder();
|
|
4884
|
+
var decoder2 = new TextDecoder();
|
|
4885
|
+
function indexOfSequence(haystack, needle, from) {
|
|
4886
|
+
outer: for (let i = from; i + needle.length <= haystack.length; i++) {
|
|
4887
|
+
for (let j = 0; j < needle.length; j++) {
|
|
4888
|
+
if (haystack[i + j] !== needle[j]) continue outer;
|
|
4889
|
+
}
|
|
4890
|
+
return i;
|
|
4891
|
+
}
|
|
4892
|
+
return -1;
|
|
4893
|
+
}
|
|
4894
|
+
function unquote(value) {
|
|
4895
|
+
return value.replace(/\\(.)/g, "$1");
|
|
4896
|
+
}
|
|
4897
|
+
function parseMultipart(contentType, raw) {
|
|
4898
|
+
const boundary = extractBoundary(contentType);
|
|
4899
|
+
const delim = encoder2.encode(`--${boundary}`);
|
|
4900
|
+
const positions = [];
|
|
4901
|
+
scan: for (let i = 0; i + delim.length <= raw.length; i++) {
|
|
4902
|
+
if (raw[i] !== delim[0]) continue;
|
|
4903
|
+
for (let j = 1; j < delim.length; j++) {
|
|
4904
|
+
if (raw[i + j] !== delim[j]) continue scan;
|
|
4905
|
+
}
|
|
4906
|
+
positions.push(i);
|
|
4907
|
+
}
|
|
4908
|
+
if (positions.length === 0) {
|
|
4909
|
+
throw new MultipartParseError(
|
|
4910
|
+
`\u8BF7\u6C42\u4F53\u91CC\u627E\u4E0D\u5230 boundary "${boundary}" \u7684\u5206\u9694\u7B26\u2014\u2014\u53EF\u80FD\u662F\u8BF7\u6C42\u88AB\u622A\u65AD\u6216 Content-Type \u4E0E\u8BF7\u6C42\u4F53\u4E0D\u5339\u914D`
|
|
4911
|
+
);
|
|
4912
|
+
}
|
|
4913
|
+
const lastPos = positions[positions.length - 1];
|
|
4914
|
+
if (raw[lastPos + delim.length] !== 45 || raw[lastPos + delim.length + 1] !== 45) {
|
|
4915
|
+
throw new MultipartParseError("multipart \u6570\u636E\u88AB\u622A\u65AD\uFF1A\u7F3A\u5C11\u7EC8\u7ED3\u5206\u9694\u7B26 --boundary--");
|
|
4916
|
+
}
|
|
4917
|
+
const files = [];
|
|
4918
|
+
const fields = {};
|
|
4919
|
+
let fieldCount = 0;
|
|
4920
|
+
for (let k = 0; k + 1 < positions.length; k++) {
|
|
4921
|
+
const partStart = positions[k] + delim.length + 2;
|
|
4922
|
+
const partEnd = positions[k + 1] - 2;
|
|
4923
|
+
if (raw[partStart - 2] !== 13 || raw[partStart - 1] !== 10) {
|
|
4924
|
+
throw new MultipartParseError("multipart \u5206\u9694\u7B26\u540E\u7F3A\u5C11 CRLF\uFF0C\u8BF7\u6C42\u4F53\u683C\u5F0F\u975E\u6CD5");
|
|
4925
|
+
}
|
|
4926
|
+
if (partEnd < partStart) {
|
|
4927
|
+
throw new MultipartParseError("multipart part \u5185\u5BB9\u4E3A\u7A7A\uFF08header \u4E0E\u6B63\u6587\u90FD\u4E0D\u5B58\u5728\uFF09");
|
|
4928
|
+
}
|
|
4929
|
+
const part = raw.subarray(partStart, partEnd);
|
|
4930
|
+
const headerSep = indexOfSequence(part, HEADER_BODY_SEP, 0);
|
|
4931
|
+
if (headerSep < 0) {
|
|
4932
|
+
throw new MultipartParseError("multipart part \u7F3A\u5C11 header \u4E0E\u6B63\u6587\u4E4B\u95F4\u7684\u7A7A\u884C\u5206\u9694");
|
|
4933
|
+
}
|
|
4934
|
+
const headerLines = decoder2.decode(part.subarray(0, headerSep)).split("\r\n");
|
|
4935
|
+
const data = part.subarray(headerSep + HEADER_BODY_SEP.length);
|
|
4936
|
+
const disposition = headerLines.find(
|
|
4937
|
+
(line) => line.toLowerCase().startsWith("content-disposition:")
|
|
4938
|
+
);
|
|
4939
|
+
if (disposition === void 0) {
|
|
4940
|
+
throw new MultipartParseError("multipart part \u7F3A\u5C11 Content-Disposition \u5934");
|
|
4941
|
+
}
|
|
4942
|
+
const nameMatch = /name="((?:[^"\\]|\\.)*)"/.exec(disposition);
|
|
4943
|
+
if (nameMatch === null) {
|
|
4944
|
+
throw new MultipartParseError("multipart part \u7684 Content-Disposition \u7F3A\u5C11 name \u53C2\u6570");
|
|
4945
|
+
}
|
|
4946
|
+
const fieldName = unquote(nameMatch[1]);
|
|
4947
|
+
const filenameMatch = /filename="((?:[^"\\]|\\.)*)"/.exec(disposition);
|
|
4948
|
+
if (filenameMatch !== null) {
|
|
4949
|
+
const clientName = unquote(filenameMatch[1]);
|
|
4950
|
+
if (clientName === "") continue;
|
|
4951
|
+
const typeLine = headerLines.find((line) => line.toLowerCase().startsWith("content-type:"));
|
|
4952
|
+
const type = typeLine === void 0 ? "application/octet-stream" : typeLine.slice(typeLine.indexOf(":") + 1).trim();
|
|
4953
|
+
files.push({ name: clientName, type, size: data.length, data });
|
|
4954
|
+
} else {
|
|
4955
|
+
const value = decoder2.decode(data);
|
|
4956
|
+
const prev = fields[fieldName];
|
|
4957
|
+
if (prev === void 0) fields[fieldName] = value;
|
|
4958
|
+
else if (typeof prev === "string") fields[fieldName] = [prev, value];
|
|
4959
|
+
else fields[fieldName] = [...prev, value];
|
|
4960
|
+
fieldCount++;
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
return { fields: fieldCount > 0 ? fields : void 0, files };
|
|
4964
|
+
}
|
|
4965
|
+
|
|
4845
4966
|
// packages/cli/src/dev-shared.ts
|
|
4846
4967
|
var BEARER_TOKEN_RE = /^Bearer\s+(.+)$/i;
|
|
4847
|
-
function bearerUserResolverFromEnv() {
|
|
4848
|
-
const raw = process.env.ADEP_AUTH_ISSUER;
|
|
4849
|
-
|
|
4850
|
-
|
|
4968
|
+
function bearerUserResolverFromEnv(fileEnv = {}) {
|
|
4969
|
+
const raw = firstNonEmpty(process.env.ADEP_AUTH_ISSUER, fileEnv.ADEP_AUTH_ISSUER);
|
|
4970
|
+
return raw === void 0 ? void 0 : createBearerUserResolver(raw);
|
|
4971
|
+
}
|
|
4972
|
+
function firstNonEmpty(...values) {
|
|
4973
|
+
for (const value of values) {
|
|
4974
|
+
const trimmed = value?.trim();
|
|
4975
|
+
if (trimmed !== void 0 && trimmed !== "") return trimmed;
|
|
4976
|
+
}
|
|
4977
|
+
return void 0;
|
|
4851
4978
|
}
|
|
4852
4979
|
function createBearerUserResolver(issuer) {
|
|
4853
4980
|
const userinfoUrl = `${issuer.replace(/\/+$/, "")}/oauth/userinfo`;
|
|
@@ -4914,25 +5041,41 @@ function mergeSharedIntoFunctions(files) {
|
|
|
4914
5041
|
}
|
|
4915
5042
|
return out;
|
|
4916
5043
|
}
|
|
4917
|
-
function
|
|
4918
|
-
return new Promise((
|
|
5044
|
+
function readRawBody(req) {
|
|
5045
|
+
return new Promise((resolveRaw, rejectRaw) => {
|
|
4919
5046
|
const chunks = [];
|
|
4920
5047
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
4921
|
-
req.on("end", () =>
|
|
4922
|
-
|
|
4923
|
-
if (raw.length === 0) {
|
|
4924
|
-
resolveBody(void 0);
|
|
4925
|
-
return;
|
|
4926
|
-
}
|
|
4927
|
-
try {
|
|
4928
|
-
resolveBody(JSON.parse(raw));
|
|
4929
|
-
} catch {
|
|
4930
|
-
resolveBody(raw);
|
|
4931
|
-
}
|
|
4932
|
-
});
|
|
4933
|
-
req.on("error", rejectBody);
|
|
5048
|
+
req.on("end", () => resolveRaw(Buffer.concat(chunks)));
|
|
5049
|
+
req.on("error", rejectRaw);
|
|
4934
5050
|
});
|
|
4935
5051
|
}
|
|
5052
|
+
async function bodyOf(req) {
|
|
5053
|
+
const raw = (await readRawBody(req)).toString("utf8");
|
|
5054
|
+
if (raw.length === 0) return void 0;
|
|
5055
|
+
try {
|
|
5056
|
+
return JSON.parse(raw);
|
|
5057
|
+
} catch {
|
|
5058
|
+
return raw;
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
async function bodyWithFiles(req) {
|
|
5062
|
+
const contentType = String(req.headers["content-type"] ?? "");
|
|
5063
|
+
if (!contentType.toLowerCase().startsWith("multipart/form-data")) {
|
|
5064
|
+
return { body: await bodyOf(req) };
|
|
5065
|
+
}
|
|
5066
|
+
const bytes = await readRawBody(req);
|
|
5067
|
+
let parsed;
|
|
5068
|
+
try {
|
|
5069
|
+
parsed = parseMultipart(contentType, bytes);
|
|
5070
|
+
} catch (error) {
|
|
5071
|
+
const message = error instanceof MultipartParseError ? error.message : `multipart \u89E3\u6790\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`;
|
|
5072
|
+
throw new ExecutorError(400, "FN_MULTIPART_INVALID", message);
|
|
5073
|
+
}
|
|
5074
|
+
return {
|
|
5075
|
+
body: parsed.fields,
|
|
5076
|
+
...parsed.files.length > 0 ? { files: [...parsed.files] } : {}
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
4936
5079
|
function writeJson(res, status, payload) {
|
|
4937
5080
|
res.writeHead(status, { "content-type": "application/json" });
|
|
4938
5081
|
res.end(JSON.stringify(payload));
|
|
@@ -4947,13 +5090,14 @@ async function requestInput(url, req, readBody) {
|
|
|
4947
5090
|
for (const [key, value] of Object.entries(req.headers)) {
|
|
4948
5091
|
if (typeof value === "string") headers[key] = value;
|
|
4949
5092
|
}
|
|
4950
|
-
const
|
|
5093
|
+
const parsed = req.method === "GET" || req.method === "HEAD" ? void 0 : await readBody(req);
|
|
4951
5094
|
return {
|
|
4952
5095
|
method: req.method ?? "GET",
|
|
4953
5096
|
path: url.pathname,
|
|
4954
5097
|
query,
|
|
4955
5098
|
headers,
|
|
4956
|
-
...body === void 0 ? {} : { body }
|
|
5099
|
+
...parsed?.body === void 0 ? {} : { body: parsed.body },
|
|
5100
|
+
...parsed?.files === void 0 ? {} : { files: parsed.files }
|
|
4957
5101
|
};
|
|
4958
5102
|
}
|
|
4959
5103
|
|
|
@@ -5024,8 +5168,8 @@ async function startDevServer(options) {
|
|
|
5024
5168
|
...options.db === void 0 ? {} : { db: options.db },
|
|
5025
5169
|
...options.dbFile === void 0 ? {} : { dbFile: options.dbFile }
|
|
5026
5170
|
});
|
|
5027
|
-
const bearerUser = bearerUserResolverFromEnv();
|
|
5028
5171
|
const simEnv = await loadSimEnv(cwd).catch(() => ({}));
|
|
5172
|
+
let bearerUser = bearerUserResolverFromEnv(simEnv);
|
|
5029
5173
|
const fetchConfig = resolveLocalFetchConfig(simEnv);
|
|
5030
5174
|
const executor = new WorkerFunctionExecutor({
|
|
5031
5175
|
deps: { rootDir: cwd, builtin: LOCAL_BUILTIN_DEPS },
|
|
@@ -5139,6 +5283,7 @@ async function startDevServer(options) {
|
|
|
5139
5283
|
]);
|
|
5140
5284
|
files = nextFiles;
|
|
5141
5285
|
env = { ...config.environment, ...parseEnvFile(envText2) };
|
|
5286
|
+
bearerUser = bearerUserResolverFromEnv(await loadSimEnv(cwd).catch(() => ({})));
|
|
5142
5287
|
};
|
|
5143
5288
|
const envText = await readFile7(join10(cwd, ".env.local"), "utf8").catch(() => "");
|
|
5144
5289
|
env = { ...config.environment, ...parseEnvFile(envText) };
|
|
@@ -5156,7 +5301,7 @@ async function startDevServer(options) {
|
|
|
5156
5301
|
}
|
|
5157
5302
|
const buildInput = async (fnName, entry, url, req) => {
|
|
5158
5303
|
const hasEnv = Object.keys(env).length > 0;
|
|
5159
|
-
const request = await requestInput(url, req,
|
|
5304
|
+
const request = await requestInput(url, req, bodyWithFiles);
|
|
5160
5305
|
if (bearerUser !== void 0) request.user = await bearerUser(request.headers);
|
|
5161
5306
|
return {
|
|
5162
5307
|
project: { id: "local", slug: config.name },
|
|
@@ -5230,9 +5375,9 @@ async function startDevServer(options) {
|
|
|
5230
5375
|
writeJson(res, 404, { error: { code: "FN_NOT_FOUND", message: `\u51FD\u6570 "${fnName}" \u4E0D\u5B58\u5728` } });
|
|
5231
5376
|
return;
|
|
5232
5377
|
}
|
|
5233
|
-
const input = await buildInput(fnName, entry, url, req);
|
|
5234
5378
|
const startedAt = performance.now();
|
|
5235
5379
|
try {
|
|
5380
|
+
const input = await buildInput(fnName, entry, url, req);
|
|
5236
5381
|
const result = await executor.execute(input);
|
|
5237
5382
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
5238
5383
|
for (const line of result.logs) log(`[adep] ${line}`);
|
|
@@ -5305,7 +5450,9 @@ async function startDevServer(options) {
|
|
|
5305
5450
|
log(`[adep] curl \u793A\u4F8B\uFF1Acurl ${baseUrl}${curlPath}`);
|
|
5306
5451
|
printBoundaries(log);
|
|
5307
5452
|
if (bearerUser !== void 0) {
|
|
5308
|
-
log(
|
|
5453
|
+
log(
|
|
5454
|
+
`[adep] \u767B\u5F55\u5373\u670D\u52A1\uFF1AADEP_AUTH_ISSUER \u5DF2\u914D\u7F6E\uFF0CBearer token \u5C06\u89E3\u6790\u4E3A\u7528\u6237\u8EAB\u4EFD\uFF08userinfo \u7AEF\u70B9\uFF09`
|
|
5455
|
+
);
|
|
5309
5456
|
}
|
|
5310
5457
|
log(`[adep] \u6570\u636E\u5E93\uFF1A${dbLabel} \u2192 ${dbTargetText}`);
|
|
5311
5458
|
startStateAlarmScheduler();
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"homepage": "https://adep.top",
|
|
9
9
|
"bugs": "https://gitcode.com/yunqiang_wu/ai-yunke/issues",
|
|
10
|
-
"version": "0.4.
|
|
10
|
+
"version": "0.4.11",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"description": "`adep` 命令行工具包位:登录 / 初始化 / 本地调试 / 部署 / 数据库维护 / 云存储 / 静态托管 / 微前端组件(widget),实现见任务单 CLI-001 ~ CLI-003 与 FE-002;子路径 `@adep/cli/vite` 提供云函数 vite 插件(CLI-014)",
|
|
13
13
|
"bin": {
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"esbuild": "0.25.12",
|
|
31
31
|
"yaml": "2.9.1",
|
|
32
32
|
"zod": "^4.6.6",
|
|
33
|
-
"@adep/runtime": "0.3.5",
|
|
34
33
|
"@adep/app-runtime": "0.1.1",
|
|
35
34
|
"@adep/cf-compat": "0.1.4",
|
|
36
|
-
"@adep/vite-plugin": "0.1.
|
|
37
|
-
"@adep/crypto": "0.1.1"
|
|
35
|
+
"@adep/vite-plugin": "0.1.11",
|
|
36
|
+
"@adep/crypto": "0.1.1",
|
|
37
|
+
"@adep/runtime": "0.3.7"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@adep/types": "0.3.2"
|