@stacksjs/buddy 0.70.118 → 0.70.120

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,6 +6,7 @@ import { runAction } from "@stacksjs/actions";
6
6
  import { italic, onUnknownSubcommand, outro, prompts, runCommand } from "@stacksjs/cli";
7
7
  import { app, dns as dnsConfig, email as emailConfig, cloud as cloudConfig } from "@stacksjs/config";
8
8
  import { addDomain, hasUserDomainBeenAddedToCloud, syncDnsConfig } from "@stacksjs/dns";
9
+ import { loadProjectDnsConfig } from "../config";
9
10
  import { encryptEnv, env } from "@stacksjs/env";
10
11
  import { Action } from "@stacksjs/enums";
11
12
  import { path as p } from "@stacksjs/path";
@@ -1072,7 +1073,8 @@ export async function reconcileMailDns(res, ip, logger) {
1072
1073
  }
1073
1074
  }
1074
1075
  async function reconcileConfigDns(sites, logger) {
1075
- if (["a", "aaaa", "cname", "mx", "txt"].reduce((total, key) => total + (Array.isArray(dnsConfig?.[key]) ? dnsConfig[key].length : 0), 0) === 0)
1076
+ const projectDnsConfig = await loadProjectDnsConfig(dnsConfig);
1077
+ if (["a", "aaaa", "cname", "mx", "txt"].reduce((total, key) => total + (Array.isArray(projectDnsConfig?.[key]) ? projectDnsConfig[key].length : 0), 0) === 0)
1076
1078
  return;
1077
1079
  const domains = new Set;
1078
1080
  for (const site of Object.values(sites))
@@ -1080,7 +1082,7 @@ async function reconcileConfigDns(sites, logger) {
1080
1082
  domains.add(site.domain.replace(/^www\./, ""));
1081
1083
  for (const domain of domains)
1082
1084
  try {
1083
- const result = await syncDnsConfig(domain, dnsConfig);
1085
+ const result = await syncDnsConfig(domain, projectDnsConfig);
1084
1086
  if (!result.provider)
1085
1087
  continue;
1086
1088
  if (result.created || result.failed)
@@ -3,6 +3,7 @@ import { log, onUnknownSubcommand } from "@stacksjs/cli";
3
3
  import { config } from "@stacksjs/config";
4
4
  import { renderDnsConfig, resolveLiveRecords, syncDnsConfig } from "@stacksjs/dns";
5
5
  import { ExitCode } from "@stacksjs/types";
6
+ import { loadProjectDnsConfig } from "../config";
6
7
  export function dns(buddy) {
7
8
  const descriptions = {
8
9
  dns: "Lists the DNS records for a domain",
@@ -74,7 +75,7 @@ export function dns(buddy) {
74
75
  buddy.command("dns:diff [domain]", "Show which config/dns.ts records are missing from the live zone").option("--verbose", descriptions.verbose, { default: !1 }).action(async (domain, options) => {
75
76
  const target = bareDomain(domain);
76
77
  log.debug(`Running \`buddy dns:diff ${target}\` ...`, options);
77
- const { plan, provider } = await syncDnsConfig(target, config.dns, { dryRun: !0 });
78
+ const dnsConfig = await loadProjectDnsConfig(config.dns), { plan, provider } = await syncDnsConfig(target, dnsConfig, { dryRun: !0 });
78
79
  for (const item of plan.items) {
79
80
  const detail = item.record.type === "TXT" || item.record.type === "MX" ? ` ${item.record.content}` : ` \u2192 ${item.record.content}`;
80
81
  console.log(` ${item.action === "create" ? "+ create" : " keep "} ${item.record.type.padEnd(5)} ${item.record.name}${detail}`);
@@ -86,7 +87,7 @@ ${plan.create.length} to create, ${plan.keep.length} already present (${provider
86
87
  buddy.command("dns:sync [domain]", "Additively sync config/dns.ts to the registrar (creates missing records; never deletes or overwrites)").option("--dry-run", "Show the plan without writing any records", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (domain, options) => {
87
88
  const target = bareDomain(domain);
88
89
  log.debug(`Running \`buddy dns:sync ${target}\` ...`, options);
89
- const result = await syncDnsConfig(target, config.dns, { dryRun: options.dryRun });
90
+ const dnsConfig = await loadProjectDnsConfig(config.dns), result = await syncDnsConfig(target, dnsConfig, { dryRun: options.dryRun });
90
91
  if (!result.provider && !options.dryRun) {
91
92
  log.warn(`No DNS provider credentials found (e.g. PORKBUN_API_KEY / PORKBUN_SECRET_KEY) \u2014 nothing was synced. ${result.plan.create.length} record(s) would be created.`);
92
93
  process.exit(ExitCode.Success);
@@ -75,6 +75,25 @@ console.log('[${name}] popup')
75
75
  log.success(`Packaged ${config.name} (${target}) \u2192 ${out}`);
76
76
  }
77
77
  });
78
+ 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) => {
79
+ const { provisionSafariApp } = await import("@stacksjs/browser-extension"), { config } = await load(), result = await provisionSafariApp(config, {
80
+ keyId: options.apiKeyId,
81
+ issuerId: options.apiIssuerId,
82
+ keyPath: options.apiKeyPath,
83
+ checkOnly: Boolean(options.check)
84
+ });
85
+ for (const resource of [result.container, result.extension])
86
+ if (resource.created)
87
+ log.success(`Registered Bundle ID ${resource.identifier}`);
88
+ else if (resource.exists)
89
+ log.success(`Bundle ID exists: ${resource.identifier}`);
90
+ else
91
+ log.warn(`Bundle ID is missing: ${resource.identifier}`);
92
+ if (result.appRecord.exists)
93
+ log.success(`App Store Connect app record exists (${result.appRecord.id})`);
94
+ else
95
+ log.warn("App Store Connect app record is missing. Apple requires creating it in the App Store Connect website.");
96
+ });
78
97
  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) => {
79
98
  const { scaffoldSafariApp } = await import("@stacksjs/browser-extension"), { config } = await load(), { dir, written, skipped } = await scaffoldSafariApp(config, {
80
99
  bundleId: options.bundleId,
package/dist/config.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { CLI } from '@stacksjs/cli';
2
+ import type { DnsConfig } from '@stacksjs/types';
3
+ export declare function loadProjectDnsConfig(fallback: DnsConfig): Promise<DnsConfig>;
2
4
  /**
3
5
  * Validate the buddy config structure
4
6
  */
package/dist/config.js CHANGED
@@ -1,6 +1,14 @@
1
1
  import { existsSync } from "node:fs";
2
+ import { pathToFileURL } from "node:url";
2
3
  import { log } from "@stacksjs/cli";
3
4
  import { path as p } from "@stacksjs/path";
5
+ export async function loadProjectDnsConfig(fallback) {
6
+ const configPath = p.projectConfigPath("dns.ts");
7
+ if (!existsSync(configPath))
8
+ return fallback;
9
+ const loaded = await import(`${pathToFileURL(configPath).href}?updated=${Date.now()}`);
10
+ return loaded.default ?? loaded.dns ?? fallback;
11
+ }
4
12
  export function validateConfig(config) {
5
13
  const errors = [];
6
14
  if (typeof config !== "object" || config === null) {
@@ -27,6 +27,7 @@ const commandRegistry = {
27
27
  "extension:build": { path: "./commands/extension.js", exportName: "extension" },
28
28
  "extension:package": { path: "./commands/extension.js", exportName: "extension" },
29
29
  "extension:safari:init": { path: "./commands/extension.js", exportName: "extension" },
30
+ "extension:safari:provision": { path: "./commands/extension.js", exportName: "extension" },
30
31
  "extension:safari:app": { path: "./commands/extension.js", exportName: "extension" },
31
32
  "extension:safari:publish": { path: "./commands/extension.js", exportName: "extension" },
32
33
  "dashboard:install": { path: "./commands/features.js", exportName: "features" },
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.118",
5
+ "version": "0.70.120",
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.118",
96
- "@stacksjs/ai": "^0.70.118",
97
- "@stacksjs/alias": "^0.70.118",
98
- "@stacksjs/arrays": "^0.70.118",
99
- "@stacksjs/auth": "^0.70.118",
100
- "@stacksjs/build": "^0.70.118",
101
- "@stacksjs/cache": "^0.70.118",
102
- "@stacksjs/cli": "^0.70.118",
95
+ "@stacksjs/actions": "^0.70.120",
96
+ "@stacksjs/ai": "^0.70.120",
97
+ "@stacksjs/alias": "^0.70.120",
98
+ "@stacksjs/arrays": "^0.70.120",
99
+ "@stacksjs/auth": "^0.70.120",
100
+ "@stacksjs/build": "^0.70.120",
101
+ "@stacksjs/cache": "^0.70.120",
102
+ "@stacksjs/cli": "^0.70.120",
103
103
  "@stacksjs/clapp": "^0.2.10",
104
- "@stacksjs/cloud": "^0.70.118",
105
- "@stacksjs/collections": "^0.70.118",
106
- "@stacksjs/config": "^0.70.118",
107
- "@stacksjs/database": "^0.70.118",
108
- "@stacksjs/desktop": "^0.70.118",
109
- "@stacksjs/dns": "^0.70.118",
110
- "@stacksjs/email": "^0.70.118",
111
- "@stacksjs/enums": "^0.70.118",
112
- "@stacksjs/error-handling": "^0.70.118",
113
- "@stacksjs/events": "^0.70.118",
114
- "@stacksjs/git": "^0.70.118",
104
+ "@stacksjs/cloud": "^0.70.120",
105
+ "@stacksjs/collections": "^0.70.120",
106
+ "@stacksjs/config": "^0.70.120",
107
+ "@stacksjs/database": "^0.70.120",
108
+ "@stacksjs/desktop": "^0.70.120",
109
+ "@stacksjs/dns": "^0.70.120",
110
+ "@stacksjs/email": "^0.70.120",
111
+ "@stacksjs/enums": "^0.70.120",
112
+ "@stacksjs/error-handling": "^0.70.120",
113
+ "@stacksjs/events": "^0.70.120",
114
+ "@stacksjs/git": "^0.70.120",
115
115
  "@stacksjs/gitit": "^0.2.5",
116
- "@stacksjs/health": "^0.70.118",
116
+ "@stacksjs/health": "^0.70.120",
117
117
  "@stacksjs/dnsx": "^0.2.3",
118
118
  "@stacksjs/httx": "^0.1.10",
119
- "@stacksjs/lint": "^0.70.118",
120
- "@stacksjs/logging": "^0.70.118",
121
- "@stacksjs/notifications": "^0.70.118",
122
- "@stacksjs/objects": "^0.70.118",
123
- "@stacksjs/orm": "^0.70.118",
124
- "@stacksjs/path": "^0.70.118",
125
- "@stacksjs/payments": "^0.70.118",
126
- "@stacksjs/realtime": "^0.70.118",
127
- "@stacksjs/router": "^0.70.118",
119
+ "@stacksjs/lint": "^0.70.120",
120
+ "@stacksjs/logging": "^0.70.120",
121
+ "@stacksjs/notifications": "^0.70.120",
122
+ "@stacksjs/objects": "^0.70.120",
123
+ "@stacksjs/orm": "^0.70.120",
124
+ "@stacksjs/path": "^0.70.120",
125
+ "@stacksjs/payments": "^0.70.120",
126
+ "@stacksjs/realtime": "^0.70.120",
127
+ "@stacksjs/router": "^0.70.120",
128
128
  "@stacksjs/rpx": "^0.11.29",
129
- "@stacksjs/search-engine": "^0.70.118",
130
- "@stacksjs/security": "^0.70.118",
131
- "@stacksjs/server": "^0.70.118",
132
- "@stacksjs/storage": "^0.70.118",
133
- "@stacksjs/strings": "^0.70.118",
134
- "@stacksjs/testing": "^0.70.118",
135
- "@stacksjs/tunnel": "^0.70.118",
136
- "@stacksjs/types": "^0.70.118",
137
- "@stacksjs/ui": "^0.70.118",
138
- "@stacksjs/utils": "^0.70.118",
139
- "@stacksjs/validation": "^0.70.118",
129
+ "@stacksjs/search-engine": "^0.70.120",
130
+ "@stacksjs/security": "^0.70.120",
131
+ "@stacksjs/server": "^0.70.120",
132
+ "@stacksjs/storage": "^0.70.120",
133
+ "@stacksjs/strings": "^0.70.120",
134
+ "@stacksjs/testing": "^0.70.120",
135
+ "@stacksjs/tunnel": "^0.70.120",
136
+ "@stacksjs/types": "^0.70.120",
137
+ "@stacksjs/ui": "^0.70.120",
138
+ "@stacksjs/utils": "^0.70.120",
139
+ "@stacksjs/validation": "^0.70.120",
140
140
  "@stacksjs/ts-cloud": "^0.7.36"
141
141
  },
142
142
  "devDependencies": {