@everystack/cli 0.2.5 → 0.2.6
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 +13 -13
- package/src/cli/commands/logs.ts +46 -2
- package/src/cli/config.ts +6 -0
- package/src/cli/discover.ts +40 -12
- package/src/cli/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@everystack/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "CLI and OTA updates for Expo apps on everystack",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"publishConfig": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"lint": "tsc --noEmit"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@aws-sdk/client-cloudfront-keyvaluestore": "3.
|
|
45
|
-
"@aws-sdk/signature-v4a": "3.
|
|
44
|
+
"@aws-sdk/client-cloudfront-keyvaluestore": "3.1053.0",
|
|
45
|
+
"@aws-sdk/signature-v4a": "3.1048.0",
|
|
46
46
|
"glob": "13.0.6",
|
|
47
47
|
"node-forge": "1.4.0",
|
|
48
48
|
"structured-headers": "1.0.1",
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@everystack/server": ">=0.1.0",
|
|
53
|
-
"@aws-sdk/client-cloudfront": "3.
|
|
54
|
-
"@aws-sdk/client-cloudwatch-logs": "3.
|
|
55
|
-
"@aws-sdk/client-lambda": "3.
|
|
56
|
-
"@aws-sdk/client-s3": "3.
|
|
57
|
-
"@aws-sdk/s3-request-presigner": "3.
|
|
53
|
+
"@aws-sdk/client-cloudfront": "3.1053.0",
|
|
54
|
+
"@aws-sdk/client-cloudwatch-logs": "3.1053.0",
|
|
55
|
+
"@aws-sdk/client-lambda": "3.1053.0",
|
|
56
|
+
"@aws-sdk/client-s3": "3.1053.0",
|
|
57
|
+
"@aws-sdk/s3-request-presigner": "3.1053.0",
|
|
58
58
|
"drizzle-orm": "0.41.0",
|
|
59
59
|
"expo-updates": "55.0.21",
|
|
60
60
|
"react": "19.2.6",
|
|
@@ -90,11 +90,11 @@
|
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@aws-sdk/client-cloudfront": "3.
|
|
94
|
-
"@aws-sdk/client-cloudwatch-logs": "3.
|
|
95
|
-
"@aws-sdk/client-lambda": "3.
|
|
96
|
-
"@aws-sdk/client-s3": "3.
|
|
97
|
-
"@aws-sdk/s3-request-presigner": "3.
|
|
93
|
+
"@aws-sdk/client-cloudfront": "3.1053.0",
|
|
94
|
+
"@aws-sdk/client-cloudwatch-logs": "3.1053.0",
|
|
95
|
+
"@aws-sdk/client-lambda": "3.1053.0",
|
|
96
|
+
"@aws-sdk/client-s3": "3.1053.0",
|
|
97
|
+
"@aws-sdk/s3-request-presigner": "3.1053.0",
|
|
98
98
|
"@types/jest": "29.5.14",
|
|
99
99
|
"@types/node": "22.19.18",
|
|
100
100
|
"@types/node-forge": "1.3.14",
|
package/src/cli/commands/logs.ts
CHANGED
|
@@ -85,6 +85,42 @@ export async function logsErrorsCommand(flags: Record<string, string>): Promise<
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
const VALID_LOG_ORIGINS = ['api', 'media', 'worker'] as const;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve a Lambda function name from the --origin flag.
|
|
92
|
+
* Defaults to 'api' if no origin is specified.
|
|
93
|
+
*/
|
|
94
|
+
function resolveFunctionForOrigin(
|
|
95
|
+
config: { apiFunctionName: string; imageFunctionName?: string; workerFunctionName?: string },
|
|
96
|
+
origin?: string,
|
|
97
|
+
): string {
|
|
98
|
+
const resolved = origin || 'api';
|
|
99
|
+
|
|
100
|
+
if (!VALID_LOG_ORIGINS.includes(resolved as typeof VALID_LOG_ORIGINS[number])) {
|
|
101
|
+
throw new Error(`Invalid origin "${resolved}". Must be one of: ${VALID_LOG_ORIGINS.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
switch (resolved) {
|
|
105
|
+
case 'media':
|
|
106
|
+
if (!config.imageFunctionName) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
'No image function found. Add imageFunctionName to sst.config.ts outputs or use --stage for auto-discovery.',
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return config.imageFunctionName;
|
|
112
|
+
case 'worker':
|
|
113
|
+
if (!config.workerFunctionName) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
'No worker function found. Add workerFunctionName to sst.config.ts outputs or use --stage for auto-discovery.',
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return config.workerFunctionName;
|
|
119
|
+
default:
|
|
120
|
+
return config.apiFunctionName;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
88
124
|
export async function logsTailCommand(flags: Record<string, string>): Promise<void> {
|
|
89
125
|
step('Resolving deployed config...');
|
|
90
126
|
let config;
|
|
@@ -95,7 +131,15 @@ export async function logsTailCommand(flags: Record<string, string>): Promise<vo
|
|
|
95
131
|
process.exit(1);
|
|
96
132
|
}
|
|
97
133
|
|
|
98
|
-
|
|
134
|
+
let functionName: string;
|
|
135
|
+
try {
|
|
136
|
+
functionName = resolveFunctionForOrigin(config, flags.origin);
|
|
137
|
+
} catch (err: any) {
|
|
138
|
+
fail(err.message);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
info(`Region: ${config.region}, Function: ${functionName}`);
|
|
99
143
|
|
|
100
144
|
const filterPattern = flags.filter;
|
|
101
145
|
const since = flags.since || '5m'; // 5m, 1h, 1d
|
|
@@ -110,7 +154,7 @@ export async function logsTailCommand(flags: Record<string, string>): Promise<vo
|
|
|
110
154
|
const client = new CloudWatchLogsClient({ region: config.region });
|
|
111
155
|
|
|
112
156
|
// Resolve actual log group from Lambda config (handles SST name changes)
|
|
113
|
-
const logGroupName = await resolveLogGroup(config.region,
|
|
157
|
+
const logGroupName = await resolveLogGroup(config.region, functionName);
|
|
114
158
|
|
|
115
159
|
// Parse since duration to milliseconds
|
|
116
160
|
const sinceMs = parseDuration(since);
|
package/src/cli/config.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface CliConfig {
|
|
|
15
15
|
baseUrl: string;
|
|
16
16
|
region: string;
|
|
17
17
|
apiFunctionName: string;
|
|
18
|
+
imageFunctionName?: string;
|
|
19
|
+
workerFunctionName?: string;
|
|
18
20
|
updatesBucket: string;
|
|
19
21
|
clientBundlesBucket: string;
|
|
20
22
|
kvsArn?: string;
|
|
@@ -26,6 +28,8 @@ interface SstOutputs {
|
|
|
26
28
|
apiUrl?: string;
|
|
27
29
|
imageUrl?: string;
|
|
28
30
|
apiFunctionName?: string;
|
|
31
|
+
imageFunctionName?: string;
|
|
32
|
+
workerFunctionName?: string;
|
|
29
33
|
updatesBucket?: string;
|
|
30
34
|
clientBundlesBucket?: string;
|
|
31
35
|
kvsArn?: string;
|
|
@@ -93,6 +97,8 @@ export async function resolveConfig(stage?: string): Promise<CliConfig> {
|
|
|
93
97
|
baseUrl: outputs.routerUrl,
|
|
94
98
|
region,
|
|
95
99
|
apiFunctionName: outputs.apiFunctionName,
|
|
100
|
+
imageFunctionName: outputs.imageFunctionName,
|
|
101
|
+
workerFunctionName: outputs.workerFunctionName,
|
|
96
102
|
updatesBucket: outputs.updatesBucket,
|
|
97
103
|
clientBundlesBucket: outputs.clientBundlesBucket,
|
|
98
104
|
kvsArn: outputs.kvsArn,
|
package/src/cli/discover.ts
CHANGED
|
@@ -14,11 +14,13 @@
|
|
|
14
14
|
import fs from 'node:fs/promises';
|
|
15
15
|
import path from 'node:path';
|
|
16
16
|
|
|
17
|
-
/** Mirrors
|
|
17
|
+
/** Mirrors CliConfig from config.ts — defined locally to avoid circular imports. */
|
|
18
18
|
interface DiscoveredConfig {
|
|
19
19
|
baseUrl: string;
|
|
20
20
|
region: string;
|
|
21
21
|
apiFunctionName: string;
|
|
22
|
+
imageFunctionName?: string;
|
|
23
|
+
workerFunctionName?: string;
|
|
22
24
|
updatesBucket: string;
|
|
23
25
|
clientBundlesBucket: string;
|
|
24
26
|
kvsArn?: string;
|
|
@@ -129,24 +131,23 @@ interface LambdaResult {
|
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
/**
|
|
132
|
-
* Find
|
|
133
|
-
*
|
|
134
|
+
* Find a Lambda function by SST resource name prefix.
|
|
135
|
+
* Returns the function name if found, undefined if not.
|
|
134
136
|
*/
|
|
135
|
-
export async function
|
|
137
|
+
export async function discoverFunction(
|
|
136
138
|
region: string,
|
|
137
139
|
prefix: string,
|
|
138
|
-
|
|
140
|
+
resourceName: string,
|
|
141
|
+
): Promise<string | undefined> {
|
|
139
142
|
const {
|
|
140
143
|
LambdaClient,
|
|
141
144
|
ListFunctionsCommand,
|
|
142
|
-
GetFunctionConfigurationCommand,
|
|
143
145
|
} = await import('@aws-sdk/client-lambda');
|
|
144
146
|
|
|
145
147
|
const client = new LambdaClient({ region });
|
|
146
|
-
const needle = `${prefix}
|
|
148
|
+
const needle = `${prefix}${resourceName}-`.toLowerCase();
|
|
147
149
|
|
|
148
150
|
let marker: string | undefined;
|
|
149
|
-
let matchName: string | undefined;
|
|
150
151
|
|
|
151
152
|
do {
|
|
152
153
|
const res = await client.send(
|
|
@@ -155,14 +156,25 @@ export async function discoverLambda(
|
|
|
155
156
|
const items = res.Functions || [];
|
|
156
157
|
for (const fn of items) {
|
|
157
158
|
if (fn.FunctionName && fn.FunctionName.toLowerCase().startsWith(needle)) {
|
|
158
|
-
|
|
159
|
-
break;
|
|
159
|
+
return fn.FunctionName;
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
if (matchName) break;
|
|
163
162
|
marker = res.NextMarker;
|
|
164
163
|
} while (marker);
|
|
165
164
|
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Find the API Lambda function for a stage.
|
|
170
|
+
* Extracts CDN_URL from environment variables for routerUrl.
|
|
171
|
+
*/
|
|
172
|
+
export async function discoverLambda(
|
|
173
|
+
region: string,
|
|
174
|
+
prefix: string,
|
|
175
|
+
): Promise<LambdaResult> {
|
|
176
|
+
const matchName = await discoverFunction(region, prefix, 'ApiFunction');
|
|
177
|
+
|
|
166
178
|
if (!matchName) {
|
|
167
179
|
throw new Error(
|
|
168
180
|
`No API Lambda found for prefix "${prefix}ApiFunction-*". ` +
|
|
@@ -171,6 +183,12 @@ export async function discoverLambda(
|
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
// Get env vars for routerUrl (CDN_URL)
|
|
186
|
+
const {
|
|
187
|
+
LambdaClient,
|
|
188
|
+
GetFunctionConfigurationCommand,
|
|
189
|
+
} = await import('@aws-sdk/client-lambda');
|
|
190
|
+
|
|
191
|
+
const client = new LambdaClient({ region });
|
|
174
192
|
const config = await client.send(
|
|
175
193
|
new GetFunctionConfigurationCommand({ FunctionName: matchName }),
|
|
176
194
|
);
|
|
@@ -236,10 +254,12 @@ export async function discoverConfig(
|
|
|
236
254
|
const prefix = `${appName}-${stage}-`;
|
|
237
255
|
|
|
238
256
|
// Run CF function + Lambda + S3 discovery in parallel
|
|
239
|
-
const [cfResult, lambdaResult, bucketsResult] = await Promise.all([
|
|
257
|
+
const [cfResult, lambdaResult, bucketsResult, imageFn, workerFn] = await Promise.all([
|
|
240
258
|
discoverCfFunction(region, prefix),
|
|
241
259
|
discoverLambda(region, prefix),
|
|
242
260
|
discoverBuckets(region, prefix),
|
|
261
|
+
discoverFunction(region, prefix, 'ImageFunction').catch(() => undefined),
|
|
262
|
+
discoverFunction(region, prefix, 'WorkerFunction').catch(() => undefined),
|
|
243
263
|
]);
|
|
244
264
|
|
|
245
265
|
// Distribution discovery is best-effort (not critical for most CLI operations)
|
|
@@ -269,6 +289,8 @@ export async function discoverConfig(
|
|
|
269
289
|
baseUrl: lambdaResult.routerUrl || '',
|
|
270
290
|
region,
|
|
271
291
|
apiFunctionName: lambdaResult.functionName,
|
|
292
|
+
imageFunctionName: imageFn,
|
|
293
|
+
workerFunctionName: workerFn,
|
|
272
294
|
updatesBucket: bucketsResult.updatesBucket,
|
|
273
295
|
clientBundlesBucket: bucketsResult.clientBundlesBucket,
|
|
274
296
|
kvsArn: cfResult.kvsArn,
|
|
@@ -286,6 +308,8 @@ interface CachedOutputs {
|
|
|
286
308
|
_cachedAt: number;
|
|
287
309
|
routerUrl?: string;
|
|
288
310
|
apiFunctionName?: string;
|
|
311
|
+
imageFunctionName?: string;
|
|
312
|
+
workerFunctionName?: string;
|
|
289
313
|
updatesBucket?: string;
|
|
290
314
|
clientBundlesBucket?: string;
|
|
291
315
|
kvsArn?: string;
|
|
@@ -308,6 +332,8 @@ export async function getCachedConfig(stage: string): Promise<DiscoveredConfig |
|
|
|
308
332
|
baseUrl: cached.routerUrl || '',
|
|
309
333
|
region: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1',
|
|
310
334
|
apiFunctionName: cached.apiFunctionName,
|
|
335
|
+
imageFunctionName: cached.imageFunctionName,
|
|
336
|
+
workerFunctionName: cached.workerFunctionName,
|
|
311
337
|
updatesBucket: cached.updatesBucket,
|
|
312
338
|
clientBundlesBucket: cached.clientBundlesBucket,
|
|
313
339
|
kvsArn: cached.kvsArn,
|
|
@@ -323,6 +349,8 @@ export async function setCachedConfig(stage: string, config: DiscoveredConfig):
|
|
|
323
349
|
_cachedAt: Date.now(),
|
|
324
350
|
routerUrl: config.baseUrl,
|
|
325
351
|
apiFunctionName: config.apiFunctionName,
|
|
352
|
+
imageFunctionName: config.imageFunctionName,
|
|
353
|
+
workerFunctionName: config.workerFunctionName,
|
|
326
354
|
updatesBucket: config.updatesBucket,
|
|
327
355
|
clientBundlesBucket: config.clientBundlesBucket,
|
|
328
356
|
kvsArn: config.kvsArn,
|
package/src/cli/index.ts
CHANGED
|
@@ -167,7 +167,7 @@ Usage:
|
|
|
167
167
|
everystack diag [url] --hydration Analyze SSR hydration issues (fetches full HTML)
|
|
168
168
|
everystack analyze:ssr [--app ./app] Scan app code for SSR anti-patterns
|
|
169
169
|
everystack logs:errors [--stage <name>] [--limit 20] [--level error|fatal] [--source <name>]
|
|
170
|
-
everystack logs:tail [--stage <name>] [--filter <pattern>] [--since 5m]
|
|
170
|
+
everystack logs:tail [--stage <name>] [--origin api|media|worker] [--filter <pattern>] [--since 5m]
|
|
171
171
|
everystack logs:query [--stage <name>] [--level <level>] [--source <name>] [--traceId <id>] [--search <text>]
|
|
172
172
|
everystack branches list
|
|
173
173
|
everystack branches create --name <name>
|