lecodes-cli 2.2.8 → 2.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +141 -25
- package/package.json +8 -8
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/VERSION.json +3 -3
- package/runtime/web/player.js +2 -2
- package/runtime/web-lite/lite.js +1 -1
- package/src/commands/app/shared.ts +1 -2
- package/src/commands/plugin.ts +8 -2
- package/src/plugin/emitPackage.ts +98 -0
- package/src/plugin/generate.ts +51 -16
package/dist/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "lecodes-cli",
|
|
55
|
-
version: "2.2.
|
|
55
|
+
version: "2.2.9",
|
|
56
56
|
dependencies: {
|
|
57
57
|
"@letary/chisel": "^0.14.0",
|
|
58
58
|
jimp: "^1.6.1",
|
|
@@ -76,7 +76,7 @@ var init_package = __esm(() => {
|
|
|
76
76
|
},
|
|
77
77
|
peerDependencies: {
|
|
78
78
|
"lecodes-design": "^0.11.0",
|
|
79
|
-
"lecodes-headless": "^2.2.
|
|
79
|
+
"lecodes-headless": "^2.2.9",
|
|
80
80
|
"lecodes-3d-editor": "^0.9.0",
|
|
81
81
|
"lecodes-assets": "^0.2.1",
|
|
82
82
|
"heic-decode": "^2.1.0",
|
|
@@ -146,7 +146,7 @@ var init_package = __esm(() => {
|
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
// ../../sdk/src/version.ts
|
|
149
|
-
var SDK_VERSION = "2.2.
|
|
149
|
+
var SDK_VERSION = "2.2.9", sdkMajor = (version) => {
|
|
150
150
|
const m = version?.match(/^(\d+)\.\d+\.\d+/);
|
|
151
151
|
return m ? Number(m[1]) : null;
|
|
152
152
|
}, bundleSdkVersion = (head) => head.slice(0, 2000).match(/^\/\/ sdk: (\d+\.\d+\.\d+\S*)/m)?.[1] ?? null, bundleRunsOn = (bundleVersion, hostVersion) => sdkMajor(bundleVersion) !== null && sdkMajor(bundleVersion) === sdkMajor(hostVersion);
|
|
@@ -217959,6 +217959,82 @@ var readManifest2 = (dir, id) => {
|
|
|
217959
217959
|
};
|
|
217960
217960
|
var readManifestIfAny = (dir, id) => existsSync14(join17(dir, MANIFEST_FILE)) ? readManifest2(dir, id) : null;
|
|
217961
217961
|
|
|
217962
|
+
// src/plugin/emitPackage.ts
|
|
217963
|
+
class PackageError extends Error {
|
|
217964
|
+
}
|
|
217965
|
+
var swiftPackageName = (url) => (url.replace(/\/+$/, "").split("/").pop() ?? url).replace(/\.git$/, "");
|
|
217966
|
+
var iosModule = (id, manifest) => manifest.ios?.module ?? `LeCodes${pascal(id)}`;
|
|
217967
|
+
var PACKAGE_FILE = "Package.swift";
|
|
217968
|
+
var DEFAULT_SDK_PATH = "../lecodes";
|
|
217969
|
+
var emitPackageSwift = (plugins, sdkPath = DEFAULT_SDK_PATH) => {
|
|
217970
|
+
const ios = plugins.filter((p) => p.manifest.ios !== null);
|
|
217971
|
+
const packages = new Map;
|
|
217972
|
+
for (const p of ios) {
|
|
217973
|
+
for (const pkg of p.manifest.ios.packages ?? []) {
|
|
217974
|
+
const prior = packages.get(pkg.url);
|
|
217975
|
+
if (prior && (prior.exact !== pkg.exact || prior.from !== pkg.from)) {
|
|
217976
|
+
throw new PackageError(`"${p.id}" pins ${pkg.url} at ${pkg.exact ?? `from ${pkg.from}`} but "${prior.by}" pins ${prior.exact ?? `from ${prior.from}`} — one package resolves once`);
|
|
217977
|
+
}
|
|
217978
|
+
if (!prior)
|
|
217979
|
+
packages.set(pkg.url, { ...pkg, by: p.id });
|
|
217980
|
+
}
|
|
217981
|
+
}
|
|
217982
|
+
const moduleOf = (p) => iosModule(p.id, p.manifest);
|
|
217983
|
+
const products = ios.map((p) => ` .library(name: "${moduleOf(p)}", targets: ["${moduleOf(p)}"]),`);
|
|
217984
|
+
const dependencies = [
|
|
217985
|
+
` .package(name: "lecodes", path: sdk),`,
|
|
217986
|
+
...[...packages.values()].map((pkg) => ` .package(url: "${pkg.url}", ${pkg.exact ? `exact: "${pkg.exact}"` : `from: "${pkg.from}"`}),`)
|
|
217987
|
+
];
|
|
217988
|
+
const targets = ios.map((p) => {
|
|
217989
|
+
const deps = [
|
|
217990
|
+
`.product(name: "LeCodes", package: "lecodes")`,
|
|
217991
|
+
...(p.manifest.ios.packages ?? []).flatMap((pkg) => pkg.products.map((name) => `.product(name: "${name}", package: "${swiftPackageName(pkg.url)}")`))
|
|
217992
|
+
];
|
|
217993
|
+
return [
|
|
217994
|
+
` // ${p.id}`,
|
|
217995
|
+
` .target(`,
|
|
217996
|
+
` name: "${moduleOf(p)}",`,
|
|
217997
|
+
` dependencies: [${deps.join(", ")}],`,
|
|
217998
|
+
` path: "plugins/${p.id}/ios"`,
|
|
217999
|
+
` ),`
|
|
218000
|
+
].join(`
|
|
218001
|
+
`);
|
|
218002
|
+
});
|
|
218003
|
+
return `// swift-tools-version:5.9
|
|
218004
|
+
// GENERATED by \`lecodes plugin gen\` from the plugins' manifests (lecodes-plugin.json) — do not edit.
|
|
218005
|
+
//
|
|
218006
|
+
// The plugins with an iOS half as ONE SwiftPM package: a target per plugin (its sources in
|
|
218007
|
+
// plugins/<id>/ios, the packages its manifest names) and a product per plugin. Each plugin is its
|
|
218008
|
+
// own module: an Xcode project links a plugin as a product instead of compiling its folder, and two
|
|
218009
|
+
// plugins may name a type alike.
|
|
218010
|
+
//
|
|
218011
|
+
// The SDK is the LeCodes package on disk: LECODES_IOS_SDK_PATH, else the path below (the repo's
|
|
218012
|
+
// package.json \`lecodes.iosSdkPath\`, or the sibling ../lecodes). A shell made by \`lecodes app sync\`
|
|
218013
|
+
// does not use this package: it vendors the sources into targets of its own, pinned by
|
|
218014
|
+
// plugins.lock.json.
|
|
218015
|
+
import PackageDescription
|
|
218016
|
+
|
|
218017
|
+
let sdk = Context.environment["LECODES_IOS_SDK_PATH"] ?? ${JSON.stringify(sdkPath)}
|
|
218018
|
+
|
|
218019
|
+
let package = Package(
|
|
218020
|
+
name: "lecodes-plugins",
|
|
218021
|
+
platforms: [.iOS(.v15)],
|
|
218022
|
+
products: [
|
|
218023
|
+
${products.join(`
|
|
218024
|
+
`)}
|
|
218025
|
+
],
|
|
218026
|
+
dependencies: [
|
|
218027
|
+
${dependencies.join(`
|
|
218028
|
+
`)}
|
|
218029
|
+
],
|
|
218030
|
+
targets: [
|
|
218031
|
+
${targets.join(`
|
|
218032
|
+
`)}
|
|
218033
|
+
]
|
|
218034
|
+
)
|
|
218035
|
+
`;
|
|
218036
|
+
};
|
|
218037
|
+
|
|
217962
218038
|
// src/commands/app/shared.ts
|
|
217963
218039
|
var FIRST_PARTY_PLUGINS = {
|
|
217964
218040
|
camera: "letary/lecodes-plugins",
|
|
@@ -218006,7 +218082,6 @@ var desktopDefaultViewport = (root) => {
|
|
|
218006
218082
|
height: cfg.desktop.window?.height ?? DESKTOP_DEFAULT_WINDOW.height
|
|
218007
218083
|
};
|
|
218008
218084
|
};
|
|
218009
|
-
var swiftPackageName = (url) => (url.replace(/\/+$/, "").split("/").pop() ?? url).replace(/\.git$/, "");
|
|
218010
218085
|
var isLocalPluginSpec = (spec) => spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/") || spec.startsWith("file:");
|
|
218011
218086
|
var resolveUpdateUrl = (update, root, sdkVersion) => {
|
|
218012
218087
|
if (update === false)
|
|
@@ -231179,7 +231254,7 @@ var loadTypescript = (dir) => {
|
|
|
231179
231254
|
var generatePlugin = (ts, plugin2) => {
|
|
231180
231255
|
const file = join46(plugin2.dir, CONTRACT_FILE);
|
|
231181
231256
|
const contract = readContract(ts, file, readFileSync33(file, "utf8"));
|
|
231182
|
-
readManifestIfAny(plugin2.dir, plugin2.id);
|
|
231257
|
+
const manifest = readManifestIfAny(plugin2.dir, plugin2.id);
|
|
231183
231258
|
const handWritten = existsSync41(join46(plugin2.dir, "sdk", `${plugin2.id}.ts`));
|
|
231184
231259
|
const single = contract.channels.length === 1;
|
|
231185
231260
|
const files = contract.channels.map((channel) => ({
|
|
@@ -231203,7 +231278,7 @@ var generatePlugin = (ts, plugin2) => {
|
|
|
231203
231278
|
${foreign.map((f5) => ` ${f5}`).join(`
|
|
231204
231279
|
`)}`);
|
|
231205
231280
|
}
|
|
231206
|
-
return { contract, files };
|
|
231281
|
+
return { contract, manifest, files };
|
|
231207
231282
|
};
|
|
231208
231283
|
var hostImports = (web) => {
|
|
231209
231284
|
const found = [];
|
|
@@ -231243,32 +231318,53 @@ var kotlinPackage = (android) => {
|
|
|
231243
231318
|
}
|
|
231244
231319
|
return { dir, name: relative8(root, dir).split(/[\\/]/).join(".") };
|
|
231245
231320
|
};
|
|
231321
|
+
var repoSdkPath = (root) => {
|
|
231322
|
+
const file = join46(root, "package.json");
|
|
231323
|
+
if (!existsSync41(file))
|
|
231324
|
+
return DEFAULT_SDK_PATH;
|
|
231325
|
+
try {
|
|
231326
|
+
const pkg = JSON.parse(readFileSync33(file, "utf8"));
|
|
231327
|
+
const path2 = pkg.lecodes?.iosSdkPath;
|
|
231328
|
+
if (path2 !== undefined && typeof path2 !== "string")
|
|
231329
|
+
throw new PackageError(`package.json lecodes.iosSdkPath: a path, as a string`);
|
|
231330
|
+
return path2 ?? DEFAULT_SDK_PATH;
|
|
231331
|
+
} catch (e2) {
|
|
231332
|
+
if (e2 instanceof PackageError)
|
|
231333
|
+
throw e2;
|
|
231334
|
+
throw new PackageError(`package.json does not parse: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
231335
|
+
}
|
|
231336
|
+
};
|
|
231246
231337
|
var generate = (path2, opts = {}) => {
|
|
231247
231338
|
const plugins = findPlugins(path2);
|
|
231248
231339
|
if (plugins.length === 0)
|
|
231249
231340
|
throw new CliError(`No plugin under ${resolve23(path2)}: a plugin is a directory with a ${CONTRACT_FILE} (one, or plugins/<id>/ of a repo).`);
|
|
231250
231341
|
const ts = loadTypescript(plugins[0].dir);
|
|
231251
231342
|
const root = resolve23(path2);
|
|
231252
|
-
const report = { plugins: [], failures: [] };
|
|
231343
|
+
const report = { plugins: [], repo: { written: [], stale: [], fresh: [] }, failures: [] };
|
|
231344
|
+
const place = (f5, entry) => {
|
|
231345
|
+
const name = shown(root, f5.file) || basename23(f5.file);
|
|
231346
|
+
const current = existsSync41(f5.file) ? readFileSync33(f5.file, "utf8") : null;
|
|
231347
|
+
if (current === f5.text) {
|
|
231348
|
+
entry.fresh.push(name);
|
|
231349
|
+
return;
|
|
231350
|
+
}
|
|
231351
|
+
if (opts.check) {
|
|
231352
|
+
entry.stale.push(name);
|
|
231353
|
+
return;
|
|
231354
|
+
}
|
|
231355
|
+
mkdirSync26(join46(f5.file, ".."), { recursive: true });
|
|
231356
|
+
writeFileSync28(f5.file, f5.text);
|
|
231357
|
+
entry.written.push(name);
|
|
231358
|
+
};
|
|
231359
|
+
const manifests = [];
|
|
231253
231360
|
for (const plugin2 of plugins) {
|
|
231254
231361
|
try {
|
|
231255
|
-
const { contract, files } = generatePlugin(ts, plugin2);
|
|
231362
|
+
const { contract, manifest, files } = generatePlugin(ts, plugin2);
|
|
231363
|
+
if (manifest)
|
|
231364
|
+
manifests.push({ id: plugin2.id, manifest });
|
|
231256
231365
|
const entry = { id: plugin2.id, contract, written: [], stale: [], fresh: [] };
|
|
231257
|
-
for (const f5 of files)
|
|
231258
|
-
|
|
231259
|
-
const current = existsSync41(f5.file) ? readFileSync33(f5.file, "utf8") : null;
|
|
231260
|
-
if (current === f5.text) {
|
|
231261
|
-
entry.fresh.push(name);
|
|
231262
|
-
continue;
|
|
231263
|
-
}
|
|
231264
|
-
if (opts.check) {
|
|
231265
|
-
entry.stale.push(name);
|
|
231266
|
-
continue;
|
|
231267
|
-
}
|
|
231268
|
-
mkdirSync26(join46(f5.file, ".."), { recursive: true });
|
|
231269
|
-
writeFileSync28(f5.file, f5.text);
|
|
231270
|
-
entry.written.push(name);
|
|
231271
|
-
}
|
|
231366
|
+
for (const f5 of files)
|
|
231367
|
+
place(f5, entry);
|
|
231272
231368
|
report.plugins.push(entry);
|
|
231273
231369
|
} catch (e2) {
|
|
231274
231370
|
if (e2 instanceof ContractError)
|
|
@@ -231284,6 +231380,17 @@ ${e2.problems.map((p2) => ` ${p2}`).join(`
|
|
|
231284
231380
|
throw e2;
|
|
231285
231381
|
}
|
|
231286
231382
|
}
|
|
231383
|
+
const isRepo = !existsSync41(join46(root, CONTRACT_FILE));
|
|
231384
|
+
if (isRepo && report.failures.length === 0 && manifests.some((m) => m.manifest.ios)) {
|
|
231385
|
+
try {
|
|
231386
|
+
place({ file: join46(root, PACKAGE_FILE), text: emitPackageSwift(manifests, repoSdkPath(root)) }, report.repo);
|
|
231387
|
+
} catch (e2) {
|
|
231388
|
+
if (e2 instanceof PackageError)
|
|
231389
|
+
report.failures.push(`${PACKAGE_FILE}: ${e2.message}`);
|
|
231390
|
+
else
|
|
231391
|
+
throw e2;
|
|
231392
|
+
}
|
|
231393
|
+
}
|
|
231287
231394
|
return report;
|
|
231288
231395
|
};
|
|
231289
231396
|
|
|
@@ -231294,7 +231401,7 @@ var gen = defineCommand({
|
|
|
231294
231401
|
usage: "[path]",
|
|
231295
231402
|
description: `The path is one plugin (a directory with a contract.d.ts) or a repo that keeps its plugins in plugins/<id>/; the current directory when omitted.
|
|
231296
231403
|
|
|
231297
|
-
Writes sdk/<id>.gen.ts — the wrapper an app calls: the wire call by call, the class with the wire's methods as its own, and the public export when the plugin has no hand-written sdk/<id>.ts. Where the plugin has an ios/ folder, writes ios/<Name>.gen.swift — the contract's types, the protocol the plugin implements and the glue that reads a call off the wire. Where it has an android/ folder, writes the same as <Name>.gen.kt into the folder of the plugin's Kotlin package (android/ is laid out as a Gradle module: the package is the folder the path under android/src/main/java narrows down to). Where it has a web/ folder, writes web/<id>.gen.ts — the same for the web half, in a file that imports nothing; a web half that imports a LeCodes package is refused, because it would run on that host only. A contract the generator does not understand is an error with its line, and every problem of a file is reported at once.
|
|
231404
|
+
Writes sdk/<id>.gen.ts — the wrapper an app calls: the wire call by call, the class with the wire's methods as its own, and the public export when the plugin has no hand-written sdk/<id>.ts. Where the plugin has an ios/ folder, writes ios/<Name>.gen.swift — the contract's types, the protocol the plugin implements and the glue that reads a call off the wire. Where it has an android/ folder, writes the same as <Name>.gen.kt into the folder of the plugin's Kotlin package (android/ is laid out as a Gradle module: the package is the folder the path under android/src/main/java narrows down to). Where it has a web/ folder, writes web/<id>.gen.ts — the same for the web half, in a file that imports nothing; a web half that imports a LeCodes package is refused, because it would run on that host only. A repo of plugins also gets its Package.swift from the manifests: the iOS halves as one SwiftPM package, a target and a product per plugin, the SDK as a package on disk (LECODES_IOS_SDK_PATH, else the repo's package.json lecodes.iosSdkPath, else ../lecodes) — what an Xcode project links the halves as (a shell vendors the sources instead). A contract the generator does not understand is an error with its line, and every problem of a file is reported at once.
|
|
231298
231405
|
|
|
231299
231406
|
Generated files are committed. Reading a contract needs TypeScript in the plugin's repo.`,
|
|
231300
231407
|
flags: {
|
|
@@ -231313,9 +231420,18 @@ Generated files are committed. Reading a contract needs TypeScript in the plugin
|
|
|
231313
231420
|
for (const f5 of p2.fresh)
|
|
231314
231421
|
log(c.dim(` fresh ${f5}`));
|
|
231315
231422
|
}
|
|
231423
|
+
if (report.repo.written.length + report.repo.stale.length + report.repo.fresh.length > 0) {
|
|
231424
|
+
info(`${c.bold("the repo")} ${c.dim("Package.swift from the manifests")}`);
|
|
231425
|
+
for (const f5 of report.repo.written)
|
|
231426
|
+
log(c.green(` written ${f5}`));
|
|
231427
|
+
for (const f5 of report.repo.stale)
|
|
231428
|
+
log(c.red(` stale ${f5}`));
|
|
231429
|
+
for (const f5 of report.repo.fresh)
|
|
231430
|
+
log(c.dim(` fresh ${f5}`));
|
|
231431
|
+
}
|
|
231316
231432
|
for (const failure2 of report.failures)
|
|
231317
231433
|
log(c.red(failure2));
|
|
231318
|
-
const stale = report.plugins.reduce((n2, p2) => n2 + p2.stale.length, 0);
|
|
231434
|
+
const stale = report.plugins.reduce((n2, p2) => n2 + p2.stale.length, 0) + report.repo.stale.length;
|
|
231319
231435
|
if (report.failures.length)
|
|
231320
231436
|
throw new CliError(`${report.failures.length} contract${report.failures.length === 1 ? "" : "s"} did not generate.`);
|
|
231321
231437
|
if (stale)
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lecodes-cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.9",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@letary/chisel": "^0.14.0",
|
|
6
6
|
"jimp": "^1.6.1",
|
|
7
|
-
"lecodes-sdk": "2.2.
|
|
7
|
+
"lecodes-sdk": "2.2.9"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"lecodes-design": "https://storage.yandexcloud.net/le-codes/releases/packages/lecodes-design/lecodes-design-0.11.0.tgz",
|
|
11
|
-
"lecodes-headless": "2.2.
|
|
11
|
+
"lecodes-headless": "2.2.9",
|
|
12
12
|
"qrcode-terminal": "^0.12.0",
|
|
13
13
|
"lecodes-3d-editor": "https://storage.yandexcloud.net/le-codes/releases/packages/lecodes-3d-editor/lecodes-3d-editor-0.9.0.tgz",
|
|
14
14
|
"lecodes-assets": "0.2.1",
|
|
15
15
|
"lecodes-creator-nav": "0.19.0",
|
|
16
|
-
"lecodes-gl-lite": "2.2.
|
|
17
|
-
"lecodes-web-frame": "2.2.
|
|
18
|
-
"lecodes-web-player": "2.2.
|
|
19
|
-
"lecodes-web-shared": "2.2.
|
|
16
|
+
"lecodes-gl-lite": "2.2.9",
|
|
17
|
+
"lecodes-web-frame": "2.2.9",
|
|
18
|
+
"lecodes-web-player": "2.2.9",
|
|
19
|
+
"lecodes-web-shared": "2.2.9",
|
|
20
20
|
"lecodes-web-lite": "2.0.2",
|
|
21
21
|
"heic-decode": "^2.1.0",
|
|
22
22
|
"marcidb-embedded": "^0.15.0",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"lecodes-design": "^0.11.0",
|
|
27
|
-
"lecodes-headless": "^2.2.
|
|
27
|
+
"lecodes-headless": "^2.2.9",
|
|
28
28
|
"lecodes-3d-editor": "^0.9.0",
|
|
29
29
|
"lecodes-assets": "^0.2.1",
|
|
30
30
|
"heic-decode": "^2.1.0",
|