@everystack/cli 0.2.2 → 0.2.4
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 +1 -1
- package/src/cli/commands/update.ts +17 -2
- package/src/handler/assets.ts +15 -0
- package/src/storage/index.ts +2 -0
- package/src/storage/s3.ts +10 -0
package/package.json
CHANGED
|
@@ -20,6 +20,12 @@ export interface UpdateFlags {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export async function updateCommand(flags: UpdateFlags & Record<string, string>): Promise<void> {
|
|
23
|
+
// Signal publish context so app.config.js can detect it's not a dev session.
|
|
24
|
+
// Without this, dotenv guards that skip .env.local for EAS_BUILD/EAS_UPDATE
|
|
25
|
+
// don't know to skip for everystack update, causing local dev overrides
|
|
26
|
+
// (e.g. OUTBOUND_HOST=localhost → LAN IP) to leak into the manifest.
|
|
27
|
+
process.env.EVERYSTACK_UPDATE = '1';
|
|
28
|
+
|
|
23
29
|
// Propagate --stage to ENVIRONMENT before app.config.js evaluation.
|
|
24
30
|
// Without this, the manifest snapshots whatever the local shell has
|
|
25
31
|
// (often unset → 'development'), baking wrong API URLs and feature
|
|
@@ -406,8 +412,17 @@ async function loadAppConfig(): Promise<any> {
|
|
|
406
412
|
// Handle Expo's function export pattern: export default () => ({ ... })
|
|
407
413
|
if (typeof resolved === 'function') resolved = resolved();
|
|
408
414
|
return resolved.expo || resolved;
|
|
409
|
-
} catch {
|
|
410
|
-
|
|
415
|
+
} catch (e) {
|
|
416
|
+
const configPath = path.resolve('app.config.js');
|
|
417
|
+
try {
|
|
418
|
+
await fs.access(configPath);
|
|
419
|
+
// File exists but failed to import — surface the real error
|
|
420
|
+
throw new Error(`Failed to load app.config.js: ${e instanceof Error ? e.message : e}`);
|
|
421
|
+
} catch (accessErr) {
|
|
422
|
+
if (accessErr instanceof Error && accessErr.message.startsWith('Failed to load'))
|
|
423
|
+
throw accessErr;
|
|
424
|
+
throw new Error('Could not find app.json or app.config.js');
|
|
425
|
+
}
|
|
411
426
|
}
|
|
412
427
|
}
|
|
413
428
|
}
|
package/src/handler/assets.ts
CHANGED
|
@@ -11,6 +11,21 @@ export async function handleAssets(request: Request, options: UpdatesHandlerOpti
|
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// Redirect to a presigned S3 URL instead of proxying the bytes through Lambda.
|
|
15
|
+
// Lambda function URLs cap responses at 6 MB; Hermes bytecode bundles exceed that.
|
|
16
|
+
if (options.storage.presignGet) {
|
|
17
|
+
const presignedUrl = await options.storage.presignGet(key);
|
|
18
|
+
return new Response(null, {
|
|
19
|
+
status: 302,
|
|
20
|
+
headers: {
|
|
21
|
+
location: presignedUrl,
|
|
22
|
+
'cache-control': 'private, max-age=300',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Fallback: direct streaming for non-S3 backends (local dev, filesystem).
|
|
28
|
+
// No Lambda payload limit applies in these environments.
|
|
14
29
|
const result = await options.storage.get(key);
|
|
15
30
|
|
|
16
31
|
if (!result) {
|
package/src/storage/index.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface StorageAdapter {
|
|
|
8
8
|
delete(key: string): Promise<void>;
|
|
9
9
|
/** Generate a presigned PUT URL. S3-only — returns null for other backends. */
|
|
10
10
|
presignPut?(key: string, contentType: string, expiresIn?: number): Promise<string>;
|
|
11
|
+
/** Generate a presigned GET URL. S3-only — returns undefined for other backends. */
|
|
12
|
+
presignGet?(key: string, expiresIn?: number): Promise<string>;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export type StorageOptions =
|
package/src/storage/s3.ts
CHANGED
|
@@ -122,4 +122,14 @@ export class S3StorageAdapter implements StorageAdapter {
|
|
|
122
122
|
ContentType: contentType,
|
|
123
123
|
}), { expiresIn });
|
|
124
124
|
}
|
|
125
|
+
|
|
126
|
+
async presignGet(key: string, expiresIn: number = 3600): Promise<string> {
|
|
127
|
+
const { GetObjectCommand } = await import('@aws-sdk/client-s3');
|
|
128
|
+
const { getSignedUrl } = await import('@aws-sdk/s3-request-presigner');
|
|
129
|
+
const client = await this.getClient();
|
|
130
|
+
return getSignedUrl(client, new GetObjectCommand({
|
|
131
|
+
Bucket: this.bucket,
|
|
132
|
+
Key: key,
|
|
133
|
+
}), { expiresIn });
|
|
134
|
+
}
|
|
125
135
|
}
|