alchemy 0.27.0 → 0.29.0
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/README.md +1 -1
- package/lib/alchemy.d.ts +21 -1
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +42 -8
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.js +3 -12
- package/lib/apply.js.map +1 -1
- package/lib/cloudflare/do-state-store/internal.d.ts +1 -1
- package/lib/cloudflare/do-state-store/internal.d.ts.map +1 -1
- package/lib/cloudflare/do-state-store/internal.js +2 -2
- package/lib/cloudflare/do-state-store/internal.js.map +1 -1
- package/lib/cloudflare/do-state-store/store.d.ts.map +1 -1
- package/lib/cloudflare/do-state-store/store.js +19 -4
- package/lib/cloudflare/do-state-store/store.js.map +1 -1
- package/lib/cloudflare/secrets-store.d.ts.map +1 -1
- package/lib/cloudflare/secrets-store.js +21 -17
- package/lib/cloudflare/secrets-store.js.map +1 -1
- package/lib/cloudflare/worker-assets.d.ts.map +1 -1
- package/lib/cloudflare/worker-assets.js +9 -0
- package/lib/cloudflare/worker-assets.js.map +1 -1
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +3 -6
- package/lib/destroy.js.map +1 -1
- package/lib/github/comment.d.ts +156 -0
- package/lib/github/comment.d.ts.map +1 -0
- package/lib/github/comment.js +192 -0
- package/lib/github/comment.js.map +1 -0
- package/lib/github/index.d.ts +1 -0
- package/lib/github/index.d.ts.map +1 -1
- package/lib/github/index.js +1 -0
- package/lib/github/index.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/scope.d.ts +2 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +1 -1
- package/lib/scope.js.map +1 -1
- package/lib/util/cli.d.ts +2 -13
- package/lib/util/cli.d.ts.map +1 -1
- package/lib/util/cli.js +46 -60
- package/lib/util/cli.js.map +1 -1
- package/lib/util/logger.d.ts +1 -1
- package/lib/util/logger.d.ts.map +1 -1
- package/lib/util/telemetry/client.js +1 -1
- package/lib/util/telemetry/client.js.map +1 -1
- package/package.json +2 -5
- package/src/alchemy.ts +71 -9
- package/src/apply.ts +4 -17
- package/src/cloudflare/do-state-store/internal.ts +2 -1
- package/src/cloudflare/do-state-store/store.ts +26 -4
- package/src/cloudflare/secrets-store.ts +22 -21
- package/src/cloudflare/worker-assets.ts +16 -0
- package/src/destroy.ts +4 -7
- package/src/github/comment.ts +278 -0
- package/src/github/index.ts +1 -0
- package/src/index.ts +1 -1
- package/src/scope.ts +10 -6
- package/src/util/cli.ts +117 -0
- package/src/util/logger.ts +1 -1
- package/src/util/telemetry/client.ts +1 -1
- package/src/util/cli.tsx +0 -221
package/lib/util/cli.js
CHANGED
|
@@ -1,64 +1,32 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Box, render, Static, Text, useApp } from "ink";
|
|
3
|
-
import Spinner from "ink-spinner";
|
|
4
|
-
import { format } from "node:util";
|
|
5
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
1
|
import packageJson from "../../package.json" with { type: "json" };
|
|
7
2
|
import { dedent } from "./dedent.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
exit: () => exit(),
|
|
30
|
-
});
|
|
31
|
-
return () => {
|
|
32
|
-
setTasks(new Map());
|
|
33
|
-
setLogs([]);
|
|
34
|
-
};
|
|
35
|
-
}, [exit, log, setLogger, task]);
|
|
36
|
-
return (_jsxs(_Fragment, { children: [_jsx(Static, { items: logs, children: (log) => {
|
|
37
|
-
if (log.id === 0) {
|
|
38
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "column", borderStyle: "round", padding: 1, children: [_jsxs(Text, { color: "green", bold: true, children: ["Alchemy (v", packageJson.version, ")"] }), _jsxs(Text, { color: "gray", bold: true, children: ["App:", " ", _jsx(Text, { color: "magenta", bold: false, children: alchemyInfo.appName })] }), _jsxs(Text, { color: "gray", bold: true, children: ["Phase:", " ", _jsx(Text, { color: "magenta", bold: false, children: alchemyInfo.phase })] }), _jsxs(Text, { color: "gray", bold: true, children: ["Stage:", " ", _jsx(Text, { color: "magenta", bold: false, children: alchemyInfo.stage })] })] }), _jsx(Text, { color: "green", bold: true, children: "Logs" })] }, log.text));
|
|
39
|
-
}
|
|
40
|
-
return (_jsx(Text, { color: "gray", wrap: "wrap", children: log.text }, log.id));
|
|
41
|
-
} }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "Tasks" }), _jsx(Box, { flexDirection: "column", paddingLeft: 1, children: Array.from(tasks.entries()).map(([id, task]) => (_jsxs(Box, { flexDirection: "row", gap: 1, children: [!task.status || task.status === "pending" ? (_jsx(Spinner, {})) : task.status === "success" ? (_jsx(Text, { color: "green", children: "\u2713" })) : (_jsx(Text, { color: "red", children: "\u2717" })), task.prefix && (_jsx(Text, { color: task.prefixColor ?? "white", bold: true, children: task.prefix.padStart(9) })), task.resource && (_jsxs(Text, { color: "gray", bold: true, children: ["[", task.resource, "]"] })), _jsx(Text, { bold: true, children: task.message })] }, id))) })] })] }));
|
|
42
|
-
}
|
|
3
|
+
// ANSI color codes
|
|
4
|
+
const colors = {
|
|
5
|
+
reset: "\x1b[0m",
|
|
6
|
+
cyanBright: "\x1b[96m",
|
|
7
|
+
yellowBright: "\x1b[93m",
|
|
8
|
+
magenta: "\x1b[35m",
|
|
9
|
+
greenBright: "\x1b[92m",
|
|
10
|
+
redBright: "\x1b[91m",
|
|
11
|
+
gray: "\x1b[90m",
|
|
12
|
+
};
|
|
13
|
+
// Check if colors should be disabled
|
|
14
|
+
const shouldDisableColors = () => {
|
|
15
|
+
return Boolean(process.env.CI || process.env.NO_COLOR || !process.stdout.isTTY);
|
|
16
|
+
};
|
|
17
|
+
// Apply color if colors are enabled
|
|
18
|
+
const colorize = (text, color) => {
|
|
19
|
+
if (shouldDisableColors()) {
|
|
20
|
+
return text;
|
|
21
|
+
}
|
|
22
|
+
return `${colors[color]}${text}${colors.reset}`;
|
|
23
|
+
};
|
|
43
24
|
let loggerApi = null;
|
|
44
|
-
export const createLoggerInstance = (alchemyInfo) => {
|
|
25
|
+
export const createLoggerInstance = (alchemyInfo, customLogger) => {
|
|
45
26
|
if (loggerApi)
|
|
46
27
|
return loggerApi;
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
!process.stdin.isTTY) {
|
|
50
|
-
loggerApi = createFallbackLogger(alchemyInfo);
|
|
51
|
-
return loggerApi;
|
|
52
|
-
}
|
|
53
|
-
render(_jsx(LoggerCLI, { alchemyInfo: alchemyInfo, setLogger: (logger) => {
|
|
54
|
-
loggerApi = logger;
|
|
55
|
-
} }), {
|
|
56
|
-
exitOnCtrlC: true,
|
|
57
|
-
});
|
|
58
|
-
process.on("SIGINT", () => {
|
|
59
|
-
loggerApi?.exit();
|
|
60
|
-
process.exit(0);
|
|
61
|
-
});
|
|
28
|
+
// Use custom logger if provided, otherwise use the basic fallback logger
|
|
29
|
+
loggerApi = customLogger ?? createFallbackLogger(alchemyInfo);
|
|
62
30
|
return loggerApi;
|
|
63
31
|
};
|
|
64
32
|
export const createDummyLogger = () => {
|
|
@@ -72,7 +40,7 @@ export const createDummyLogger = () => {
|
|
|
72
40
|
};
|
|
73
41
|
export const createFallbackLogger = (alchemyInfo) => {
|
|
74
42
|
console.log(dedent `
|
|
75
|
-
Alchemy (v${packageJson.version})
|
|
43
|
+
${colorize("Alchemy", "cyanBright")} (v${packageJson.version})
|
|
76
44
|
App: ${alchemyInfo.appName}
|
|
77
45
|
Phase: ${alchemyInfo.phase}
|
|
78
46
|
Stage: ${alchemyInfo.stage}
|
|
@@ -80,9 +48,27 @@ export const createFallbackLogger = (alchemyInfo) => {
|
|
|
80
48
|
`);
|
|
81
49
|
return {
|
|
82
50
|
log: console.log,
|
|
83
|
-
error: console.error,
|
|
84
|
-
warn: console.warn,
|
|
85
|
-
task: () => {
|
|
51
|
+
error: (...args) => console.error(colorize("ERROR", "redBright"), ...args),
|
|
52
|
+
warn: (...args) => console.warn(colorize("WARN", "yellowBright"), ...args),
|
|
53
|
+
task: (_id, data) => {
|
|
54
|
+
const prefix = data.prefix ? `[${data.prefix}]` : "";
|
|
55
|
+
// Pad the prefix to ensure consistent alignment (12 characters total including brackets)
|
|
56
|
+
const paddedPrefix = prefix.padEnd(12);
|
|
57
|
+
const prefixWithColor = data.prefixColor && prefix
|
|
58
|
+
? colorize(paddedPrefix, data.prefixColor)
|
|
59
|
+
: paddedPrefix;
|
|
60
|
+
const resource = data.resource ? colorize(data.resource, "gray") : "";
|
|
61
|
+
const message = data.message;
|
|
62
|
+
if (prefixWithColor && resource) {
|
|
63
|
+
console.log(`${prefixWithColor}${resource} ${message}`);
|
|
64
|
+
}
|
|
65
|
+
else if (prefixWithColor) {
|
|
66
|
+
console.log(`${prefixWithColor}${message}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log(`${message}`);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
86
72
|
exit: () => { },
|
|
87
73
|
};
|
|
88
74
|
};
|
package/lib/util/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/util/cli.
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/util/cli.ts"],"names":[],"mappings":"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"}
|
package/lib/util/logger.d.ts
CHANGED
package/lib/util/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,MAAM,WAajB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/util/telemetry/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAgBvC,MAAM,OAAO,mBAAmB;IAC9B,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,CAAC,CAAuB,IAAG,CAAC;IAClC,QAAQ;QACN,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,eAAe;IAML;IALrB,KAAK,CAAgB;IAEb,MAAM,GAAsB,EAAE,CAAC;IAC/B,OAAO,CAAqB;IAEpC,YAAqB,OAA+B;QAA/B,YAAO,GAAP,OAAO,CAAwB;QAClD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,MAAM,OAAO,CAAC;YAC3B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CACT;YACE,KAAK,EAAE,WAAW;SACnB,EACD,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAA2B,EAAE,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;QACxD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/util/telemetry/client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"module": "./lib/index.js",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -162,7 +162,6 @@
|
|
|
162
162
|
"@types/diff": "^5.0.0",
|
|
163
163
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
164
164
|
"@types/node": "latest",
|
|
165
|
-
"@types/react": "^19.1.6",
|
|
166
165
|
"@types/turndown": "^5.0.5",
|
|
167
166
|
"ai": "^4.1.16",
|
|
168
167
|
"arktype": "^2.1.16",
|
|
@@ -170,12 +169,10 @@
|
|
|
170
169
|
"change-case": "^5.4.4",
|
|
171
170
|
"cloudflare": "^4.2.0",
|
|
172
171
|
"cpx": "^1.5.0",
|
|
173
|
-
"ink": "^6.0.0",
|
|
174
|
-
"ink-spinner": "^5.0.0",
|
|
175
172
|
"libsodium-wrappers": "^0.7.15",
|
|
173
|
+
"miniflare": "^4.0.0",
|
|
176
174
|
"openpgp": "^6.1.0",
|
|
177
175
|
"prettier": "^3.5.3",
|
|
178
|
-
"react": "^19.1.0",
|
|
179
176
|
"turndown": "^7.2.0",
|
|
180
177
|
"typedoc": "^0.28.1",
|
|
181
178
|
"typedoc-plugin-markdown": "^4.6.0",
|
package/src/alchemy.ts
CHANGED
|
@@ -17,6 +17,40 @@ import { secret } from "./secret.ts";
|
|
|
17
17
|
import type { StateStoreType } from "./state.ts";
|
|
18
18
|
import { logger } from "./util/logger.ts";
|
|
19
19
|
import { TelemetryClient } from "./util/telemetry/client.ts";
|
|
20
|
+
import type { LoggerApi } from "./util/cli.ts";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Parses CLI arguments to extract alchemy options
|
|
24
|
+
*/
|
|
25
|
+
function parseCliArgs(): Partial<AlchemyOptions> {
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
const options: Partial<AlchemyOptions> = {};
|
|
28
|
+
|
|
29
|
+
// Parse phase from CLI arguments
|
|
30
|
+
if (args.includes("--destroy")) {
|
|
31
|
+
options.phase = "destroy";
|
|
32
|
+
} else if (args.includes("--read")) {
|
|
33
|
+
options.phase = "read";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Parse quiet flag
|
|
37
|
+
if (args.includes("--quiet")) {
|
|
38
|
+
options.quiet = true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parse stage argument (--stage my-stage)
|
|
42
|
+
const stageIndex = args.indexOf("--stage");
|
|
43
|
+
if (stageIndex !== -1 && stageIndex + 1 < args.length) {
|
|
44
|
+
options.stage = args[stageIndex + 1];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Get password from environment variables
|
|
48
|
+
if (process.env.ALCHEMY_PASSWORD) {
|
|
49
|
+
options.password = process.env.ALCHEMY_PASSWORD;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return options;
|
|
53
|
+
}
|
|
20
54
|
|
|
21
55
|
/**
|
|
22
56
|
* Type alias for semantic highlighting of `alchemy` as a type keyword
|
|
@@ -28,9 +62,16 @@ export const alchemy: Alchemy = _alchemy as any;
|
|
|
28
62
|
/**
|
|
29
63
|
* The Alchemy interface provides core functionality and is augmented by providers.
|
|
30
64
|
* Supports both application scoping with secrets and template string interpolation.
|
|
65
|
+
* Automatically parses CLI arguments for common options.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Simple usage with automatic CLI argument parsing
|
|
69
|
+
* const app = await alchemy("my-app");
|
|
70
|
+
* // Now supports: --destroy, --read, --quiet, --stage my-stage
|
|
71
|
+
* // Environment variables: PASSWORD, ALCHEMY_PASSWORD, ALCHEMY_STAGE, USER
|
|
31
72
|
*
|
|
32
73
|
* @example
|
|
33
|
-
* // Create an application scope with
|
|
74
|
+
* // Create an application scope with explicit options (overrides CLI args)
|
|
34
75
|
* const app = await alchemy("github:alchemy", {
|
|
35
76
|
* stage: "prod",
|
|
36
77
|
* phase: "up",
|
|
@@ -68,8 +109,15 @@ export interface Alchemy {
|
|
|
68
109
|
/**
|
|
69
110
|
* Creates a new application scope with the given name and options.
|
|
70
111
|
* Used to create and manage resources with proper secret handling.
|
|
112
|
+
* Automatically parses CLI arguments: --destroy, --read, --quiet, --stage <name>
|
|
113
|
+
* Environment variables: PASSWORD, ALCHEMY_PASSWORD, ALCHEMY_STAGE, USER
|
|
71
114
|
*
|
|
72
115
|
* @example
|
|
116
|
+
* // Simple usage with CLI argument parsing
|
|
117
|
+
* const app = await alchemy("my-app");
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* // With explicit options (overrides CLI args)
|
|
73
121
|
* const app = await alchemy("my-app", {
|
|
74
122
|
* stage: "prod",
|
|
75
123
|
* // Required for encrypting/decrypting secrets
|
|
@@ -114,20 +162,29 @@ async function _alchemy(
|
|
|
114
162
|
): Promise<Scope | string | never> {
|
|
115
163
|
if (typeof args[0] === "string") {
|
|
116
164
|
const [appName, options] = args as [string, AlchemyOptions?];
|
|
117
|
-
|
|
165
|
+
|
|
166
|
+
// Parse CLI arguments and merge with provided options (explicit options take precedence)
|
|
167
|
+
const cliOptions = parseCliArgs();
|
|
168
|
+
const mergedOptions = {
|
|
169
|
+
...cliOptions,
|
|
170
|
+
...options,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const phase = isRuntime ? "read" : (mergedOptions?.phase ?? "up");
|
|
118
174
|
const telemetryClient =
|
|
119
|
-
|
|
175
|
+
mergedOptions?.parent?.telemetryClient ??
|
|
120
176
|
TelemetryClient.create({
|
|
121
177
|
phase,
|
|
122
|
-
enabled:
|
|
123
|
-
quiet:
|
|
178
|
+
enabled: mergedOptions?.telemetry ?? true,
|
|
179
|
+
quiet: mergedOptions?.quiet ?? false,
|
|
124
180
|
});
|
|
125
181
|
const root = new Scope({
|
|
126
|
-
...
|
|
182
|
+
...mergedOptions,
|
|
127
183
|
appName,
|
|
128
|
-
stage:
|
|
184
|
+
stage:
|
|
185
|
+
mergedOptions?.stage ?? process.env.ALCHEMY_STAGE ?? process.env.USER,
|
|
129
186
|
phase,
|
|
130
|
-
password:
|
|
187
|
+
password: mergedOptions?.password ?? process.env.ALCHEMY_PASSWORD,
|
|
131
188
|
telemetryClient,
|
|
132
189
|
});
|
|
133
190
|
try {
|
|
@@ -137,7 +194,7 @@ async function _alchemy(
|
|
|
137
194
|
// see Scope.finalize for where we pop the global scope
|
|
138
195
|
Scope.globals.push(root);
|
|
139
196
|
}
|
|
140
|
-
if (
|
|
197
|
+
if (mergedOptions?.phase === "destroy") {
|
|
141
198
|
await destroy(root);
|
|
142
199
|
return process.exit(0);
|
|
143
200
|
}
|
|
@@ -308,6 +365,11 @@ export interface AlchemyOptions {
|
|
|
308
365
|
* @default true
|
|
309
366
|
*/
|
|
310
367
|
telemetry?: boolean;
|
|
368
|
+
/**
|
|
369
|
+
* A custom logger instance to use for this scope.
|
|
370
|
+
* If not provided, the default fallback logger will be used.
|
|
371
|
+
*/
|
|
372
|
+
logger?: LoggerApi;
|
|
311
373
|
}
|
|
312
374
|
|
|
313
375
|
export interface ScopeOptions extends AlchemyOptions {
|
package/src/apply.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { Scope } from "./scope.ts";
|
|
16
16
|
import { serialize } from "./serde.ts";
|
|
17
17
|
import type { State } from "./state.ts";
|
|
18
|
-
import { formatFQN } from "./util/cli.
|
|
18
|
+
import { formatFQN } from "./util/cli.ts";
|
|
19
19
|
import { logger } from "./util/logger.ts";
|
|
20
20
|
import type { Telemetry } from "./util/telemetry/index.ts";
|
|
21
21
|
|
|
@@ -41,12 +41,6 @@ async function _apply<Out extends Resource>(
|
|
|
41
41
|
const scope = resource[ResourceScope];
|
|
42
42
|
const start = performance.now();
|
|
43
43
|
try {
|
|
44
|
-
logger.task(resource[ResourceFQN], {
|
|
45
|
-
prefix: "SETUP",
|
|
46
|
-
prefixColor: "cyanBright",
|
|
47
|
-
resource: formatFQN(resource[ResourceFQN]),
|
|
48
|
-
message: "Setting up Resource...",
|
|
49
|
-
});
|
|
50
44
|
const quiet = props?.quiet ?? scope.quiet;
|
|
51
45
|
await scope.init();
|
|
52
46
|
let state: State | undefined = (await scope.state.get(
|
|
@@ -112,13 +106,12 @@ async function _apply<Out extends Resource>(
|
|
|
112
106
|
) {
|
|
113
107
|
if (!quiet) {
|
|
114
108
|
logger.task(resource[ResourceFQN], {
|
|
115
|
-
prefix: "
|
|
109
|
+
prefix: "skipped",
|
|
116
110
|
prefixColor: "yellowBright",
|
|
117
111
|
resource: formatFQN(resource[ResourceFQN]),
|
|
118
112
|
message: "Skipped Resource (no changes)",
|
|
119
113
|
status: "success",
|
|
120
114
|
});
|
|
121
|
-
logger.log(`Skipping ${resource[ResourceFQN]} (no changes)`);
|
|
122
115
|
}
|
|
123
116
|
options?.resolveInnerScope?.(
|
|
124
117
|
new Scope({
|
|
@@ -142,14 +135,11 @@ async function _apply<Out extends Resource>(
|
|
|
142
135
|
|
|
143
136
|
if (!quiet) {
|
|
144
137
|
logger.task(resource[ResourceFQN], {
|
|
145
|
-
prefix: phase === "create" ? "
|
|
138
|
+
prefix: phase === "create" ? "creating" : "updating",
|
|
146
139
|
prefixColor: "magenta",
|
|
147
140
|
resource: formatFQN(resource[ResourceFQN]),
|
|
148
141
|
message: `${phase === "create" ? "Creating" : "Updating"} Resource...`,
|
|
149
142
|
});
|
|
150
|
-
logger.log(
|
|
151
|
-
`${phase === "create" ? "Create" : "Update"}: "${resource[ResourceFQN]}"`,
|
|
152
|
-
);
|
|
153
143
|
}
|
|
154
144
|
|
|
155
145
|
scope.telemetryClient.record({
|
|
@@ -195,15 +185,12 @@ async function _apply<Out extends Resource>(
|
|
|
195
185
|
);
|
|
196
186
|
if (!quiet) {
|
|
197
187
|
logger.task(resource[ResourceFQN], {
|
|
198
|
-
prefix: phase === "create" ? "
|
|
188
|
+
prefix: phase === "create" ? "created" : "updated",
|
|
199
189
|
prefixColor: "greenBright",
|
|
200
190
|
resource: formatFQN(resource[ResourceFQN]),
|
|
201
191
|
message: `${phase === "create" ? "Created" : "Updated"} Resource`,
|
|
202
192
|
status: "success",
|
|
203
193
|
});
|
|
204
|
-
logger.log(
|
|
205
|
-
`${phase === "create" ? "Created" : "Updated"}: "${resource[ResourceFQN]}"`,
|
|
206
|
-
);
|
|
207
194
|
}
|
|
208
195
|
|
|
209
196
|
const status = phase === "create" ? "created" : "updated";
|
|
@@ -104,6 +104,7 @@ export async function upsertStateStoreWorker(
|
|
|
104
104
|
api: CloudflareApi,
|
|
105
105
|
workerName: string,
|
|
106
106
|
token: string,
|
|
107
|
+
force: boolean,
|
|
107
108
|
) {
|
|
108
109
|
const key = `worker:${workerName}`;
|
|
109
110
|
const cached = cache.get(key);
|
|
@@ -111,7 +112,7 @@ export async function upsertStateStoreWorker(
|
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
const { found, tag } = await getWorkerStatus(api, workerName);
|
|
114
|
-
if (found && tag === TAG) {
|
|
115
|
+
if (found && tag === TAG && !force) {
|
|
115
116
|
cache.set(key, TAG);
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
@@ -88,7 +88,12 @@ export class DOStateStore implements StateStore {
|
|
|
88
88
|
const api = await createCloudflareApi(this.options);
|
|
89
89
|
const [subdomain, _] = await Promise.all([
|
|
90
90
|
getAccountSubdomain(api),
|
|
91
|
-
upsertStateStoreWorker(
|
|
91
|
+
upsertStateStoreWorker(
|
|
92
|
+
api,
|
|
93
|
+
workerName,
|
|
94
|
+
token,
|
|
95
|
+
this.options.worker?.force ?? false,
|
|
96
|
+
),
|
|
92
97
|
]);
|
|
93
98
|
const client = new DOStateStoreClient({
|
|
94
99
|
app: this.scope.appName ?? "alchemy",
|
|
@@ -97,9 +102,26 @@ export class DOStateStore implements StateStore {
|
|
|
97
102
|
token,
|
|
98
103
|
});
|
|
99
104
|
// This ensures the token is correct and the worker is ready to use.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
let last: Response | undefined;
|
|
106
|
+
let delay = 1000;
|
|
107
|
+
for (let i = 0; i < 20; i++) {
|
|
108
|
+
const res = await client.validate();
|
|
109
|
+
if (res.ok) {
|
|
110
|
+
return client;
|
|
111
|
+
}
|
|
112
|
+
if (!last) {
|
|
113
|
+
console.log("Waiting for state store deployment...");
|
|
114
|
+
}
|
|
115
|
+
last = res;
|
|
116
|
+
// Exponential backoff with jitter
|
|
117
|
+
const jitter = Math.random() * 0.1 * delay;
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, delay + jitter));
|
|
119
|
+
delay *= 1.5; // Increase the delay for next attempt
|
|
120
|
+
delay = Math.min(delay, 10000); // Cap at 10 seconds
|
|
121
|
+
}
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Failed to access state store: ${last?.status} ${last?.statusText}`,
|
|
124
|
+
);
|
|
103
125
|
}
|
|
104
126
|
|
|
105
127
|
private async getClient() {
|
|
@@ -220,33 +220,34 @@ const _SecretsStore = Resource("cloudflare::SecretsStore", async function <
|
|
|
220
220
|
|
|
221
221
|
await insertSecrets(api, storeId, props);
|
|
222
222
|
} else {
|
|
223
|
-
|
|
223
|
+
// If adopt is true, first check if a store with this name already exists
|
|
224
|
+
if (props.adopt) {
|
|
225
|
+
console.log(`Checking for existing secrets store '${name}' to adopt`);
|
|
226
|
+
const existingStore = await findSecretsStoreByName(api, name);
|
|
227
|
+
|
|
228
|
+
if (existingStore) {
|
|
229
|
+
console.log(`Found existing secrets store '${name}', adopting it`);
|
|
230
|
+
storeId = existingStore.id;
|
|
231
|
+
createdAt = existingStore.createdAt || Date.now();
|
|
232
|
+
} else {
|
|
233
|
+
console.log(
|
|
234
|
+
`No existing secrets store '${name}' found, creating new one`,
|
|
235
|
+
);
|
|
236
|
+
const { id } = await createSecretsStore(api, {
|
|
237
|
+
...props,
|
|
238
|
+
name,
|
|
239
|
+
});
|
|
240
|
+
createdAt = Date.now();
|
|
241
|
+
storeId = id;
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
// Default behavior: create a new store
|
|
224
245
|
const { id } = await createSecretsStore(api, {
|
|
225
246
|
...props,
|
|
226
247
|
name,
|
|
227
248
|
});
|
|
228
249
|
createdAt = Date.now();
|
|
229
250
|
storeId = id;
|
|
230
|
-
} catch (error) {
|
|
231
|
-
if (
|
|
232
|
-
props.adopt &&
|
|
233
|
-
error instanceof Error &&
|
|
234
|
-
error.message.includes("already exists")
|
|
235
|
-
) {
|
|
236
|
-
console.log(`Secrets store '${name}' already exists, adopting it`);
|
|
237
|
-
const existingStore = await findSecretsStoreByName(api, name);
|
|
238
|
-
|
|
239
|
-
if (!existingStore) {
|
|
240
|
-
throw new Error(
|
|
241
|
-
`Failed to find existing secrets store '${name}' for adoption`,
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
storeId = existingStore.id;
|
|
246
|
-
createdAt = existingStore.createdAt || Date.now();
|
|
247
|
-
} else {
|
|
248
|
-
throw error;
|
|
249
|
-
}
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
await insertSecrets(api, storeId, props);
|
|
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { AsyncQueue } from "../util/async-queue.ts";
|
|
5
5
|
import { getContentType } from "../util/content-type.ts";
|
|
6
|
+
import { CloudflareApiError } from "./api-error.ts";
|
|
6
7
|
import type { CloudflareApi } from "./api.ts";
|
|
7
8
|
import type { Assets } from "./assets.ts";
|
|
8
9
|
import type { AssetsConfig, WorkerProps } from "./worker.ts";
|
|
@@ -84,6 +85,21 @@ export async function uploadAssets(
|
|
|
84
85
|
const sessionData =
|
|
85
86
|
(await uploadSessionResponse.json()) as UploadSessionResponse;
|
|
86
87
|
|
|
88
|
+
if (!sessionData?.success) {
|
|
89
|
+
if (sessionData?.errors) {
|
|
90
|
+
throw new CloudflareApiError(
|
|
91
|
+
`Failed to start assets upload session:\n${sessionData.errors
|
|
92
|
+
.map((error) => `- ${error.code}: ${error.message}`)
|
|
93
|
+
.join("\n")}`,
|
|
94
|
+
uploadSessionResponse,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
throw new CloudflareApiError(
|
|
98
|
+
`Failed to start assets upload session: ${uploadSessionResponse.statusText}`,
|
|
99
|
+
uploadSessionResponse,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
87
103
|
// If there are no buckets, assets are already uploaded or empty
|
|
88
104
|
if (!sessionData.result.buckets || sessionData.result.buckets.length === 0) {
|
|
89
105
|
return {
|
package/src/destroy.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
ResourceSeq,
|
|
11
11
|
} from "./resource.ts";
|
|
12
12
|
import { Scope } from "./scope.ts";
|
|
13
|
-
import { formatFQN } from "./util/cli.
|
|
13
|
+
import { formatFQN } from "./util/cli.ts";
|
|
14
14
|
import { logger } from "./util/logger.ts";
|
|
15
15
|
|
|
16
16
|
export class DestroyedSignal extends Error {}
|
|
@@ -70,7 +70,6 @@ export async function destroy<Type extends string>(
|
|
|
70
70
|
parent: instance[ResourceScope],
|
|
71
71
|
scopeName: instance[ResourceID],
|
|
72
72
|
});
|
|
73
|
-
logger.log("Destroying scope", scope.chain.join("/"));
|
|
74
73
|
return await destroy(scope, options);
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -90,12 +89,11 @@ export async function destroy<Type extends string>(
|
|
|
90
89
|
try {
|
|
91
90
|
if (!quiet) {
|
|
92
91
|
logger.task(instance[ResourceFQN], {
|
|
93
|
-
prefix: "
|
|
94
|
-
prefixColor: "
|
|
92
|
+
prefix: "deleting",
|
|
93
|
+
prefixColor: "redBright",
|
|
95
94
|
resource: formatFQN(instance[ResourceFQN]),
|
|
96
95
|
message: "Deleting Resource...",
|
|
97
96
|
});
|
|
98
|
-
logger.log(`Delete: "${instance[ResourceFQN]}"`);
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
const state = await scope.state.get(instance[ResourceID]);
|
|
@@ -152,13 +150,12 @@ export async function destroy<Type extends string>(
|
|
|
152
150
|
|
|
153
151
|
if (!quiet) {
|
|
154
152
|
logger.task(instance[ResourceFQN], {
|
|
155
|
-
prefix: "
|
|
153
|
+
prefix: "deleted",
|
|
156
154
|
prefixColor: "greenBright",
|
|
157
155
|
resource: formatFQN(instance[ResourceFQN]),
|
|
158
156
|
message: "Deleted Resource",
|
|
159
157
|
status: "success",
|
|
160
158
|
});
|
|
161
|
-
logger.log(`Deleted: "${instance[ResourceFQN]}"`);
|
|
162
159
|
}
|
|
163
160
|
} catch (error) {
|
|
164
161
|
logger.error(error);
|