@capgo/capacitor-pretty-toast 8.1.0
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/CapgoCapacitorPrettyToast.podspec +17 -0
- package/LICENSE +373 -0
- package/Package.swift +28 -0
- package/README.md +341 -0
- package/android/build.gradle +71 -0
- package/android/src/main/AndroidManifest.xml +6 -0
- package/android/src/main/java/com/toast/PrettyToastPlugin.kt +197 -0
- package/android/src/main/java/com/toast/ToastOverlay.kt +495 -0
- package/android/src/main/java/com/toast/anim/CutoutMorphAnimator.kt +235 -0
- package/android/src/main/java/com/toast/anim/SlideAnimator.kt +64 -0
- package/android/src/main/java/com/toast/anim/ToastAnimator.kt +23 -0
- package/android/src/main/java/com/toast/backdrop/BackdropSampler.kt +142 -0
- package/android/src/main/java/com/toast/backdrop/OutlineController.kt +100 -0
- package/android/src/main/java/com/toast/cutout/CutoutDetector.kt +88 -0
- package/android/src/main/java/com/toast/cutout/CutoutInfo.kt +28 -0
- package/android/src/main/java/com/toast/gesture/ToastGestureHandler.kt +68 -0
- package/android/src/main/java/com/toast/ui/IconMapper.kt +26 -0
- package/android/src/main/java/com/toast/ui/PassThroughFrameLayout.kt +53 -0
- package/android/src/main/java/com/toast/ui/ToastViewFactory.kt +224 -0
- package/android/src/main/java/com/toast/util/Density.kt +17 -0
- package/android/src/main/java/com/toast/util/StatusBarController.kt +24 -0
- package/android/src/main/java/com/toast/util/ToastConstants.kt +36 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/android/src/main/res/drawable/ic_arrow_downward.xml +9 -0
- package/android/src/main/res/drawable/ic_arrow_upward.xml +9 -0
- package/android/src/main/res/drawable/ic_cancel.xml +9 -0
- package/android/src/main/res/drawable/ic_check_circle.xml +9 -0
- package/android/src/main/res/drawable/ic_favorite.xml +9 -0
- package/android/src/main/res/drawable/ic_info.xml +9 -0
- package/android/src/main/res/drawable/ic_mail.xml +9 -0
- package/android/src/main/res/drawable/ic_notifications.xml +9 -0
- package/android/src/main/res/drawable/ic_touch_app.xml +9 -0
- package/android/src/main/res/drawable/ic_warning.xml +9 -0
- package/android/src/main/res/drawable/ic_wifi.xml +9 -0
- package/android/src/main/res/values/colors.xml +3 -0
- package/android/src/main/res/values/strings.xml +3 -0
- package/android/src/main/res/values/styles.xml +3 -0
- package/android/src/test/java/com/toast/PrettyToastPluginTest.kt +26 -0
- package/dist/docs.json +459 -0
- package/dist/esm/controller.d.ts +30 -0
- package/dist/esm/controller.js +271 -0
- package/dist/esm/controller.js.map +1 -0
- package/dist/esm/definitions.d.ts +144 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/driver.d.ts +19 -0
- package/dist/esm/driver.js +24 -0
- package/dist/esm/driver.js.map +1 -0
- package/dist/esm/icons.d.ts +14 -0
- package/dist/esm/icons.js +138 -0
- package/dist/esm/icons.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal-plugin.d.ts +2 -0
- package/dist/esm/internal-plugin.js +5 -0
- package/dist/esm/internal-plugin.js.map +1 -0
- package/dist/esm/internal-types.d.ts +31 -0
- package/dist/esm/internal-types.js +2 -0
- package/dist/esm/internal-types.js.map +1 -0
- package/dist/esm/toast.d.ts +1 -0
- package/dist/esm/toast.js +5 -0
- package/dist/esm/toast.js.map +1 -0
- package/dist/esm/web-renderer.d.ts +36 -0
- package/dist/esm/web-renderer.js +296 -0
- package/dist/esm/web-renderer.js.map +1 -0
- package/dist/esm/web.d.ts +10 -0
- package/dist/esm/web.js +28 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +770 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +773 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/PrettyToastPlugin/CustomHostingView.swift +13 -0
- package/ios/Sources/PrettyToastPlugin/PassThroughWindow.swift +143 -0
- package/ios/Sources/PrettyToastPlugin/PrettyToastColorParser.swift +94 -0
- package/ios/Sources/PrettyToastPlugin/PrettyToastPlugin.swift +138 -0
- package/ios/Sources/PrettyToastPlugin/PrettyToastView.swift +267 -0
- package/ios/Sources/PrettyToastPlugin/Toast.swift +29 -0
- package/ios/Sources/PrettyToastPlugin/ToastManager.swift +392 -0
- package/ios/Tests/PrettyToastPluginTests/PrettyToastPluginTests.swift +21 -0
- package/package.json +98 -0
- package/scripts/check-capacitor-plugin-wiring.mjs +254 -0
- package/scripts/deploy-example-capgo.mjs +86 -0
- package/scripts/test-ios.sh +14 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
@testable import PrettyToastPlugin
|
|
3
|
+
|
|
4
|
+
final class PrettyToastPluginTests: XCTestCase {
|
|
5
|
+
func testPluginMetadata() {
|
|
6
|
+
let plugin = PrettyToastPlugin()
|
|
7
|
+
XCTAssertEqual(plugin.identifier, "PrettyToastPlugin")
|
|
8
|
+
XCTAssertEqual(plugin.jsName, "PrettyToast")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
func testPluginMethods() {
|
|
12
|
+
let plugin = PrettyToastPlugin()
|
|
13
|
+
let methodNames = plugin.pluginMethods.map(\.name)
|
|
14
|
+
XCTAssertEqual(methodNames, ["showCurrentToast", "updateCurrentToast", "dismissCurrentToast"])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func testHexColorParsing() {
|
|
18
|
+
let color = PrettyToastColorParser.parse("#FF0000")
|
|
19
|
+
XCTAssertNotNil(color)
|
|
20
|
+
}
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/capacitor-pretty-toast",
|
|
3
|
+
"version": "8.1.0",
|
|
4
|
+
"description": "Native-first pretty toast notifications for Capacitor and the web",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/src/test/",
|
|
12
|
+
"android/build.gradle",
|
|
13
|
+
"dist/",
|
|
14
|
+
"ios/Sources",
|
|
15
|
+
"ios/Tests",
|
|
16
|
+
"scripts/",
|
|
17
|
+
"Package.swift",
|
|
18
|
+
"CapgoCapacitorPrettyToast.podspec"
|
|
19
|
+
],
|
|
20
|
+
"author": "Martin Donadieu <martin@capgo.app>",
|
|
21
|
+
"license": "MPL-2.0",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/Cap-go/capacitor-pretty-toast.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/Cap-go/capacitor-pretty-toast/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://capgo.app/docs/plugins/pretty-toast/",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"capacitor",
|
|
32
|
+
"plugin",
|
|
33
|
+
"toast",
|
|
34
|
+
"notifications",
|
|
35
|
+
"dynamic-island",
|
|
36
|
+
"web"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"verify": "bun run verify:web && bun run verify:ios && bun run verify:android",
|
|
40
|
+
"verify:ios": "xcodebuild -scheme CapgoCapacitorPrettyToast -destination generic/platform=iOS",
|
|
41
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
42
|
+
"verify:web": "bun run build && bun test",
|
|
43
|
+
"test": "bun test && bun run test:ios && bun run test:android",
|
|
44
|
+
"test:ios": "./scripts/test-ios.sh",
|
|
45
|
+
"test:android": "cd android && ./gradlew test && cd ..",
|
|
46
|
+
"lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
|
|
47
|
+
"fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
|
|
48
|
+
"eslint": "eslint . --ext ts",
|
|
49
|
+
"prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
50
|
+
"swiftlint": "node-swiftlint",
|
|
51
|
+
"docgen": "docgen --api PrettyToastPlugin --output-readme README.md --output-json dist/docs.json",
|
|
52
|
+
"build": "bun run clean && bun run docgen && tsc && rollup -c rollup.config.mjs",
|
|
53
|
+
"clean": "rimraf ./dist",
|
|
54
|
+
"watch": "tsc --watch",
|
|
55
|
+
"prepublishOnly": "bun run build",
|
|
56
|
+
"check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs",
|
|
57
|
+
"example:install": "cd example-app && bun install --frozen-lockfile",
|
|
58
|
+
"example:build": "bun run build && cd example-app && bun install --frozen-lockfile && bun run build",
|
|
59
|
+
"example:capgo:deploy": "bun run example:build && bun scripts/deploy-example-capgo.mjs"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@capacitor/android": "^8.0.0",
|
|
63
|
+
"@capacitor/cli": "^8.0.0",
|
|
64
|
+
"@capacitor/core": "^8.0.0",
|
|
65
|
+
"@capacitor/docgen": "^0.3.1",
|
|
66
|
+
"@capacitor/ios": "^8.0.0",
|
|
67
|
+
"@ionic/eslint-config": "^0.4.0",
|
|
68
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
69
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
70
|
+
"@types/node": "^24.10.1",
|
|
71
|
+
"eslint": "^8.57.1",
|
|
72
|
+
"eslint-plugin-import": "^2.31.0",
|
|
73
|
+
"husky": "^9.1.7",
|
|
74
|
+
"prettier": "^3.6.2",
|
|
75
|
+
"prettier-plugin-java": "^2.7.7",
|
|
76
|
+
"prettier-pretty-check": "^0.2.0",
|
|
77
|
+
"rimraf": "^6.1.0",
|
|
78
|
+
"rollup": "^4.53.2",
|
|
79
|
+
"swiftlint": "^2.0.0",
|
|
80
|
+
"typescript": "^5.9.3"
|
|
81
|
+
},
|
|
82
|
+
"peerDependencies": {
|
|
83
|
+
"@capacitor/core": ">=8.0.0"
|
|
84
|
+
},
|
|
85
|
+
"prettier": "@ionic/prettier-config",
|
|
86
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
87
|
+
"eslintConfig": {
|
|
88
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
89
|
+
},
|
|
90
|
+
"capacitor": {
|
|
91
|
+
"ios": {
|
|
92
|
+
"src": "ios"
|
|
93
|
+
},
|
|
94
|
+
"android": {
|
|
95
|
+
"src": "android"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Capacitor plugin wiring/name checker.
|
|
4
|
+
*
|
|
5
|
+
* Enforces that runtime plugin name matches across:
|
|
6
|
+
* - JS: registerPlugin('Name')
|
|
7
|
+
* - Android: @CapacitorPlugin(name = "Name")
|
|
8
|
+
* - iOS: CAPBridgedPlugin jsName = "Name"
|
|
9
|
+
*
|
|
10
|
+
* And (when iOS is declared in package.json capacitor config):
|
|
11
|
+
* - CocoaPods podspec s.name matches SwiftPM Package(name: ...) and .library(name: ...)
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node tools/check-capacitor-plugin-wiring.mjs # checks current working dir
|
|
15
|
+
* node tools/check-capacitor-plugin-wiring.mjs --dir path # checks given plugin dir
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import fs from "node:fs";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
|
|
21
|
+
const SKIP_DIRS = new Set([
|
|
22
|
+
"node_modules",
|
|
23
|
+
"dist",
|
|
24
|
+
"build",
|
|
25
|
+
".build",
|
|
26
|
+
".gradle",
|
|
27
|
+
"Pods",
|
|
28
|
+
"DerivedData",
|
|
29
|
+
".swiftpm",
|
|
30
|
+
".git",
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
function readText(p) {
|
|
34
|
+
try {
|
|
35
|
+
return fs.readFileSync(p, "utf8");
|
|
36
|
+
} catch {
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function exists(p) {
|
|
42
|
+
try {
|
|
43
|
+
fs.accessSync(p);
|
|
44
|
+
return true;
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function walkFiles(rootDir, exts) {
|
|
51
|
+
const out = [];
|
|
52
|
+
const stack = [rootDir];
|
|
53
|
+
while (stack.length) {
|
|
54
|
+
const dir = stack.pop();
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
58
|
+
} catch {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
for (const e of entries) {
|
|
62
|
+
if (e.isDirectory()) {
|
|
63
|
+
if (SKIP_DIRS.has(e.name)) continue;
|
|
64
|
+
stack.push(path.join(dir, e.name));
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!e.isFile()) continue;
|
|
68
|
+
for (const ext of exts) {
|
|
69
|
+
if (e.name.endsWith(ext)) {
|
|
70
|
+
out.push(path.join(dir, e.name));
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
out.sort();
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function uniq(arr) {
|
|
81
|
+
const out = [];
|
|
82
|
+
for (const x of arr) {
|
|
83
|
+
if (!x) continue;
|
|
84
|
+
if (!out.includes(x)) out.push(x);
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function parseArgs(argv) {
|
|
90
|
+
const out = { dir: process.cwd() };
|
|
91
|
+
for (let i = 2; i < argv.length; i++) {
|
|
92
|
+
const a = argv[i];
|
|
93
|
+
if (a === "--dir" || a === "--pluginDir") {
|
|
94
|
+
out.dir = path.resolve(argv[++i] || ".");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const args = parseArgs(process.argv);
|
|
102
|
+
const pluginDir = args.dir;
|
|
103
|
+
const pkgPath = path.join(pluginDir, "package.json");
|
|
104
|
+
|
|
105
|
+
if (!exists(pkgPath)) {
|
|
106
|
+
console.error(`[wiring] ERROR: missing package.json in ${pluginDir}`);
|
|
107
|
+
process.exit(2);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let pkg;
|
|
111
|
+
try {
|
|
112
|
+
pkg = JSON.parse(readText(pkgPath));
|
|
113
|
+
} catch (e) {
|
|
114
|
+
console.error(`[wiring] ERROR: invalid package.json (${pkgPath}): ${e?.message || e}`);
|
|
115
|
+
process.exit(2);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const cap = typeof pkg.capacitor === "object" && pkg.capacitor ? pkg.capacitor : {};
|
|
119
|
+
const supportsAndroid = typeof cap.android === "object" && cap.android;
|
|
120
|
+
const supportsIos = typeof cap.ios === "object" && cap.ios;
|
|
121
|
+
|
|
122
|
+
// Not a Capacitor plugin package (e.g. meta/workspace package).
|
|
123
|
+
// We only enforce wiring rules for actual plugin packages declaring a `capacitor` config.
|
|
124
|
+
if (!supportsAndroid && !supportsIos) {
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ---------------- JS (registerPlugin) ----------------
|
|
129
|
+
const jsSrcDir = path.join(pluginDir, "src");
|
|
130
|
+
let jsName = "";
|
|
131
|
+
if (exists(jsSrcDir)) {
|
|
132
|
+
const jsFiles = walkFiles(jsSrcDir, [".ts", ".js"]);
|
|
133
|
+
const reRegister = /registerPlugin(?:<[^>]*>)?\(\s*['"]([^'"]+)['"]/;
|
|
134
|
+
for (const f of jsFiles) {
|
|
135
|
+
const m = reRegister.exec(readText(f));
|
|
136
|
+
if (m) {
|
|
137
|
+
jsName = m[1];
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ---------------- Android (@CapacitorPlugin) ----------------
|
|
144
|
+
let androidNames = [];
|
|
145
|
+
if (supportsAndroid) {
|
|
146
|
+
const androidMain = path.join(pluginDir, "android", "src", "main");
|
|
147
|
+
const files = walkFiles(androidMain, [".java", ".kt"]);
|
|
148
|
+
const foundAnnotations = [];
|
|
149
|
+
for (const f of files) {
|
|
150
|
+
const txt = readText(f);
|
|
151
|
+
if (!txt.includes("@CapacitorPlugin")) continue;
|
|
152
|
+
foundAnnotations.push(f);
|
|
153
|
+
const m =
|
|
154
|
+
/@CapacitorPlugin\(\s*name\s*=\s*"([^"]+)"/.exec(txt) ||
|
|
155
|
+
/@CapacitorPlugin\(\s*name\s*=\s*([A-Za-z0-9_]+)\b/.exec(txt);
|
|
156
|
+
if (m) androidNames.push(m[1]);
|
|
157
|
+
}
|
|
158
|
+
androidNames = uniq(androidNames);
|
|
159
|
+
|
|
160
|
+
// Enforce explicit name attribute to prevent silent class-name drift.
|
|
161
|
+
if (foundAnnotations.length && !androidNames.length) {
|
|
162
|
+
console.error(
|
|
163
|
+
`[wiring] ERROR: Android has @CapacitorPlugin but none specify name = \"...\". Add an explicit name to the plugin class.`
|
|
164
|
+
);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ---------------- iOS (jsName) ----------------
|
|
170
|
+
let iosJsNames = [];
|
|
171
|
+
if (supportsIos) {
|
|
172
|
+
const iosDir = path.join(pluginDir, "ios");
|
|
173
|
+
const scanRoot = exists(path.join(iosDir, "Sources")) ? path.join(iosDir, "Sources") : iosDir;
|
|
174
|
+
const swiftFiles = walkFiles(scanRoot, [".swift"]);
|
|
175
|
+
const reJsName = /\bjsName\s*=\s*"([^"]+)"/g;
|
|
176
|
+
for (const f of swiftFiles) {
|
|
177
|
+
const txt = readText(f);
|
|
178
|
+
if (!txt.includes("jsName")) continue;
|
|
179
|
+
let m;
|
|
180
|
+
while ((m = reJsName.exec(txt))) iosJsNames.push(m[1]);
|
|
181
|
+
}
|
|
182
|
+
iosJsNames = uniq(iosJsNames);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ---------------- Podspec/SPM ----------------
|
|
186
|
+
function parsePodspecName(podspecPath) {
|
|
187
|
+
const txt = readText(podspecPath);
|
|
188
|
+
const m = /\bs\.name\s*=\s*'([^']+)'/.exec(txt);
|
|
189
|
+
return m ? m[1] : "";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function parseSpmNames(packageSwiftPath) {
|
|
193
|
+
const txt = readText(packageSwiftPath);
|
|
194
|
+
const pkg = /Package\(\s*name\s*:\s*"([^"]+)"/.exec(txt)?.[1] || "";
|
|
195
|
+
const libs = [];
|
|
196
|
+
const reLib = /\.library\(\s*name\s*:\s*"([^"]+)"/g;
|
|
197
|
+
let m;
|
|
198
|
+
while ((m = reLib.exec(txt))) libs.push(m[1]);
|
|
199
|
+
return { pkgName: pkg, libNames: uniq(libs) };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ---------------- Validate ----------------
|
|
203
|
+
const errors = [];
|
|
204
|
+
|
|
205
|
+
if (!jsName) {
|
|
206
|
+
errors.push("JS: no registerPlugin('...') found under src/");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (supportsAndroid) {
|
|
210
|
+
if (!androidNames.length) errors.push("Android: missing @CapacitorPlugin(name = \"...\")");
|
|
211
|
+
if (jsName && androidNames.length && androidNames.some((n) => n !== jsName)) {
|
|
212
|
+
errors.push(`Android: @CapacitorPlugin(name)=${JSON.stringify(androidNames)} != JS registerPlugin=${jsName}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (supportsIos) {
|
|
217
|
+
if (!iosJsNames.length) errors.push('iOS: missing jsName = "..." in Swift sources');
|
|
218
|
+
if (jsName && iosJsNames.length && iosJsNames.some((n) => n !== jsName)) {
|
|
219
|
+
errors.push(`iOS: jsName=${JSON.stringify(iosJsNames)} != JS registerPlugin=${jsName}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const podspecs = fs
|
|
223
|
+
.readdirSync(pluginDir, { withFileTypes: true })
|
|
224
|
+
.filter((e) => e.isFile() && e.name.endsWith(".podspec"))
|
|
225
|
+
.map((e) => path.join(pluginDir, e.name))
|
|
226
|
+
.sort();
|
|
227
|
+
if (!podspecs.length) errors.push("iOS: missing *.podspec at plugin root");
|
|
228
|
+
if (podspecs.length > 1) errors.push(`iOS: multiple podspecs at plugin root: ${podspecs.map((p) => path.basename(p))}`);
|
|
229
|
+
|
|
230
|
+
const pkgSwift = path.join(pluginDir, "Package.swift");
|
|
231
|
+
if (!exists(pkgSwift)) {
|
|
232
|
+
errors.push("iOS: missing Package.swift at plugin root");
|
|
233
|
+
} else if (podspecs.length) {
|
|
234
|
+
const podName = parsePodspecName(podspecs[0]);
|
|
235
|
+
const { pkgName, libNames } = parseSpmNames(pkgSwift);
|
|
236
|
+
if (!podName) errors.push("Podspec: missing s.name = '...'");
|
|
237
|
+
if (!pkgName) errors.push('SPM: missing Package(name: "...")');
|
|
238
|
+
if (podName && pkgName && podName !== pkgName) {
|
|
239
|
+
errors.push(`Podspec: s.name=${podName} != Package(name)=${pkgName}`);
|
|
240
|
+
}
|
|
241
|
+
if (pkgName && libNames.length && !libNames.includes(pkgName)) {
|
|
242
|
+
errors.push(`SPM: Package(name)=${pkgName} not present in .library(name) list ${JSON.stringify(libNames)}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (errors.length) {
|
|
248
|
+
const relDir = path.relative(process.cwd(), pluginDir) || ".";
|
|
249
|
+
console.error(`[wiring] FAIL in ${relDir}`);
|
|
250
|
+
for (const e of errors) console.error(`- ${e}`);
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
process.exit(0);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const repoRoot = resolve(scriptDir, '..');
|
|
9
|
+
const appDir = resolve(repoRoot, 'example-app');
|
|
10
|
+
const distDir = resolve(appDir, 'dist');
|
|
11
|
+
const packageJsonPath = resolve(repoRoot, 'package.json');
|
|
12
|
+
const capacitorConfigPath = resolve(appDir, 'capacitor.config.json');
|
|
13
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
14
|
+
const capacitorConfig = JSON.parse(readFileSync(capacitorConfigPath, 'utf8'));
|
|
15
|
+
const packageVersion = packageJson.version;
|
|
16
|
+
|
|
17
|
+
const appId = process.env.CAPGO_APP_ID || 'app.capgo.pretty.toast';
|
|
18
|
+
const channel = process.env.CAPGO_CHANNEL || process.argv[2] || 'production';
|
|
19
|
+
const bundle = packageVersion;
|
|
20
|
+
const comment =
|
|
21
|
+
process.env.CAPGO_COMMENT ||
|
|
22
|
+
(process.env.GITHUB_RUN_NUMBER
|
|
23
|
+
? `Pretty Toast example ${packageVersion} from run ${process.env.GITHUB_RUN_NUMBER}`
|
|
24
|
+
: `Pretty Toast example ${packageVersion}`);
|
|
25
|
+
|
|
26
|
+
if (!packageVersion) {
|
|
27
|
+
console.error('Missing package.json version.');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
capacitorConfig.plugins ??= {};
|
|
32
|
+
capacitorConfig.plugins.CapacitorUpdater ??= {};
|
|
33
|
+
capacitorConfig.plugins.CapacitorUpdater.version = packageVersion;
|
|
34
|
+
writeFileSync(capacitorConfigPath, `${JSON.stringify(capacitorConfig, null, 2)}\n`);
|
|
35
|
+
|
|
36
|
+
const configVersion = capacitorConfig.plugins.CapacitorUpdater.version;
|
|
37
|
+
|
|
38
|
+
if (configVersion !== packageVersion) {
|
|
39
|
+
console.error(
|
|
40
|
+
`CapacitorUpdater.version (${configVersion ?? 'missing'}) must match package.json version (${packageVersion}).`,
|
|
41
|
+
);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!existsSync(distDir)) {
|
|
46
|
+
console.error('Missing example-app/dist. Run bun run --cwd example-app build first.');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!process.env.CAPGO_TOKEN) {
|
|
51
|
+
console.error('Missing CAPGO_TOKEN.');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const args = [
|
|
56
|
+
'@capgo/cli@7.108.3',
|
|
57
|
+
'bundle',
|
|
58
|
+
'upload',
|
|
59
|
+
appId,
|
|
60
|
+
'--path',
|
|
61
|
+
'dist',
|
|
62
|
+
'--channel',
|
|
63
|
+
channel,
|
|
64
|
+
'--bundle',
|
|
65
|
+
bundle,
|
|
66
|
+
'--package-json',
|
|
67
|
+
'../package.json,package.json',
|
|
68
|
+
'--node-modules',
|
|
69
|
+
'../node_modules,node_modules',
|
|
70
|
+
'--delta',
|
|
71
|
+
'--no-key',
|
|
72
|
+
'--ignore-checksum-check',
|
|
73
|
+
'--version-exists-ok',
|
|
74
|
+
'--comment',
|
|
75
|
+
comment,
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
console.log(`Deploying ${appId}@${bundle} to Capgo channel "${channel}"`);
|
|
79
|
+
|
|
80
|
+
const result = spawnSync('bunx', args, {
|
|
81
|
+
cwd: appDir,
|
|
82
|
+
stdio: 'inherit',
|
|
83
|
+
env: process.env,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
process.exit(result.status ?? 1);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
5
|
+
cd "$ROOT_DIR"
|
|
6
|
+
|
|
7
|
+
SIMULATOR_ID=$(xcrun simctl list devices available | awk -F '[()]' '/iPhone/{print $2; exit}')
|
|
8
|
+
|
|
9
|
+
if [[ -z "${SIMULATOR_ID:-}" ]]; then
|
|
10
|
+
echo "No available iPhone simulator found. Please install one via Xcode." >&2
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
xcodebuild test -scheme CapgoCapacitorPrettyToast -destination "id=${SIMULATOR_ID}" "$@"
|