@stacksjs/buddy 0.70.258 → 0.70.260
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/cli.d.ts +11 -1
- package/dist/cli.js +5 -164
- package/dist/commands/about.js +1 -35
- package/dist/commands/add.js +1 -25
- package/dist/commands/ai-context.js +4 -27
- package/dist/commands/auth.js +1 -68
- package/dist/commands/build.js +1 -221
- package/dist/commands/cd.js +8 -39
- package/dist/commands/changelog.js +1 -32
- package/dist/commands/clean.js +1 -44
- package/dist/commands/cloud.js +2 -519
- package/dist/commands/commit.js +1 -16
- package/dist/commands/completion.js +6 -42
- package/dist/commands/config-migrate.js +6 -94
- package/dist/commands/configure.js +2 -45
- package/dist/commands/create.js +1 -162
- package/dist/commands/deploy.js +13 -1676
- package/dist/commands/desktop-apple.js +12 -399
- package/dist/commands/dev.js +6 -1083
- package/dist/commands/dns.js +3 -103
- package/dist/commands/docs/buddy-commands.js +10 -132
- package/dist/commands/docs/buddy-commands.test.js +1 -38
- package/dist/commands/docs/framework-repo.js +1 -14
- package/dist/commands/docs/framework-repo.test.js +1 -68
- package/dist/commands/docs/generated-artifacts.js +3 -70
- package/dist/commands/docs/generated-artifacts.test.js +1 -19
- package/dist/commands/docs/links.js +2 -85
- package/dist/commands/docs/links.test.js +4 -66
- package/dist/commands/docs.js +1 -24
- package/dist/commands/doctor.js +2 -478
- package/dist/commands/domains.js +2 -152
- package/dist/commands/email.js +31 -503
- package/dist/commands/env.js +1 -312
- package/dist/commands/extension.js +1 -239
- package/dist/commands/features.js +9 -345
- package/dist/commands/fresh.js +1 -46
- package/dist/commands/generate.js +2 -152
- package/dist/commands/http.js +1 -33
- package/dist/commands/index.js +1 -57
- package/dist/commands/install.js +1 -22
- package/dist/commands/key.js +1 -23
- package/dist/commands/link.js +2 -147
- package/dist/commands/lint.js +2 -84
- package/dist/commands/list.js +1 -140
- package/dist/commands/mail.js +15 -1477
- package/dist/commands/maintenance.js +1 -141
- package/dist/commands/make.js +1 -392
- package/dist/commands/migrate-project.js +1 -49
- package/dist/commands/migrate.js +27 -625
- package/dist/commands/outdated.js +1 -19
- package/dist/commands/package.js +1 -17
- package/dist/commands/phone.js +17 -181
- package/dist/commands/ports.js +2 -118
- package/dist/commands/prepublish.js +1 -17
- package/dist/commands/projects.js +1 -29
- package/dist/commands/protocol/craft-evidence.js +4 -98
- package/dist/commands/protocol/craft-evidence.test.js +1 -20
- package/dist/commands/protocol/desktop-lifecycle-report.js +3 -57
- package/dist/commands/protocol/desktop-lifecycle-report.test.js +1 -32
- package/dist/commands/protocol/desktop-support.js +2 -32
- package/dist/commands/protocol/desktop-workflow.test.js +3 -35
- package/dist/commands/protocol/driver-registry.js +2 -71
- package/dist/commands/protocol/pantry-evidence.js +4 -144
- package/dist/commands/protocol/pantry-evidence.test.js +1 -29
- package/dist/commands/protocol/release-manifest.js +3 -102
- package/dist/commands/protocol/release-manifest.test.js +2 -34
- package/dist/commands/protocol/run-conformance.js +4 -346
- package/dist/commands/protocol/run-conformance.test.js +1 -52
- package/dist/commands/protocol/run-driver-contracts.js +4 -83
- package/dist/commands/protocol/run-driver-contracts.test.js +1 -18
- package/dist/commands/protocol/source-manifest.js +3 -113
- package/dist/commands/protocol/sync-suite.js +3 -136
- package/dist/commands/protocol/sync-suite.test.js +1 -44
- package/dist/commands/protocol.js +1 -60
- package/dist/commands/publish.js +8 -500
- package/dist/commands/queue.js +1 -248
- package/dist/commands/release.js +1 -42
- package/dist/commands/route.js +1 -21
- package/dist/commands/run-tool.js +1 -9
- package/dist/commands/saas.js +1 -25
- package/dist/commands/schedule.js +1 -61
- package/dist/commands/search.js +1 -84
- package/dist/commands/seed.js +1 -47
- package/dist/commands/serve.js +1 -55
- package/dist/commands/setup-ai.js +2 -121
- package/dist/commands/setup.js +2 -305
- package/dist/commands/share.js +1 -214
- package/dist/commands/sms.js +32 -319
- package/dist/commands/stacks.js +1 -72
- package/dist/commands/telemetry.js +1 -74
- package/dist/commands/test.js +1 -130
- package/dist/commands/tinker.js +1 -37
- package/dist/commands/types.js +1 -18
- package/dist/commands/upgrade.js +1 -98
- package/dist/commands/user.js +3 -84
- package/dist/commands/version.js +1 -14
- package/dist/config.js +1 -231
- package/dist/custom-cli.js +1 -23
- package/dist/database-preflight.js +1 -88
- package/dist/global-options.js +1 -4
- package/dist/index.js +1 -1
- package/dist/lazy-commands.js +1 -241
- package/dist/migrators/index.js +2 -62
- package/dist/migrators/laravel/index.js +1 -148
- package/dist/migrators/laravel/migrations.js +4 -231
- package/dist/migrators/laravel/models.js +8 -111
- package/dist/migrators/rails/index.js +1 -11
- package/dist/production-server.js +1 -257
- package/dist/project-setup.js +1 -36
- package/dist/serve-entry.js +1 -5
- package/dist/version-info.js +1 -5
- package/package.json +53 -46
|
@@ -1,19 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import process from "node:process";
|
|
3
|
-
import { log } from "@stacksjs/logging";
|
|
4
|
-
import { projectPath } from "@stacksjs/path";
|
|
5
|
-
import { onUnknownSubcommand } from "@stacksjs/cli";
|
|
6
|
-
export function outdated(buddy) {
|
|
7
|
-
const descriptions = {
|
|
8
|
-
outdated: "List all the outdated project dependencies",
|
|
9
|
-
project: "Target a specific project",
|
|
10
|
-
verbose: "Enable verbose output"
|
|
11
|
-
};
|
|
12
|
-
buddy.command("outdated", descriptions.outdated).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async () => {
|
|
13
|
-
log.debug("Running `buddy outdated` ...");
|
|
14
|
-
$.cwd(projectPath());
|
|
15
|
-
const response = await $`bun outdated`.text();
|
|
16
|
-
console.log(response);
|
|
17
|
-
});
|
|
18
|
-
onUnknownSubcommand(buddy, "outdated");
|
|
19
|
-
}
|
|
1
|
+
import{$}from"bun";import process from"node:process";import{log}from"@stacksjs/logging";import{projectPath}from"@stacksjs/path";import{onUnknownSubcommand}from"@stacksjs/cli";export function outdated(buddy){const descriptions={outdated:"List all the outdated project dependencies",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("outdated",descriptions.outdated).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async()=>{log.debug("Running `buddy outdated` ...");$.cwd(projectPath());const response=await $`bun outdated`.text();console.log(response)});onUnknownSubcommand(buddy,"outdated")}
|
package/dist/commands/package.js
CHANGED
|
@@ -1,17 +1 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
|
|
3
|
-
import { ExitCode } from "@stacksjs/types";
|
|
4
|
-
export function packageCommands(buddy) {
|
|
5
|
-
buddy.command("package:discover", "Discover Stacks-compatible packages from pantry").option("--verbose", "Enable verbose output", { default: !1 }).action(async () => {
|
|
6
|
-
const perf = await intro("buddy package:discover"), { discoverPackages } = await import("@stacksjs/actions"), manifest = await discoverPackages(), count = Object.keys(manifest.packages).length;
|
|
7
|
-
if (count > 0) {
|
|
8
|
-
log.success(`Discovered ${count} Stacks package${count === 1 ? "" : "s"}:`);
|
|
9
|
-
for (const name of Object.keys(manifest.packages))
|
|
10
|
-
log.info(` - ${name}`);
|
|
11
|
-
} else
|
|
12
|
-
log.info("No Stacks-compatible packages found in pantry");
|
|
13
|
-
await outro("Package discovery complete", { startTime: perf, useSeconds: !0 });
|
|
14
|
-
process.exit(ExitCode.Success);
|
|
15
|
-
});
|
|
16
|
-
onUnknownSubcommand(buddy, "package");
|
|
17
|
-
}
|
|
1
|
+
import process from"node:process";import{intro,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{ExitCode}from"@stacksjs/types";export function packageCommands(buddy){buddy.command("package:discover","Discover Stacks-compatible packages from pantry").option("--verbose","Enable verbose output",{default:!1}).action(async()=>{const perf=await intro("buddy package:discover"),{discoverPackages}=await import("@stacksjs/actions"),manifest=await discoverPackages(),count=Object.keys(manifest.packages).length;if(count>0){log.success(`Discovered ${count} Stacks package${count===1?"":"s"}:`);for(const name of Object.keys(manifest.packages))log.info(` - ${name}`)}else log.info("No Stacks-compatible packages found in pantry");await outro("Package discovery complete",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"package")}
|
package/dist/commands/phone.js
CHANGED
|
@@ -1,188 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const TIMEOUT_MS = 30000;
|
|
4
|
-
async function withTimeout(promise, ms = TIMEOUT_MS) {
|
|
5
|
-
let timeoutId;
|
|
6
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
7
|
-
timeoutId = setTimeout(() => reject(Error(`Operation timed out after ${ms}ms`)), ms);
|
|
8
|
-
});
|
|
9
|
-
try {
|
|
10
|
-
return await Promise.race([promise, timeoutPromise]);
|
|
11
|
-
} finally {
|
|
12
|
-
clearTimeout(timeoutId);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function loadAwsCredentials() {
|
|
16
|
-
const envPath = ".env.production";
|
|
17
|
-
if (existsSync(envPath)) {
|
|
18
|
-
const content = readFileSync(envPath, "utf-8");
|
|
19
|
-
for (const line of content.split(`
|
|
20
|
-
`)) {
|
|
21
|
-
const eq = line.indexOf("=");
|
|
22
|
-
if (eq > 0 && !line.startsWith("#"))
|
|
23
|
-
process.env[line.slice(0, eq).trim()] = line.slice(eq + 1).trim();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const descriptions = {
|
|
28
|
-
phone: "Phone/voice service management commands",
|
|
29
|
-
status: "Show phone service status",
|
|
30
|
-
numbers: "List phone numbers",
|
|
31
|
-
search: "Search available phone numbers",
|
|
32
|
-
setup: "Initialize phone infrastructure"
|
|
33
|
-
};
|
|
34
|
-
export function phone(buddy) {
|
|
35
|
-
buddy.command("phone", descriptions.phone).action(async () => {
|
|
36
|
-
console.log(`
|
|
1
|
+
import{getErrorMessage}from"@stacksjs/utils";import{readFileSync,existsSync}from"node:fs";const TIMEOUT_MS=30000;async function withTimeout(promise,ms=TIMEOUT_MS){let timeoutId;const timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(Error(`Operation timed out after ${ms}ms`)),ms)});try{return await Promise.race([promise,timeoutPromise])}finally{clearTimeout(timeoutId)}}function loadAwsCredentials(){const envPath=".env.production";if(existsSync(envPath)){const content=readFileSync(envPath,"utf-8");for(const line of content.split(`
|
|
2
|
+
`)){const eq=line.indexOf("=");if(eq>0&&!line.startsWith("#"))process.env[line.slice(0,eq).trim()]=line.slice(eq+1).trim()}}}const descriptions={phone:"Phone/voice service management commands",status:"Show phone service status",numbers:"List phone numbers",search:"Search available phone numbers",setup:"Initialize phone infrastructure"};export function phone(buddy){buddy.command("phone",descriptions.phone).action(async()=>{console.log(`
|
|
37
3
|
\uD83D\uDCDE Phone Service Commands
|
|
38
|
-
`);
|
|
39
|
-
console.log(" buddy phone:status - Show phone service status");
|
|
40
|
-
console.log(" buddy phone:numbers - List phone numbers");
|
|
41
|
-
console.log(" buddy phone:search - Search available phone numbers");
|
|
42
|
-
console.log(" buddy phone:setup - Initialize phone infrastructure");
|
|
43
|
-
console.log("");
|
|
44
|
-
process.exit(0);
|
|
45
|
-
});
|
|
46
|
-
buddy.command("phone:status", descriptions.status).action(async () => {
|
|
47
|
-
console.log(`
|
|
4
|
+
`);console.log(" buddy phone:status - Show phone service status");console.log(" buddy phone:numbers - List phone numbers");console.log(" buddy phone:search - Search available phone numbers");console.log(" buddy phone:setup - Initialize phone infrastructure");console.log("");process.exit(0)});buddy.command("phone:status",descriptions.status).action(async()=>{console.log(`
|
|
48
5
|
\uD83D\uDCDE Phone Service Status
|
|
49
|
-
`);
|
|
50
|
-
loadAwsCredentials();
|
|
51
|
-
try {
|
|
52
|
-
const { ConnectClient } = await import("@stacksjs/ts-cloud"), connect = new ConnectClient(process.env.AWS_REGION || "us-east-1"), instanceAlias = `${(process.env.APP_NAME || "stacks").toLowerCase().replace(/[^a-z0-9-]/g, "-")}-phone`;
|
|
53
|
-
console.log(`Looking for Connect instance: ${instanceAlias}`);
|
|
54
|
-
const instance = (await withTimeout(connect.listInstances({ MaxResults: 100 }))).InstanceSummaryList?.find((i) => i.InstanceAlias === instanceAlias);
|
|
55
|
-
if (instance) {
|
|
56
|
-
console.log(`
|
|
6
|
+
`);loadAwsCredentials();try{const{ConnectClient}=await import("@stacksjs/ts-cloud"),connect=new ConnectClient(process.env.AWS_REGION||"us-east-1"),instanceAlias=`${(process.env.APP_NAME||"stacks").toLowerCase().replace(/[^a-z0-9-]/g,"-")}-phone`;console.log(`Looking for Connect instance: ${instanceAlias}`);const instance=(await withTimeout(connect.listInstances({MaxResults:100}))).InstanceSummaryList?.find((i)=>i.InstanceAlias===instanceAlias);if(instance){console.log(`
|
|
57
7
|
\u2705 Phone Service Active
|
|
58
|
-
`);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (instance.Id)
|
|
65
|
-
try {
|
|
66
|
-
const numbers = await withTimeout(connect.listPhoneNumbers({ InstanceId: instance.Id }));
|
|
67
|
-
if (numbers.ListPhoneNumbersSummaryList && numbers.ListPhoneNumbersSummaryList.length > 0) {
|
|
68
|
-
console.log(`
|
|
69
|
-
Phone Numbers:`);
|
|
70
|
-
for (const num of numbers.ListPhoneNumbersSummaryList)
|
|
71
|
-
console.log(` \uD83D\uDCF1 ${num.PhoneNumber} (${num.PhoneNumberType})`);
|
|
72
|
-
} else
|
|
73
|
-
console.log(`
|
|
74
|
-
No phone numbers claimed yet.`);
|
|
75
|
-
} catch {
|
|
76
|
-
console.log(`
|
|
77
|
-
Could not retrieve phone numbers.`);
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
console.log(`
|
|
81
|
-
\u274C Phone service not deployed.`);
|
|
82
|
-
console.log(`
|
|
83
|
-
\uD83D\uDCA1 To set up phone service:`);
|
|
84
|
-
console.log(" 1. Enable phone in config/phone.ts");
|
|
85
|
-
console.log(" 2. Run `buddy deploy`");
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error("Error checking status:", getErrorMessage(error));
|
|
89
|
-
}
|
|
90
|
-
process.exit(0);
|
|
91
|
-
});
|
|
92
|
-
buddy.command("phone:numbers", descriptions.numbers).action(async () => {
|
|
93
|
-
console.log(`
|
|
8
|
+
`);console.log(` Instance ID: ${instance.Id}`);console.log(` Alias: ${instance.InstanceAlias}`);console.log(` Status: ${instance.InstanceStatus}`);console.log(` Inbound Calls: ${instance.InboundCallsEnabled?"Enabled":"Disabled"}`);console.log(` Outbound Calls: ${instance.OutboundCallsEnabled?"Enabled":"Disabled"}`);if(instance.Id)try{const numbers=await withTimeout(connect.listPhoneNumbers({InstanceId:instance.Id}));if(numbers.ListPhoneNumbersSummaryList&&numbers.ListPhoneNumbersSummaryList.length>0){console.log(`
|
|
9
|
+
Phone Numbers:`);for(const num of numbers.ListPhoneNumbersSummaryList)console.log(` \uD83D\uDCF1 ${num.PhoneNumber} (${num.PhoneNumberType})`)}else console.log(`
|
|
10
|
+
No phone numbers claimed yet.`)}catch{console.log(`
|
|
11
|
+
Could not retrieve phone numbers.`)}}else{console.log(`
|
|
12
|
+
\u274C Phone service not deployed.`);console.log(`
|
|
13
|
+
\uD83D\uDCA1 To set up phone service:`);console.log(" 1. Enable phone in config/phone.ts");console.log(" 2. Run `buddy deploy`")}}catch(error){console.error("Error checking status:",getErrorMessage(error))}process.exit(0)});buddy.command("phone:numbers",descriptions.numbers).action(async()=>{console.log(`
|
|
94
14
|
\uD83D\uDCDE Phone Numbers
|
|
95
|
-
`);
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
const { ConnectClient } = await import("@stacksjs/ts-cloud"), connect = new ConnectClient(process.env.AWS_REGION || "us-east-1"), instanceAlias = `${(process.env.APP_NAME || "stacks").toLowerCase().replace(/[^a-z0-9-]/g, "-")}-phone`, instance = (await withTimeout(connect.listInstances({ MaxResults: 100 }))).InstanceSummaryList?.find((i) => i.InstanceAlias === instanceAlias);
|
|
99
|
-
if (!instance?.Id) {
|
|
100
|
-
console.log("Phone service not deployed. Run `buddy phone:setup` first.");
|
|
101
|
-
process.exit(0);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const numbers = await withTimeout(connect.listPhoneNumbers({ InstanceId: instance.Id }));
|
|
105
|
-
if (!numbers.ListPhoneNumbersSummaryList || numbers.ListPhoneNumbersSummaryList.length === 0) {
|
|
106
|
-
console.log("No phone numbers claimed.");
|
|
107
|
-
console.log("\n\uD83D\uDCA1 Use `buddy phone:search` to find available numbers.");
|
|
108
|
-
process.exit(0);
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
console.log(`Claimed Phone Numbers:
|
|
112
|
-
`);
|
|
113
|
-
for (const num of numbers.ListPhoneNumbersSummaryList) {
|
|
114
|
-
console.log(` \uD83D\uDCF1 ${num.PhoneNumber}`);
|
|
115
|
-
console.log(` Type: ${num.PhoneNumberType}`);
|
|
116
|
-
console.log(` Country: ${num.PhoneNumberCountryCode}`);
|
|
117
|
-
if (num.PhoneNumberDescription)
|
|
118
|
-
console.log(` Description: ${num.PhoneNumberDescription}`);
|
|
119
|
-
console.log("");
|
|
120
|
-
}
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error("Error listing numbers:", getErrorMessage(error));
|
|
123
|
-
}
|
|
124
|
-
process.exit(0);
|
|
125
|
-
});
|
|
126
|
-
buddy.command("phone:search [country]", descriptions.search).option("-t, --type <type>", "Phone number type (TOLL_FREE, DID)", { default: "TOLL_FREE" }).action(async (country, options) => {
|
|
127
|
-
const countryCode = country?.toUpperCase() || "US", phoneType = options.type?.toUpperCase() || "TOLL_FREE";
|
|
128
|
-
console.log(`
|
|
15
|
+
`);loadAwsCredentials();try{const{ConnectClient}=await import("@stacksjs/ts-cloud"),connect=new ConnectClient(process.env.AWS_REGION||"us-east-1"),instanceAlias=`${(process.env.APP_NAME||"stacks").toLowerCase().replace(/[^a-z0-9-]/g,"-")}-phone`,instance=(await withTimeout(connect.listInstances({MaxResults:100}))).InstanceSummaryList?.find((i)=>i.InstanceAlias===instanceAlias);if(!instance?.Id){console.log("Phone service not deployed. Run `buddy phone:setup` first.");process.exit(0);return}const numbers=await withTimeout(connect.listPhoneNumbers({InstanceId:instance.Id}));if(!numbers.ListPhoneNumbersSummaryList||numbers.ListPhoneNumbersSummaryList.length===0){console.log("No phone numbers claimed.");console.log("\n\uD83D\uDCA1 Use `buddy phone:search` to find available numbers.");process.exit(0);return}console.log(`Claimed Phone Numbers:
|
|
16
|
+
`);for(const num of numbers.ListPhoneNumbersSummaryList){console.log(` \uD83D\uDCF1 ${num.PhoneNumber}`);console.log(` Type: ${num.PhoneNumberType}`);console.log(` Country: ${num.PhoneNumberCountryCode}`);if(num.PhoneNumberDescription)console.log(` Description: ${num.PhoneNumberDescription}`);console.log("")}}catch(error){console.error("Error listing numbers:",getErrorMessage(error))}process.exit(0)});buddy.command("phone:search [country]",descriptions.search).option("-t, --type <type>","Phone number type (TOLL_FREE, DID)",{default:"TOLL_FREE"}).action(async(country,options)=>{const countryCode=country?.toUpperCase()||"US",phoneType=options.type?.toUpperCase()||"TOLL_FREE";console.log(`
|
|
129
17
|
\uD83D\uDCDE Searching for ${phoneType} numbers in ${countryCode}...
|
|
130
|
-
`);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const { ConnectClient } = await import("@stacksjs/ts-cloud"), connect = new ConnectClient(process.env.AWS_REGION || "us-east-1"), instanceAlias = `${(process.env.APP_NAME || "stacks").toLowerCase().replace(/[^a-z0-9-]/g, "-")}-phone`, instance = (await withTimeout(connect.listInstances({ MaxResults: 100 }))).InstanceSummaryList?.find((i) => i.InstanceAlias === instanceAlias);
|
|
134
|
-
if (!instance?.Arn) {
|
|
135
|
-
console.log("Phone service not deployed. Run `buddy phone:setup` first.");
|
|
136
|
-
process.exit(0);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const available = await withTimeout(connect.searchAvailablePhoneNumbers({
|
|
140
|
-
TargetArn: instance.Arn,
|
|
141
|
-
PhoneNumberCountryCode: countryCode,
|
|
142
|
-
PhoneNumberType: phoneType,
|
|
143
|
-
MaxResults: 10
|
|
144
|
-
}));
|
|
145
|
-
if (!available.AvailableNumbersList || available.AvailableNumbersList.length === 0) {
|
|
146
|
-
console.log(`No ${phoneType} numbers available in ${countryCode}.`);
|
|
147
|
-
console.log(`
|
|
148
|
-
\uD83D\uDCA1 Try a different country or number type.`);
|
|
149
|
-
process.exit(0);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
console.log(`Available Phone Numbers:
|
|
153
|
-
`);
|
|
154
|
-
for (const num of available.AvailableNumbersList)
|
|
155
|
-
console.log(` \uD83D\uDCF1 ${num.PhoneNumber}`);
|
|
156
|
-
console.log("\n\uD83D\uDCA1 To claim a number, use `buddy phone:claim <number>`");
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (getErrorMessage(error).includes("not authorized")) {
|
|
159
|
-
console.log("Not authorized to search phone numbers.");
|
|
160
|
-
console.log("Make sure your AWS account has Amazon Connect permissions.");
|
|
161
|
-
} else
|
|
162
|
-
console.error("Error searching numbers:", getErrorMessage(error));
|
|
163
|
-
}
|
|
164
|
-
process.exit(0);
|
|
165
|
-
});
|
|
166
|
-
buddy.command("phone:setup", descriptions.setup).action(async () => {
|
|
167
|
-
console.log(`
|
|
18
|
+
`);loadAwsCredentials();try{const{ConnectClient}=await import("@stacksjs/ts-cloud"),connect=new ConnectClient(process.env.AWS_REGION||"us-east-1"),instanceAlias=`${(process.env.APP_NAME||"stacks").toLowerCase().replace(/[^a-z0-9-]/g,"-")}-phone`,instance=(await withTimeout(connect.listInstances({MaxResults:100}))).InstanceSummaryList?.find((i)=>i.InstanceAlias===instanceAlias);if(!instance?.Arn){console.log("Phone service not deployed. Run `buddy phone:setup` first.");process.exit(0);return}const available=await withTimeout(connect.searchAvailablePhoneNumbers({TargetArn:instance.Arn,PhoneNumberCountryCode:countryCode,PhoneNumberType:phoneType,MaxResults:10}));if(!available.AvailableNumbersList||available.AvailableNumbersList.length===0){console.log(`No ${phoneType} numbers available in ${countryCode}.`);console.log(`
|
|
19
|
+
\uD83D\uDCA1 Try a different country or number type.`);process.exit(0);return}console.log(`Available Phone Numbers:
|
|
20
|
+
`);for(const num of available.AvailableNumbersList)console.log(` \uD83D\uDCF1 ${num.PhoneNumber}`);console.log("\n\uD83D\uDCA1 To claim a number, use `buddy phone:claim <number>`")}catch(error){if(getErrorMessage(error).includes("not authorized")){console.log("Not authorized to search phone numbers.");console.log("Make sure your AWS account has Amazon Connect permissions.")}else console.error("Error searching numbers:",getErrorMessage(error))}process.exit(0)});buddy.command("phone:setup",descriptions.setup).action(async()=>{console.log(`
|
|
168
21
|
\uD83D\uDCDE Phone Service Setup
|
|
169
|
-
`);
|
|
170
|
-
console.log("Amazon Connect setup requires manual configuration.");
|
|
171
|
-
console.log(`
|
|
22
|
+
`);console.log("Amazon Connect setup requires manual configuration.");console.log(`
|
|
172
23
|
Steps to set up phone service:
|
|
173
|
-
`);
|
|
174
|
-
console.log("1. Enable phone in config/phone.ts:");
|
|
175
|
-
console.log(" enabled: true");
|
|
176
|
-
console.log("");
|
|
177
|
-
console.log("2. Run `buddy deploy` to create the Connect instance");
|
|
178
|
-
console.log("");
|
|
179
|
-
console.log("3. Access the Connect console to:");
|
|
180
|
-
console.log(" - Claim phone numbers");
|
|
181
|
-
console.log(" - Configure contact flows");
|
|
182
|
-
console.log(" - Set up routing profiles");
|
|
183
|
-
console.log("");
|
|
184
|
-
console.log("4. Use `buddy phone:status` to verify setup");
|
|
185
|
-
console.log("");
|
|
186
|
-
process.exit(0);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
24
|
+
`);console.log("1. Enable phone in config/phone.ts:");console.log(" enabled: true");console.log("");console.log("2. Run `buddy deploy` to create the Connect instance");console.log("");console.log("3. Access the Connect console to:");console.log(" - Claim phone numbers");console.log(" - Configure contact flows");console.log(" - Set up routing profiles");console.log("");console.log("4. Use `buddy phone:status` to verify setup");console.log("");process.exit(0)})}
|
package/dist/commands/ports.js
CHANGED
|
@@ -1,118 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { intro, italic, onUnknownSubcommand, outro } from "@stacksjs/cli";
|
|
4
|
-
import { ports as projectPorts } from "@stacksjs/config";
|
|
5
|
-
import { log } from "@stacksjs/logging";
|
|
6
|
-
import { findProjectPath, path as p, projectPath } from "@stacksjs/path";
|
|
7
|
-
import { ExitCode } from "@stacksjs/types";
|
|
8
|
-
import { findStacksProjects } from "@stacksjs/utils";
|
|
9
|
-
export function ports(buddy) {
|
|
10
|
-
const descriptions = {
|
|
11
|
-
command: "Let buddy check your project for potential issues and misconfigurations",
|
|
12
|
-
ports: "Check if the ports are available",
|
|
13
|
-
project: "Target a specific project",
|
|
14
|
-
verbose: "Enable verbose output"
|
|
15
|
-
};
|
|
16
|
-
buddy.command("ports", descriptions.command).option("-l, --list", "List the used ports", { default: !0 }).option("-c, --check", "Check if the ports are available", {
|
|
17
|
-
default: !1
|
|
18
|
-
}).option("-p, --project [name]", descriptions.project, {
|
|
19
|
-
default: void 0
|
|
20
|
-
}).option("-q, --quiet", "Use minimal output", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
21
|
-
log.debug("Running `buddy ports` ...", options);
|
|
22
|
-
let perf;
|
|
23
|
-
if (!options.quiet)
|
|
24
|
-
perf = await intro("buddy ports");
|
|
25
|
-
if (options.project) {
|
|
26
|
-
const path = await findProjectPath(options.project);
|
|
27
|
-
log.debug(`Path: ${path}`);
|
|
28
|
-
const ports = await getPortsForProjectPath(path, options);
|
|
29
|
-
log.debug(`./buddy ports --quiet response for ${projectPath}`, ports);
|
|
30
|
-
outputPorts(ports, options);
|
|
31
|
-
} else
|
|
32
|
-
outputPorts(projectPorts, options);
|
|
33
|
-
if (!options.quiet)
|
|
34
|
-
await outro("Exited", { startTime: perf, useSeconds: !1 });
|
|
35
|
-
process.exit(ExitCode.Success);
|
|
36
|
-
});
|
|
37
|
-
buddy.command("ports:list", descriptions.ports).option("-p, --project [name]", descriptions.project, {
|
|
38
|
-
default: void 0
|
|
39
|
-
}).option("-q, --quiet", "Use minimal output", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
40
|
-
log.debug("Running `buddy ports:list` ...", options);
|
|
41
|
-
let perf;
|
|
42
|
-
if (!options.quiet)
|
|
43
|
-
perf = await intro("buddy ports:list");
|
|
44
|
-
if (options.project) {
|
|
45
|
-
if (!options.quiet)
|
|
46
|
-
log.info(`Listing ports for project: ${italic(options.project)}`);
|
|
47
|
-
const path = await findProjectPath(options.project);
|
|
48
|
-
log.debug(`Path: ${path}`);
|
|
49
|
-
const ports = await getPortsForProjectPath(path, options);
|
|
50
|
-
outputPorts(ports, options);
|
|
51
|
-
} else
|
|
52
|
-
outputPorts(projectPorts, options);
|
|
53
|
-
if (!options.quiet)
|
|
54
|
-
await outro("Exited", { startTime: perf, useSeconds: !1 });
|
|
55
|
-
process.exit(ExitCode.Success);
|
|
56
|
-
});
|
|
57
|
-
buddy.command("ports:check", descriptions.ports).option("-p, --project [name]", descriptions.project, {
|
|
58
|
-
default: projectPath()
|
|
59
|
-
}).option("-q, --quiet", "Use minimal output", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
60
|
-
log.debug("Running `buddy ports:check` ...", options);
|
|
61
|
-
let perf;
|
|
62
|
-
if (!options.quiet)
|
|
63
|
-
perf = await intro("buddy ports:check");
|
|
64
|
-
const projects = await findStacksProjects(void 0, { quiet: !0 });
|
|
65
|
-
log.debug("Running `buddy ports`");
|
|
66
|
-
log.debug(`Found ${projects.length} projects`);
|
|
67
|
-
log.debug("Projects:", projects);
|
|
68
|
-
const projectsPorts = {};
|
|
69
|
-
for (const project of projects)
|
|
70
|
-
projectsPorts[project] = await getPortsForProjectPath(project, options);
|
|
71
|
-
log.info("ProjectsPorts:", projectsPorts);
|
|
72
|
-
if (!options.quiet)
|
|
73
|
-
await outro("Exited", { startTime: perf, useSeconds: !1 });
|
|
74
|
-
process.exit(ExitCode.Success);
|
|
75
|
-
});
|
|
76
|
-
onUnknownSubcommand(buddy, "ports");
|
|
77
|
-
}
|
|
78
|
-
async function getPortsForProjectPath(path, options) {
|
|
79
|
-
if (!options.quiet)
|
|
80
|
-
log.info(`Checking ports for project: ${italic(path)}`);
|
|
81
|
-
$.cwd(path);
|
|
82
|
-
try {
|
|
83
|
-
$.env(await import(`${path}/.env`));
|
|
84
|
-
} catch (err) {
|
|
85
|
-
if (!options.quiet)
|
|
86
|
-
log.warn(`[ports] Failed to load ${path}/.env (${err.message}). Falling back to current environment.`);
|
|
87
|
-
}
|
|
88
|
-
const projectList = await $`./buddy projects:list --quiet`.text();
|
|
89
|
-
log.debug("ProjectListResponse", projectList);
|
|
90
|
-
const projects = projectList.split(`
|
|
91
|
-
`).filter((line) => line.startsWith(" - ")).map((line) => line.trim().substring(4));
|
|
92
|
-
log.debug("Projects:", projects);
|
|
93
|
-
const ppath = options.project ?? p.projectPath();
|
|
94
|
-
let projectPath = projects.find((project) => project.includes(ppath));
|
|
95
|
-
log.debug(`Checking ports for project: ${projectPath}`);
|
|
96
|
-
if (projectPath === "" || !projectPath)
|
|
97
|
-
projectPath = p.projectPath();
|
|
98
|
-
log.debug(`$ Running: ./buddy ports:list --quiet via ${projectPath}`);
|
|
99
|
-
const response = await $`./buddy ports:list --quiet`.json();
|
|
100
|
-
log.debug(`Response for ./buddy ports:list --quiet via ${projectPath}`, response);
|
|
101
|
-
let validJsonString = response.replace(/(\w+)(?=\s*:)/g, '"$1"');
|
|
102
|
-
validJsonString = validJsonString.replace(/,(\s*\})/g, "$1");
|
|
103
|
-
let ports;
|
|
104
|
-
try {
|
|
105
|
-
ports = JSON.parse(validJsonString);
|
|
106
|
-
} catch {
|
|
107
|
-
throw Error(`Failed to parse ports configuration: ${validJsonString.slice(0, 200)}`);
|
|
108
|
-
}
|
|
109
|
-
log.debug(`Ports for ${projectPath}`, ports);
|
|
110
|
-
return ports;
|
|
111
|
-
}
|
|
112
|
-
function outputPorts(ports, options) {
|
|
113
|
-
if (!options.quiet)
|
|
114
|
-
console.log("");
|
|
115
|
-
console.log(ports);
|
|
116
|
-
if (!options.quiet)
|
|
117
|
-
console.log("");
|
|
118
|
-
}
|
|
1
|
+
import{$}from"bun";import process from"node:process";import{intro,italic,onUnknownSubcommand,outro}from"@stacksjs/cli";import{ports as projectPorts}from"@stacksjs/config";import{log}from"@stacksjs/logging";import{findProjectPath,path as p,projectPath}from"@stacksjs/path";import{ExitCode}from"@stacksjs/types";import{findStacksProjects}from"@stacksjs/utils";export function ports(buddy){const descriptions={command:"Let buddy check your project for potential issues and misconfigurations",ports:"Check if the ports are available",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("ports",descriptions.command).option("-l, --list","List the used ports",{default:!0}).option("-c, --check","Check if the ports are available",{default:!1}).option("-p, --project [name]",descriptions.project,{default:void 0}).option("-q, --quiet","Use minimal output",{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy ports` ...",options);let perf;if(!options.quiet)perf=await intro("buddy ports");if(options.project){const path=await findProjectPath(options.project);log.debug(`Path: ${path}`);const ports=await getPortsForProjectPath(path,options);log.debug(`./buddy ports --quiet response for ${projectPath}`,ports);outputPorts(ports,options)}else outputPorts(projectPorts,options);if(!options.quiet)await outro("Exited",{startTime:perf,useSeconds:!1});process.exit(ExitCode.Success)});buddy.command("ports:list",descriptions.ports).option("-p, --project [name]",descriptions.project,{default:void 0}).option("-q, --quiet","Use minimal output",{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy ports:list` ...",options);let perf;if(!options.quiet)perf=await intro("buddy ports:list");if(options.project){if(!options.quiet)log.info(`Listing ports for project: ${italic(options.project)}`);const path=await findProjectPath(options.project);log.debug(`Path: ${path}`);const ports=await getPortsForProjectPath(path,options);outputPorts(ports,options)}else outputPorts(projectPorts,options);if(!options.quiet)await outro("Exited",{startTime:perf,useSeconds:!1});process.exit(ExitCode.Success)});buddy.command("ports:check",descriptions.ports).option("-p, --project [name]",descriptions.project,{default:projectPath()}).option("-q, --quiet","Use minimal output",{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy ports:check` ...",options);let perf;if(!options.quiet)perf=await intro("buddy ports:check");const projects=await findStacksProjects(void 0,{quiet:!0});log.debug("Running `buddy ports`");log.debug(`Found ${projects.length} projects`);log.debug("Projects:",projects);const projectsPorts={};for(const project of projects)projectsPorts[project]=await getPortsForProjectPath(project,options);log.info("ProjectsPorts:",projectsPorts);if(!options.quiet)await outro("Exited",{startTime:perf,useSeconds:!1});process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"ports")}async function getPortsForProjectPath(path,options){if(!options.quiet)log.info(`Checking ports for project: ${italic(path)}`);$.cwd(path);try{$.env(await import(`${path}/.env`))}catch(err){if(!options.quiet)log.warn(`[ports] Failed to load ${path}/.env (${err.message}). Falling back to current environment.`)}const projectList=await $`./buddy projects:list --quiet`.text();log.debug("ProjectListResponse",projectList);const projects=projectList.split(`
|
|
2
|
+
`).filter((line)=>line.startsWith(" - ")).map((line)=>line.trim().substring(4));log.debug("Projects:",projects);const ppath=options.project??p.projectPath();let projectPath=projects.find((project)=>project.includes(ppath));log.debug(`Checking ports for project: ${projectPath}`);if(projectPath===""||!projectPath)projectPath=p.projectPath();log.debug(`$ Running: ./buddy ports:list --quiet via ${projectPath}`);const response=await $`./buddy ports:list --quiet`.json();log.debug(`Response for ./buddy ports:list --quiet via ${projectPath}`,response);let validJsonString=response.replace(/(\w+)(?=\s*:)/g,'"$1"');validJsonString=validJsonString.replace(/,(\s*\})/g,"$1");let ports;try{ports=JSON.parse(validJsonString)}catch{throw Error(`Failed to parse ports configuration: ${validJsonString.slice(0,200)}`)}log.debug(`Ports for ${projectPath}`,ports);return ports}function outputPorts(ports,options){if(!options.quiet)console.log("");console.log(ports);if(!options.quiet)console.log("")}
|
|
@@ -1,17 +1 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import { runAction } from "@stacksjs/actions";
|
|
3
|
-
import { Action } from "@stacksjs/enums";
|
|
4
|
-
import { log } from "@stacksjs/logging";
|
|
5
|
-
import { onUnknownSubcommand } from "@stacksjs/cli";
|
|
6
|
-
export function prepublish(buddy) {
|
|
7
|
-
const descriptions = {
|
|
8
|
-
command: "Run your prepublish script",
|
|
9
|
-
project: "Target a specific project",
|
|
10
|
-
verbose: "Enable verbose output"
|
|
11
|
-
};
|
|
12
|
-
buddy.command("prepublish", descriptions.command).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
13
|
-
log.debug("Running `buddy prepublish` ...", options);
|
|
14
|
-
await runAction(Action.Prepublish, options);
|
|
15
|
-
});
|
|
16
|
-
onUnknownSubcommand(buddy, "prepublish");
|
|
17
|
-
}
|
|
1
|
+
import process from"node:process";import{runAction}from"@stacksjs/actions";import{Action}from"@stacksjs/enums";import{log}from"@stacksjs/logging";import{onUnknownSubcommand}from"@stacksjs/cli";export function prepublish(buddy){const descriptions={command:"Run your prepublish script",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("prepublish",descriptions.command).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy prepublish` ...",options);await runAction(Action.Prepublish,options)});onUnknownSubcommand(buddy,"prepublish")}
|
|
@@ -1,29 +1 @@
|
|
|
1
|
-
import process from
|
|
2
|
-
import { intro, log, onUnknownSubcommand } from "@stacksjs/cli";
|
|
3
|
-
import { ExitCode } from "@stacksjs/types";
|
|
4
|
-
import { findStacksProjects } from "@stacksjs/utils";
|
|
5
|
-
export function projects(buddy) {
|
|
6
|
-
const descriptions = {
|
|
7
|
-
projects: "Find all Stacks projects on your system",
|
|
8
|
-
verbose: "Enable verbose output"
|
|
9
|
-
};
|
|
10
|
-
buddy.command("projects", descriptions.projects).option("-q, --quiet", "Use minimal output", { default: !1 }).option("-l, --list", "List all local Stacks projects", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
11
|
-
log.debug("Running `buddy projects` ...", options);
|
|
12
|
-
if (!options.quiet)
|
|
13
|
-
await intro("buddy projects");
|
|
14
|
-
const projects = await findStacksProjects(void 0, options);
|
|
15
|
-
for (const project of projects)
|
|
16
|
-
console.log(" - ", project);
|
|
17
|
-
process.exit(ExitCode.Success);
|
|
18
|
-
});
|
|
19
|
-
buddy.command("projects:list", descriptions.projects).option("-q, --quiet", "Use minimal output", { default: !1 }).option("-l, --list", "List all local Stacks projects", { default: !0 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
20
|
-
log.debug("Running `buddy projects` ...", options);
|
|
21
|
-
if (!options.quiet)
|
|
22
|
-
await intro("buddy projects:list");
|
|
23
|
-
const projects = await findStacksProjects(void 0, options);
|
|
24
|
-
for (const project of projects)
|
|
25
|
-
console.log(" - ", project);
|
|
26
|
-
process.exit(ExitCode.Success);
|
|
27
|
-
});
|
|
28
|
-
onUnknownSubcommand(buddy, "projects");
|
|
29
|
-
}
|
|
1
|
+
import process from"node:process";import{intro,log,onUnknownSubcommand}from"@stacksjs/cli";import{ExitCode}from"@stacksjs/types";import{findStacksProjects}from"@stacksjs/utils";export function projects(buddy){const descriptions={projects:"Find all Stacks projects on your system",verbose:"Enable verbose output"};buddy.command("projects",descriptions.projects).option("-q, --quiet","Use minimal output",{default:!1}).option("-l, --list","List all local Stacks projects",{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy projects` ...",options);if(!options.quiet)await intro("buddy projects");const projects=await findStacksProjects(void 0,options);for(const project of projects)console.log(" - ",project);process.exit(ExitCode.Success)});buddy.command("projects:list",descriptions.projects).option("-q, --quiet","Use minimal output",{default:!1}).option("-l, --list","List all local Stacks projects",{default:!0}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy projects` ...",options);if(!options.quiet)await intro("buddy projects:list");const projects=await findStacksProjects(void 0,options);for(const project of projects)console.log(" - ",project);process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"projects")}
|
|
@@ -1,98 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
schemaVersion: 1,
|
|
6
|
-
status: "source-verified-ci-retained",
|
|
7
|
-
source: {
|
|
8
|
-
repository: "https://github.com/home-lang/craft",
|
|
9
|
-
version: "0.0.48",
|
|
10
|
-
tag: "v0.0.48",
|
|
11
|
-
revision: "bf75807669e3af6cfb4ae34724be5c613442aee2"
|
|
12
|
-
},
|
|
13
|
-
issues: {
|
|
14
|
-
support: "https://github.com/stacksjs/stacks/issues/2059",
|
|
15
|
-
signing: "https://github.com/stacksjs/stacks/issues/2062",
|
|
16
|
-
lifecycle: "https://github.com/stacksjs/stacks/issues/2063",
|
|
17
|
-
upstreamActions: "https://github.com/home-lang/craft/issues/11",
|
|
18
|
-
dmgContention: "https://github.com/home-lang/craft/issues/16"
|
|
19
|
-
},
|
|
20
|
-
contracts: [
|
|
21
|
-
{ path: "packages/typescript/src/package.ts", sha256: "a7522f8c79dbd50a0f3bbc113525fb46eb8d6d1bab711d434cae85dc892ccdc1" },
|
|
22
|
-
{ path: "packages/typescript/src/package.test.ts", sha256: "673338f3793e397a83590daf84815869b0698b4afe97eaad8039426418554b7a" },
|
|
23
|
-
{ path: "scripts/native-lifecycle.ts", sha256: "a2c0af2c2165981ca7fbd31880adeec64db64fc305d4ca3efe62a11483b289b4" },
|
|
24
|
-
{ path: "scripts/native-lifecycle-plan.ts", sha256: "ac8e8f101246e94c0c26fdcbf9202536426bf192a303606079273d9689e4e27d" },
|
|
25
|
-
{ path: "scripts/native-lifecycle-plan.test.ts", sha256: "5cc839b60f7c8e32716f29201b159af817f4ac40b2c7963131124b3ac5de0638" },
|
|
26
|
-
{ path: ".github/workflows/native-lifecycle.yml", sha256: "493b614554f03dc669724ff31bd56ae8361851dd2a9b32ac37560d9c0bb1b85e" },
|
|
27
|
-
{ path: ".github/workflows/release.yml", sha256: "e3c7edd45841a7260fb4dfe810f0ff3f63f3117f7d0f4d14984e4dfb36b1f638" }
|
|
28
|
-
],
|
|
29
|
-
lifecycleMatrix: [
|
|
30
|
-
{ runner: "macos-15", platform: "darwin", architecture: "arm64", formats: ["dmg", "pkg"] },
|
|
31
|
-
{ runner: "macos-15-intel", platform: "darwin", architecture: "x64", formats: ["dmg", "pkg"] },
|
|
32
|
-
{ runner: "ubuntu-24.04", platform: "linux", architecture: "x64", formats: ["deb"] },
|
|
33
|
-
{ runner: "windows-2025", platform: "win32", architecture: "x64", formats: ["msi", "zip"] }
|
|
34
|
-
],
|
|
35
|
-
lifecycleOperations: ["install", "launch", "update", "rollback", "uninstall"],
|
|
36
|
-
stacksWorkflow: "https://github.com/stacksjs/stacks/actions/workflows/desktop-lifecycle.yml",
|
|
37
|
-
release: {
|
|
38
|
-
sourceTagged: !0,
|
|
39
|
-
githubRelease: null,
|
|
40
|
-
packagePublished: !1,
|
|
41
|
-
signing: "pending",
|
|
42
|
-
notarization: "pending",
|
|
43
|
-
blockedBy: "https://github.com/home-lang/craft/issues/11"
|
|
44
|
-
},
|
|
45
|
-
verification: {
|
|
46
|
-
local: ["bun test packages/typescript/src/package.test.ts scripts/native-lifecycle-plan.test.ts", "bun run typecheck", "bun .github/scripts/native-lifecycle.ts"],
|
|
47
|
-
retained: "https://github.com/stacksjs/stacks/actions/runs/29890804159"
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
export function validateCraftEvidence(evidence) {
|
|
51
|
-
const errors = [];
|
|
52
|
-
if (evidence.source.tag !== `v${evidence.source.version}`)
|
|
53
|
-
errors.push("Craft tag does not match its version");
|
|
54
|
-
if (!/^[a-f0-9]{40}$/.test(evidence.source.revision))
|
|
55
|
-
errors.push("Craft revision is not a full commit SHA");
|
|
56
|
-
if (evidence.contracts.length !== 7)
|
|
57
|
-
errors.push("all Craft packaging/release contracts must be pinned");
|
|
58
|
-
for (const contract of evidence.contracts)
|
|
59
|
-
if (!/^[a-f0-9]{64}$/.test(contract.sha256))
|
|
60
|
-
errors.push(`${contract.path}: invalid SHA-256 digest`);
|
|
61
|
-
const targets = new Set(evidence.lifecycleMatrix.map((row) => `${row.platform}/${row.architecture}`));
|
|
62
|
-
for (const target of ["darwin/arm64", "darwin/x64", "linux/x64", "win32/x64"])
|
|
63
|
-
if (!targets.has(target))
|
|
64
|
-
errors.push(`Craft lifecycle matrix is missing ${target}`);
|
|
65
|
-
if (evidence.release.signing !== "pending" || evidence.release.notarization !== "pending")
|
|
66
|
-
errors.push("Craft signing/notarization cannot be promoted without retained release evidence");
|
|
67
|
-
if (!evidence.release.blockedBy)
|
|
68
|
-
errors.push("Craft release blocker must be linked");
|
|
69
|
-
return errors;
|
|
70
|
-
}
|
|
71
|
-
function serializedEvidence() {
|
|
72
|
-
return `${JSON.stringify(craftEvidence, null, 2)}
|
|
73
|
-
`;
|
|
74
|
-
}
|
|
75
|
-
export async function run() {
|
|
76
|
-
const errors = validateCraftEvidence(craftEvidence);
|
|
77
|
-
if (process.argv.includes("--write")) {
|
|
78
|
-
if (errors.length)
|
|
79
|
-
throw Error(errors.join(`
|
|
80
|
-
`));
|
|
81
|
-
writeFileSync(outputPath, serializedEvidence());
|
|
82
|
-
console.log(`Wrote Craft evidence for ${craftEvidence.source.tag}`);
|
|
83
|
-
} else if (process.argv.includes("--check")) {
|
|
84
|
-
if (!existsSync(outputPath))
|
|
85
|
-
errors.push(".github/protocol/evidence/craft.json is missing");
|
|
86
|
-
else if (readFileSync(outputPath, "utf8") !== serializedEvidence())
|
|
87
|
-
errors.push("Craft evidence is stale; run bun run protocol:craft");
|
|
88
|
-
if (errors.length)
|
|
89
|
-
throw Error(errors.join(`
|
|
90
|
-
`));
|
|
91
|
-
console.log(`Craft evidence pins ${craftEvidence.source.tag} at ${craftEvidence.source.revision}`);
|
|
92
|
-
} else {
|
|
93
|
-
console.error("usage: bun storage/framework/core/buddy/src/commands/protocol/craft-evidence.ts --write | --check");
|
|
94
|
-
process.exit(2);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (import.meta.main)
|
|
98
|
-
await run();
|
|
1
|
+
import{existsSync,readFileSync,writeFileSync}from"node:fs";import{resolve}from"node:path";const root=resolve(import.meta.dir,"../../../../../../.."),outputPath=resolve(root,".github/protocol/evidence/craft.json");export const craftEvidence={schemaVersion:1,status:"source-verified-ci-retained",source:{repository:"https://github.com/home-lang/craft",version:"0.0.48",tag:"v0.0.48",revision:"bf75807669e3af6cfb4ae34724be5c613442aee2"},issues:{support:"https://github.com/stacksjs/stacks/issues/2059",signing:"https://github.com/stacksjs/stacks/issues/2062",lifecycle:"https://github.com/stacksjs/stacks/issues/2063",upstreamActions:"https://github.com/home-lang/craft/issues/11",dmgContention:"https://github.com/home-lang/craft/issues/16"},contracts:[{path:"packages/typescript/src/package.ts",sha256:"a7522f8c79dbd50a0f3bbc113525fb46eb8d6d1bab711d434cae85dc892ccdc1"},{path:"packages/typescript/src/package.test.ts",sha256:"673338f3793e397a83590daf84815869b0698b4afe97eaad8039426418554b7a"},{path:"scripts/native-lifecycle.ts",sha256:"a2c0af2c2165981ca7fbd31880adeec64db64fc305d4ca3efe62a11483b289b4"},{path:"scripts/native-lifecycle-plan.ts",sha256:"ac8e8f101246e94c0c26fdcbf9202536426bf192a303606079273d9689e4e27d"},{path:"scripts/native-lifecycle-plan.test.ts",sha256:"5cc839b60f7c8e32716f29201b159af817f4ac40b2c7963131124b3ac5de0638"},{path:".github/workflows/native-lifecycle.yml",sha256:"493b614554f03dc669724ff31bd56ae8361851dd2a9b32ac37560d9c0bb1b85e"},{path:".github/workflows/release.yml",sha256:"e3c7edd45841a7260fb4dfe810f0ff3f63f3117f7d0f4d14984e4dfb36b1f638"}],lifecycleMatrix:[{runner:"macos-15",platform:"darwin",architecture:"arm64",formats:["dmg","pkg"]},{runner:"macos-15-intel",platform:"darwin",architecture:"x64",formats:["dmg","pkg"]},{runner:"ubuntu-24.04",platform:"linux",architecture:"x64",formats:["deb"]},{runner:"windows-2025",platform:"win32",architecture:"x64",formats:["msi","zip"]}],lifecycleOperations:["install","launch","update","rollback","uninstall"],stacksWorkflow:"https://github.com/stacksjs/stacks/actions/workflows/desktop-lifecycle.yml",release:{sourceTagged:!0,githubRelease:null,packagePublished:!1,signing:"pending",notarization:"pending",blockedBy:"https://github.com/home-lang/craft/issues/11"},verification:{local:["bun test packages/typescript/src/package.test.ts scripts/native-lifecycle-plan.test.ts","bun run typecheck","bun .github/scripts/native-lifecycle.ts"],retained:"https://github.com/stacksjs/stacks/actions/runs/29890804159"}};export function validateCraftEvidence(evidence){const errors=[];if(evidence.source.tag!==`v${evidence.source.version}`)errors.push("Craft tag does not match its version");if(!/^[a-f0-9]{40}$/.test(evidence.source.revision))errors.push("Craft revision is not a full commit SHA");if(evidence.contracts.length!==7)errors.push("all Craft packaging/release contracts must be pinned");for(const contract of evidence.contracts)if(!/^[a-f0-9]{64}$/.test(contract.sha256))errors.push(`${contract.path}: invalid SHA-256 digest`);const targets=new Set(evidence.lifecycleMatrix.map((row)=>`${row.platform}/${row.architecture}`));for(const target of["darwin/arm64","darwin/x64","linux/x64","win32/x64"])if(!targets.has(target))errors.push(`Craft lifecycle matrix is missing ${target}`);if(evidence.release.signing!=="pending"||evidence.release.notarization!=="pending")errors.push("Craft signing/notarization cannot be promoted without retained release evidence");if(!evidence.release.blockedBy)errors.push("Craft release blocker must be linked");return errors}function serializedEvidence(){return`${JSON.stringify(craftEvidence,null,2)}
|
|
2
|
+
`}export async function run(){const errors=validateCraftEvidence(craftEvidence);if(process.argv.includes("--write")){if(errors.length)throw Error(errors.join(`
|
|
3
|
+
`));writeFileSync(outputPath,serializedEvidence());console.log(`Wrote Craft evidence for ${craftEvidence.source.tag}`)}else if(process.argv.includes("--check")){if(!existsSync(outputPath))errors.push(".github/protocol/evidence/craft.json is missing");else if(readFileSync(outputPath,"utf8")!==serializedEvidence())errors.push("Craft evidence is stale; run bun run protocol:craft");if(errors.length)throw Error(errors.join(`
|
|
4
|
+
`));console.log(`Craft evidence pins ${craftEvidence.source.tag} at ${craftEvidence.source.revision}`)}else{console.error("usage: bun storage/framework/core/buddy/src/commands/protocol/craft-evidence.ts --write | --check");process.exit(2)}}if(import.meta.main)await run();
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { craftEvidence, validateCraftEvidence } from "./craft-evidence";
|
|
3
|
-
describe("Craft protocol evidence", () => {
|
|
4
|
-
it("pins the full native lifecycle and release contract", () => {
|
|
5
|
-
expect(validateCraftEvidence(craftEvidence)).toEqual([]);
|
|
6
|
-
expect(craftEvidence.lifecycleMatrix).toHaveLength(4);
|
|
7
|
-
expect(craftEvidence.lifecycleOperations).toEqual(["install", "launch", "update", "rollback", "uninstall"]);
|
|
8
|
-
});
|
|
9
|
-
it("rejects untraceable source and premature signing claims", () => {
|
|
10
|
-
const invalid = structuredClone(craftEvidence);
|
|
11
|
-
Object.assign(invalid.source, { tag: "latest", revision: "short" });
|
|
12
|
-
Object.assign(invalid.release, { signing: "enforced", notarization: "enforced", blockedBy: "" });
|
|
13
|
-
expect(validateCraftEvidence(invalid)).toEqual(expect.arrayContaining([
|
|
14
|
-
"Craft tag does not match its version",
|
|
15
|
-
"Craft revision is not a full commit SHA",
|
|
16
|
-
"Craft signing/notarization cannot be promoted without retained release evidence",
|
|
17
|
-
"Craft release blocker must be linked"
|
|
18
|
-
]));
|
|
19
|
-
});
|
|
20
|
-
});
|
|
1
|
+
import{describe,expect,it}from"bun:test";import{craftEvidence,validateCraftEvidence}from"./craft-evidence";describe("Craft protocol evidence",()=>{it("pins the full native lifecycle and release contract",()=>{expect(validateCraftEvidence(craftEvidence)).toEqual([]);expect(craftEvidence.lifecycleMatrix).toHaveLength(4);expect(craftEvidence.lifecycleOperations).toEqual(["install","launch","update","rollback","uninstall"])});it("rejects untraceable source and premature signing claims",()=>{const invalid=structuredClone(craftEvidence);Object.assign(invalid.source,{tag:"latest",revision:"short"});Object.assign(invalid.release,{signing:"enforced",notarization:"enforced",blockedBy:""});expect(validateCraftEvidence(invalid)).toEqual(expect.arrayContaining(["Craft tag does not match its version","Craft revision is not a full commit SHA","Craft signing/notarization cannot be promoted without retained release evidence","Craft release blocker must be linked"]))})});
|