@lucent-lang/lucent 0.0.4
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/app.plugin.js +92 -0
- package/bin/lucent.cjs +16 -0
- package/core/index.cjs +11 -0
- package/dist/bench-CR3E7e2e.js +304 -0
- package/dist/build-CAIrRSYA.js +7 -0
- package/dist/build-check-QozuNJm5.js +92 -0
- package/dist/check-1SCmYlqA.js +7 -0
- package/dist/clean-BVwpbJ5K.js +35 -0
- package/dist/cli.js +406 -0
- package/dist/codes-CIuwXt1S.js +260 -0
- package/dist/compiler.js +4 -0
- package/dist/confirm-BYF5eY3q.js +34 -0
- package/dist/dashboard-B-NzjjaN.js +91 -0
- package/dist/dev-BYWMP7oC.js +221 -0
- package/dist/diagnostic-BM9sXmwl.js +30 -0
- package/dist/diff-BTDo3Sro.js +44 -0
- package/dist/doctor-C0PrfWT6.js +230 -0
- package/dist/doctor-DdR4JnVc.js +30 -0
- package/dist/explain--vV1oaRl.js +35 -0
- package/dist/format-D9fnIMEx.js +53 -0
- package/dist/init-gIabu1S_.js +207 -0
- package/dist/live-steps-BGcWFM9M.js +79 -0
- package/dist/new-module-C2mtb0op.js +66 -0
- package/dist/package-manager-BnxwCySi.js +30 -0
- package/dist/package.json +3 -0
- package/dist/packages-HyskKIsY.js +150 -0
- package/dist/pipeline-CH7-2cxu.js +232 -0
- package/dist/project-D8tEet0k.js +150 -0
- package/dist/sdk-coverage-BoW_3Efd.js +64 -0
- package/dist/sdk-prefetch-mo04JDZV.js +89 -0
- package/dist/sdk-search-Iv4K3-8a.js +124 -0
- package/dist/sdk-show-CkrdlqlP.js +74 -0
- package/dist/sdks-Xoyiy2E4.js +28 -0
- package/dist/src-BD7f1_aZ.js +11493 -0
- package/dist/steps--_h-FFS7.js +24 -0
- package/dist/theme-uv5bc0aK.js +134 -0
- package/dist/tsconfig-S4uyLNzf.js +59 -0
- package/dist/version-bqpIO5sP.js +26 -0
- package/gradle/lucent-classpath.gradle +38 -0
- package/gradle/lucent-classpath.init.gradle +6 -0
- package/gradle/lucent.gradle +24 -0
- package/lib/core.cjs +106 -0
- package/lib/globals.d.ts +36 -0
- package/lib/sdk/android.d.ts +8 -0
- package/lib/sdk/core.d.ts +23 -0
- package/lib/sdk/ios.d.ts +33 -0
- package/lib/sdk/platform.d.ts +8 -0
- package/lib/sdk/thread.d.ts +8 -0
- package/metro/index.cjs +72 -0
- package/metro/index.d.ts +6 -0
- package/metro/transformer.cjs +70 -0
- package/package.json +61 -0
- package/runtime/cpp/lucent/abort.cpp +61 -0
- package/runtime/cpp/lucent/abort.h +54 -0
- package/runtime/cpp/lucent/array.h +442 -0
- package/runtime/cpp/lucent/async.h +236 -0
- package/runtime/cpp/lucent/builtins.cpp +163 -0
- package/runtime/cpp/lucent/bytes.h +129 -0
- package/runtime/cpp/lucent/console.h +17 -0
- package/runtime/cpp/lucent/core.h +129 -0
- package/runtime/cpp/lucent/date.cpp +441 -0
- package/runtime/cpp/lucent/date.h +82 -0
- package/runtime/cpp/lucent/equality.h +87 -0
- package/runtime/cpp/lucent/function.h +61 -0
- package/runtime/cpp/lucent/generator.h +244 -0
- package/runtime/cpp/lucent/helpers.h +226 -0
- package/runtime/cpp/lucent/jserror.cpp +51 -0
- package/runtime/cpp/lucent/jserror.h +66 -0
- package/runtime/cpp/lucent/jsi/convert.cpp +202 -0
- package/runtime/cpp/lucent/jsi/convert.h +612 -0
- package/runtime/cpp/lucent/jsi/host.cpp +322 -0
- package/runtime/cpp/lucent/jsi/host.h +166 -0
- package/runtime/cpp/lucent/json.cpp +243 -0
- package/runtime/cpp/lucent/json.h +164 -0
- package/runtime/cpp/lucent/json_parse.h +138 -0
- package/runtime/cpp/lucent/jsstring.cpp +874 -0
- package/runtime/cpp/lucent/jsstring.h +152 -0
- package/runtime/cpp/lucent/lucent.h +24 -0
- package/runtime/cpp/lucent/map.h +344 -0
- package/runtime/cpp/lucent/native.cpp +76 -0
- package/runtime/cpp/lucent/native.h +116 -0
- package/runtime/cpp/lucent/number.cpp +545 -0
- package/runtime/cpp/lucent/number.h +190 -0
- package/runtime/cpp/lucent/ops.h +165 -0
- package/runtime/cpp/lucent/platform/android.cpp +437 -0
- package/runtime/cpp/lucent/platform/android.h +117 -0
- package/runtime/cpp/lucent/platform/ios.h +297 -0
- package/runtime/cpp/lucent/platform/ios.mm +31 -0
- package/runtime/cpp/lucent/regexp.cpp +440 -0
- package/runtime/cpp/lucent/regexp.h +107 -0
- package/runtime/cpp/lucent/scheduler.cpp +153 -0
- package/runtime/cpp/lucent/scheduler.h +160 -0
- package/runtime/cpp/lucent/unicode_data.inc +4051 -0
- package/runtime/cpp/rn/LucentModule.cpp +35 -0
- package/runtime/cpp/rn/LucentModule.h +37 -0
- package/runtime/cpp/third_party/quickjs/LICENSE +22 -0
- package/runtime/cpp/third_party/quickjs/README.md +11 -0
- package/runtime/cpp/third_party/quickjs/cutils.c +641 -0
- package/runtime/cpp/third_party/quickjs/cutils.h +457 -0
- package/runtime/cpp/third_party/quickjs/libregexp-opcode.h +73 -0
- package/runtime/cpp/third_party/quickjs/libregexp.c +3448 -0
- package/runtime/cpp/third_party/quickjs/libregexp.h +65 -0
- package/runtime/cpp/third_party/quickjs/libunicode-table.h +5206 -0
- package/runtime/cpp/third_party/quickjs/libunicode.c +2124 -0
- package/runtime/cpp/third_party/quickjs/libunicode.h +196 -0
- package/runtime/js/index.d.ts +7 -0
- package/runtime/js/index.js +60 -0
- package/runtime/native/LucentNative.podspec +28 -0
- package/runtime/native/android/CMakeLists.txt +51 -0
- package/runtime/native/android/build.gradle +22 -0
- package/runtime/native/android/include/lucentnative.h +16 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +25 -0
- package/runtime/native/android/src/main/java/dev/lucent/NativeProxy.java +132 -0
- package/runtime/native/ios/LucentRegistration.mm +23 -0
- package/runtime/native/package.json +6 -0
- package/runtime/native/react-native.config.js +19 -0
- package/runtime/test/jsi/harness.cpp +181 -0
- package/schemas/build.schema.json +152 -0
- package/schemas/check.schema.json +74 -0
- package/schemas/doctor.schema.json +40 -0
- package/schemas/lucent.schema.json +43 -0
- package/schemas/sdk-prefetch.schema.json +37 -0
- package/schemas/sdk-search.schema.json +54 -0
- package/ts-plugin/index.d.ts +4 -0
- package/ts-plugin/index.js +99 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { n as version } from "./version-bqpIO5sP.js";
|
|
2
|
+
import { i as table } from "./format-D9fnIMEx.js";
|
|
3
|
+
import { n as systemProbe, t as diagnose } from "./doctor-C0PrfWT6.js";
|
|
4
|
+
//#region src/cli/commands/doctor.ts
|
|
5
|
+
function run({ root, out }) {
|
|
6
|
+
const checks = diagnose(root, systemProbe(version()));
|
|
7
|
+
const failures = checks.filter((c) => c.status === "fail").length;
|
|
8
|
+
const warnings = checks.filter((c) => c.status === "warn").length;
|
|
9
|
+
if (out.json) {
|
|
10
|
+
out.data({
|
|
11
|
+
ok: failures === 0,
|
|
12
|
+
checks
|
|
13
|
+
});
|
|
14
|
+
return failures ? 1 : 0;
|
|
15
|
+
}
|
|
16
|
+
const t = out.theme;
|
|
17
|
+
const symbol = (c) => c.status === "ok" ? t.success(t.symbols.ok) : c.status === "fail" ? t.error(t.symbols.fail) : c.status === "warn" ? t.warn(t.symbols.warn) : t.dim(t.symbols.off);
|
|
18
|
+
out.print(`${t.brand(t.symbols.brand)} ${t.bold("lucent doctor")} ${t.dim(version())}\n`);
|
|
19
|
+
const rows = table(checks.map((c) => [`${symbol(c)} ${c.label}`, c.status === "skip" ? t.dim(c.detail) : c.detail]));
|
|
20
|
+
checks.forEach((c, i) => {
|
|
21
|
+
out.print(rows[i]);
|
|
22
|
+
if (c.fix) out.print(` ${c.status === "fail" ? t.error("fix") : t.warn("fix")} ${c.fix}`);
|
|
23
|
+
});
|
|
24
|
+
out.print("");
|
|
25
|
+
const summary = [failures && t.error(`${failures} problem${failures === 1 ? "" : "s"}`), warnings && t.warn(`${warnings} warning${warnings === 1 ? "" : "s"}`)].filter(Boolean).join(` ${t.dim("·")} `);
|
|
26
|
+
out.print(summary || t.success("everything Lucent needs is in place"));
|
|
27
|
+
return failures ? 1 : 0;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { run };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { n as Explanations, r as docsUrl } from "./codes-CIuwXt1S.js";
|
|
2
|
+
import { i as table, r as link } from "./format-D9fnIMEx.js";
|
|
3
|
+
//#region src/cli/commands/explain.ts
|
|
4
|
+
function run({ positionals, out }) {
|
|
5
|
+
const t = out.theme;
|
|
6
|
+
const [wanted] = positionals;
|
|
7
|
+
if (!wanted) {
|
|
8
|
+
for (const line of table(Object.entries(Explanations).map(([code, e]) => [t.bold(code), e.title]))) out.print(line);
|
|
9
|
+
out.print(t.dim("\nlucent explain <code> for one of them"));
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
const code = `LUCENT${wanted.replace(/^lucent/i, "")}`;
|
|
13
|
+
const e = Explanations[code];
|
|
14
|
+
if (!e) {
|
|
15
|
+
out.error(`${t.error(t.symbols.fail)} no ${code}: run lucent explain for the list of codes`);
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
const indent = (text) => text.trimEnd().split("\n").map((l) => ` ${l}`).join("\n");
|
|
19
|
+
out.print(`${t.bold(code)} ${e.title}\n`);
|
|
20
|
+
out.print(`${e.details}\n`);
|
|
21
|
+
out.print(`${t.success("fix")} ${e.fix}\n`);
|
|
22
|
+
for (const [label, files, paint] of [[
|
|
23
|
+
"wrong",
|
|
24
|
+
e.wrong,
|
|
25
|
+
t.error
|
|
26
|
+
], [
|
|
27
|
+
"right",
|
|
28
|
+
e.right,
|
|
29
|
+
t.success
|
|
30
|
+
]]) for (const [file, source] of Object.entries(files)) out.print(`${paint(`${label === "wrong" ? t.symbols.fail : t.symbols.ok} ${label}`)} ${t.dim(file)}\n${indent(source)}\n`);
|
|
31
|
+
out.print(t.dim(link(docsUrl(code), docsUrl(code), t.terminal)));
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { run };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/cli/ui/format.ts
|
|
2
|
+
const ANSI = /\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\/g;
|
|
3
|
+
function visibleWidth(s) {
|
|
4
|
+
return [...s.replace(ANSI, "")].length;
|
|
5
|
+
}
|
|
6
|
+
function pad(s, width) {
|
|
7
|
+
return s + " ".repeat(Math.max(0, width - visibleWidth(s)));
|
|
8
|
+
}
|
|
9
|
+
function duration(ms) {
|
|
10
|
+
if (ms < 1e3) return `${Math.round(ms)} ms`;
|
|
11
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)} s`;
|
|
12
|
+
const s = Math.round(ms / 1e3);
|
|
13
|
+
return `${Math.floor(s / 60)} m ${s % 60} s`;
|
|
14
|
+
}
|
|
15
|
+
function table(rows, gap = 2) {
|
|
16
|
+
const widths = [];
|
|
17
|
+
for (const r of rows) r.forEach((cell, i) => widths[i] = Math.max(widths[i] ?? 0, visibleWidth(cell)));
|
|
18
|
+
return rows.map((r) => r.map((cell, i) => i === r.length - 1 ? cell : pad(cell, widths[i] + gap)).join(""));
|
|
19
|
+
}
|
|
20
|
+
function link(text, url, terminal) {
|
|
21
|
+
return terminal.links ? `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\` : text;
|
|
22
|
+
}
|
|
23
|
+
function codeFrame(source, span, theme) {
|
|
24
|
+
const lines = source.split("\n");
|
|
25
|
+
const first = Math.max(1, span.line - 1);
|
|
26
|
+
const last = Math.min(lines.length, span.line + 1);
|
|
27
|
+
const gutter = String(last).length;
|
|
28
|
+
const { bar, ellipsis } = theme.symbols;
|
|
29
|
+
const indent = " ";
|
|
30
|
+
const room = Math.max(20, theme.terminal.width - 4 - gutter - 3);
|
|
31
|
+
const start = Math.max(0, Math.min(span.column - 1 - Math.floor(room / 3), (lines[span.line - 1] ?? "").length - room));
|
|
32
|
+
const cut = (text) => {
|
|
33
|
+
let s = text.slice(start, start + room);
|
|
34
|
+
if (start > 0) s = ellipsis + s.slice(ellipsis.length);
|
|
35
|
+
if (text.length > start + room) s = s.slice(0, room - ellipsis.length) + ellipsis;
|
|
36
|
+
return s;
|
|
37
|
+
};
|
|
38
|
+
const out = [];
|
|
39
|
+
for (let n = first; n <= last; n++) {
|
|
40
|
+
const text = (lines[n - 1] ?? "").replace(/\t/g, " ");
|
|
41
|
+
if (n === last && text.trim() === "" && n !== span.line) continue;
|
|
42
|
+
const num = String(n).padStart(gutter);
|
|
43
|
+
out.push(`${indent}${n === span.line ? theme.bold(num) : theme.dim(num)} ${theme.dim(bar)} ${cut(text)}`);
|
|
44
|
+
if (n === span.line) {
|
|
45
|
+
const at = span.column - 1 - start;
|
|
46
|
+
const width = Math.max(1, Math.min(span.length, room - at));
|
|
47
|
+
out.push(`${indent}${" ".repeat(gutter)} ${theme.dim(bar)} ${" ".repeat(Math.max(0, at))}${theme.error("^".repeat(width))}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out.join("\n");
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { visibleWidth as a, table as i, duration as n, link as r, codeFrame as t };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { t as packageFile } from "./version-bqpIO5sP.js";
|
|
2
|
+
import { n as withLucentTsconfig } from "./tsconfig-S4uyLNzf.js";
|
|
3
|
+
import { n as runner, t as packageManagerOf } from "./package-manager-BnxwCySi.js";
|
|
4
|
+
import { t as renderDiff } from "./diff-BTDo3Sro.js";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
//#region src/cli/init/patch.ts
|
|
9
|
+
const plugin = createRequire(import.meta.url)(packageFile("app.plugin.js"));
|
|
10
|
+
const GRADLE_LINE = plugin.GRADLE_LINE;
|
|
11
|
+
const applyGradleTask = plugin.applyGradleTask;
|
|
12
|
+
const METRO_REQUIRE = "const { withLucent } = require(\"@lucent-lang/lucent/metro\");";
|
|
13
|
+
function metroConfig(expo) {
|
|
14
|
+
return expo ? `const { getDefaultConfig } = require("expo/metro-config");\n${METRO_REQUIRE}\n\nmodule.exports = withLucent(getDefaultConfig(__dirname));\n` : `const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");\n${METRO_REQUIRE}\n\nmodule.exports = withLucent(mergeConfig(getDefaultConfig(__dirname), {}));\n`;
|
|
15
|
+
}
|
|
16
|
+
function wrapMetro(text) {
|
|
17
|
+
if (text.includes("@lucent-lang/lucent/metro") && /withLucent\(/.test(text)) return void 0;
|
|
18
|
+
const m = /^module\.exports\s*=\s*([\s\S]+?);?\s*$/m.exec(text);
|
|
19
|
+
if (!m || text.slice(m.index + m[0].length).trim()) return "manual";
|
|
20
|
+
const lines = `${text.slice(0, m.index)}module.exports = withLucent(${m[1].trim()});\n`.split("\n");
|
|
21
|
+
const lastRequire = lines.reduce((at, l, i) => /^(const|let|var) .*=\s*require\(/.test(l) ? i : at, -1);
|
|
22
|
+
lines.splice(lastRequire + 1, 0, METRO_REQUIRE);
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}
|
|
25
|
+
function addExpoPlugin(text) {
|
|
26
|
+
const json = JSON.parse(text);
|
|
27
|
+
const target = json.expo ?? json;
|
|
28
|
+
const plugins = target.plugins ?? [];
|
|
29
|
+
if (plugins.some((p) => p === "@lucent-lang/lucent" || Array.isArray(p) && p[0] === "@lucent-lang/lucent")) return void 0;
|
|
30
|
+
target.plugins = [...plugins, "@lucent-lang/lucent"];
|
|
31
|
+
const indent = /^[ \t]+(?=")/m.exec(text)?.[0] ?? " ";
|
|
32
|
+
return `${JSON.stringify(json, null, indent)}\n`;
|
|
33
|
+
}
|
|
34
|
+
const RN_ENTRY = `"lucent": { root: require("path").join(__dirname, ".lucent", "native") }`;
|
|
35
|
+
function linkNativePackage(text) {
|
|
36
|
+
if (text === void 0) return `module.exports = {\n dependencies: {\n ${RN_ENTRY},\n },\n};\n`;
|
|
37
|
+
if (text.includes("\"lucent-native\"")) return text.replace("\"lucent-native\"", "\"lucent\"");
|
|
38
|
+
if (/["']?lucent["']?\s*:\s*\{\s*root:/.test(text)) return void 0;
|
|
39
|
+
const deps = /dependencies\s*:\s*\{/.exec(text);
|
|
40
|
+
if (!deps) return "manual";
|
|
41
|
+
const at = deps.index + deps[0].length;
|
|
42
|
+
return `${text.slice(0, at)}\n ${RN_ENTRY},${text.slice(at)}`;
|
|
43
|
+
}
|
|
44
|
+
const RN_CONFIG_SNIPPET = `module.exports = {\n dependencies: {\n ${RN_ENTRY},\n },\n};`;
|
|
45
|
+
function ignoreNativePackage(text) {
|
|
46
|
+
const current = text ?? "";
|
|
47
|
+
if (current.split("\n").some((l) => l.trim() === ".lucent/" || l.trim() === ".lucent" || l.trim() === "/.lucent")) return void 0;
|
|
48
|
+
return `${current}${current && !current.endsWith("\n") ? "\n" : ""}# Lucent's generated native package\n.lucent/\n`;
|
|
49
|
+
}
|
|
50
|
+
const HELLO = `// A Lucent module: this runs as C++, and JavaScript calls it like any function:
|
|
51
|
+
//
|
|
52
|
+
// import { hello } from "./src/hello.lucent";
|
|
53
|
+
// hello("Ada"); // "Hello, Ada, from native code"
|
|
54
|
+
export function hello(name: string): string {
|
|
55
|
+
return \`Hello, \${name}, from native code\`;
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/cli/init/plan.ts
|
|
60
|
+
const read = (root, file) => fs.existsSync(path.join(root, file)) ? fs.readFileSync(path.join(root, file), "utf8") : void 0;
|
|
61
|
+
const first = (root, files) => files.find((f) => fs.existsSync(path.join(root, f)));
|
|
62
|
+
function planInit(root) {
|
|
63
|
+
const pkg = JSON.parse(read(root, "package.json") ?? "{}");
|
|
64
|
+
const kind = "expo" in {
|
|
65
|
+
...pkg.dependencies,
|
|
66
|
+
...pkg.devDependencies
|
|
67
|
+
} ? "expo" : "bare";
|
|
68
|
+
const packageManager = packageManagerOf(root)?.name ?? "npm";
|
|
69
|
+
const changes = [];
|
|
70
|
+
const manual = [];
|
|
71
|
+
const change = (file, why, after) => {
|
|
72
|
+
if (after !== void 0) changes.push({
|
|
73
|
+
file,
|
|
74
|
+
why,
|
|
75
|
+
before: read(root, file),
|
|
76
|
+
after
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
const metro = first(root, [
|
|
80
|
+
"metro.config.js",
|
|
81
|
+
"metro.config.cjs",
|
|
82
|
+
"metro.config.mjs",
|
|
83
|
+
"metro.config.ts"
|
|
84
|
+
]);
|
|
85
|
+
const wrapped = metro ? wrapMetro(read(root, metro)) : metroConfig(kind === "expo");
|
|
86
|
+
const metroWhy = "bundle each *.lucent.ts as the proxy of its native module";
|
|
87
|
+
if (wrapped === "manual") manual.push({
|
|
88
|
+
file: metro,
|
|
89
|
+
why: metroWhy,
|
|
90
|
+
snippet: "const { withLucent } = require(\"@lucent-lang/lucent/metro\");\n// …\nexport default withLucent(config);"
|
|
91
|
+
});
|
|
92
|
+
else change(metro ?? "metro.config.js", metroWhy, wrapped);
|
|
93
|
+
if (kind === "expo") {
|
|
94
|
+
const pluginWhy = "compile the modules during expo prebuild, and link the native package";
|
|
95
|
+
if (fs.existsSync(path.join(root, "app.json"))) change("app.json", pluginWhy, addExpoPlugin(read(root, "app.json")));
|
|
96
|
+
else {
|
|
97
|
+
const config = first(root, ["app.config.ts", "app.config.js"]);
|
|
98
|
+
if (config && !read(root, config).includes("@lucent-lang/lucent")) manual.push({
|
|
99
|
+
file: config,
|
|
100
|
+
why: pluginWhy,
|
|
101
|
+
snippet: "plugins: [\"@lucent-lang/lucent\"]"
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
const gradleWhy = "run lucent build before every Android build";
|
|
106
|
+
if (fs.existsSync(path.join(root, "android/app/build.gradle"))) change("android/app/build.gradle", gradleWhy, applyGradleTask(read(root, "android/app/build.gradle")));
|
|
107
|
+
else if (fs.existsSync(path.join(root, "android/app/build.gradle.kts")) && !read(root, "android/app/build.gradle.kts").includes("lucent.gradle")) manual.push({
|
|
108
|
+
file: "android/app/build.gradle.kts",
|
|
109
|
+
why: gradleWhy,
|
|
110
|
+
snippet: `apply(from = ${GRADLE_LINE.replace(/^apply from: /, "")})`
|
|
111
|
+
});
|
|
112
|
+
const linked = linkNativePackage(read(root, "react-native.config.js"));
|
|
113
|
+
const linkWhy = "autolink the generated native package (.lucent/native)";
|
|
114
|
+
if (linked === "manual") manual.push({
|
|
115
|
+
file: "react-native.config.js",
|
|
116
|
+
why: linkWhy,
|
|
117
|
+
snippet: RN_CONFIG_SNIPPET
|
|
118
|
+
});
|
|
119
|
+
else change("react-native.config.js", linkWhy, linked);
|
|
120
|
+
}
|
|
121
|
+
const tsconfig = read(root, "tsconfig.json");
|
|
122
|
+
if (tsconfig !== void 0) {
|
|
123
|
+
const tsWhy = "let editors and tsc resolve lucent:* and check indexing as the compiler does";
|
|
124
|
+
try {
|
|
125
|
+
change("tsconfig.json", tsWhy, withLucentTsconfig(tsconfig));
|
|
126
|
+
} catch (e) {
|
|
127
|
+
manual.push({
|
|
128
|
+
file: "tsconfig.json",
|
|
129
|
+
why: `${tsWhy} (${e.message})`,
|
|
130
|
+
snippet: "\"noUncheckedIndexedAccess\": true,\n\"paths\": { \"lucent:*\": [\"./.lucent/native/types/*\"] }"
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
change(".gitignore", "the native package is generated, like a build output", ignoreNativePackage(read(root, ".gitignore")));
|
|
135
|
+
if (!hasModules(root)) change("src/hello.lucent.ts", "a first module to try", HELLO);
|
|
136
|
+
const x = runner(packageManager);
|
|
137
|
+
return {
|
|
138
|
+
kind,
|
|
139
|
+
packageManager,
|
|
140
|
+
changes,
|
|
141
|
+
manual,
|
|
142
|
+
next: kind === "expo" ? `${x} expo run:ios` : `${x} lucent build && ${x} react-native run-ios`
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function hasModules(root) {
|
|
146
|
+
const walk = (dir) => fs.readdirSync(dir, { withFileTypes: true }).some((e) => {
|
|
147
|
+
if (e.name === "node_modules" || e.name.startsWith(".") || e.name === "ios" || e.name === "android") return false;
|
|
148
|
+
return e.isDirectory() ? walk(path.join(dir, e.name)) : /\.lucent\.tsx?$/.test(e.name);
|
|
149
|
+
});
|
|
150
|
+
return walk(root);
|
|
151
|
+
}
|
|
152
|
+
function applyChanges(root, changes) {
|
|
153
|
+
for (const c of changes) {
|
|
154
|
+
fs.mkdirSync(path.dirname(path.join(root, c.file)), { recursive: true });
|
|
155
|
+
fs.writeFileSync(path.join(root, c.file), c.after);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/cli/commands/init.ts
|
|
160
|
+
async function run({ root, flags, out }) {
|
|
161
|
+
const t = out.theme;
|
|
162
|
+
const plan = planInit(root);
|
|
163
|
+
out.print(`${t.brand(t.symbols.brand)} ${t.bold("lucent init")} ${t.dim(`${plan.kind === "expo" ? "Expo app" : "bare React Native app"} · ${plan.packageManager}`)}\n`);
|
|
164
|
+
const nextLine = () => out.print(`\n${t.dim("next")} ${plan.next}`);
|
|
165
|
+
const manual = () => {
|
|
166
|
+
for (const m of plan.manual) out.print(`${t.warn(t.symbols.warn)} ${m.file} ${t.dim(m.why)}; add by hand:\n${m.snippet.split("\n").map((l) => ` ${l}`).join("\n")}`);
|
|
167
|
+
};
|
|
168
|
+
if (!plan.changes.length) {
|
|
169
|
+
out.print(`${t.success(t.symbols.ok)} already set up`);
|
|
170
|
+
manual();
|
|
171
|
+
nextLine();
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
let accepted;
|
|
175
|
+
if (flags.yes) accepted = plan.changes;
|
|
176
|
+
else if (out.terminal.interactive) {
|
|
177
|
+
const [{ render }, { createElement }, { Confirm }] = await Promise.all([
|
|
178
|
+
import("ink"),
|
|
179
|
+
import("react"),
|
|
180
|
+
import("./confirm-BYF5eY3q.js")
|
|
181
|
+
]);
|
|
182
|
+
const answers = await new Promise((resolve) => {
|
|
183
|
+
const app = render(createElement(Confirm, {
|
|
184
|
+
changes: plan.changes,
|
|
185
|
+
theme: t,
|
|
186
|
+
onDone: (a) => setTimeout(() => (app.unmount(), resolve(a)), 20)
|
|
187
|
+
}), { interactive: true });
|
|
188
|
+
});
|
|
189
|
+
accepted = plan.changes.filter((_, i) => answers[i]);
|
|
190
|
+
applyChanges(root, accepted);
|
|
191
|
+
manual();
|
|
192
|
+
nextLine();
|
|
193
|
+
return 0;
|
|
194
|
+
} else {
|
|
195
|
+
for (const c of plan.changes) out.print(`${t.bold(c.file)}${c.before === void 0 ? t.dim(" (new)") : ""} ${t.dim(c.why)}\n${renderDiff(c.before ?? "", c.after, t)}\n`);
|
|
196
|
+
manual();
|
|
197
|
+
out.error(`${t.warn(t.symbols.warn)} nothing was changed: run lucent init --yes to apply these, or run lucent init in a terminal to choose`);
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
applyChanges(root, accepted);
|
|
201
|
+
for (const c of accepted) out.print(`${t.success(t.symbols.ok)} ${c.file} ${t.dim(c.why)}`);
|
|
202
|
+
manual();
|
|
203
|
+
nextLine();
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
export { run };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { n as stepLine } from "./steps--_h-FFS7.js";
|
|
2
|
+
import { Static, Text, render } from "ink";
|
|
3
|
+
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/cli/ui/live-steps.tsx
|
|
6
|
+
const FRAMES = [
|
|
7
|
+
"◐",
|
|
8
|
+
"◓",
|
|
9
|
+
"◑",
|
|
10
|
+
"◒"
|
|
11
|
+
];
|
|
12
|
+
function StepList({ store, theme }) {
|
|
13
|
+
const state = useSyncExternalStore(store.subscribe, store.get);
|
|
14
|
+
const [frame, setFrame] = useState(0);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const timer = setInterval(() => setFrame((f) => (f + 1) % FRAMES.length), 120);
|
|
17
|
+
return () => clearInterval(timer);
|
|
18
|
+
}, []);
|
|
19
|
+
const spinner = theme.terminal.unicode ? FRAMES[frame] : theme.symbols.busy;
|
|
20
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Static, {
|
|
21
|
+
items: state.done,
|
|
22
|
+
children: (r, i) => /* @__PURE__ */ jsx(Text, { children: stepLine(r, theme) }, i)
|
|
23
|
+
}), state.running ? /* @__PURE__ */ jsx(Text, { children: `${theme.progress(spinner)} ${state.running.label}${theme.dim(theme.symbols.ellipsis)}` }) : null] });
|
|
24
|
+
}
|
|
25
|
+
function createStore() {
|
|
26
|
+
let state = { done: [] };
|
|
27
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
28
|
+
return {
|
|
29
|
+
get: () => state,
|
|
30
|
+
set(next) {
|
|
31
|
+
state = next;
|
|
32
|
+
for (const l of listeners) l();
|
|
33
|
+
},
|
|
34
|
+
subscribe(listener) {
|
|
35
|
+
listeners.add(listener);
|
|
36
|
+
return () => listeners.delete(listener);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function liveSteps(theme, stdout = process.stdout) {
|
|
41
|
+
const store = createStore();
|
|
42
|
+
const app = render(/* @__PURE__ */ jsx(StepList, {
|
|
43
|
+
store,
|
|
44
|
+
theme
|
|
45
|
+
}), {
|
|
46
|
+
patchConsole: false,
|
|
47
|
+
stdout,
|
|
48
|
+
interactive: true
|
|
49
|
+
});
|
|
50
|
+
const results = [];
|
|
51
|
+
let closed = false;
|
|
52
|
+
return {
|
|
53
|
+
results,
|
|
54
|
+
start(_name, label) {
|
|
55
|
+
store.set({
|
|
56
|
+
...store.get(),
|
|
57
|
+
running: { label }
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
finish(r) {
|
|
61
|
+
results.push(r);
|
|
62
|
+
store.set({ done: [...store.get().done, r] });
|
|
63
|
+
},
|
|
64
|
+
flush: () => new Promise((resolve) => setTimeout(resolve, 20)),
|
|
65
|
+
async close() {
|
|
66
|
+
if (closed) return;
|
|
67
|
+
closed = true;
|
|
68
|
+
store.set({
|
|
69
|
+
...store.get(),
|
|
70
|
+
running: void 0
|
|
71
|
+
});
|
|
72
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
73
|
+
app.unmount();
|
|
74
|
+
await app.waitUntilExit();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { liveSteps };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/cli/commands/new-module.ts
|
|
4
|
+
const platforms = ["ios", "android"];
|
|
5
|
+
const branches = {
|
|
6
|
+
ios: {
|
|
7
|
+
label: "iOS",
|
|
8
|
+
imports: ["import { UIDevice } from \"lucent:ios/UIKit\";", "import { main } from \"lucent:thread\";"],
|
|
9
|
+
body: ["const system = await main(() => UIDevice.current.systemName);", "return `Hello, ${name}, from ${system}`;"]
|
|
10
|
+
},
|
|
11
|
+
android: {
|
|
12
|
+
label: "Android",
|
|
13
|
+
imports: ["import { Build_VERSION } from \"lucent:android/android.os\";"],
|
|
14
|
+
body: ["return `Hello, ${name}, from Android ${Build_VERSION.RELEASE ?? \"\"}`;"]
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const unimplemented = (p) => [`throw error("ERR_UNIMPLEMENTED", "hello is not implemented on ${branches[p].label} yet");`];
|
|
18
|
+
function platformModule(name, wanted) {
|
|
19
|
+
const missing = platforms.filter((p) => !wanted.includes(p));
|
|
20
|
+
const imports = [
|
|
21
|
+
"import { PLATFORM } from \"lucent:platform\";",
|
|
22
|
+
...wanted.flatMap((p) => branches[p].imports),
|
|
23
|
+
...missing.length ? ["import { error } from \"lucent:core\";"] : []
|
|
24
|
+
];
|
|
25
|
+
const body = (p) => (wanted.includes(p) ? branches[p].body : unimplemented(p)).map((l) => ` ${l}`).join("\n");
|
|
26
|
+
return `// Runs natively on each platform; JavaScript imports it from "./src/${name}.lucent".
|
|
27
|
+
${imports.join("\n")}
|
|
28
|
+
|
|
29
|
+
export async function hello(name: string): Promise<string> {
|
|
30
|
+
if (PLATFORM === "ios") {
|
|
31
|
+
${body("ios")}
|
|
32
|
+
} else {
|
|
33
|
+
${body("android")}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
const sharedModule = (name) => `// Runs as C++; JavaScript imports it from "./src/${name}.lucent".
|
|
39
|
+
export function hello(name: string): string {
|
|
40
|
+
return \`Hello, \${name}, from native code\`;
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
function run({ root, flags, positionals, out }) {
|
|
44
|
+
const t = out.theme;
|
|
45
|
+
const [name] = positionals;
|
|
46
|
+
if (!name || !/^[A-Za-z_$][\w$]*$/.test(name)) {
|
|
47
|
+
out.error(`${t.error(t.symbols.fail)} ${name ? `${name} is not a module name: use letters, digits and _, like a JavaScript name` : "name the module: lucent new module <name>"}`);
|
|
48
|
+
return 2;
|
|
49
|
+
}
|
|
50
|
+
const wanted = platforms.filter((p) => flags[p]);
|
|
51
|
+
const file = `src/${name}.lucent.ts`;
|
|
52
|
+
const target = path.join(root, file);
|
|
53
|
+
if (fs.existsSync(target)) {
|
|
54
|
+
out.error(`${t.error(t.symbols.fail)} ${file} exists; nothing was written`);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
58
|
+
fs.writeFileSync(target, wanted.length ? platformModule(name, wanted) : sharedModule(name));
|
|
59
|
+
out.print(`${t.success(t.symbols.ok)} ${file}`);
|
|
60
|
+
const missing = wanted.length ? platforms.find((p) => !wanted.includes(p)) : void 0;
|
|
61
|
+
if (missing) out.print(t.dim(`\nThe ${branches[missing].label} branch throws until you implement it.`));
|
|
62
|
+
out.print(`\n${t.dim("use it")} import { hello } from "./src/${name}.lucent";`);
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { run };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/cli/package-manager.ts
|
|
4
|
+
const LOCKFILES = [
|
|
5
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
6
|
+
["yarn.lock", "yarn"],
|
|
7
|
+
["package-lock.json", "npm"],
|
|
8
|
+
["bun.lock", "bun"],
|
|
9
|
+
["bun.lockb", "bun"]
|
|
10
|
+
];
|
|
11
|
+
function packageManagerOf(root) {
|
|
12
|
+
for (let dir = path.resolve(root);; dir = path.dirname(dir)) {
|
|
13
|
+
const found = LOCKFILES.find(([f]) => fs.existsSync(path.join(dir, f)));
|
|
14
|
+
if (found) return {
|
|
15
|
+
name: found[1],
|
|
16
|
+
lockfile: path.join(dir, found[0])
|
|
17
|
+
};
|
|
18
|
+
if (path.dirname(dir) === dir) return void 0;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function runner(pm) {
|
|
22
|
+
return {
|
|
23
|
+
npm: "npx",
|
|
24
|
+
pnpm: "pnpm exec",
|
|
25
|
+
yarn: "yarn",
|
|
26
|
+
bun: "bunx"
|
|
27
|
+
}[pm];
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { runner as n, packageManagerOf as t };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region ../compiler/src/packages.ts
|
|
5
|
+
function nativeDependencies(packages) {
|
|
6
|
+
const out = {
|
|
7
|
+
pods: {},
|
|
8
|
+
gradle: {},
|
|
9
|
+
permissions: [],
|
|
10
|
+
infoPlist: {}
|
|
11
|
+
};
|
|
12
|
+
const owners = /* @__PURE__ */ new Map();
|
|
13
|
+
const merge = (kind, into, key, value, from) => {
|
|
14
|
+
const id = `${kind} ${key}`;
|
|
15
|
+
if (into[key] !== void 0 && into[key] !== value) throw new Error(`${kind}${key}: ${owners.get(id)} wants ${into[key]}, ${from} wants ${value}`);
|
|
16
|
+
into[key] = value;
|
|
17
|
+
if (!owners.has(id)) owners.set(id, from);
|
|
18
|
+
};
|
|
19
|
+
for (const p of packages) {
|
|
20
|
+
for (const [pod, version] of Object.entries(p.native?.ios?.pods ?? {})) merge("pod ", out.pods, pod, version, p.name);
|
|
21
|
+
for (const [artifact, version] of Object.entries(p.native?.android?.dependencies ?? {})) merge("", out.gradle, artifact, version, p.name);
|
|
22
|
+
for (const perm of p.native?.android?.permissions ?? []) if (!out.permissions.includes(perm)) out.permissions.push(perm);
|
|
23
|
+
for (const [key, value] of Object.entries(p.native?.ios?.infoPlist ?? {})) {
|
|
24
|
+
merge("Info.plist ", Object.fromEntries(Object.entries(out.infoPlist).map(([k, v]) => [k, v.value])), key, value, p.name);
|
|
25
|
+
out.infoPlist[key] ??= {
|
|
26
|
+
value,
|
|
27
|
+
from: p.name
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
out.permissions.sort();
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
const read = (file) => {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
37
|
+
} catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function lucentPackageOf(file) {
|
|
42
|
+
for (let dir = path.dirname(path.resolve(file));; dir = path.dirname(dir)) {
|
|
43
|
+
const pkg = read(path.join(dir, "package.json"));
|
|
44
|
+
if (pkg) {
|
|
45
|
+
if (!pkg.lucent || !pkg.name) return void 0;
|
|
46
|
+
const native = fs.existsSync(path.join(dir, "lucent.json")) ? JSON.parse(fs.readFileSync(path.join(dir, "lucent.json"), "utf8")) : void 0;
|
|
47
|
+
return {
|
|
48
|
+
name: pkg.name,
|
|
49
|
+
version: pkg.version ?? "0.0.0",
|
|
50
|
+
dir,
|
|
51
|
+
sources: path.join(dir, pkg.lucent.sources ?? "."),
|
|
52
|
+
compatible: pkg.lucent.compatible,
|
|
53
|
+
...native ? { native } : {}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (path.dirname(dir) === dir) return void 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function lucentPackages(root) {
|
|
60
|
+
const found = /* @__PURE__ */ new Map();
|
|
61
|
+
const visit = (from, deps) => {
|
|
62
|
+
for (const name of Object.keys(deps)) {
|
|
63
|
+
const dir = resolvePackage(from, name);
|
|
64
|
+
if (!dir || found.has(dir)) continue;
|
|
65
|
+
const pkg = lucentPackageOf(path.join(dir, "package.json"));
|
|
66
|
+
if (!pkg || pkg.dir !== dir) continue;
|
|
67
|
+
if (pkg.compatible && !satisfies(lucentVersion(), pkg.compatible)) throw new Error(`${pkg.name}@${pkg.version} supports Lucent ${pkg.compatible}, not ${lucentVersion()}: update one of them`);
|
|
68
|
+
found.set(dir, pkg);
|
|
69
|
+
visit(dir, read(path.join(dir, "package.json"))?.dependencies ?? {});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
visit(root, read(path.join(root, "package.json"))?.dependencies ?? {});
|
|
73
|
+
return [...found.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
74
|
+
}
|
|
75
|
+
function resolvePackage(from, name) {
|
|
76
|
+
for (let dir = path.resolve(from);; dir = path.dirname(dir)) {
|
|
77
|
+
const candidate = path.join(dir, "node_modules", name);
|
|
78
|
+
if (fs.existsSync(path.join(candidate, "package.json"))) return fs.realpathSync(candidate);
|
|
79
|
+
if (path.dirname(dir) === dir) return void 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
let version;
|
|
83
|
+
function lucentVersion() {
|
|
84
|
+
version ??= read(path.join(path.dirname(fileURLToPath(import.meta.url)), "../package.json"))?.version ?? "0.0.0";
|
|
85
|
+
return version;
|
|
86
|
+
}
|
|
87
|
+
function satisfies(version, range) {
|
|
88
|
+
const v = parse(version);
|
|
89
|
+
return range.split("||").some((alt) => alt.trim().split(/\s+/).filter(Boolean).every((c) => comparator(v, c)));
|
|
90
|
+
}
|
|
91
|
+
function parse(v) {
|
|
92
|
+
const [a = 0, b = 0, c = 0] = v.replace(/^v/, "").split("-")[0].split(".").map((x) => /^\d+$/.test(x) ? Number(x) : 0);
|
|
93
|
+
return [
|
|
94
|
+
a,
|
|
95
|
+
b,
|
|
96
|
+
c
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
function cmp(a, b) {
|
|
100
|
+
for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] - b[i];
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
function comparator(v, c) {
|
|
104
|
+
const m = /^(\^|~|>=|<=|>|<|=)?v?([\dxX*]+)(?:\.([\dxX*]+))?(?:\.([\dxX*]+))?/.exec(c);
|
|
105
|
+
if (!m) return false;
|
|
106
|
+
const op = m[1] ?? "";
|
|
107
|
+
const parts = [
|
|
108
|
+
m[2],
|
|
109
|
+
m[3],
|
|
110
|
+
m[4]
|
|
111
|
+
];
|
|
112
|
+
const wild = parts.findIndex((p) => p === void 0 || /[xX*]/.test(p));
|
|
113
|
+
const nums = parts.map((p) => p === void 0 || /[xX*]/.test(p) ? 0 : Number(p));
|
|
114
|
+
if (op === "" || op === "=") {
|
|
115
|
+
if (wild === -1) return cmp(v, nums) === 0;
|
|
116
|
+
return nums.slice(0, wild).every((n, i) => v[i] === n);
|
|
117
|
+
}
|
|
118
|
+
if (op === "^") {
|
|
119
|
+
const upper = nums[0] > 0 || wild === 1 ? [
|
|
120
|
+
nums[0] + 1,
|
|
121
|
+
0,
|
|
122
|
+
0
|
|
123
|
+
] : nums[1] > 0 || wild === 2 ? [
|
|
124
|
+
0,
|
|
125
|
+
nums[1] + 1,
|
|
126
|
+
0
|
|
127
|
+
] : [
|
|
128
|
+
0,
|
|
129
|
+
0,
|
|
130
|
+
nums[2] + 1
|
|
131
|
+
];
|
|
132
|
+
return cmp(v, nums) >= 0 && cmp(v, upper) < 0;
|
|
133
|
+
}
|
|
134
|
+
if (op === "~") {
|
|
135
|
+
const upper = wild === 1 ? [
|
|
136
|
+
nums[0] + 1,
|
|
137
|
+
0,
|
|
138
|
+
0
|
|
139
|
+
] : [
|
|
140
|
+
nums[0],
|
|
141
|
+
nums[1] + 1,
|
|
142
|
+
0
|
|
143
|
+
];
|
|
144
|
+
return cmp(v, nums) >= 0 && cmp(v, upper) < 0;
|
|
145
|
+
}
|
|
146
|
+
const d = cmp(v, nums);
|
|
147
|
+
return op === ">=" ? d >= 0 : op === ">" ? d > 0 : op === "<=" ? d <= 0 : d < 0;
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
export { satisfies as a, nativeDependencies as i, lucentPackages as n, lucentVersion as r, lucentPackageOf as t };
|