@stacksjs/buddy 0.70.141 → 0.70.143

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.
@@ -6,3 +6,4 @@ import type { CLI } from '@stacksjs/types';
6
6
  * packaging.
7
7
  */
8
8
  export declare function extension(buddy: CLI): void;
9
+ declare type SafariPlatform = 'macos' | 'ios';
@@ -1,5 +1,14 @@
1
1
  import process from "node:process";
2
2
  import { log } from "@stacksjs/cli";
3
+ function parseSafariPlatforms(platform) {
4
+ if (!platform)
5
+ return;
6
+ if (platform === "all")
7
+ return ["macos", "ios"];
8
+ if (platform === "macos" || platform === "ios")
9
+ return [platform];
10
+ throw Error(`Invalid Safari platform ${platform}; use macos, ios, or all`);
11
+ }
3
12
  export function extension(buddy) {
4
13
  const load = async () => {
5
14
  const { loadExtensionConfig } = await import("@stacksjs/browser-extension"), config = await loadExtensionConfig(process.cwd());
@@ -112,12 +121,14 @@ console.log('[${name}] popup')
112
121
  if (result.artifacts.length)
113
122
  log.info(`new artifacts: ${result.artifacts.join(", ")}`);
114
123
  });
115
- buddy.command("extension:safari:provision", "Register Safari Bundle IDs and check the App Store Connect app record").option("--api-key-id <id>", "App Store Connect API key ID").option("--api-issuer-id <id>", "App Store Connect API issuer ID").option("--api-key-path <path>", "Path to the App Store Connect AuthKey_*.p8 file").option("--check", "Report missing resources without creating Bundle IDs").action(async (options) => {
116
- const { provisionSafariApp } = await import("@stacksjs/browser-extension"), { config } = await load(), result = await provisionSafariApp(config, {
124
+ buddy.command("extension:safari:provision", "Register Safari Bundle IDs and check the App Store Connect app record").option("--api-key-id <id>", "App Store Connect API key ID").option("--api-issuer-id <id>", "App Store Connect API issuer ID").option("--api-key-path <path>", "Path to the App Store Connect AuthKey_*.p8 file").option("--check", "Report missing resources without creating Bundle IDs").option("--version <version>", "Create or align App Store versions (defaults to package.json)").option("--platform <platform>", "Provision macos, ios, or all (defaults to config safariPlatforms)").action(async (options) => {
125
+ const { provisionSafariApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), result = await provisionSafariApp(config, {
117
126
  keyId: options.apiKeyId,
118
127
  issuerId: options.apiIssuerId,
119
128
  keyPath: options.apiKeyPath,
120
- checkOnly: Boolean(options.check)
129
+ checkOnly: Boolean(options.check),
130
+ version: options.version ?? version,
131
+ platforms: parseSafariPlatforms(options.platform)
121
132
  });
122
133
  for (const resource of [result.container, result.extension])
123
134
  if (resource.created)
@@ -130,6 +141,10 @@ console.log('[${name}] popup')
130
141
  log.success(`App Store Connect app record exists (${result.appRecord.id})`);
131
142
  else
132
143
  log.warn("App Store Connect app record is missing. Apple requires creating it in the App Store Connect website.");
144
+ for (const appStoreVersion of result.appStoreVersions) {
145
+ const action = appStoreVersion.created ? "Created" : appStoreVersion.updated ? "Updated" : "Ready";
146
+ log.success(`${action} Safari ${appStoreVersion.platform} App Store version ${appStoreVersion.version}`);
147
+ }
133
148
  });
134
149
  buddy.command("extension:safari:init", "Scaffold the Safari container app (Xcode project) from the template").option("--bundle-id <id>", "Base bundle identifier (defaults to config safariBundleId)").option("--dir <dir>", "Output directory for the Xcode project (default safari)").option("--force", "Overwrite existing scaffold files").option("--team-id <id>", "Apple Developer team used for signing").action(async (options) => {
135
150
  const { scaffoldSafariApp } = await import("@stacksjs/browser-extension"), { config } = await load(), { dir, written, skipped } = await scaffoldSafariApp(config, {
@@ -142,8 +157,30 @@ console.log('[${name}] popup')
142
157
  if (skipped.length)
143
158
  log.info(`kept ${skipped.length} existing files (use --force to overwrite)`);
144
159
  });
145
- buddy.command("extension:safari:app", "Build the extension, sync it into the appex, and xcodebuild the container app").option("--release", "Build the Release configuration (default Debug)").option("--signed", "Allow code signing (needs an Apple Development identity)").option("--skip-xcodebuild", "Only build + sync the extension payload").option("--version <version>", "Override the extension version (defaults to package.json)").action(async (options) => {
146
- const { buildSafariApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), { appPath, resources } = await buildSafariApp(config, {
160
+ buddy.command("extension:safari:app", "Build the extension and its macOS, iPhone, and iPad Safari container apps").option("--release", "Build the Release configuration (default Debug)").option("--signed", "Allow code signing (needs an Apple Development identity)").option("--skip-xcodebuild", "Only build + sync the extension payload").option("--version <version>", "Override the extension version (defaults to package.json)").option("--platform <platform>", "Build macos, ios, or all (defaults to config safariPlatforms)").action(async (options) => {
161
+ const { buildSafariApp, buildSafariUniversalApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), platforms = parseSafariPlatforms(options.platform) ?? config.safariPlatforms ?? ["macos"];
162
+ if (platforms.includes("ios")) {
163
+ const result = await buildSafariUniversalApp(config, {
164
+ version: options.version ?? version,
165
+ release: Boolean(options.release),
166
+ signed: Boolean(options.signed),
167
+ skipXcodebuild: Boolean(options.skipXcodebuild),
168
+ platforms
169
+ });
170
+ for (const platform of platforms) {
171
+ const appPath = result.appPaths[platform];
172
+ if (appPath)
173
+ log.success(`Built Safari ${platform} app ${appPath}`);
174
+ }
175
+ if (options.skipXcodebuild)
176
+ log.success(`Generated universal Safari project \u2192 ${result.project}`);
177
+ if (result.appPaths.macos)
178
+ log.info("Open the macOS app once, then enable the extension in Safari > Settings > Extensions.");
179
+ if (result.appPaths.ios)
180
+ log.info("Install the iOS app on an iPhone, iPad, or Simulator, then enable it in Settings > Apps > Safari > Extensions.");
181
+ return;
182
+ }
183
+ const { appPath, resources } = await buildSafariApp(config, {
147
184
  version: options.version ?? version,
148
185
  release: Boolean(options.release),
149
186
  signed: Boolean(options.signed),
@@ -155,7 +192,7 @@ console.log('[${name}] popup')
155
192
  } else
156
193
  log.success(`Extension payload synced \u2192 ${resources}`);
157
194
  });
158
- buddy.command("extension:safari:publish", "Archive and validate or upload the Safari app to App Store Connect").option("--version <version>", "Override the marketing version (defaults to package.json)").option("--build-number <number>", "CFBundleVersion (defaults to GITHUB_RUN_NUMBER or Unix time)").option("--team-id <id>", "Apple Developer team (defaults to config safariTeamId)").option("--api-key-id <id>", "App Store Connect API key ID").option("--api-issuer-id <id>", "App Store Connect API issuer ID").option("--api-key-path <path>", "Path to the App Store Connect AuthKey_*.p8 file").option("--validate-only", "Create and validate the archive without uploading it").action(async (options) => {
195
+ buddy.command("extension:safari:publish", "Archive and validate or upload the Safari app to App Store Connect").option("--version <version>", "Override the marketing version (defaults to package.json)").option("--build-number <number>", "CFBundleVersion (defaults to GITHUB_RUN_NUMBER or Unix time)").option("--team-id <id>", "Apple Developer team (defaults to config safariTeamId)").option("--api-key-id <id>", "App Store Connect API key ID").option("--api-issuer-id <id>", "App Store Connect API issuer ID").option("--api-key-path <path>", "Path to the App Store Connect AuthKey_*.p8 file").option("--validate-only", "Create and validate the archive without uploading it").option("--platform <platform>", "Publish macos, ios, or all (defaults to config safariPlatforms)").action(async (options) => {
159
196
  const { publishSafariApp } = await import("@stacksjs/browser-extension"), { config, version } = await load(), result = await publishSafariApp(config, {
160
197
  version: options.version ?? version,
161
198
  buildNumber: options.buildNumber,
@@ -163,8 +200,9 @@ console.log('[${name}] popup')
163
200
  keyId: options.apiKeyId,
164
201
  issuerId: options.apiIssuerId,
165
202
  keyPath: options.apiKeyPath,
166
- validateOnly: Boolean(options.validateOnly)
203
+ validateOnly: Boolean(options.validateOnly),
204
+ platforms: parseSafariPlatforms(options.platform)
167
205
  });
168
- log.success(options.validateOnly ? `Validated Safari archive ${result.archivePath} (build ${result.buildNumber})` : `Uploaded Safari build ${result.buildNumber} to App Store Connect`);
206
+ log.success(options.validateOnly ? `Validated Safari ${result.artifacts.map((artifact) => artifact.platform).join(" + ")} archives (build ${result.buildNumber})` : `Uploaded Safari ${result.artifacts.map((artifact) => artifact.platform).join(" + ")} build ${result.buildNumber} to App Store Connect`);
169
207
  });
170
208
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/buddy",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.141",
5
+ "version": "0.70.143",
6
6
  "description": "Meet Buddy. The Stacks runtime.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -92,51 +92,51 @@
92
92
  "prepublishOnly": "bun run build"
93
93
  },
94
94
  "dependencies": {
95
- "@stacksjs/actions": "^0.70.141",
96
- "@stacksjs/ai": "^0.70.141",
97
- "@stacksjs/alias": "^0.70.141",
98
- "@stacksjs/arrays": "^0.70.141",
99
- "@stacksjs/auth": "^0.70.141",
100
- "@stacksjs/build": "^0.70.141",
101
- "@stacksjs/cache": "^0.70.141",
102
- "@stacksjs/cli": "^0.70.141",
95
+ "@stacksjs/actions": "^0.70.143",
96
+ "@stacksjs/ai": "^0.70.143",
97
+ "@stacksjs/alias": "^0.70.143",
98
+ "@stacksjs/arrays": "^0.70.143",
99
+ "@stacksjs/auth": "^0.70.143",
100
+ "@stacksjs/build": "^0.70.143",
101
+ "@stacksjs/cache": "^0.70.143",
102
+ "@stacksjs/cli": "^0.70.143",
103
103
  "@stacksjs/clapp": "^0.2.10",
104
- "@stacksjs/cloud": "^0.70.141",
105
- "@stacksjs/collections": "^0.70.141",
106
- "@stacksjs/config": "^0.70.141",
107
- "@stacksjs/database": "^0.70.141",
108
- "@stacksjs/desktop": "^0.70.141",
109
- "@stacksjs/dns": "^0.70.141",
110
- "@stacksjs/email": "^0.70.141",
111
- "@stacksjs/enums": "^0.70.141",
112
- "@stacksjs/error-handling": "^0.70.141",
113
- "@stacksjs/events": "^0.70.141",
114
- "@stacksjs/git": "^0.70.141",
104
+ "@stacksjs/cloud": "^0.70.143",
105
+ "@stacksjs/collections": "^0.70.143",
106
+ "@stacksjs/config": "^0.70.143",
107
+ "@stacksjs/database": "^0.70.143",
108
+ "@stacksjs/desktop": "^0.70.143",
109
+ "@stacksjs/dns": "^0.70.143",
110
+ "@stacksjs/email": "^0.70.143",
111
+ "@stacksjs/enums": "^0.70.143",
112
+ "@stacksjs/error-handling": "^0.70.143",
113
+ "@stacksjs/events": "^0.70.143",
114
+ "@stacksjs/git": "^0.70.143",
115
115
  "@stacksjs/gitit": "^0.2.5",
116
- "@stacksjs/health": "^0.70.141",
116
+ "@stacksjs/health": "^0.70.143",
117
117
  "@stacksjs/dnsx": "^0.2.3",
118
118
  "@stacksjs/httx": "^0.1.10",
119
- "@stacksjs/lint": "^0.70.141",
120
- "@stacksjs/logging": "^0.70.141",
121
- "@stacksjs/notifications": "^0.70.141",
122
- "@stacksjs/objects": "^0.70.141",
123
- "@stacksjs/orm": "^0.70.141",
124
- "@stacksjs/path": "^0.70.141",
125
- "@stacksjs/payments": "^0.70.141",
126
- "@stacksjs/realtime": "^0.70.141",
127
- "@stacksjs/router": "^0.70.141",
119
+ "@stacksjs/lint": "^0.70.143",
120
+ "@stacksjs/logging": "^0.70.143",
121
+ "@stacksjs/notifications": "^0.70.143",
122
+ "@stacksjs/objects": "^0.70.143",
123
+ "@stacksjs/orm": "^0.70.143",
124
+ "@stacksjs/path": "^0.70.143",
125
+ "@stacksjs/payments": "^0.70.143",
126
+ "@stacksjs/realtime": "^0.70.143",
127
+ "@stacksjs/router": "^0.70.143",
128
128
  "@stacksjs/rpx": "^0.11.29",
129
- "@stacksjs/search-engine": "^0.70.141",
130
- "@stacksjs/security": "^0.70.141",
131
- "@stacksjs/server": "^0.70.141",
132
- "@stacksjs/storage": "^0.70.141",
133
- "@stacksjs/strings": "^0.70.141",
134
- "@stacksjs/testing": "^0.70.141",
135
- "@stacksjs/tunnel": "^0.70.141",
136
- "@stacksjs/types": "^0.70.141",
137
- "@stacksjs/ui": "^0.70.141",
138
- "@stacksjs/utils": "^0.70.141",
139
- "@stacksjs/validation": "^0.70.141",
129
+ "@stacksjs/search-engine": "^0.70.143",
130
+ "@stacksjs/security": "^0.70.143",
131
+ "@stacksjs/server": "^0.70.143",
132
+ "@stacksjs/storage": "^0.70.143",
133
+ "@stacksjs/strings": "^0.70.143",
134
+ "@stacksjs/testing": "^0.70.143",
135
+ "@stacksjs/tunnel": "^0.70.143",
136
+ "@stacksjs/types": "^0.70.143",
137
+ "@stacksjs/ui": "^0.70.143",
138
+ "@stacksjs/utils": "^0.70.143",
139
+ "@stacksjs/validation": "^0.70.143",
140
140
  "@stacksjs/ts-cloud": "^0.7.47"
141
141
  },
142
142
  "devDependencies": {