@choochmeque/tauri-apple-extensions 0.1.1 → 0.2.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/LICENSE +1 -1
- package/README.md +54 -30
- package/dist/cli.js +103 -85
- package/dist/core/entitlements.d.ts +5 -2
- package/dist/core/project-discovery.d.ts +2 -2
- package/dist/core/project-yml.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +122 -78
- package/dist/types.d.ts +4 -2
- package/package.json +14 -14
- package/templates/ios/share/ShareViewController.swift +126 -0
- package/templates/macos/share/Info.plist +47 -0
- package/templates/macos/share/ShareViewController.swift +122 -0
- package/templates/share/ShareViewController.swift +0 -246
- /package/templates/{share → ios/share}/Info.plist +0 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,66 +1,99 @@
|
|
|
1
1
|
# tauri-apple-extensions
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@choochmeque/tauri-apple-extensions)
|
|
4
|
+
[](https://codecov.io/gh/Choochmeque/tauri-apple-extensions)
|
|
4
5
|
[](LICENSE)
|
|
5
6
|
|
|
6
|
-
Add iOS extensions to Tauri apps with a single command.
|
|
7
|
+
Add iOS and macOS extensions to Tauri apps with a single command.
|
|
7
8
|
|
|
8
9
|
## Features
|
|
9
10
|
|
|
10
11
|
- Automatic Xcode project configuration via XcodeGen
|
|
11
|
-
-
|
|
12
|
+
- Built-in skeleton templates with TODO markers
|
|
13
|
+
- Plugin-based template system for custom implementations
|
|
14
|
+
- Supports both iOS and macOS platforms
|
|
12
15
|
- Idempotent - safe to re-run
|
|
13
|
-
- Share Extension support (more extension types coming soon)
|
|
14
16
|
|
|
15
17
|
## Prerequisites
|
|
16
18
|
|
|
17
19
|
- [XcodeGen](https://github.com/yonaskolb/XcodeGen) installed (`brew install xcodegen`)
|
|
18
|
-
- Tauri iOS project initialized (`tauri ios init`)
|
|
20
|
+
- Tauri iOS project initialized (`tauri ios init`) for iOS extensions
|
|
21
|
+
- For macOS extensions: Tauri macOS Xcode project via [@choochmeque/tauri-macos-xcode](https://github.com/Choochmeque/tauri-macos-xcode)
|
|
19
22
|
|
|
20
23
|
## Installation
|
|
21
24
|
|
|
22
25
|
```bash
|
|
26
|
+
# npm
|
|
23
27
|
npm install -D @choochmeque/tauri-apple-extensions
|
|
24
|
-
```
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
# pnpm
|
|
30
|
+
pnpm add -D @choochmeque/tauri-apple-extensions
|
|
31
|
+
|
|
32
|
+
# yarn
|
|
33
|
+
yarn add -D @choochmeque/tauri-apple-extensions
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
# bun
|
|
36
|
+
bun add -D @choochmeque/tauri-apple-extensions
|
|
37
|
+
```
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
## Usage
|
|
31
40
|
|
|
32
41
|
```bash
|
|
33
|
-
|
|
42
|
+
# Add iOS Share Extension
|
|
43
|
+
npx @choochmeque/tauri-apple-extensions ios add share
|
|
44
|
+
|
|
45
|
+
# Add macOS Share Extension
|
|
46
|
+
npx @choochmeque/tauri-apple-extensions macos add share
|
|
34
47
|
```
|
|
35
48
|
|
|
36
|
-
|
|
49
|
+
This creates a Share Extension with a minimal skeleton template. Open the generated Swift file and implement your logic where you see `// TODO:` comments.
|
|
50
|
+
|
|
51
|
+
### Options
|
|
37
52
|
|
|
38
53
|
```bash
|
|
39
|
-
|
|
54
|
+
# Use templates from a plugin (plugin must include tauri-apple-extension config)
|
|
55
|
+
npx @choochmeque/tauri-apple-extensions ios add share --plugin <plugin-name>
|
|
56
|
+
|
|
57
|
+
# Use custom templates directory
|
|
58
|
+
npx @choochmeque/tauri-apple-extensions ios add share --templates ./path/to/templates
|
|
40
59
|
```
|
|
41
60
|
|
|
61
|
+
> **Note:** When using `--plugin`, the plugin's `package.json` must contain a `tauri-apple-extension` config. See [For Plugin Developers](#for-plugin-developers) below.
|
|
62
|
+
|
|
42
63
|
## Supported Extensions
|
|
43
64
|
|
|
44
|
-
| Type |
|
|
45
|
-
|
|
46
|
-
| `share` |
|
|
65
|
+
| Type | Description |
|
|
66
|
+
|------|-------------|
|
|
67
|
+
| `share` | Share Extension for receiving shared content |
|
|
68
|
+
|
|
69
|
+
## Post-Setup Steps
|
|
70
|
+
|
|
71
|
+
After running the tool:
|
|
72
|
+
|
|
73
|
+
1. Open the Xcode project:
|
|
74
|
+
- iOS: `src-tauri/gen/apple/*.xcodeproj`
|
|
75
|
+
- macOS: `src-tauri/gen/apple-macos/*.xcodeproj`
|
|
76
|
+
2. Select your Apple Developer Team for both targets
|
|
77
|
+
3. Enable **App Groups** capability for both targets
|
|
78
|
+
4. Configure App Groups in [Apple Developer Portal](https://developer.apple.com/account/resources/identifiers/list/applicationGroup)
|
|
47
79
|
|
|
48
80
|
## For Plugin Developers
|
|
49
81
|
|
|
50
|
-
To make your plugin compatible
|
|
82
|
+
To make your plugin compatible, add to your `package.json`:
|
|
51
83
|
|
|
52
84
|
```json
|
|
53
85
|
{
|
|
54
86
|
"tauri-apple-extension": {
|
|
55
87
|
"type": "share",
|
|
56
|
-
"templates":
|
|
88
|
+
"templates": {
|
|
89
|
+
"ios": "./templates/ios",
|
|
90
|
+
"macos": "./templates/macos"
|
|
91
|
+
}
|
|
57
92
|
}
|
|
58
93
|
}
|
|
59
94
|
```
|
|
60
95
|
|
|
61
|
-
|
|
62
|
-
- Swift source files with `{{VARIABLE}}` placeholders
|
|
63
|
-
- `Info.plist` for the extension
|
|
96
|
+
Plugins can support one or both platforms. If a user runs the command for a platform your plugin doesn't support, they'll receive a clear error message.
|
|
64
97
|
|
|
65
98
|
### Template Variables
|
|
66
99
|
|
|
@@ -72,19 +105,10 @@ Your templates directory should contain:
|
|
|
72
105
|
| `{{BUNDLE_IDENTIFIER}}` | Extension bundle identifier |
|
|
73
106
|
| `{{PRODUCT_NAME}}` | App product name |
|
|
74
107
|
|
|
75
|
-
## Post-Setup Steps
|
|
76
|
-
|
|
77
|
-
After running the tool:
|
|
78
|
-
|
|
79
|
-
1. Open the Xcode project (`src-tauri/gen/apple/*.xcodeproj`)
|
|
80
|
-
2. Select your Apple Developer Team for both targets
|
|
81
|
-
3. Enable required capabilities (e.g., App Groups) for both targets
|
|
82
|
-
4. Configure the capability in Apple Developer Portal
|
|
83
|
-
|
|
84
108
|
## Contributing
|
|
85
109
|
|
|
86
|
-
PRs
|
|
110
|
+
PRs welcome! Please open an issue first to discuss what you would like to change.
|
|
87
111
|
|
|
88
112
|
## License
|
|
89
113
|
|
|
90
|
-
MIT
|
|
114
|
+
[MIT](LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -44,17 +44,22 @@ function findTauriConfig(projectRoot) {
|
|
|
44
44
|
}
|
|
45
45
|
throw new Error("Could not find tauri.conf.json");
|
|
46
46
|
}
|
|
47
|
-
function findAppleProjectDir(projectRoot) {
|
|
47
|
+
function findAppleProjectDir(projectRoot, platform) {
|
|
48
|
+
// iOS uses 'apple', macOS uses 'apple-macos'
|
|
49
|
+
const dirName = platform === "ios" ? "apple" : "apple-macos";
|
|
50
|
+
const initHint = platform === "ios"
|
|
51
|
+
? "Run 'tauri ios init' first."
|
|
52
|
+
: "Set up macOS Xcode project using @choochmeque/tauri-macos-xcode first.";
|
|
48
53
|
const paths = [
|
|
49
|
-
path.join(projectRoot, "src-tauri", "gen",
|
|
50
|
-
path.join(projectRoot, "gen",
|
|
54
|
+
path.join(projectRoot, "src-tauri", "gen", dirName),
|
|
55
|
+
path.join(projectRoot, "gen", dirName),
|
|
51
56
|
];
|
|
52
57
|
for (const p of paths) {
|
|
53
58
|
if (fs.existsSync(p)) {
|
|
54
59
|
return p;
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
|
-
throw new Error(
|
|
62
|
+
throw new Error(`Could not find ${platform} project directory. ${initHint}`);
|
|
58
63
|
}
|
|
59
64
|
function getAppInfo(tauriConfig, projectYml) {
|
|
60
65
|
const parsed = parseYamlSimple(projectYml);
|
|
@@ -118,6 +123,25 @@ function addExtensionTarget(projectYml, targetConfig) {
|
|
|
118
123
|
}
|
|
119
124
|
return modified;
|
|
120
125
|
}
|
|
126
|
+
function addUrlSchemeToTarget(projectYml, targetName, urlScheme, bundleIdentifier) {
|
|
127
|
+
let modified = projectYml;
|
|
128
|
+
// Check if URL scheme already exists
|
|
129
|
+
if (modified.includes(`CFBundleURLSchemes`) && modified.includes(urlScheme)) {
|
|
130
|
+
return modified;
|
|
131
|
+
}
|
|
132
|
+
// Find the target's info section and add URL scheme
|
|
133
|
+
const targetRegex = new RegExp(`(${targetName}:[\\s\\S]*?info:[\\s\\S]*?properties:)([\\s\\S]*?)(\\n \\w|\\n \\w|$)`, "m");
|
|
134
|
+
const match = modified.match(targetRegex);
|
|
135
|
+
if (match) {
|
|
136
|
+
const urlSchemeYaml = `
|
|
137
|
+
CFBundleURLTypes:
|
|
138
|
+
- CFBundleURLName: ${bundleIdentifier}
|
|
139
|
+
CFBundleURLSchemes:
|
|
140
|
+
- ${urlScheme}`;
|
|
141
|
+
modified = modified.replace(targetRegex, `$1$2${urlSchemeYaml}$3`);
|
|
142
|
+
}
|
|
143
|
+
return modified;
|
|
144
|
+
}
|
|
121
145
|
function addDependencyToTarget(projectYml, mainTargetName, dependencyConfig) {
|
|
122
146
|
let modified = projectYml;
|
|
123
147
|
// Remove existing dependency if it exists
|
|
@@ -138,43 +162,31 @@ function addDependencyToTarget(projectYml, mainTargetName, dependencyConfig) {
|
|
|
138
162
|
return modified;
|
|
139
163
|
}
|
|
140
164
|
|
|
141
|
-
|
|
142
|
-
const targetName = `${appInfo.productName}_iOS`;
|
|
143
|
-
const entitlementsPath = path.join(appleDir, targetName, `${targetName}.entitlements`);
|
|
144
|
-
const appGroupId = `group.${appInfo.identifier}`;
|
|
145
|
-
let entitlements;
|
|
146
|
-
if (fs.existsSync(entitlementsPath)) {
|
|
147
|
-
entitlements = fs.readFileSync(entitlementsPath, "utf8");
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
entitlements = `<?xml version="1.0" encoding="UTF-8"?>
|
|
165
|
+
const EMPTY_ENTITLEMENTS = `<?xml version="1.0" encoding="UTF-8"?>
|
|
151
166
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
152
167
|
<plist version="1.0">
|
|
153
168
|
<dict>
|
|
154
169
|
</dict>
|
|
155
170
|
</plist>`;
|
|
156
|
-
|
|
171
|
+
function addAppGroupToEntitlements(entitlements, appGroupId) {
|
|
157
172
|
// Check if app groups already configured
|
|
158
173
|
if (entitlements.includes("com.apple.security.application-groups")) {
|
|
159
174
|
if (!entitlements.includes(appGroupId)) {
|
|
160
175
|
// Add our group to existing array
|
|
161
|
-
|
|
176
|
+
return entitlements.replace(/(<key>com\.apple\.security\.application-groups<\/key>\s*<array>)/, `$1\n <string>${appGroupId}</string>`);
|
|
162
177
|
}
|
|
178
|
+
return entitlements;
|
|
163
179
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
entitlements = entitlements.replace(/<dict>\s*<\/dict>/, `<dict>
|
|
180
|
+
// Add app groups entitlement
|
|
181
|
+
return entitlements.replace(/<dict>\s*<\/dict>/, `<dict>
|
|
167
182
|
<key>com.apple.security.application-groups</key>
|
|
168
183
|
<array>
|
|
169
184
|
<string>${appGroupId}</string>
|
|
170
185
|
</array>
|
|
171
186
|
</dict>`);
|
|
172
|
-
}
|
|
173
|
-
fs.writeFileSync(entitlementsPath, entitlements);
|
|
174
|
-
console.log(`Updated main app entitlements: ${entitlementsPath}`);
|
|
175
187
|
}
|
|
176
|
-
function
|
|
177
|
-
|
|
188
|
+
function createEntitlementsContent(appGroupId) {
|
|
189
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
178
190
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
179
191
|
<plist version="1.0">
|
|
180
192
|
<dict>
|
|
@@ -184,44 +196,28 @@ function createExtensionEntitlements(extensionDir, appGroupId) {
|
|
|
184
196
|
</array>
|
|
185
197
|
</dict>
|
|
186
198
|
</plist>`;
|
|
187
|
-
const entitlementsPath = path.join(extensionDir, `${path.basename(extensionDir)}.entitlements`);
|
|
188
|
-
fs.writeFileSync(entitlementsPath, entitlements);
|
|
189
|
-
return entitlementsPath;
|
|
190
199
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const targetName = `${appInfo.productName}
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
200
|
+
function updateMainAppEntitlements(appleDir, appInfo, platform) {
|
|
201
|
+
const platformSuffix = platform === "ios" ? "iOS" : "macOS";
|
|
202
|
+
const targetName = `${appInfo.productName}_${platformSuffix}`;
|
|
203
|
+
const entitlementsPath = path.join(appleDir, targetName, `${targetName}.entitlements`);
|
|
204
|
+
const appGroupId = `group.${appInfo.identifier}`;
|
|
205
|
+
let entitlements;
|
|
206
|
+
if (fs.existsSync(entitlementsPath)) {
|
|
207
|
+
entitlements = fs.readFileSync(entitlementsPath, "utf8");
|
|
199
208
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (infoPlist.includes("CFBundleURLSchemes")) {
|
|
203
|
-
if (!infoPlist.includes(urlScheme)) {
|
|
204
|
-
console.log(`URL scheme may need manual configuration. Add '${urlScheme}' to CFBundleURLSchemes.`);
|
|
205
|
-
}
|
|
206
|
-
return;
|
|
209
|
+
else {
|
|
210
|
+
entitlements = EMPTY_ENTITLEMENTS;
|
|
207
211
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
<string>${appInfo.identifier}</string>
|
|
218
|
-
</dict>
|
|
219
|
-
</array>
|
|
220
|
-
`;
|
|
221
|
-
// Insert before the last </dict>
|
|
222
|
-
infoPlist = infoPlist.replace(/(\s*)<\/dict>\s*<\/plist>/, `\n${urlSchemeEntry}$1</dict>\n</plist>`);
|
|
223
|
-
fs.writeFileSync(infoPlistPath, infoPlist);
|
|
224
|
-
console.log(`Added URL scheme '${urlScheme}' to Info.plist`);
|
|
212
|
+
entitlements = addAppGroupToEntitlements(entitlements, appGroupId);
|
|
213
|
+
fs.writeFileSync(entitlementsPath, entitlements);
|
|
214
|
+
console.log(`Updated main app entitlements: ${entitlementsPath}`);
|
|
215
|
+
}
|
|
216
|
+
function createExtensionEntitlements(extensionDir, appGroupId) {
|
|
217
|
+
const entitlements = createEntitlementsContent(appGroupId);
|
|
218
|
+
const entitlementsPath = path.join(extensionDir, `${path.basename(extensionDir)}.entitlements`);
|
|
219
|
+
fs.writeFileSync(entitlementsPath, entitlements);
|
|
220
|
+
return entitlementsPath;
|
|
225
221
|
}
|
|
226
222
|
|
|
227
223
|
function runXcodeGen(appleDir) {
|
|
@@ -269,7 +265,7 @@ const shareExtension = {
|
|
|
269
265
|
extensionName(appInfo) {
|
|
270
266
|
return `${appInfo.productName}-ShareExtension`;
|
|
271
267
|
},
|
|
272
|
-
createFiles(appleDir, appInfo, templatesDir) {
|
|
268
|
+
createFiles(appleDir, appInfo, templatesDir, _platform) {
|
|
273
269
|
const extensionDir = path.join(appleDir, "ShareExtension");
|
|
274
270
|
const appGroupId = `group.${appInfo.identifier}`;
|
|
275
271
|
const urlScheme = appInfo.productName
|
|
@@ -362,16 +358,19 @@ const shareExtension = {
|
|
|
362
358
|
createExtensionEntitlements(extensionDir, appGroupId);
|
|
363
359
|
console.log(`Created ShareExtension files in ${extensionDir}`);
|
|
364
360
|
},
|
|
365
|
-
updateProjectYml(projectYml, appInfo) {
|
|
361
|
+
updateProjectYml(projectYml, appInfo, platform) {
|
|
366
362
|
const extensionName = this.extensionName(appInfo);
|
|
367
363
|
const extensionBundleId = `${appInfo.identifier}.ShareExtension`;
|
|
368
|
-
const
|
|
364
|
+
const platformSuffix = platform === "ios" ? "iOS" : "macOS";
|
|
365
|
+
const platformValue = platform === "ios" ? "iOS" : "macOS";
|
|
366
|
+
const deploymentTarget = platform === "ios" ? "14.0" : "11.0";
|
|
367
|
+
const targetName = `${appInfo.productName}_${platformSuffix}`;
|
|
369
368
|
// Create the extension target YAML
|
|
370
369
|
const extensionTarget = `
|
|
371
370
|
${extensionName}:
|
|
372
371
|
type: app-extension
|
|
373
|
-
platform:
|
|
374
|
-
deploymentTarget: "
|
|
372
|
+
platform: ${platformValue}
|
|
373
|
+
deploymentTarget: "${deploymentTarget}"
|
|
375
374
|
sources:
|
|
376
375
|
- path: ShareExtension
|
|
377
376
|
info:
|
|
@@ -405,6 +404,11 @@ const shareExtension = {
|
|
|
405
404
|
modified = addDependencyToTarget(modified, targetName, {
|
|
406
405
|
target: extensionName,
|
|
407
406
|
});
|
|
407
|
+
// Add URL scheme to main app for deep linking from extension
|
|
408
|
+
const urlScheme = appInfo.productName
|
|
409
|
+
.toLowerCase()
|
|
410
|
+
.replace(/[^a-z0-9]/g, "");
|
|
411
|
+
modified = addUrlSchemeToTarget(modified, targetName, urlScheme, appInfo.identifier);
|
|
408
412
|
return modified;
|
|
409
413
|
},
|
|
410
414
|
};
|
|
@@ -415,6 +419,7 @@ const EXTENSIONS = {
|
|
|
415
419
|
share: shareExtension,
|
|
416
420
|
};
|
|
417
421
|
function resolveTemplatesDir(options, extensionType) {
|
|
422
|
+
const { platform } = options;
|
|
418
423
|
// Option 1: Explicit templates path
|
|
419
424
|
if (options.templates) {
|
|
420
425
|
const templatesPath = path.resolve(process.cwd(), options.templates);
|
|
@@ -434,16 +439,20 @@ function resolveTemplatesDir(options, extensionType) {
|
|
|
434
439
|
if (extensionConfig.type !== extensionType) {
|
|
435
440
|
throw new Error(`Plugin ${options.plugin} is for '${extensionConfig.type}' extension, not '${extensionType}'`);
|
|
436
441
|
}
|
|
437
|
-
const
|
|
442
|
+
const platformTemplates = extensionConfig.templates[platform];
|
|
443
|
+
if (!platformTemplates) {
|
|
444
|
+
throw new Error(`Plugin ${options.plugin} does not support ${platform} platform`);
|
|
445
|
+
}
|
|
446
|
+
const templatesPath = path.join(pluginPath, platformTemplates);
|
|
438
447
|
if (!fs.existsSync(templatesPath)) {
|
|
439
448
|
throw new Error(`Plugin templates directory not found: ${templatesPath}`);
|
|
440
449
|
}
|
|
441
450
|
return templatesPath;
|
|
442
451
|
}
|
|
443
|
-
// Option 3: Default templates (from bundled dist/cli.js -> ../templates)
|
|
444
|
-
const defaultTemplates = path.join(__dirname$1, "../templates", extensionType);
|
|
452
|
+
// Option 3: Default templates (from bundled dist/cli.js -> ../templates/{platform}/{type})
|
|
453
|
+
const defaultTemplates = path.join(__dirname$1, "../templates", platform, extensionType);
|
|
445
454
|
if (!fs.existsSync(defaultTemplates)) {
|
|
446
|
-
throw new Error(`No templates found. Use --plugin or --templates to specify templates.`);
|
|
455
|
+
throw new Error(`No templates found for ${platform}/${extensionType}. Use --plugin or --templates to specify templates.`);
|
|
447
456
|
}
|
|
448
457
|
return defaultTemplates;
|
|
449
458
|
}
|
|
@@ -461,7 +470,9 @@ function resolvePluginPath(pluginName) {
|
|
|
461
470
|
throw new Error(`Plugin ${pluginName} not found in node_modules. Make sure it's installed.`);
|
|
462
471
|
}
|
|
463
472
|
async function addExtension(type, options) {
|
|
464
|
-
|
|
473
|
+
const { platform } = options;
|
|
474
|
+
const platformDisplay = platform === "ios" ? "iOS" : "macOS";
|
|
475
|
+
console.log(`\nTauri Apple Extensions - Add ${type} (${platformDisplay})\n`);
|
|
465
476
|
try {
|
|
466
477
|
// Validate extension type
|
|
467
478
|
const extension = EXTENSIONS[type];
|
|
@@ -473,7 +484,7 @@ async function addExtension(type, options) {
|
|
|
473
484
|
const projectRoot = findProjectRoot();
|
|
474
485
|
console.log(`Project root: ${projectRoot}`);
|
|
475
486
|
const tauriConfig = findTauriConfig(projectRoot);
|
|
476
|
-
const appleDir = findAppleProjectDir(projectRoot);
|
|
487
|
+
const appleDir = findAppleProjectDir(projectRoot, platform);
|
|
477
488
|
console.log(`Apple project dir: ${appleDir}`);
|
|
478
489
|
// Get app info
|
|
479
490
|
let projectYml = readProjectYml(appleDir);
|
|
@@ -493,16 +504,14 @@ async function addExtension(type, options) {
|
|
|
493
504
|
console.log(`\nUsing templates from: ${templatesDir}`);
|
|
494
505
|
// Run extension setup
|
|
495
506
|
console.log(`\n1. Creating ${extension.displayName} files...`);
|
|
496
|
-
extension.createFiles(appleDir, appInfo, templatesDir);
|
|
507
|
+
extension.createFiles(appleDir, appInfo, templatesDir, platform);
|
|
497
508
|
console.log(`\n2. Updating main app entitlements...`);
|
|
498
|
-
updateMainAppEntitlements(appleDir, appInfo);
|
|
499
|
-
console.log(`\n3.
|
|
500
|
-
addUrlSchemeToInfoPlist(appleDir, appInfo);
|
|
501
|
-
console.log(`\n4. Updating project.yml...`);
|
|
509
|
+
updateMainAppEntitlements(appleDir, appInfo, platform);
|
|
510
|
+
console.log(`\n3. Updating project.yml (extension target + URL scheme)...`);
|
|
502
511
|
projectYml = readProjectYml(appleDir);
|
|
503
|
-
projectYml = extension.updateProjectYml(projectYml, appInfo);
|
|
512
|
+
projectYml = extension.updateProjectYml(projectYml, appInfo, platform);
|
|
504
513
|
writeProjectYml(appleDir, projectYml);
|
|
505
|
-
console.log(`\
|
|
514
|
+
console.log(`\n4. Regenerating Xcode project...`);
|
|
506
515
|
runXcodeGen(appleDir);
|
|
507
516
|
console.log(`\n========================================`);
|
|
508
517
|
console.log(`${extension.displayName} setup complete!`);
|
|
@@ -525,12 +534,21 @@ async function addExtension(type, options) {
|
|
|
525
534
|
const program = new Command();
|
|
526
535
|
program
|
|
527
536
|
.name("tauri-apple-extensions")
|
|
528
|
-
.description("Add
|
|
529
|
-
.version("0.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
.description("
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
537
|
+
.description("Add Apple extensions to Tauri apps")
|
|
538
|
+
.version("0.2.0");
|
|
539
|
+
function createPlatformCommand(platform) {
|
|
540
|
+
const cmd = new Command(platform);
|
|
541
|
+
cmd.description(`Manage ${platform === "ios" ? "iOS" : "macOS"} extensions`);
|
|
542
|
+
cmd
|
|
543
|
+
.command("add <type>")
|
|
544
|
+
.description("Add an extension (e.g., share)")
|
|
545
|
+
.option("-p, --plugin <name>", "Plugin to use for templates")
|
|
546
|
+
.option("-t, --templates <path>", "Custom templates directory")
|
|
547
|
+
.action((type, options) => {
|
|
548
|
+
addExtension(type, { ...options, platform });
|
|
549
|
+
});
|
|
550
|
+
return cmd;
|
|
551
|
+
}
|
|
552
|
+
program.addCommand(createPlatformCommand("ios"));
|
|
553
|
+
program.addCommand(createPlatformCommand("macos"));
|
|
536
554
|
program.parse();
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type { AppInfo } from "../types.js";
|
|
2
|
-
export declare
|
|
1
|
+
import type { AppInfo, Platform } from "../types.js";
|
|
2
|
+
export declare const EMPTY_ENTITLEMENTS = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n</dict>\n</plist>";
|
|
3
|
+
export declare function addAppGroupToEntitlements(entitlements: string, appGroupId: string): string;
|
|
4
|
+
export declare function createEntitlementsContent(appGroupId: string): string;
|
|
5
|
+
export declare function updateMainAppEntitlements(appleDir: string, appInfo: AppInfo, platform: Platform): void;
|
|
3
6
|
export declare function createExtensionEntitlements(extensionDir: string, appGroupId: string): string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AppInfo, TauriConfig } from "../types.js";
|
|
1
|
+
import type { AppInfo, TauriConfig, Platform } from "../types.js";
|
|
2
2
|
export declare function findProjectRoot(): string;
|
|
3
3
|
export declare function findTauriConfig(projectRoot: string): TauriConfig;
|
|
4
|
-
export declare function findAppleProjectDir(projectRoot: string): string;
|
|
4
|
+
export declare function findAppleProjectDir(projectRoot: string, platform: Platform): string;
|
|
5
5
|
export declare function getAppInfo(tauriConfig: TauriConfig, projectYml: string): AppInfo;
|
|
@@ -2,4 +2,5 @@ import type { TargetConfig, DependencyConfig } from "../types.js";
|
|
|
2
2
|
export declare function readProjectYml(appleDir: string): string;
|
|
3
3
|
export declare function writeProjectYml(appleDir: string, content: string): void;
|
|
4
4
|
export declare function addExtensionTarget(projectYml: string, targetConfig: TargetConfig): string;
|
|
5
|
+
export declare function addUrlSchemeToTarget(projectYml: string, targetName: string, urlScheme: string, bundleIdentifier: string): string;
|
|
5
6
|
export declare function addDependencyToTarget(projectYml: string, mainTargetName: string, dependencyConfig: DependencyConfig): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { addExtension } from "./commands/add.js";
|
|
2
2
|
export { findProjectRoot, findTauriConfig, findAppleProjectDir, getAppInfo, } from "./core/project-discovery.js";
|
|
3
|
-
export { readProjectYml, writeProjectYml } from "./core/project-yml.js";
|
|
3
|
+
export { readProjectYml, writeProjectYml, addUrlSchemeToTarget, } from "./core/project-yml.js";
|
|
4
4
|
export { updateMainAppEntitlements, createExtensionEntitlements, } from "./core/entitlements.js";
|
|
5
5
|
export { addUrlSchemeToInfoPlist } from "./core/info-plist.js";
|
|
6
6
|
export { runXcodeGen } from "./core/xcodegen.js";
|