lecodes-cli 2.2.6 → 2.2.8
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 +96 -15
- package/package.json +8 -8
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/VERSION.json +3 -3
- package/runtime/web/assets/browser-BpFb50ko.js +1 -0
- package/runtime/web/assets/webrtc-CbCltXvl.js +1 -0
- package/runtime/web/player.js +6 -6
- package/runtime/web-lite/lite.js +1 -1
- package/runtime/web-lite/plugins/browser/index-BpFb50ko.js +1 -0
- package/runtime/web-lite/plugins/webrtc/index-CbCltXvl.js +1 -0
- package/runtime/web-lite/plugins.json +3 -1
- package/src/commands/app/android.ts +30 -3
- package/src/commands/app/desktop.ts +3 -2
- package/src/commands/app/index.ts +4 -4
- package/src/commands/app/shared.ts +18 -0
- package/src/commands/app/templates/android.ts +14 -2
- package/src/commands/app/templates/ios.ts +35 -3
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.8",
|
|
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.8",
|
|
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.8", 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);
|
|
@@ -1703,7 +1703,9 @@ var init_chisel = __esm(() => {
|
|
|
1703
1703
|
"NativeView",
|
|
1704
1704
|
"CameraView",
|
|
1705
1705
|
"MapView",
|
|
1706
|
-
"QRScanner"
|
|
1706
|
+
"QRScanner",
|
|
1707
|
+
"WebView",
|
|
1708
|
+
"RTCVideoView"
|
|
1707
1709
|
],
|
|
1708
1710
|
containers: ["UIColumn", "UIRow", "UIBox", "UIButton", "UIScrollable", "UIScreen", "UIWidget"],
|
|
1709
1711
|
text: "UIText",
|
|
@@ -217963,7 +217965,19 @@ var FIRST_PARTY_PLUGINS = {
|
|
|
217963
217965
|
"qr-scanner": "letary/lecodes-plugins",
|
|
217964
217966
|
map: "letary/lecodes-plugins",
|
|
217965
217967
|
geolocation: "letary/lecodes-plugins",
|
|
217966
|
-
push: "letary/lecodes-plugins"
|
|
217968
|
+
push: "letary/lecodes-plugins",
|
|
217969
|
+
browser: "letary/lecodes-plugins"
|
|
217970
|
+
};
|
|
217971
|
+
var urlSchemeOf = (config) => {
|
|
217972
|
+
const scheme = config?.urlScheme;
|
|
217973
|
+
if (scheme === undefined)
|
|
217974
|
+
return;
|
|
217975
|
+
if (typeof scheme !== "string" || !/^[a-z][a-z0-9+.-]*$/.test(scheme)) {
|
|
217976
|
+
throw new CliError(`app.json "urlScheme" must be lowercase letters, digits, "+", "-" or ".", starting with a letter — got ${JSON.stringify(scheme)}.`);
|
|
217977
|
+
}
|
|
217978
|
+
if (scheme === "http" || scheme === "https")
|
|
217979
|
+
throw new CliError(`app.json "urlScheme" is the app's OWN scheme ("myshop" → myshop://…), not ${scheme}.`);
|
|
217980
|
+
return scheme;
|
|
217967
217981
|
};
|
|
217968
217982
|
var readAppConfigAt = (root) => readJson2(join18(root, "app.json"));
|
|
217969
217983
|
var DESKTOP_DEFAULT_WINDOW = { width: 1280, height: 720 };
|
|
@@ -218887,11 +218901,30 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
|
218887
218901
|
LeCodesAppHooks.coldStartNotification(response)
|
|
218888
218902
|
}
|
|
218889
218903
|
|
|
218904
|
+
let controller = ViewController()
|
|
218905
|
+
// Cold-started by a link (app.json "urlScheme", or a universal link): the engine reads it as
|
|
218906
|
+
// app.launchUrl — set BEFORE the view loads, which boots the JS world.
|
|
218907
|
+
if let url = connectionOptions.urlContexts.first?.url
|
|
218908
|
+
?? connectionOptions.userActivities.first(where: { $0.activityType == NSUserActivityTypeBrowsingWeb })?.webpageURL {
|
|
218909
|
+
controller.engine.setLaunchUrl(url.absoluteString)
|
|
218910
|
+
}
|
|
218890
218911
|
let window = UIWindow(windowScene: windowScene)
|
|
218891
|
-
window.rootViewController =
|
|
218912
|
+
window.rootViewController = controller
|
|
218892
218913
|
self.window = window
|
|
218893
218914
|
window.makeKeyAndVisible()
|
|
218894
218915
|
}
|
|
218916
|
+
|
|
218917
|
+
// A link while the app runs: the "url" app event (an OAuth redirect back into the app, a
|
|
218918
|
+
// checkout's return — what Browser.open(url, { returnUrl }) resolves on).
|
|
218919
|
+
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
|
218920
|
+
guard let url = URLContexts.first?.url else { return }
|
|
218921
|
+
(window?.rootViewController as? ViewController)?.engine.emitUrl(url.absoluteString)
|
|
218922
|
+
}
|
|
218923
|
+
|
|
218924
|
+
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
|
218925
|
+
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else { return }
|
|
218926
|
+
(window?.rootViewController as? ViewController)?.engine.emitUrl(url.absoluteString)
|
|
218927
|
+
}
|
|
218895
218928
|
}
|
|
218896
218929
|
`;
|
|
218897
218930
|
var VIEW_CONTROLLER = `//
|
|
@@ -218952,9 +218985,22 @@ ${body}</dict>
|
|
|
218952
218985
|
</plist>
|
|
218953
218986
|
`;
|
|
218954
218987
|
};
|
|
218955
|
-
var infoPlistTemplate = (pluginKeys, updateUrl) => {
|
|
218988
|
+
var infoPlistTemplate = (pluginKeys, updateUrl, urlScheme) => {
|
|
218956
218989
|
const xml = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
218957
218990
|
const keys = Object.keys(pluginKeys).sort();
|
|
218991
|
+
const schemeBlock = !urlScheme ? "" : `
|
|
218992
|
+
<!-- lecodes:urlScheme — app.json "urlScheme": links the app opens on (the "url" app event) -->
|
|
218993
|
+
<key>CFBundleURLTypes</key>
|
|
218994
|
+
<array>
|
|
218995
|
+
<dict>
|
|
218996
|
+
<key>CFBundleURLName</key>
|
|
218997
|
+
<string>${xml(urlScheme)}</string>
|
|
218998
|
+
<key>CFBundleURLSchemes</key>
|
|
218999
|
+
<array>
|
|
219000
|
+
<string>${xml(urlScheme)}</string>
|
|
219001
|
+
</array>
|
|
219002
|
+
</dict>
|
|
219003
|
+
</array>`;
|
|
218958
219004
|
const pluginBlock = keys.length === 0 ? "" : `
|
|
218959
219005
|
<!-- lecodes:plugins — merged from installed plugin manifests by \`lecodes app sync\` -->
|
|
218960
219006
|
${keys.map((k) => ` <key>${k}</key>
|
|
@@ -218972,7 +219018,7 @@ ${keys.map((k) => ` <key>${k}</key>
|
|
|
218972
219018
|
so App Store Connect skips the "Missing Compliance" prompt on every build.
|
|
218973
219019
|
Flip to <true/> only if the app adds its own non-exempt cryptography. -->
|
|
218974
219020
|
<key>ITSAppUsesNonExemptEncryption</key>
|
|
218975
|
-
<false
|
|
219021
|
+
<false/>${schemeBlock}
|
|
218976
219022
|
<key>UIApplicationSceneManifest</key>
|
|
218977
219023
|
<dict>
|
|
218978
219024
|
<key>UIApplicationSupportsMultipleScenes</key>
|
|
@@ -220359,7 +220405,16 @@ var APP_PROGUARD_RULES = `# R8 rules for app-local code (yours — \`lecodes app
|
|
|
220359
220405
|
# reflection, e.g.
|
|
220360
220406
|
# -keep class com.example.myapp.MyBridge { *; }
|
|
220361
220407
|
`;
|
|
220362
|
-
var
|
|
220408
|
+
var urlSchemeFilter = (urlScheme) => !urlScheme ? "" : `
|
|
220409
|
+
<!-- lecodes:urlScheme — app.json "urlScheme": links the app opens on (the "url" app event) -->
|
|
220410
|
+
<intent-filter>
|
|
220411
|
+
<action android:name="android.intent.action.VIEW" />
|
|
220412
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
220413
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
220414
|
+
<data android:scheme="${urlScheme}" />
|
|
220415
|
+
</intent-filter>
|
|
220416
|
+
<!-- /lecodes:urlScheme -->`;
|
|
220417
|
+
var appManifestTemplate = (urlScheme) => `<?xml version="1.0" encoding="utf-8"?>
|
|
220363
220418
|
<!-- Generated by \`lecodes app init\` — yours to edit. Sync leaves it alone, except that with
|
|
220364
220419
|
app.json "icon" set it restamps the android:icon VALUE to the generated @mipmap set.
|
|
220365
220420
|
Plugin permissions/services arrive through the plugin modules' own manifests via the AGP
|
|
@@ -220384,7 +220439,7 @@ var appManifestTemplate = () => `<?xml version="1.0" encoding="utf-8"?>
|
|
|
220384
220439
|
<intent-filter>
|
|
220385
220440
|
<action android:name="android.intent.action.MAIN" />
|
|
220386
220441
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
220387
|
-
</intent-filter
|
|
220442
|
+
</intent-filter>${urlSchemeFilter(urlScheme)}
|
|
220388
220443
|
</activity>
|
|
220389
220444
|
</application>
|
|
220390
220445
|
|
|
@@ -221010,7 +221065,7 @@ var initAndroid = async (opts) => {
|
|
|
221010
221065
|
write("gradle/wrapper/gradle-wrapper.jar", wrapperJar);
|
|
221011
221066
|
write("app/build.gradle.kts", appBuildGradleTemplate(identity, config.android.minify ?? true));
|
|
221012
221067
|
write("app/proguard-rules.pro", APP_PROGUARD_RULES);
|
|
221013
|
-
write("app/src/main/AndroidManifest.xml", appManifestTemplate());
|
|
221068
|
+
write("app/src/main/AndroidManifest.xml", appManifestTemplate(urlSchemeOf(config)));
|
|
221014
221069
|
write(`app/src/main/java/${pkgPath}/MainActivity.kt`, mainActivityTemplate(identity.applicationId));
|
|
221015
221070
|
write(`app/src/main/java/${pkgPath}/AppViewModel.kt`, appViewModelTemplate(identity.applicationId));
|
|
221016
221071
|
write("app/src/main/res/values/themes.xml", themesXmlTemplate());
|
|
@@ -221188,10 +221243,36 @@ var syncAndroid = async (root, config, prior) => {
|
|
|
221188
221243
|
await writeAndroidIcons(androidDir, await loadIconMaster(root, config));
|
|
221189
221244
|
restampManifestIcon(androidDir);
|
|
221190
221245
|
}
|
|
221246
|
+
restampManifestUrlScheme(androidDir, urlSchemeOf(config));
|
|
221191
221247
|
log("");
|
|
221192
221248
|
success(`Android shell synced: app.js + ${runtimePlugins.length} plugin(s), SDK ${sdkVersion}, v${config.version ?? "1.0.0"} (${config.android?.versionCode ?? 1}).`);
|
|
221193
221249
|
note("Build & run from Android Studio (`lecodes app open android`) — user files in android/app/ were not touched.");
|
|
221194
221250
|
};
|
|
221251
|
+
var restampManifestUrlScheme = (androidDir, urlScheme) => {
|
|
221252
|
+
const path2 = join21(androidDir, "app", "src", "main", "AndroidManifest.xml");
|
|
221253
|
+
if (!existsSync19(path2))
|
|
221254
|
+
return;
|
|
221255
|
+
const content = readFileSync18(path2, "utf8");
|
|
221256
|
+
const tagged = /\n[ \t]*<!-- lecodes:urlScheme[\s\S]*?<!-- \/lecodes:urlScheme -->/;
|
|
221257
|
+
const block = urlSchemeFilter(urlScheme);
|
|
221258
|
+
let next;
|
|
221259
|
+
if (tagged.test(content))
|
|
221260
|
+
next = content.replace(tagged, block);
|
|
221261
|
+
else if (!urlScheme)
|
|
221262
|
+
return;
|
|
221263
|
+
else {
|
|
221264
|
+
const launcher = /(<category android:name="android\.intent\.category\.LAUNCHER" \/>\s*<\/intent-filter>)/;
|
|
221265
|
+
if (!launcher.test(content)) {
|
|
221266
|
+
warn(`couldn't find the launcher activity in app/src/main/AndroidManifest.xml — add an intent-filter for the "${urlScheme}" scheme yourself.`);
|
|
221267
|
+
return;
|
|
221268
|
+
}
|
|
221269
|
+
next = content.replace(launcher, `$1${block}`);
|
|
221270
|
+
}
|
|
221271
|
+
if (next === content)
|
|
221272
|
+
return;
|
|
221273
|
+
writeFileSync14(path2, next);
|
|
221274
|
+
log(`${c.green("updated")} android/app/src/main/AndroidManifest.xml: urlScheme ${urlScheme ? `→ ${urlScheme}://` : "removed"}`);
|
|
221275
|
+
};
|
|
221195
221276
|
var restampAppBuildGradle = (androidDir, config, gradlePlugins) => {
|
|
221196
221277
|
const path2 = join21(androidDir, "app", "build.gradle.kts");
|
|
221197
221278
|
if (!existsSync19(path2)) {
|
|
@@ -222692,7 +222773,7 @@ var buildDesktop = async (flags) => {
|
|
|
222692
222773
|
localShaders: true,
|
|
222693
222774
|
desktopRenderer: renderer
|
|
222694
222775
|
});
|
|
222695
|
-
const wanted = new Set([...js.matchAll(/fetchLocal\("([^"]+)"\)/g)].map((m) => m[1]));
|
|
222776
|
+
const wanted = new Set([...js.matchAll(/(?:fetchLocal|_creatorFetch\.local)\("([^"]+)"\)/g)].map((m) => m[1]));
|
|
222696
222777
|
const shipped = resources.filter((r2) => !r2.remote && (r2.shader || wanted.has(r2.name)));
|
|
222697
222778
|
const byName = new Map;
|
|
222698
222779
|
for (const r2 of resources) {
|
|
@@ -222991,7 +223072,7 @@ var initIos = async (opts) => {
|
|
|
222991
223072
|
write("App/AppDelegate.swift", APP_DELEGATE);
|
|
222992
223073
|
write("App/SceneDelegate.swift", SCENE_DELEGATE);
|
|
222993
223074
|
write("App/ViewController.swift", VIEW_CONTROLLER);
|
|
222994
|
-
write("App/Info.plist", infoPlistTemplate({}));
|
|
223075
|
+
write("App/Info.plist", infoPlistTemplate({}, undefined, urlSchemeOf(config)));
|
|
222995
223076
|
write("App/App.entitlements", entitlementsTemplate({}));
|
|
222996
223077
|
write("App/Base.lproj/LaunchScreen.storyboard", LAUNCH_STORYBOARD);
|
|
222997
223078
|
write("App/Assets.xcassets/Contents.json", ASSETS_ROOT_JSON);
|
|
@@ -223178,7 +223259,7 @@ var syncIos = async (root, config) => {
|
|
|
223178
223259
|
for (const [key, values] of Object.entries(infoValues))
|
|
223179
223260
|
mergedKeys[key] = [...new Set(values)].join(" ");
|
|
223180
223261
|
const updateUrl = resolveUpdateUrl(config.update, root, sdkVersion);
|
|
223181
|
-
writeFileSync18(join25(iosDir, "App", "Info.plist"), infoPlistTemplate(mergedKeys, updateUrl));
|
|
223262
|
+
writeFileSync18(join25(iosDir, "App", "Info.plist"), infoPlistTemplate(mergedKeys, updateUrl, urlSchemeOf(config)));
|
|
223182
223263
|
if (updateUrl)
|
|
223183
223264
|
log(`${c.green("update")} OTA source ${updateUrl} — checked natively at launch, new code applies next launch${config.update === undefined ? c.dim(' ("update": false in app.json turns it off)') : ""}`);
|
|
223184
223265
|
else if (config.update === false)
|
|
@@ -223240,7 +223321,7 @@ var sync2 = defineCommand({
|
|
|
223240
223321
|
usage: "[ios|android]",
|
|
223241
223322
|
description: `Compiles the bundle and embeds the assets it references (ios/App/Resources/ resp. the android assets/; offline by default, also for server projects — app.json "resources": {"remote": [globs]} keeps heavy assets streaming), picks the SDK variant from the bundle's engine use, vendors the app.json plugins (pinned in plugins.lock.json) and regenerates the CLI-owned shell files. User files (ios/App/*.swift, android/app/) are never touched.
|
|
223242
223323
|
|
|
223243
|
-
Native OTA JS updates at launch (both shells; the current launch runs the newest LOCAL bundle, a download applies on the next): on by default for a pushed project (its bundle on the platform, the launcher's own URL), app.json "update": {"url": …} for custom hosting, "update": false turns it off. A download runs only when it is of the shell's SDK major and not older than the bundle running. app.json "icon" (a square ≥1024px image) renders the app icons every sync ("iconBackground": the adaptive / flatten backdrop). No platform = every shell that exists; a dual-shell project compiles once.`,
|
|
223324
|
+
Native OTA JS updates at launch (both shells; the current launch runs the newest LOCAL bundle, a download applies on the next): on by default for a pushed project (its bundle on the platform, the launcher's own URL), app.json "update": {"url": …} for custom hosting, "update": false turns it off. A download runs only when it is of the shell's SDK major and not older than the bundle running. app.json "icon" (a square ≥1024px image) renders the app icons every sync ("iconBackground": the adaptive / flatten backdrop). app.json "urlScheme" ("myshop") is the scheme the shells open on: iOS CFBundleURLTypes, Android a BROWSABLE intent-filter — a link arrives as app.launchUrl / the "url" event (the return of Browser.open with a returnUrl). No platform = every shell that exists; a dual-shell project compiles once.`,
|
|
223244
223325
|
examples: ["lecodes app sync", "lecodes app sync android"],
|
|
223245
223326
|
run: ({ args }) => runSync(args[0])
|
|
223246
223327
|
});
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lecodes-cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.8",
|
|
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.8"
|
|
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.8",
|
|
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.8",
|
|
17
|
+
"lecodes-web-frame": "2.2.8",
|
|
18
|
+
"lecodes-web-player": "2.2.8",
|
|
19
|
+
"lecodes-web-shared": "2.2.8",
|
|
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.8",
|
|
28
28
|
"lecodes-3d-editor": "^0.9.0",
|
|
29
29
|
"lecodes-assets": "^0.2.1",
|
|
30
30
|
"heic-decode": "^2.1.0",
|