@stacksjs/buddy 0.70.86 → 0.70.88
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/package.json +2 -2
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -165
- package/dist/commands/about.d.ts +0 -2
- package/dist/commands/about.js +0 -35
- package/dist/commands/add.d.ts +0 -2
- package/dist/commands/add.js +0 -33
- package/dist/commands/auth.d.ts +0 -2
- package/dist/commands/auth.js +0 -68
- package/dist/commands/build.d.ts +0 -2
- package/dist/commands/build.js +0 -153
- package/dist/commands/cd.d.ts +0 -20
- package/dist/commands/cd.js +0 -39
- package/dist/commands/changelog.d.ts +0 -2
- package/dist/commands/changelog.js +0 -32
- package/dist/commands/clean.d.ts +0 -2
- package/dist/commands/clean.js +0 -37
- package/dist/commands/cloud.d.ts +0 -2
- package/dist/commands/cloud.js +0 -503
- package/dist/commands/commit.d.ts +0 -2
- package/dist/commands/commit.js +0 -16
- package/dist/commands/completion.d.ts +0 -2
- package/dist/commands/completion.js +0 -143
- package/dist/commands/config-migrate.d.ts +0 -26
- package/dist/commands/config-migrate.js +0 -94
- package/dist/commands/configure.d.ts +0 -2
- package/dist/commands/configure.js +0 -48
- package/dist/commands/create.d.ts +0 -2
- package/dist/commands/create.js +0 -141
- package/dist/commands/deploy.d.ts +0 -107
- package/dist/commands/deploy.js +0 -1439
- package/dist/commands/dev.d.ts +0 -10
- package/dist/commands/dev.js +0 -907
- package/dist/commands/dns.d.ts +0 -2
- package/dist/commands/dns.js +0 -102
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -285
- package/dist/commands/domains.d.ts +0 -2
- package/dist/commands/domains.js +0 -159
- package/dist/commands/email.d.ts +0 -2
- package/dist/commands/email.js +0 -524
- package/dist/commands/env.d.ts +0 -2
- package/dist/commands/env.js +0 -246
- package/dist/commands/extension.d.ts +0 -8
- package/dist/commands/extension.js +0 -78
- package/dist/commands/features.d.ts +0 -180
- package/dist/commands/features.js +0 -422
- package/dist/commands/fresh.d.ts +0 -2
- package/dist/commands/fresh.js +0 -39
- package/dist/commands/generate.d.ts +0 -2
- package/dist/commands/generate.js +0 -104
- package/dist/commands/http.d.ts +0 -2
- package/dist/commands/http.js +0 -33
- package/dist/commands/index.d.ts +0 -53
- package/dist/commands/index.js +0 -53
- package/dist/commands/install.d.ts +0 -2
- package/dist/commands/install.js +0 -22
- package/dist/commands/key.d.ts +0 -2
- package/dist/commands/key.js +0 -23
- package/dist/commands/lint.d.ts +0 -2
- package/dist/commands/lint.js +0 -46
- package/dist/commands/list.d.ts +0 -2
- package/dist/commands/list.js +0 -108
- package/dist/commands/mail.d.ts +0 -2
- package/dist/commands/mail.js +0 -693
- package/dist/commands/maintenance.d.ts +0 -2
- package/dist/commands/maintenance.js +0 -141
- package/dist/commands/make.d.ts +0 -2
- package/dist/commands/make.js +0 -375
- package/dist/commands/migrate-project.d.ts +0 -2
- package/dist/commands/migrate-project.js +0 -49
- package/dist/commands/migrate.d.ts +0 -4
- package/dist/commands/migrate.js +0 -455
- package/dist/commands/outdated.d.ts +0 -2
- package/dist/commands/outdated.js +0 -19
- package/dist/commands/package.d.ts +0 -2
- package/dist/commands/package.js +0 -17
- package/dist/commands/phone.d.ts +0 -2
- package/dist/commands/phone.js +0 -188
- package/dist/commands/ports.d.ts +0 -2
- package/dist/commands/ports.js +0 -118
- package/dist/commands/prepublish.d.ts +0 -2
- package/dist/commands/prepublish.js +0 -17
- package/dist/commands/projects.d.ts +0 -2
- package/dist/commands/projects.js +0 -29
- package/dist/commands/publish.d.ts +0 -2
- package/dist/commands/publish.js +0 -172
- package/dist/commands/queue.d.ts +0 -2
- package/dist/commands/queue.js +0 -248
- package/dist/commands/release.d.ts +0 -2
- package/dist/commands/release.js +0 -30
- package/dist/commands/route.d.ts +0 -2
- package/dist/commands/route.js +0 -21
- package/dist/commands/saas.d.ts +0 -2
- package/dist/commands/saas.js +0 -25
- package/dist/commands/schedule.d.ts +0 -2
- package/dist/commands/schedule.js +0 -61
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/search.js +0 -84
- package/dist/commands/seed.d.ts +0 -2
- package/dist/commands/seed.js +0 -71
- package/dist/commands/serve.d.ts +0 -25
- package/dist/commands/serve.js +0 -182
- package/dist/commands/setup.d.ts +0 -12
- package/dist/commands/setup.js +0 -215
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/share.js +0 -214
- package/dist/commands/sms.d.ts +0 -2
- package/dist/commands/sms.js +0 -328
- package/dist/commands/stacks.d.ts +0 -2
- package/dist/commands/stacks.js +0 -69
- package/dist/commands/telemetry.d.ts +0 -2
- package/dist/commands/telemetry.js +0 -74
- package/dist/commands/test.d.ts +0 -2
- package/dist/commands/test.js +0 -130
- package/dist/commands/tinker.d.ts +0 -2
- package/dist/commands/tinker.js +0 -37
- package/dist/commands/types.d.ts +0 -2
- package/dist/commands/types.js +0 -18
- package/dist/commands/upgrade.d.ts +0 -2
- package/dist/commands/upgrade.js +0 -98
- package/dist/commands/version.d.ts +0 -2
- package/dist/commands/version.js +0 -16
- package/dist/config.d.ts +0 -43
- package/dist/config.js +0 -223
- package/dist/custom-cli.d.ts +0 -1
- package/dist/custom-cli.js +0 -23
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lazy-commands.d.ts +0 -61
- package/dist/lazy-commands.js +0 -188
- package/dist/migrators/index.d.ts +0 -9
- package/dist/migrators/index.js +0 -62
- package/dist/migrators/laravel/index.d.ts +0 -2
- package/dist/migrators/laravel/index.js +0 -148
- package/dist/migrators/laravel/migrations.d.ts +0 -52
- package/dist/migrators/laravel/migrations.js +0 -232
- package/dist/migrators/laravel/models.d.ts +0 -34
- package/dist/migrators/laravel/models.js +0 -134
- package/dist/migrators/rails/index.d.ts +0 -2
- package/dist/migrators/rails/index.js +0 -11
- package/dist/migrators/types.d.ts +0 -44
- package/dist/migrators/types.js +0 -0
package/dist/commands/serve.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import process from "node:process";
|
|
5
|
-
import { log } from "@stacksjs/cli";
|
|
6
|
-
globalThis.requestContext = {
|
|
7
|
-
cookie(name) {
|
|
8
|
-
return globalThis.__stxServeCookies?.[name] ?? null;
|
|
9
|
-
},
|
|
10
|
-
url() {
|
|
11
|
-
return globalThis.__stxServeSearch ?? "";
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
function parseCookies(req) {
|
|
15
|
-
const out = {}, header = req.headers.get("cookie") || "";
|
|
16
|
-
if (!header)
|
|
17
|
-
return out;
|
|
18
|
-
for (const part of header.split(";")) {
|
|
19
|
-
const trimmed = part.trim(), eq = trimmed.indexOf("=");
|
|
20
|
-
if (eq === -1)
|
|
21
|
-
continue;
|
|
22
|
-
const k = trimmed.slice(0, eq).trim(), v = trimmed.slice(eq + 1).trim();
|
|
23
|
-
if (!k)
|
|
24
|
-
continue;
|
|
25
|
-
try {
|
|
26
|
-
out[k] = decodeURIComponent(v);
|
|
27
|
-
} catch {
|
|
28
|
-
out[k] = v;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return out;
|
|
32
|
-
}
|
|
33
|
-
export function serve(buddy) {
|
|
34
|
-
buddy.command("serve", "Start the production HTTP server (STX views + /api proxy + coming-soon/maintenance gate)").option("-p, --port <port>", "Port to listen on (defaults to PORT env or 3000)").option("--verbose", "Enable verbose output", { default: !1 }).action(async (options) => {
|
|
35
|
-
if (options?.port)
|
|
36
|
-
process.env.PORT = String(options.port);
|
|
37
|
-
process.env.APP_ENV = process.env.APP_ENV || "production";
|
|
38
|
-
const port = Number(process.env.PORT) || 3000, { config, overridesReady } = await import("@stacksjs/config");
|
|
39
|
-
await overridesReady;
|
|
40
|
-
const { injectGlobalAutoImports } = await import("@stacksjs/server");
|
|
41
|
-
await injectGlobalAutoImports();
|
|
42
|
-
let stxServe;
|
|
43
|
-
const serveCandidates = [
|
|
44
|
-
join(homedir(), "Code/Tools/stx/packages/bun-plugin/dist/serve.js"),
|
|
45
|
-
join(process.cwd(), "pantry/bun-plugin-stx/dist/serve.js")
|
|
46
|
-
];
|
|
47
|
-
for (const entry of serveCandidates)
|
|
48
|
-
try {
|
|
49
|
-
if (existsSync(entry)) {
|
|
50
|
-
({ serve: stxServe } = await import(entry));
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
} catch {}
|
|
54
|
-
if (!stxServe)
|
|
55
|
-
({ serve: stxServe } = await import("bun-plugin-stx/serve"));
|
|
56
|
-
const stxModule = await resolveVendoredStxModule(), { site: siteConfig, i18n: i18nConfig } = await loadStxSiteConfig(), userViewsPath = "resources/views", defaultsResources = resolveDefaultsResources(), defaultViewsPath = join(defaultsResources, "views"), userLayoutsPath = existsSync("resources/views/layouts") ? "resources/views/layouts" : "resources/layouts", userComponentsPath = existsSync("resources/views/components") ? "resources/views/components" : "resources/components", apiBase = process.env.API_URL || `http://127.0.0.1:${Number(process.env.PORT_API) || config.ports?.api || 3008}`;
|
|
57
|
-
log.info(`Starting production server on port ${port}...`);
|
|
58
|
-
await stxServe({
|
|
59
|
-
patterns: [userViewsPath, defaultViewsPath],
|
|
60
|
-
port,
|
|
61
|
-
autoIncrementPort: !1,
|
|
62
|
-
reusePort: ["production", "staging", "development"].includes((process.env.APP_ENV || "").toLowerCase()),
|
|
63
|
-
componentsDir: join(defaultsResources, "components"),
|
|
64
|
-
layoutsDir: userLayoutsPath,
|
|
65
|
-
partialsDir: userComponentsPath,
|
|
66
|
-
fallbackLayoutsDir: join(defaultsResources, "layouts"),
|
|
67
|
-
fallbackPartialsDir: defaultViewsPath,
|
|
68
|
-
quiet: options?.verbose !== !0,
|
|
69
|
-
...stxModule && { stxModule },
|
|
70
|
-
...i18nConfig && { i18n: i18nConfig },
|
|
71
|
-
...siteConfig?.url && { site: siteConfig },
|
|
72
|
-
onRequest: async (req) => {
|
|
73
|
-
const { maintenanceGate, isApiBoundRequest, proxyToBackend } = await import("@stacksjs/server"), gated = await maintenanceGate(req);
|
|
74
|
-
if (gated)
|
|
75
|
-
return gated;
|
|
76
|
-
const url = new URL(req.url);
|
|
77
|
-
if (isApiBoundRequest(req, url.pathname))
|
|
78
|
-
try {
|
|
79
|
-
return await proxyToBackend(req, apiBase);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
log.error(`API proxy to ${apiBase} failed: ${error.message}`);
|
|
82
|
-
return new Response("Bad Gateway", { status: 502 });
|
|
83
|
-
}
|
|
84
|
-
if (existsSync(join(process.cwd(), "resources/views/blog.stx"))) {
|
|
85
|
-
const { renderBlogFeed } = await import("@stacksjs/actions/blog"), feed = await renderBlogFeed(req);
|
|
86
|
-
if (feed)
|
|
87
|
-
return feed;
|
|
88
|
-
}
|
|
89
|
-
globalThis.__stxServeSearch = url.search;
|
|
90
|
-
globalThis.__stxServeCookies = parseCookies(req);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
log.success(`Production server listening on http://0.0.0.0:${port}`);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
export function serveApi(buddy) {
|
|
98
|
-
buddy.command("serve:api", "Start the production API server (bun-router routes the frontend proxies /api to)").option("-p, --port <port>", "Port to listen on (defaults to PORT env or 3008)").action(async (options) => {
|
|
99
|
-
if (options?.port)
|
|
100
|
-
process.env.PORT = String(options.port);
|
|
101
|
-
process.env.APP_ENV = process.env.APP_ENV || "production";
|
|
102
|
-
await import("@stacksjs/actions/serve/api");
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
function resolveDefaultsResources() {
|
|
106
|
-
const vendored = "storage/framework/defaults/resources";
|
|
107
|
-
if (existsSync(vendored))
|
|
108
|
-
return vendored;
|
|
109
|
-
try {
|
|
110
|
-
const pkgJson = Bun.resolveSync("@stacksjs/defaults/package.json", process.cwd());
|
|
111
|
-
return join(dirname(pkgJson), "resources");
|
|
112
|
-
} catch {
|
|
113
|
-
return vendored;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
async function resolveVendoredStxModule() {
|
|
117
|
-
const candidates = [
|
|
118
|
-
join(homedir(), "Code/Tools/stx/packages/stx/dist/index.js"),
|
|
119
|
-
join(process.cwd(), "pantry/@stacksjs/stx/dist/index.js")
|
|
120
|
-
];
|
|
121
|
-
for (const entry of candidates)
|
|
122
|
-
try {
|
|
123
|
-
if (existsSync(entry))
|
|
124
|
-
return await import(entry);
|
|
125
|
-
} catch {}
|
|
126
|
-
try {
|
|
127
|
-
return await import("@stacksjs/stx");
|
|
128
|
-
} catch {}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
function fallbackI18nFromSite(site) {
|
|
132
|
-
const locales = site.i18n.locales, defaultLocale = site.i18n.defaultLocale ?? locales[0];
|
|
133
|
-
return {
|
|
134
|
-
locales,
|
|
135
|
-
defaultLocale,
|
|
136
|
-
labels: site.i18n.labels ?? Object.fromEntries(locales.map((c) => [c, c.toUpperCase()])),
|
|
137
|
-
translations: {},
|
|
138
|
-
pickerSelector: site.i18n.pickerSelector ?? "#lang-picker"
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
async function resolveSiteI18n(site) {
|
|
142
|
-
const resolverPaths = [
|
|
143
|
-
join(homedir(), "Code/Tools/stx/packages/stx/src/site-builder/i18n.ts"),
|
|
144
|
-
join(homedir(), "Code/Tools/stx/packages/stx/dist/index.js"),
|
|
145
|
-
join(process.cwd(), "pantry/@stacksjs/stx/dist/index.js")
|
|
146
|
-
];
|
|
147
|
-
for (const resolverPath of resolverPaths)
|
|
148
|
-
try {
|
|
149
|
-
if (!existsSync(resolverPath))
|
|
150
|
-
continue;
|
|
151
|
-
const resolved = await import(resolverPath);
|
|
152
|
-
if (typeof resolved.resolveI18n !== "function")
|
|
153
|
-
continue;
|
|
154
|
-
const i18n = resolved.resolveI18n(site, process.cwd());
|
|
155
|
-
if (i18n)
|
|
156
|
-
return i18n;
|
|
157
|
-
} catch {}
|
|
158
|
-
try {
|
|
159
|
-
const resolved = await import("@stacksjs/stx");
|
|
160
|
-
if (typeof resolved.resolveI18n === "function") {
|
|
161
|
-
const i18n = resolved.resolveI18n(site, process.cwd());
|
|
162
|
-
if (i18n)
|
|
163
|
-
return i18n;
|
|
164
|
-
}
|
|
165
|
-
} catch {}
|
|
166
|
-
return fallbackI18nFromSite(site);
|
|
167
|
-
}
|
|
168
|
-
async function loadStxSiteConfig() {
|
|
169
|
-
const sitePath = join(process.cwd(), "site.config.ts");
|
|
170
|
-
if (!existsSync(sitePath))
|
|
171
|
-
return {};
|
|
172
|
-
try {
|
|
173
|
-
const site = (await import(sitePath)).default;
|
|
174
|
-
if (!site)
|
|
175
|
-
return {};
|
|
176
|
-
if (!site.i18n)
|
|
177
|
-
return { site };
|
|
178
|
-
const i18n = await resolveSiteI18n(site);
|
|
179
|
-
return { site, i18n };
|
|
180
|
-
} catch {}
|
|
181
|
-
return {};
|
|
182
|
-
}
|
package/dist/commands/setup.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { CLI, CliOptions } from '@stacksjs/types';
|
|
2
|
-
export declare function setup(buddy: CLI): void;
|
|
3
|
-
export declare function ensurePantryInstalled(): Promise<void>;
|
|
4
|
-
export declare function ensurePantryDependencies(cwd: string): Promise<void>;
|
|
5
|
-
export declare function ensureAppKey(cwd: string): Promise<void>;
|
|
6
|
-
/**
|
|
7
|
-
* Reads config/deps.ts dependencies and merges in environment-detected
|
|
8
|
-
* dependencies (e.g. DB_CONNECTION), then writes deps.yaml so pantry install
|
|
9
|
-
* picks up the correct packages.
|
|
10
|
-
*/
|
|
11
|
-
export declare function optimizePantryDeps(): Promise<void>;
|
|
12
|
-
export declare function ensureEnvIsSet(options: CliOptions): Promise<void>;
|
package/dist/commands/setup.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import process from "node:process";
|
|
4
|
-
import { runAction, setupSSL } from "@stacksjs/actions";
|
|
5
|
-
import { log, onUnknownSubcommand, runCommand } from "@stacksjs/cli";
|
|
6
|
-
import { Action } from "@stacksjs/enums";
|
|
7
|
-
import { handleError } from "@stacksjs/error-handling";
|
|
8
|
-
import { path as p } from "@stacksjs/path";
|
|
9
|
-
import { copyFile, storage } from "@stacksjs/storage";
|
|
10
|
-
import { ExitCode } from "@stacksjs/types";
|
|
11
|
-
function getTimeoutMs(envVar, fallbackMs) {
|
|
12
|
-
const value = Number(process.env[envVar]);
|
|
13
|
-
if (Number.isFinite(value) && value > 0)
|
|
14
|
-
return value;
|
|
15
|
-
return fallbackMs;
|
|
16
|
-
}
|
|
17
|
-
const PANTRY_CHECK_TIMEOUT_MS = getTimeoutMs("PANTRY_CHECK_TIMEOUT_MS", 15000), PANTRY_INSTALL_TIMEOUT_MS = getTimeoutMs("PANTRY_INSTALL_TIMEOUT_MS", 600000), PANTRY_DEPENDENCIES_TIMEOUT_MS = getTimeoutMs("PANTRY_DEPENDENCIES_TIMEOUT_MS", 1200000), KEYGEN_TIMEOUT_MS = getTimeoutMs("KEYGEN_TIMEOUT_MS", 120000), AWS_CONFIG_TIMEOUT_MS = getTimeoutMs("AWS_CONFIG_TIMEOUT_MS", 900000);
|
|
18
|
-
export function setup(buddy) {
|
|
19
|
-
const descriptions = {
|
|
20
|
-
setup: "This command ensures your project is setup correctly",
|
|
21
|
-
ssl: "Setup SSL certificates and hosts file for HTTPS development",
|
|
22
|
-
ohMyZsh: "Enable Oh My Zsh",
|
|
23
|
-
aws: "Ensures AWS is connected to the project",
|
|
24
|
-
project: "Target a specific project",
|
|
25
|
-
verbose: "Enable verbose output",
|
|
26
|
-
domain: "Custom domain to setup (defaults to APP_URL)",
|
|
27
|
-
skipHosts: "Skip adding domain to hosts file",
|
|
28
|
-
skipTrust: "Skip trusting the certificate",
|
|
29
|
-
skipAws: "Skip AWS configuration during setup",
|
|
30
|
-
skipKeygen: "Skip generating an application key during setup"
|
|
31
|
-
};
|
|
32
|
-
buddy.command("setup", descriptions.setup).alias("ensure").option("-p, --project [project]", descriptions.project, { default: !1 }).option("--skip-aws", descriptions.skipAws, { default: !1 }).option("--skip-keygen", descriptions.skipKeygen, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
33
|
-
log.debug("Running `buddy setup` ...", options);
|
|
34
|
-
await ensurePantryInstalled();
|
|
35
|
-
await optimizePantryDeps();
|
|
36
|
-
await initializeProject(options);
|
|
37
|
-
});
|
|
38
|
-
buddy.command("setup:ssl", descriptions.ssl).alias("ssl:setup").option("-d, --domain [domain]", descriptions.domain).option("--skip-hosts", descriptions.skipHosts, { default: !1 }).option("--skip-trust", descriptions.skipTrust, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
|
|
39
|
-
log.debug("Running `buddy setup:ssl` ...", options);
|
|
40
|
-
if (!await setupSSL({
|
|
41
|
-
domain: options.domain,
|
|
42
|
-
skipHosts: options.skipHosts,
|
|
43
|
-
skipTrust: options.skipTrust,
|
|
44
|
-
verbose: options.verbose
|
|
45
|
-
})) {
|
|
46
|
-
log.warn("SSL setup completed with warnings");
|
|
47
|
-
log.info("You may need to manually trust certificates or update hosts file");
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
buddy.command("setup:oh-my-zsh", descriptions.ohMyZsh).alias("upgrade:oh-my-zsh").option("--verbose", descriptions.verbose, { default: !1 }).action(async (_options) => {
|
|
51
|
-
log.debug("Running `buddy setup:oh-my-zsh` ...", _options);
|
|
52
|
-
const result = await runAction(Action.UpgradeShell);
|
|
53
|
-
if (result.isErr) {
|
|
54
|
-
log.error(result.error);
|
|
55
|
-
process.exit(ExitCode.FatalError);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
onUnknownSubcommand(buddy, "setup");
|
|
59
|
-
}
|
|
60
|
-
async function isPantryInstalled() {
|
|
61
|
-
try {
|
|
62
|
-
return (await runCommand("pantry --version", {
|
|
63
|
-
silent: !0,
|
|
64
|
-
timeoutMs: PANTRY_CHECK_TIMEOUT_MS
|
|
65
|
-
})).isOk;
|
|
66
|
-
} catch {
|
|
67
|
-
return !1;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async function installPantry() {
|
|
71
|
-
const result = await runCommand(p.frameworkPath("scripts/pantry-install"), {
|
|
72
|
-
timeoutMs: PANTRY_INSTALL_TIMEOUT_MS
|
|
73
|
-
});
|
|
74
|
-
if (result.isOk)
|
|
75
|
-
return;
|
|
76
|
-
handleError(result.error);
|
|
77
|
-
process.exit(ExitCode.FatalError);
|
|
78
|
-
}
|
|
79
|
-
export async function ensurePantryInstalled() {
|
|
80
|
-
if (await isPantryInstalled())
|
|
81
|
-
return;
|
|
82
|
-
const installer = p.frameworkPath("scripts/pantry-install");
|
|
83
|
-
if (!existsSync(installer)) {
|
|
84
|
-
log.debug("Pantry is not installed and no bundled installer is present; continuing without it.");
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
await installPantry();
|
|
88
|
-
}
|
|
89
|
-
export async function ensurePantryDependencies(cwd) {
|
|
90
|
-
if (!await isPantryInstalled()) {
|
|
91
|
-
log.debug("Pantry not installed; skipping pantry dependency install (deps come from node_modules).");
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
log.info("Installing Pantry dependencies...");
|
|
95
|
-
const result = await runCommand("pantry install", {
|
|
96
|
-
cwd,
|
|
97
|
-
timeoutMs: PANTRY_DEPENDENCIES_TIMEOUT_MS
|
|
98
|
-
});
|
|
99
|
-
if (result.isOk) {
|
|
100
|
-
log.success("Installed Pantry dependencies");
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
handleError(result.error);
|
|
104
|
-
process.exit(ExitCode.FatalError);
|
|
105
|
-
}
|
|
106
|
-
function hasAppKey(cwd) {
|
|
107
|
-
const envPath = join(cwd, ".env");
|
|
108
|
-
if (!existsSync(envPath))
|
|
109
|
-
return !1;
|
|
110
|
-
return /^APP_KEY=.+$/m.test(readFileSync(envPath, "utf-8"));
|
|
111
|
-
}
|
|
112
|
-
export async function ensureAppKey(cwd) {
|
|
113
|
-
if (hasAppKey(cwd) || process.env.APP_KEY && process.env.APP_KEY.length > 0) {
|
|
114
|
-
log.success("APP_KEY existed");
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const keyResult = await runCommand("./buddy key:generate", {
|
|
118
|
-
cwd,
|
|
119
|
-
timeoutMs: KEYGEN_TIMEOUT_MS
|
|
120
|
-
});
|
|
121
|
-
if (keyResult.isErr) {
|
|
122
|
-
handleError(keyResult.error);
|
|
123
|
-
process.exit(ExitCode.FatalError);
|
|
124
|
-
}
|
|
125
|
-
log.success("Generated application key");
|
|
126
|
-
}
|
|
127
|
-
async function initializeProject(options) {
|
|
128
|
-
const cwd = options.cwd || p.projectPath();
|
|
129
|
-
await ensurePantryDependencies(cwd);
|
|
130
|
-
await ensureEnvIsSet(options);
|
|
131
|
-
if (!options.skipKeygen)
|
|
132
|
-
await ensureAppKey(cwd);
|
|
133
|
-
if (!options.skipAws) {
|
|
134
|
-
log.info("Ensuring AWS is connected...");
|
|
135
|
-
const awsResult = await runCommand("./buddy configure:aws", {
|
|
136
|
-
cwd,
|
|
137
|
-
timeoutMs: AWS_CONFIG_TIMEOUT_MS
|
|
138
|
-
});
|
|
139
|
-
if (awsResult.isErr) {
|
|
140
|
-
handleError(awsResult.error);
|
|
141
|
-
process.exit(ExitCode.FatalError);
|
|
142
|
-
}
|
|
143
|
-
log.success("Configured AWS");
|
|
144
|
-
}
|
|
145
|
-
log.success("Project is setup");
|
|
146
|
-
log.info("Happy coding! \uD83D\uDC99");
|
|
147
|
-
}
|
|
148
|
-
const DB_CONNECTION_PACKAGES = {
|
|
149
|
-
postgres: "postgresql.org",
|
|
150
|
-
mysql: "mysql.com",
|
|
151
|
-
sqlite: "sqlite.org"
|
|
152
|
-
};
|
|
153
|
-
function detectDbPackage(cwd) {
|
|
154
|
-
const envPath = join(cwd, ".env"), envExamplePath = join(cwd, ".env.example"), filePath = existsSync(envPath) ? envPath : existsSync(envExamplePath) ? envExamplePath : void 0;
|
|
155
|
-
if (!filePath)
|
|
156
|
-
return;
|
|
157
|
-
const match = readFileSync(filePath, "utf-8").match(/^DB_CONNECTION=(.+)$/m);
|
|
158
|
-
if (!match)
|
|
159
|
-
return;
|
|
160
|
-
const value = match[1].trim().replace(/['"]/g, "");
|
|
161
|
-
return DB_CONNECTION_PACKAGES[value];
|
|
162
|
-
}
|
|
163
|
-
export async function optimizePantryDeps() {
|
|
164
|
-
const cwd = p.projectPath(), depsConfigPath = join(cwd, "config", "deps.ts");
|
|
165
|
-
if (!existsSync(depsConfigPath)) {
|
|
166
|
-
log.debug("No config/deps.ts found, skipping dependency optimization");
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
let configDeps = {};
|
|
170
|
-
try {
|
|
171
|
-
const mod = await import(depsConfigPath), config = mod.config || mod.default;
|
|
172
|
-
if (config?.dependencies)
|
|
173
|
-
configDeps = { ...config.dependencies };
|
|
174
|
-
} catch (err) {
|
|
175
|
-
log.debug("Could not load config/deps.ts, skipping dependency optimization");
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const dbPackage = detectDbPackage(cwd);
|
|
179
|
-
if (dbPackage) {
|
|
180
|
-
if (!Object.keys(configDeps).some((key) => key === dbPackage || key.startsWith(`${dbPackage}/`))) {
|
|
181
|
-
log.info(`Detected DB_CONNECTION requires ${dbPackage}, adding to dependencies`);
|
|
182
|
-
configDeps[dbPackage] = "*";
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
const lines = [
|
|
186
|
-
"# Auto-generated from config/deps.ts and .env sniffing.",
|
|
187
|
-
"# This file is regenerated on each `buddy setup` run.",
|
|
188
|
-
"#",
|
|
189
|
-
"# To learn more, please visit:",
|
|
190
|
-
"# https://stacksjs.com/docs/dependency-management",
|
|
191
|
-
"",
|
|
192
|
-
"dependencies:"
|
|
193
|
-
];
|
|
194
|
-
for (const [pkg, version] of Object.entries(configDeps))
|
|
195
|
-
lines.push(` ${pkg}: ${version}`);
|
|
196
|
-
const depsYamlPath = join(cwd, "deps.yaml");
|
|
197
|
-
writeFileSync(depsYamlPath, `${lines.join(`
|
|
198
|
-
`)}
|
|
199
|
-
`);
|
|
200
|
-
log.success("Generated deps.yaml from config/deps.ts");
|
|
201
|
-
}
|
|
202
|
-
export async function ensureEnvIsSet(options) {
|
|
203
|
-
log.info("Ensuring .env exists...");
|
|
204
|
-
const cwd = options.cwd || p.projectPath(), envPath = `${cwd}/.env`, envExamplePath = `${cwd}/.env.example`;
|
|
205
|
-
if (storage.doesNotExist(envPath)) {
|
|
206
|
-
try {
|
|
207
|
-
copyFile(envExamplePath, envPath);
|
|
208
|
-
} catch (error) {
|
|
209
|
-
handleError(error);
|
|
210
|
-
process.exit(ExitCode.FatalError);
|
|
211
|
-
}
|
|
212
|
-
log.success(".env created");
|
|
213
|
-
} else
|
|
214
|
-
log.success(".env existed");
|
|
215
|
-
}
|
package/dist/commands/share.d.ts
DELETED
package/dist/commands/share.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import { getErrorMessage } from "@stacksjs/utils";
|
|
2
|
-
import process from "node:process";
|
|
3
|
-
import {
|
|
4
|
-
runApiDevServer,
|
|
5
|
-
runDashboardDevServer,
|
|
6
|
-
runDesktopDevServer,
|
|
7
|
-
runDocsDevServer,
|
|
8
|
-
runFrontendDevServer
|
|
9
|
-
} from "@stacksjs/actions";
|
|
10
|
-
import { bold, cyan, dim, green, intro, log, outro, spinner } from "@stacksjs/cli";
|
|
11
|
-
import { ports as configPorts } from "@stacksjs/config";
|
|
12
|
-
import { ExitCode } from "@stacksjs/types";
|
|
13
|
-
const originalStdoutWrite = process.stdout.write.bind(process.stdout), originalStderrWrite = process.stderr.write.bind(process.stderr), originalConsoleLog = console.log, originalConsoleError = console.error, originalConsoleWarn = console.warn, originalConsoleInfo = console.info;
|
|
14
|
-
let _muted = !1, _verboseBuffer = [];
|
|
15
|
-
function muteOutput() {
|
|
16
|
-
_muted = !0;
|
|
17
|
-
_verboseBuffer = [];
|
|
18
|
-
const filter = (fn) => {
|
|
19
|
-
return function(chunk, ...args) {
|
|
20
|
-
if (_muted) {
|
|
21
|
-
_verboseBuffer.push(String(chunk));
|
|
22
|
-
return !0;
|
|
23
|
-
}
|
|
24
|
-
return fn(chunk, ...args);
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
process.stdout.write = filter(originalStdoutWrite);
|
|
28
|
-
process.stderr.write = filter(originalStderrWrite);
|
|
29
|
-
console.log = (...args) => {
|
|
30
|
-
if (!_muted)
|
|
31
|
-
originalConsoleLog(...args);
|
|
32
|
-
};
|
|
33
|
-
console.error = (...args) => {
|
|
34
|
-
if (!_muted)
|
|
35
|
-
originalConsoleError(...args);
|
|
36
|
-
};
|
|
37
|
-
console.warn = (...args) => {
|
|
38
|
-
if (!_muted)
|
|
39
|
-
originalConsoleWarn(...args);
|
|
40
|
-
};
|
|
41
|
-
console.info = (...args) => {
|
|
42
|
-
if (!_muted)
|
|
43
|
-
originalConsoleInfo(...args);
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
function unmuteOutput() {
|
|
47
|
-
_muted = !1;
|
|
48
|
-
process.stdout.write = originalStdoutWrite;
|
|
49
|
-
process.stderr.write = originalStderrWrite;
|
|
50
|
-
console.log = originalConsoleLog;
|
|
51
|
-
console.error = originalConsoleError;
|
|
52
|
-
console.warn = originalConsoleWarn;
|
|
53
|
-
console.info = originalConsoleInfo;
|
|
54
|
-
}
|
|
55
|
-
async function waitForPort(port, host = "localhost", timeoutMs = 30000) {
|
|
56
|
-
const start = Date.now();
|
|
57
|
-
while (Date.now() - start < timeoutMs)
|
|
58
|
-
try {
|
|
59
|
-
await (await fetch(`http://${host}:${port}`, { signal: AbortSignal.timeout(1000) })).arrayBuffer();
|
|
60
|
-
return;
|
|
61
|
-
} catch {
|
|
62
|
-
await Bun.sleep(300);
|
|
63
|
-
}
|
|
64
|
-
throw Error(`Timed out waiting for server on port ${port}`);
|
|
65
|
-
}
|
|
66
|
-
const devServerRunners = {
|
|
67
|
-
frontend: runFrontendDevServer,
|
|
68
|
-
api: runApiDevServer,
|
|
69
|
-
backend: runApiDevServer,
|
|
70
|
-
admin: runDashboardDevServer,
|
|
71
|
-
dashboard: runDashboardDevServer,
|
|
72
|
-
desktop: runDesktopDevServer,
|
|
73
|
-
docs: runDocsDevServer
|
|
74
|
-
}, companionServices = {
|
|
75
|
-
frontend: [
|
|
76
|
-
{ port: configPorts?.api || 3008, suffix: "api", label: "API", runner: runApiDevServer },
|
|
77
|
-
{ port: configPorts?.docs || 3006, suffix: "docs", label: "Docs", runner: runDocsDevServer }
|
|
78
|
-
]
|
|
79
|
-
};
|
|
80
|
-
function capitalize(s) {
|
|
81
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
82
|
-
}
|
|
83
|
-
export function share(buddy) {
|
|
84
|
-
buddy.command("share [type]", "Share your local development server via a public tunnel").option("-p, --port <port>", "Local port to share").option("--server <url>", "Tunnel server URL", { default: "api.localtunnel.dev" }).option("--subdomain <name>", "Request a specific subdomain").option("--verbose", "Enable verbose output", { default: !1 }).action(async (type, options) => {
|
|
85
|
-
const perf = await intro("buddy share"), serviceType = type || "frontend", defaultPorts = {
|
|
86
|
-
frontend: configPorts?.frontend || 3000,
|
|
87
|
-
api: configPorts?.api || 3008,
|
|
88
|
-
backend: configPorts?.backend || 3001,
|
|
89
|
-
admin: configPorts?.admin || 3002,
|
|
90
|
-
dashboard: configPorts?.admin || 3002,
|
|
91
|
-
library: configPorts?.library || 3003,
|
|
92
|
-
desktop: configPorts?.desktop || 3004,
|
|
93
|
-
email: configPorts?.email || 3005,
|
|
94
|
-
docs: configPorts?.docs || 3006,
|
|
95
|
-
inspect: configPorts?.inspect || 3007
|
|
96
|
-
}, port = options.port ? Number.parseInt(options.port, 10) : defaultPorts[serviceType] || 3000;
|
|
97
|
-
if (Number.isNaN(port) || port < 1 || port > 65535) {
|
|
98
|
-
log.error(`Invalid port: ${options.port}`);
|
|
99
|
-
process.exit(ExitCode.InvalidArgument);
|
|
100
|
-
}
|
|
101
|
-
const server = options.server || "api.localtunnel.dev", tunnels = [], companions = companionServices[serviceType] || [], s = spinner();
|
|
102
|
-
try {
|
|
103
|
-
const { localTunnel } = await import("@stacksjs/tunnel");
|
|
104
|
-
console.log();
|
|
105
|
-
const runner = devServerRunners[serviceType];
|
|
106
|
-
if (runner) {
|
|
107
|
-
s.start(`Starting ${serviceType} dev server...`);
|
|
108
|
-
muteOutput();
|
|
109
|
-
runner({ verbose: options.verbose ?? !1 }).catch(() => {});
|
|
110
|
-
await waitForPort(port);
|
|
111
|
-
unmuteOutput();
|
|
112
|
-
s.succeed(`${bold(capitalize(serviceType))} ready ${dim(`on :${port}`)}`);
|
|
113
|
-
}
|
|
114
|
-
const startedCompanions = [];
|
|
115
|
-
if (companions.length > 0) {
|
|
116
|
-
s.start("Starting companion services...");
|
|
117
|
-
muteOutput();
|
|
118
|
-
for (const companion of companions)
|
|
119
|
-
companion.runner({ verbose: options.verbose ?? !1 }).catch(() => {});
|
|
120
|
-
const results = await Promise.allSettled(companions.map((c) => waitForPort(c.port, "localhost", 60000)));
|
|
121
|
-
unmuteOutput();
|
|
122
|
-
for (let i = 0;i < companions.length; i++) {
|
|
123
|
-
const result = results[i], companion = companions[i];
|
|
124
|
-
if (!result || !companion)
|
|
125
|
-
continue;
|
|
126
|
-
if (result.status === "fulfilled") {
|
|
127
|
-
startedCompanions.push(companion);
|
|
128
|
-
s.succeed(`${bold(companion.label)} ready ${dim(`on :${companion.port}`)}`);
|
|
129
|
-
} else
|
|
130
|
-
s.fail(`${companion.label} failed to start ${dim(`on :${companion.port}`)}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
console.log();
|
|
134
|
-
s.start("Creating tunnel...");
|
|
135
|
-
const primaryTunnel = await localTunnel({
|
|
136
|
-
port,
|
|
137
|
-
server,
|
|
138
|
-
subdomain: options.subdomain,
|
|
139
|
-
verbose: options.verbose,
|
|
140
|
-
onRequest: (req) => {
|
|
141
|
-
if (options.verbose)
|
|
142
|
-
console.log(` ${dim(`${req.method} ${req.url}`)}`);
|
|
143
|
-
},
|
|
144
|
-
onReconnecting: (info) => {
|
|
145
|
-
s.start(`Reconnecting... (attempt ${info.attempt})`);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
tunnels.push(primaryTunnel);
|
|
149
|
-
const baseSubdomain = primaryTunnel.subdomain;
|
|
150
|
-
for (const companion of startedCompanions)
|
|
151
|
-
try {
|
|
152
|
-
const companionTunnel = await localTunnel({
|
|
153
|
-
port: companion.port,
|
|
154
|
-
server,
|
|
155
|
-
subdomain: `${baseSubdomain}-${companion.suffix}`,
|
|
156
|
-
verbose: options.verbose,
|
|
157
|
-
onReconnecting: (info) => {
|
|
158
|
-
s.start(`${companion.label}: reconnecting... (attempt ${info.attempt})`);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
tunnels.push(companionTunnel);
|
|
162
|
-
} catch {}
|
|
163
|
-
s.succeed(`Connected ${dim(`to ${server}`)}`);
|
|
164
|
-
const entries = [
|
|
165
|
-
{ label: capitalize(serviceType), url: primaryTunnel.url, local: `localhost:${port}` }
|
|
166
|
-
];
|
|
167
|
-
for (const companion of startedCompanions) {
|
|
168
|
-
const tunnel = tunnels.find((t) => t.subdomain === `${baseSubdomain}-${companion.suffix}`);
|
|
169
|
-
if (tunnel)
|
|
170
|
-
entries.push({ label: companion.label, url: tunnel.url, local: `localhost:${companion.port}` });
|
|
171
|
-
}
|
|
172
|
-
const maxLabel = Math.max(...entries.map((e) => e.label.length));
|
|
173
|
-
console.log();
|
|
174
|
-
for (const entry of entries) {
|
|
175
|
-
const padding = " ".repeat(maxLabel - entry.label.length + 1);
|
|
176
|
-
console.log(` ${green("\u279C")} ${bold(entry.label)}${padding} ${cyan(entry.url)}`);
|
|
177
|
-
}
|
|
178
|
-
console.log();
|
|
179
|
-
for (const entry of entries) {
|
|
180
|
-
const padding = " ".repeat(maxLabel - entry.label.length + 1);
|
|
181
|
-
console.log(` ${dim(entry.label)}${dim(padding)}${dim(entry.url)} ${dim("\u2192")} ${dim(entry.local)}`);
|
|
182
|
-
}
|
|
183
|
-
console.log();
|
|
184
|
-
console.log(` ${dim("press Ctrl+C to stop")}`);
|
|
185
|
-
console.log();
|
|
186
|
-
const cleanup = async () => {
|
|
187
|
-
console.log();
|
|
188
|
-
s.start("Closing tunnels...");
|
|
189
|
-
await Promise.all(tunnels.map((t) => t.close()));
|
|
190
|
-
s.succeed("Tunnels closed");
|
|
191
|
-
outro("Stopped sharing", { startTime: perf, useSeconds: !0 });
|
|
192
|
-
process.exit(ExitCode.Success);
|
|
193
|
-
};
|
|
194
|
-
process.on("SIGINT", () => cleanup());
|
|
195
|
-
process.on("SIGTERM", () => cleanup());
|
|
196
|
-
await new Promise(() => {});
|
|
197
|
-
} catch (error) {
|
|
198
|
-
unmuteOutput();
|
|
199
|
-
s.fail(getErrorMessage(error));
|
|
200
|
-
const caught = error instanceof Error ? error : Error(String(error));
|
|
201
|
-
if (caught.message.includes("timeout") || caught.message.includes("ECONNREFUSED")) {
|
|
202
|
-
log.error(`Could not reach tunnel server at ${server}`);
|
|
203
|
-
log.info(`Verify with: curl -sk https://${server}/status`);
|
|
204
|
-
} else
|
|
205
|
-
log.error(`Failed to create tunnel: ${caught.message}`);
|
|
206
|
-
if (options.verbose)
|
|
207
|
-
log.error(caught.stack);
|
|
208
|
-
for (const t of tunnels)
|
|
209
|
-
t.close();
|
|
210
|
-
await outro("Share failed", { startTime: perf, useSeconds: !0 });
|
|
211
|
-
process.exit(ExitCode.FatalError);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
}
|
package/dist/commands/sms.d.ts
DELETED