@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,24 @@
|
|
|
1
|
+
import { a as visibleWidth, n as duration } from "./format-D9fnIMEx.js";
|
|
2
|
+
//#region src/cli/ui/steps.ts
|
|
3
|
+
const TIME_COLUMN = 40;
|
|
4
|
+
function stepLine(r, theme) {
|
|
5
|
+
const text = `${r.status === "failed" ? theme.error(theme.symbols.fail) : r.status === "skipped" ? theme.dim(theme.symbols.off) : theme.success(theme.symbols.ok)} ${r.label}${r.detail ? ` ${theme.dim(r.detail)}` : ""}`;
|
|
6
|
+
const time = r.status === "cached" ? "cached" : r.ms !== void 0 ? duration(r.ms) : "";
|
|
7
|
+
if (!time) return text;
|
|
8
|
+
return `${text}${" ".repeat(Math.max(2, TIME_COLUMN - visibleWidth(text)))}${theme.dim(time)}`;
|
|
9
|
+
}
|
|
10
|
+
function plainSteps(print, theme) {
|
|
11
|
+
const results = [];
|
|
12
|
+
return {
|
|
13
|
+
results,
|
|
14
|
+
start: () => {},
|
|
15
|
+
finish(r) {
|
|
16
|
+
results.push(r);
|
|
17
|
+
print(stepLine(r, theme));
|
|
18
|
+
},
|
|
19
|
+
flush: async () => {},
|
|
20
|
+
close: async () => {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { stepLine as n, plainSteps as t };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
21
|
+
value: mod,
|
|
22
|
+
enumerable: true
|
|
23
|
+
}) : target, mod));
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/cli/ui/theme.ts
|
|
26
|
+
var import_picocolors = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
27
|
+
let p = process || {};
|
|
28
|
+
let argv = p.argv || [];
|
|
29
|
+
let env = p.env || {};
|
|
30
|
+
let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
31
|
+
let formatter = (open, close, replace = open) => (input) => {
|
|
32
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
33
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
34
|
+
};
|
|
35
|
+
let replaceClose = (string, close, replace, index) => {
|
|
36
|
+
let result = "", cursor = 0;
|
|
37
|
+
do {
|
|
38
|
+
result += string.substring(cursor, index) + replace;
|
|
39
|
+
cursor = index + close.length;
|
|
40
|
+
index = string.indexOf(close, cursor);
|
|
41
|
+
} while (~index);
|
|
42
|
+
return result + string.substring(cursor);
|
|
43
|
+
};
|
|
44
|
+
let createColors = (enabled = isColorSupported) => {
|
|
45
|
+
let f = enabled ? formatter : () => String;
|
|
46
|
+
return {
|
|
47
|
+
isColorSupported: enabled,
|
|
48
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
49
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
50
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
51
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
52
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
53
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
54
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
55
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
56
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
57
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
58
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
59
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
60
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
61
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
62
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
63
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
64
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
65
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
66
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
67
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
68
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
69
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
70
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
71
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
72
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
73
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
74
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
75
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
76
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
77
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
78
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
79
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
80
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
81
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
82
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
83
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
84
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
85
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
86
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
87
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
88
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
module.exports = createColors();
|
|
92
|
+
module.exports.createColors = createColors;
|
|
93
|
+
})))(), 1);
|
|
94
|
+
const UNICODE = {
|
|
95
|
+
brand: "◆",
|
|
96
|
+
ok: "✓",
|
|
97
|
+
fail: "✗",
|
|
98
|
+
warn: "!",
|
|
99
|
+
busy: "◐",
|
|
100
|
+
on: "●",
|
|
101
|
+
off: "○",
|
|
102
|
+
bar: "│",
|
|
103
|
+
rule: "─",
|
|
104
|
+
ellipsis: "…"
|
|
105
|
+
};
|
|
106
|
+
const ASCII = {
|
|
107
|
+
brand: "*",
|
|
108
|
+
ok: "+",
|
|
109
|
+
fail: "x",
|
|
110
|
+
warn: "!",
|
|
111
|
+
busy: "~",
|
|
112
|
+
on: "o",
|
|
113
|
+
off: ".",
|
|
114
|
+
bar: "|",
|
|
115
|
+
rule: "-",
|
|
116
|
+
ellipsis: "..."
|
|
117
|
+
};
|
|
118
|
+
function createTheme(terminal) {
|
|
119
|
+
const c = import_picocolors.default.createColors(terminal.color);
|
|
120
|
+
const violet = terminal.color ? (s) => `\x1b[38;5;141m${s}\x1b[39m` : (s) => s;
|
|
121
|
+
return {
|
|
122
|
+
terminal,
|
|
123
|
+
symbols: terminal.unicode ? UNICODE : ASCII,
|
|
124
|
+
brand: violet,
|
|
125
|
+
success: c.green,
|
|
126
|
+
error: c.red,
|
|
127
|
+
warn: c.yellow,
|
|
128
|
+
progress: c.cyan,
|
|
129
|
+
dim: c.dim,
|
|
130
|
+
bold: c.bold
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
export { createTheme as t };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
//#region src/cli/tsconfig.ts
|
|
3
|
+
const ENTRY = "\"lucent:*\": [\"./.lucent/native/types/*\"]";
|
|
4
|
+
function withLucentPaths(text) {
|
|
5
|
+
const { error } = ts.parseConfigFileTextToJson("tsconfig.json", text);
|
|
6
|
+
if (error) throw new Error(`tsconfig.json: ${ts.flattenDiagnosticMessageText(error.messageText, "\n")}`);
|
|
7
|
+
const sf = ts.parseJsonText("tsconfig.json", text);
|
|
8
|
+
const root = sf.statements[0]?.expression;
|
|
9
|
+
if (!root || !ts.isObjectLiteralExpression(root)) throw new Error("tsconfig.json: expected an object");
|
|
10
|
+
const options = property(root, "compilerOptions");
|
|
11
|
+
if (!options) return insert(text, sf, root, `"compilerOptions": { "paths": { ${ENTRY} } }`);
|
|
12
|
+
const paths = property(options, "paths");
|
|
13
|
+
if (!paths) return insert(text, sf, options, `"paths": { ${ENTRY} }`);
|
|
14
|
+
if (named(paths, "lucent:*")) return void 0;
|
|
15
|
+
return insert(text, sf, paths, ENTRY);
|
|
16
|
+
}
|
|
17
|
+
function withLucentTsconfig(text) {
|
|
18
|
+
const indexed = withCompilerOption(text, "noUncheckedIndexedAccess", "true");
|
|
19
|
+
return withLucentPaths(indexed ?? text) ?? indexed;
|
|
20
|
+
}
|
|
21
|
+
function withCompilerOption(text, name, value) {
|
|
22
|
+
const { error } = ts.parseConfigFileTextToJson("tsconfig.json", text);
|
|
23
|
+
if (error) throw new Error(`tsconfig.json: ${ts.flattenDiagnosticMessageText(error.messageText, "\n")}`);
|
|
24
|
+
const sf = ts.parseJsonText("tsconfig.json", text);
|
|
25
|
+
const root = sf.statements[0]?.expression;
|
|
26
|
+
if (!root || !ts.isObjectLiteralExpression(root)) throw new Error("tsconfig.json: expected an object");
|
|
27
|
+
const options = property(root, "compilerOptions");
|
|
28
|
+
if (!options) return insert(text, sf, root, `"compilerOptions": { "${name}": ${value} }`);
|
|
29
|
+
const current = named(options, name);
|
|
30
|
+
if (!current) return insert(text, sf, options, `"${name}": ${value}`);
|
|
31
|
+
if (current.initializer.getText(sf) === value) return void 0;
|
|
32
|
+
return `${text.slice(0, current.initializer.getStart(sf))}${value}${text.slice(current.initializer.getEnd())}`;
|
|
33
|
+
}
|
|
34
|
+
function named(o, name) {
|
|
35
|
+
return o.properties.find((p) => ts.isPropertyAssignment(p) && ts.isStringLiteral(p.name) && p.name.text === name);
|
|
36
|
+
}
|
|
37
|
+
function property(o, name) {
|
|
38
|
+
const value = named(o, name)?.initializer;
|
|
39
|
+
if (value === void 0) return void 0;
|
|
40
|
+
if (!ts.isObjectLiteralExpression(value)) throw new Error(`tsconfig.json: "${name}" should be an object`);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function insert(text, sf, o, member) {
|
|
44
|
+
const open = o.getStart(sf);
|
|
45
|
+
const last = o.properties.at(-1);
|
|
46
|
+
if (!last) return `${text.slice(0, open)}{ ${member} }${text.slice(o.getEnd())}`;
|
|
47
|
+
const line = (pos) => sf.getLineAndCharacterOfPosition(pos).line;
|
|
48
|
+
if (line(last.getStart(sf)) === line(open)) return `${text.slice(0, last.getEnd())}, ${member}${text.slice(last.getEnd())}`;
|
|
49
|
+
const lineStart = sf.getPositionOfLineAndCharacter(line(last.getStart(sf)), 0);
|
|
50
|
+
const indent = text.slice(lineStart, last.getStart(sf));
|
|
51
|
+
const comma = /^\s*,/.exec(text.slice(last.getEnd()));
|
|
52
|
+
if (comma) {
|
|
53
|
+
const at = last.getEnd() + comma[0].length;
|
|
54
|
+
return `${text.slice(0, at)}\n${indent}${member},${text.slice(at)}`;
|
|
55
|
+
}
|
|
56
|
+
return `${text.slice(0, last.getEnd())},\n${indent}${member}${text.slice(last.getEnd())}`;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { withLucentTsconfig as n, withLucentPaths as t };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region src/cli/version.ts
|
|
5
|
+
let found;
|
|
6
|
+
function lucentPackage() {
|
|
7
|
+
if (found) return found;
|
|
8
|
+
for (let dir = path.dirname(fileURLToPath(import.meta.url)); path.dirname(dir) !== dir; dir = path.dirname(dir)) {
|
|
9
|
+
const file = path.join(dir, "package.json");
|
|
10
|
+
if (!fs.existsSync(file)) continue;
|
|
11
|
+
const pkg = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
12
|
+
if (pkg.name === "@lucent-lang/lucent") return found = {
|
|
13
|
+
dir,
|
|
14
|
+
version: pkg.version ?? "0.0.0"
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
throw new Error("lucent is not inside the @lucent-lang/lucent package");
|
|
18
|
+
}
|
|
19
|
+
function version() {
|
|
20
|
+
return lucentPackage().version;
|
|
21
|
+
}
|
|
22
|
+
function packageFile(relative) {
|
|
23
|
+
return path.join(lucentPackage().dir, relative);
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { version as n, packageFile as t };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Registers lucentClasspath in the app project it is applied to: writes the
|
|
2
|
+
// app's resolved compile classpath (AARs and jars) to
|
|
3
|
+
// .lucent/android-classpath.json, so lucent:android/<package> can bind any
|
|
4
|
+
// library the app links (AndroidX, Play services, Firebase…).
|
|
5
|
+
// Applied by lucent.gradle (the app's Gradle task) and by
|
|
6
|
+
// lucent-classpath.init.gradle (when lucent build asks Gradle). In an app
|
|
7
|
+
// with lucent.gradle, lucent build's run applies it twice: once registers.
|
|
8
|
+
if (ext.has("lucentClasspathApplied")) return
|
|
9
|
+
ext.lucentClasspathApplied = true
|
|
10
|
+
pluginManager.withPlugin("com.android.application") {
|
|
11
|
+
// Registered after the Android plugin's own afterEvaluate, which creates the variants' configurations.
|
|
12
|
+
afterEvaluate {
|
|
13
|
+
def out = new File(rootProject.projectDir.parentFile, ".lucent/android-classpath.json")
|
|
14
|
+
def artifactType = Attribute.of("artifactType", String)
|
|
15
|
+
def compileClasspath = configurations.findByName("debugCompileClasspath") ?: configurations.findByName("releaseCompileClasspath")
|
|
16
|
+
if (compileClasspath == null) return
|
|
17
|
+
// Libraries from repositories only: the app's other projects (autolinked
|
|
18
|
+
// modules, Lucent's own) would have to be built first, and their preBuild
|
|
19
|
+
// runs lucentBuild, which needs this classpath.
|
|
20
|
+
def viewOf = { String type ->
|
|
21
|
+
compileClasspath.incoming.artifactView {
|
|
22
|
+
lenient(true)
|
|
23
|
+
componentFilter { it instanceof org.gradle.api.artifacts.component.ModuleComponentIdentifier }
|
|
24
|
+
attributes.attribute(artifactType, type)
|
|
25
|
+
}.files
|
|
26
|
+
}
|
|
27
|
+
def aars = viewOf("aar")
|
|
28
|
+
def jars = viewOf("jar")
|
|
29
|
+
tasks.register("lucentClasspath") {
|
|
30
|
+
inputs.files(aars, jars)
|
|
31
|
+
outputs.file(out)
|
|
32
|
+
doLast {
|
|
33
|
+
out.parentFile.mkdirs()
|
|
34
|
+
out.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson([aars: aars.files*.absolutePath.sort(), jars: jars.files*.absolutePath.sort()]))
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Gradle init script, passed by lucent build with --init-script: registers
|
|
2
|
+
// lucentClasspath in the app project without touching the app's build files.
|
|
3
|
+
def script = new File(buildscript.sourceFile.parentFile, "lucent-classpath.gradle")
|
|
4
|
+
gradle.allprojects { project ->
|
|
5
|
+
if (project.path == ":app") project.apply(from: script)
|
|
6
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Lucent's Gradle task. lucent init applies it in android/app/build.gradle
|
|
2
|
+
// (and the Expo config plugin during prebuild):
|
|
3
|
+
//
|
|
4
|
+
// apply from: new File(new File(["node", "--print", "require.resolve('@lucent-lang/lucent/package.json')"].execute(null, rootDir).text.trim()).parentFile, "gradle/lucent.gradle")
|
|
5
|
+
//
|
|
6
|
+
// Every build then runs `lucent build` first, so .lucent/native matches the
|
|
7
|
+
// *.lucent.ts sources however the app is built: Android Studio, ./gradlew, CI.
|
|
8
|
+
def lucentDir = buildscript.sourceFile.parentFile
|
|
9
|
+
apply from: new File(lucentDir, "lucent-classpath.gradle")
|
|
10
|
+
|
|
11
|
+
def lucentBuild = tasks.register("lucentBuild", Exec) {
|
|
12
|
+
description = "Compiles the app's *.lucent.ts modules into .lucent/native"
|
|
13
|
+
group = "lucent"
|
|
14
|
+
dependsOn "lucentClasspath"
|
|
15
|
+
workingDir rootProject.projectDir.parentFile
|
|
16
|
+
// lucentClasspath just resolved the classpath in this build: lucent build must not start Gradle again.
|
|
17
|
+
environment "LUCENT_GRADLE_CLASSPATH", "1"
|
|
18
|
+
commandLine "node", new File(lucentDir, "../bin/lucent.cjs").canonicalPath, "build"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Before any project's build, the native package's included.
|
|
22
|
+
rootProject.allprojects { p ->
|
|
23
|
+
p.tasks.matching { it.name == "preBuild" }.configureEach { dependsOn(lucentBuild) }
|
|
24
|
+
}
|
package/lib/core.cjs
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// JavaScript implementations of lucent:core, used when a Lucent module
|
|
3
|
+
// runs as plain JavaScript: the differential e2e harness, lucent bench's
|
|
4
|
+
// JavaScript side, and apps' own tests (@lucent-lang/lucent/core). Native
|
|
5
|
+
// builds use the C++ runtime.
|
|
6
|
+
|
|
7
|
+
function delay(ms, signal) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
if (!signal) return void setTimeout(resolve, ms);
|
|
10
|
+
if (signal.aborted) return void reject(signal.reason);
|
|
11
|
+
const onAbort = () => {
|
|
12
|
+
clearTimeout(timer);
|
|
13
|
+
reject(signal.reason);
|
|
14
|
+
};
|
|
15
|
+
const timer = setTimeout(() => {
|
|
16
|
+
signal.removeEventListener("abort", onAbort);
|
|
17
|
+
resolve();
|
|
18
|
+
}, ms);
|
|
19
|
+
signal.addEventListener("abort", onAbort);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function error(code, message) {
|
|
24
|
+
const e = new Error(message);
|
|
25
|
+
e.code = code;
|
|
26
|
+
return e;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function errorCode(e) {
|
|
30
|
+
return typeof e.code === "string" ? e.code : undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function utf8Encode(s) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (let i = 0; i < s.length; i++) {
|
|
36
|
+
let cp = s.charCodeAt(i);
|
|
37
|
+
if (cp >= 0xd800 && cp <= 0xdbff && i + 1 < s.length) {
|
|
38
|
+
const lo = s.charCodeAt(i + 1);
|
|
39
|
+
if (lo >= 0xdc00 && lo <= 0xdfff) {
|
|
40
|
+
cp = 0x10000 + ((cp - 0xd800) << 10) + (lo - 0xdc00);
|
|
41
|
+
i++;
|
|
42
|
+
} else cp = 0xfffd;
|
|
43
|
+
} else if (cp >= 0xd800 && cp <= 0xdfff) cp = 0xfffd;
|
|
44
|
+
if (cp < 0x80) out.push(cp);
|
|
45
|
+
else if (cp < 0x800) out.push(0xc0 | (cp >> 6), 0x80 | (cp & 63));
|
|
46
|
+
else if (cp < 0x10000) out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 63), 0x80 | (cp & 63));
|
|
47
|
+
else
|
|
48
|
+
out.push(
|
|
49
|
+
0xf0 | (cp >> 18),
|
|
50
|
+
0x80 | ((cp >> 12) & 63),
|
|
51
|
+
0x80 | ((cp >> 6) & 63),
|
|
52
|
+
0x80 | (cp & 63),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return new Uint8Array(out);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function utf8Decode(bytes) {
|
|
59
|
+
let out = "";
|
|
60
|
+
let i = 0;
|
|
61
|
+
const n = bytes.length;
|
|
62
|
+
const cont = (k) => (i + k < n && (bytes[i + k] & 0xc0) === 0x80 ? bytes[i + k] & 63 : -1);
|
|
63
|
+
while (i < n) {
|
|
64
|
+
const c = bytes[i];
|
|
65
|
+
let cp = 0xfffd;
|
|
66
|
+
let len = 1;
|
|
67
|
+
if (c < 0x80) cp = c;
|
|
68
|
+
else if ((c & 0xe0) === 0xc0) {
|
|
69
|
+
const a = cont(1);
|
|
70
|
+
if (a >= 0 && c >= 0xc2) {
|
|
71
|
+
cp = ((c & 31) << 6) | a;
|
|
72
|
+
len = 2;
|
|
73
|
+
}
|
|
74
|
+
} else if ((c & 0xf0) === 0xe0) {
|
|
75
|
+
const a = cont(1),
|
|
76
|
+
b = cont(2);
|
|
77
|
+
if (a >= 0 && b >= 0) {
|
|
78
|
+
const v = ((c & 15) << 12) | (a << 6) | b;
|
|
79
|
+
if (v >= 0x800) {
|
|
80
|
+
cp = v;
|
|
81
|
+
len = 3;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} else if ((c & 0xf8) === 0xf0) {
|
|
85
|
+
const a = cont(1),
|
|
86
|
+
b = cont(2),
|
|
87
|
+
d = cont(3);
|
|
88
|
+
if (a >= 0 && b >= 0 && d >= 0) {
|
|
89
|
+
const v = ((c & 7) << 18) | (a << 12) | (b << 6) | d;
|
|
90
|
+
if (v >= 0x10000 && v <= 0x10ffff) {
|
|
91
|
+
cp = v;
|
|
92
|
+
len = 4;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
out += String.fromCodePoint(cp);
|
|
97
|
+
i += len;
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function now() {
|
|
103
|
+
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { delay, error, errorCode, utf8Encode, utf8Decode, now };
|
package/lib/globals.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Globals available to Lucent modules beyond the ES2022 library. Only the
|
|
2
|
+
// Lucent compiler loads this file; React Native, Node and the DOM declare
|
|
3
|
+
// compatible versions, so the same source type-checks in an app's editor.
|
|
4
|
+
|
|
5
|
+
interface Console {
|
|
6
|
+
log(...data: unknown[]): void;
|
|
7
|
+
info(...data: unknown[]): void;
|
|
8
|
+
debug(...data: unknown[]): void;
|
|
9
|
+
warn(...data: unknown[]): void;
|
|
10
|
+
error(...data: unknown[]): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare var console: Console;
|
|
14
|
+
|
|
15
|
+
interface AbortSignal {
|
|
16
|
+
readonly aborted: boolean;
|
|
17
|
+
/** Not available in Lucent code: catch the error from throwIfAborted() or delay() instead. */
|
|
18
|
+
readonly reason: any;
|
|
19
|
+
throwIfAborted(): void;
|
|
20
|
+
addEventListener(type: "abort", listener: () => void): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare var AbortSignal: {
|
|
24
|
+
prototype: AbortSignal;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface AbortController {
|
|
28
|
+
readonly signal: AbortSignal;
|
|
29
|
+
/** In Lucent code, `reason` must be an Error. */
|
|
30
|
+
abort(reason?: any): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare var AbortController: {
|
|
34
|
+
prototype: AbortController;
|
|
35
|
+
new (): AbortController;
|
|
36
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// lucent:android — Android helpers for platform code.
|
|
2
|
+
import type { Context } from "lucent:android/android.content";
|
|
3
|
+
|
|
4
|
+
/** The application Context. */
|
|
5
|
+
export declare function appContext(): Context;
|
|
6
|
+
|
|
7
|
+
/** Whether the device runs at least API level `api` (`Build.VERSION.SDK_INT >= api`). */
|
|
8
|
+
export declare function available(platform: "android", api: number): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers available to Lucent modules. Each one has a native implementation
|
|
3
|
+
* in the Lucent runtime and a JavaScript implementation (the e2e harness's
|
|
4
|
+
* core.js) so the same source also runs as plain TypeScript.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Resolves after `ms` milliseconds; rejects with the signal's reason if it aborts first. */
|
|
8
|
+
export declare function delay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
9
|
+
|
|
10
|
+
/** An Error with a machine-readable `code`, visible to JavaScript as `error.code`. */
|
|
11
|
+
export declare function error(code: string, message: string): Error;
|
|
12
|
+
|
|
13
|
+
/** The `code` of an error created with `error()`, or undefined. */
|
|
14
|
+
export declare function errorCode(e: Error): string | undefined;
|
|
15
|
+
|
|
16
|
+
/** UTF-8 encoding of a string (like `new TextEncoder().encode(s)`). */
|
|
17
|
+
export declare function utf8Encode(s: string): Uint8Array;
|
|
18
|
+
|
|
19
|
+
/** Decodes UTF-8 bytes (like `new TextDecoder().decode(b)`), replacing invalid sequences. */
|
|
20
|
+
export declare function utf8Decode(bytes: Uint8Array): string;
|
|
21
|
+
|
|
22
|
+
/** Milliseconds from a monotonic clock, for measuring durations. */
|
|
23
|
+
export declare function now(): number;
|
package/lib/sdk/ios.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// lucent:ios — iOS helpers for platform code.
|
|
2
|
+
|
|
3
|
+
/** Whether the OS is at least `major.minor` (Swift's `#available`). */
|
|
4
|
+
export declare function available(platform: "ios", major: number, minor?: number): boolean;
|
|
5
|
+
|
|
6
|
+
/** The root of Objective-C objects. Values of type `Any` (`id`) arrive as NSObjects. */
|
|
7
|
+
export declare class NSObject {
|
|
8
|
+
private readonly __lucent_NSObject: never;
|
|
9
|
+
protected constructor();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** What can go where Objective-C takes `Any` (`id`), CoreFoundation values included. */
|
|
13
|
+
export type ObjCValue = string | number | boolean | Uint8Array | Date | NSObject | null;
|
|
14
|
+
|
|
15
|
+
/** The main dispatch queue (dispatch_get_main_queue()), for APIs that take a queue. */
|
|
16
|
+
export declare function mainQueue(): NSObject;
|
|
17
|
+
|
|
18
|
+
/** Swift's `as? String`: the string an `Any` holds, or null. */
|
|
19
|
+
export declare function asString(value: NSObject | null): string | null;
|
|
20
|
+
/** Swift's `as? Double` (an NSNumber). */
|
|
21
|
+
export declare function asNumber(value: NSObject | null): number | null;
|
|
22
|
+
/** Swift's `as? Bool` (an NSNumber). */
|
|
23
|
+
export declare function asBoolean(value: NSObject | null): boolean | null;
|
|
24
|
+
/** Swift's `as? Data`. */
|
|
25
|
+
export declare function asData(value: NSObject | null): Uint8Array | null;
|
|
26
|
+
/** Swift's `as? Date`. */
|
|
27
|
+
export declare function asDate(value: NSObject | null): Date | null;
|
|
28
|
+
|
|
29
|
+
/** An out-parameter of a C function (`CFTypeRef *`): pass it, then read `value`. */
|
|
30
|
+
export declare class Out<T> {
|
|
31
|
+
constructor();
|
|
32
|
+
readonly value: T | null;
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// lucent:platform — which platform the code runs on.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The platform: `if (PLATFORM === "ios") { … } else { … }` and
|
|
5
|
+
* `PLATFORM === "ios" ? … : …` compile each platform's branch only, so a
|
|
6
|
+
* shared module can use `lucent:ios/…` and `lucent:android/…` in them.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PLATFORM: "ios" | "android";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// lucent:thread — thread affinity for platform code.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Runs `f` on the platform's main thread (the main queue on iOS, the main
|
|
5
|
+
* Looper on Android) and resolves with its result. Main-thread-only SDK
|
|
6
|
+
* APIs may only be used inside `f`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function main<T>(f: () => T): Promise<T>;
|
package/metro/index.cjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Metro integration. `*.lucent.ts` files stay the source of truth for types;
|
|
3
|
+
// when bundling, their contents are replaced by the generated JS proxy that
|
|
4
|
+
// forwards to the native module (written by `lucent build`).
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { spawn } = require("node:child_process");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wraps a Metro config:
|
|
10
|
+
* module.exports = withLucent(getDefaultConfig(__dirname));
|
|
11
|
+
*
|
|
12
|
+
* When Metro runs as a dev server, `lucent dev --compact` keeps
|
|
13
|
+
* `.lucent/native` up to date while you edit *.lucent.ts files, one line
|
|
14
|
+
* per build in Metro's output (it never reads Metro's keys; for the full
|
|
15
|
+
* dashboard, run `lucent dev` in a terminal of its own). Set
|
|
16
|
+
* `{ watch: false }` or LUCENT_WATCH=0 to turn that off (LUCENT_WATCH=1 forces it).
|
|
17
|
+
*/
|
|
18
|
+
function withLucent(config, options = {}) {
|
|
19
|
+
if (shouldWatch(options)) startWatcher(config.projectRoot || process.cwd());
|
|
20
|
+
const upstream =
|
|
21
|
+
(config.transformer && config.transformer.babelTransformerPath) || defaultTransformer();
|
|
22
|
+
// Transformer workers inherit the environment.
|
|
23
|
+
process.env.LUCENT_UPSTREAM_TRANSFORMER = upstream;
|
|
24
|
+
return {
|
|
25
|
+
...config,
|
|
26
|
+
transformer: {
|
|
27
|
+
...config.transformer,
|
|
28
|
+
babelTransformerPath: path.join(__dirname, "transformer.cjs"),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function defaultTransformer() {
|
|
34
|
+
for (const candidate of [
|
|
35
|
+
"@react-native/metro-babel-transformer",
|
|
36
|
+
"@expo/metro-config/babel-transformer",
|
|
37
|
+
]) {
|
|
38
|
+
try {
|
|
39
|
+
return require.resolve(candidate, { paths: [process.cwd()] });
|
|
40
|
+
} catch {
|
|
41
|
+
// try the next one
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
throw new Error(
|
|
45
|
+
"Lucent: could not find Metro's babel transformer; set transformer.babelTransformerPath first",
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function shouldWatch(options) {
|
|
50
|
+
if (options.watch !== undefined) return options.watch;
|
|
51
|
+
if (process.env.LUCENT_WATCH === "0") return false;
|
|
52
|
+
if (process.env.LUCENT_WATCH === "1") return true;
|
|
53
|
+
// Dev servers: `react-native start`, `expo start`, `expo run:ios|android`.
|
|
54
|
+
return process.argv.some((a) => a === "start" || a === "run:ios" || a === "run:android");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let watcher;
|
|
58
|
+
|
|
59
|
+
function startWatcher(root) {
|
|
60
|
+
// Metro may load the config more than once in a process.
|
|
61
|
+
if (watcher || process.env.LUCENT_WATCH_CHILD) return;
|
|
62
|
+
const bin = path.join(__dirname, "../bin/lucent.cjs");
|
|
63
|
+
// stdin stays Metro's: its keys (r reload, d dev menu) are not ours.
|
|
64
|
+
watcher = spawn(process.execPath, [bin, "dev", "--compact", "--root", root], {
|
|
65
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
66
|
+
env: { ...process.env, LUCENT_WATCH_CHILD: "1" },
|
|
67
|
+
});
|
|
68
|
+
// Ctrl-C reaches the watcher through the process group; this covers the rest.
|
|
69
|
+
process.on("exit", () => watcher.kill());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { withLucent };
|
package/metro/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface LucentMetroOptions {
|
|
2
|
+
/** Rebuild .lucent/native while the dev server runs (default: on for dev servers; LUCENT_WATCH=0/1 overrides). */
|
|
3
|
+
watch?: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export declare function withLucent<T extends object>(config: T, options?: LucentMetroOptions): T;
|