@hot-updater/cloudflare 1.2.0-rc.0 → 1.2.0-rc.10
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/index.cjs +13 -87
- package/dist/index.d.cts +12 -6
- package/dist/index.d.mts +12 -6
- package/dist/index.mjs +14 -88
- package/dist/init/index.cjs +75 -19
- package/dist/init/index.d.cts +2 -1
- package/dist/init/index.d.mts +2 -1
- package/dist/init/index.mjs +75 -19
- package/dist/worker/index.cjs +39 -0
- package/dist/worker/index.d.cts +3 -2
- package/dist/worker/index.d.mts +3 -2
- package/dist/worker/index.mjs +39 -0
- package/package.json +10 -9
- package/src/d1Rest.ts +21 -5
- package/src/r2S3Storage.ts +18 -141
- package/src/r2Storage.ts +2 -3
- package/src/r2WorkerStorage.ts +56 -3
- package/worker/dist/README.md +1 -1
- package/worker/dist/index.js +43 -1
- package/worker/dist/index.js.map +3 -3
package/dist/index.cjs
CHANGED
|
@@ -24,9 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
25
25
|
let cloudflare = require("cloudflare");
|
|
26
26
|
cloudflare = __toESM(cloudflare, 1);
|
|
27
|
-
let
|
|
28
|
-
let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
|
|
29
|
-
let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
|
|
27
|
+
let _hot_updater_storage_s3 = require("@hot-updater/storage-s3");
|
|
30
28
|
//#region src/d1Executor.ts
|
|
31
29
|
var D1ExecutionError = class extends Error {
|
|
32
30
|
name = "D1ExecutionError";
|
|
@@ -86,7 +84,12 @@ const encode = ({ sql, params }) => ({
|
|
|
86
84
|
* time, or a batch D1 runs in one transaction.
|
|
87
85
|
*/
|
|
88
86
|
const d1RestRunner = (config) => {
|
|
89
|
-
const
|
|
87
|
+
const { cloudflareApiToken } = config;
|
|
88
|
+
let client;
|
|
89
|
+
const connect = () => client ??= (async () => new cloudflare.default({ apiToken: typeof cloudflareApiToken === "function" ? await cloudflareApiToken() : cloudflareApiToken }))().catch((error) => {
|
|
90
|
+
client = void 0;
|
|
91
|
+
throw error;
|
|
92
|
+
});
|
|
90
93
|
const batch = async (statements) => {
|
|
91
94
|
const [first] = statements;
|
|
92
95
|
if (first === void 0) return [];
|
|
@@ -97,7 +100,7 @@ const d1RestRunner = (config) => {
|
|
|
97
100
|
account_id: config.accountId,
|
|
98
101
|
batch: statements.map(encode)
|
|
99
102
|
};
|
|
100
|
-
const page = await
|
|
103
|
+
const page = await (await connect()).d1.database.query(config.databaseId, body);
|
|
101
104
|
const results = [];
|
|
102
105
|
for await (const resultPage of page.iterPages()) for (const result of resultPage.result) results.push(toSqlResult(result));
|
|
103
106
|
if (results.length !== statements.length) throw new D1ExecutionError();
|
|
@@ -152,94 +155,17 @@ const d1Database = (config) => ({
|
|
|
152
155
|
});
|
|
153
156
|
//#endregion
|
|
154
157
|
//#region src/r2S3Storage.ts
|
|
155
|
-
/** Devices download right after the update check that returns the URL. */
|
|
156
|
-
const PRESIGNED_URL_EXPIRES_IN_SECONDS = 3600;
|
|
157
|
-
const isObjectNotFoundError = (error) => {
|
|
158
|
-
if (error instanceof Error && (error.name === "NotFound" || error.name === "NoSuchKey")) return true;
|
|
159
|
-
return typeof error === "object" && error !== null && "$metadata" in error && error.$metadata?.httpStatusCode === 404;
|
|
160
|
-
};
|
|
161
158
|
const createR2S3Storage = (config) => {
|
|
162
|
-
const { accountId,
|
|
163
|
-
|
|
159
|
+
const { accountId, endpoint, forcePathStyle, region, ...s3Config } = config;
|
|
160
|
+
return (0, _hot_updater_storage_s3.createS3Storage)({
|
|
161
|
+
name: "r2Storage",
|
|
162
|
+
protocol: "r2"
|
|
163
|
+
}, {
|
|
164
164
|
...s3Config,
|
|
165
165
|
endpoint: endpoint ?? `https://${accountId}.r2.cloudflarestorage.com`,
|
|
166
166
|
forcePathStyle: forcePathStyle ?? true,
|
|
167
167
|
region: region ?? "auto"
|
|
168
168
|
});
|
|
169
|
-
const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(basePath);
|
|
170
|
-
const parseAndValidate = (storageUri) => {
|
|
171
|
-
const parsed = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
|
|
172
|
-
if (parsed.bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${parsed.bucket}".`);
|
|
173
|
-
return parsed;
|
|
174
|
-
};
|
|
175
|
-
return (0, _hot_updater_plugin_core.createStorageAdapter)({
|
|
176
|
-
name: "r2Storage",
|
|
177
|
-
protocol: "r2",
|
|
178
|
-
async put({ key, body, contentLength, contentType }) {
|
|
179
|
-
const storageKey = getStorageKey(key);
|
|
180
|
-
await new _aws_sdk_lib_storage.Upload({
|
|
181
|
-
client,
|
|
182
|
-
params: {
|
|
183
|
-
Body: body,
|
|
184
|
-
Bucket: bucketName,
|
|
185
|
-
CacheControl: "max-age=31536000",
|
|
186
|
-
ContentLength: contentLength,
|
|
187
|
-
ContentType: contentType,
|
|
188
|
-
Key: storageKey
|
|
189
|
-
}
|
|
190
|
-
}).done();
|
|
191
|
-
return { storageUri: (0, _hot_updater_plugin_core.createStorageUri)({
|
|
192
|
-
protocol: "r2",
|
|
193
|
-
bucket: bucketName,
|
|
194
|
-
key: storageKey
|
|
195
|
-
}) };
|
|
196
|
-
},
|
|
197
|
-
async get({ storageUri }) {
|
|
198
|
-
const { key } = parseAndValidate(storageUri);
|
|
199
|
-
try {
|
|
200
|
-
const response = await client.send(new _aws_sdk_client_s3.GetObjectCommand({
|
|
201
|
-
Bucket: bucketName,
|
|
202
|
-
Key: key
|
|
203
|
-
}));
|
|
204
|
-
if (!response.Body) return { response: null };
|
|
205
|
-
const headers = new Headers();
|
|
206
|
-
if (response.ContentType) headers.set("content-type", response.ContentType);
|
|
207
|
-
if (response.ContentLength !== void 0) headers.set("content-length", String(response.ContentLength));
|
|
208
|
-
return { response: new Response(response.Body.transformToWebStream(), { headers }) };
|
|
209
|
-
} catch (error) {
|
|
210
|
-
if (isObjectNotFoundError(error)) return { response: null };
|
|
211
|
-
throw error;
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
async getDownloadUrl({ storageUri }) {
|
|
215
|
-
const { key } = parseAndValidate(storageUri);
|
|
216
|
-
return { url: await (0, _aws_sdk_s3_request_presigner.getSignedUrl)(client, new _aws_sdk_client_s3.GetObjectCommand({
|
|
217
|
-
Bucket: bucketName,
|
|
218
|
-
Key: key
|
|
219
|
-
}), { expiresIn: PRESIGNED_URL_EXPIRES_IN_SECONDS }) };
|
|
220
|
-
},
|
|
221
|
-
async exists({ storageUri }) {
|
|
222
|
-
const { key } = parseAndValidate(storageUri);
|
|
223
|
-
try {
|
|
224
|
-
await client.send(new _aws_sdk_client_s3.HeadObjectCommand({
|
|
225
|
-
Bucket: bucketName,
|
|
226
|
-
Key: key
|
|
227
|
-
}));
|
|
228
|
-
return { exists: true };
|
|
229
|
-
} catch (error) {
|
|
230
|
-
if (isObjectNotFoundError(error)) return { exists: false };
|
|
231
|
-
throw error;
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
async delete({ storageUri }) {
|
|
235
|
-
const { key } = parseAndValidate(storageUri);
|
|
236
|
-
await client.send(new _aws_sdk_client_s3.DeleteObjectCommand({
|
|
237
|
-
Bucket: bucketName,
|
|
238
|
-
Key: key
|
|
239
|
-
}));
|
|
240
|
-
return { deleted: true };
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
169
|
};
|
|
244
170
|
//#endregion
|
|
245
171
|
//#region src/r2Storage.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { StorageAdapterWith, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
|
-
import { S3ClientConfig } from "@
|
|
1
|
+
import { Lazy, StorageAdapterWith, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
|
+
import { S3ClientConfig, S3CredentialsOption, S3StorageOperations } from "@hot-updater/storage-s3";
|
|
3
3
|
//#region src/d1Rest.d.ts
|
|
4
4
|
interface D1RestConfig {
|
|
5
5
|
readonly databaseId: string;
|
|
6
6
|
readonly accountId: string;
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* An API token with D1 edit permission, or a function that returns it,
|
|
9
|
+
* such as `secret("<name>")` in `hot-updater.config.ts`: called on the
|
|
10
|
+
* first query, so a config loads without the token.
|
|
11
|
+
*/
|
|
12
|
+
readonly cloudflareApiToken: Lazy<string>;
|
|
8
13
|
}
|
|
9
14
|
//#endregion
|
|
10
15
|
//#region src/d1Executor.d.ts
|
|
@@ -26,16 +31,17 @@ type D1DatabaseConfig = D1RestConfig;
|
|
|
26
31
|
declare const d1Database: (config: D1DatabaseConfig) => ToolingDatabase;
|
|
27
32
|
//#endregion
|
|
28
33
|
//#region src/r2S3Storage.d.ts
|
|
29
|
-
interface R2S3StorageConfig extends S3ClientConfig {
|
|
34
|
+
interface R2S3StorageConfig extends Omit<S3ClientConfig, "credentials"> {
|
|
30
35
|
accountId: string;
|
|
31
36
|
bucketName: string;
|
|
32
|
-
credentials
|
|
37
|
+
/** The SDK's credentials, or an R2 access key whose fields are lazy. */
|
|
38
|
+
credentials: NonNullable<S3CredentialsOption>;
|
|
33
39
|
/** Base path where bundles will be stored in the bucket. */
|
|
34
40
|
basePath?: string;
|
|
35
41
|
}
|
|
36
42
|
//#endregion
|
|
37
43
|
//#region src/r2Storage.d.ts
|
|
38
44
|
type R2StorageConfig = R2S3StorageConfig;
|
|
39
|
-
declare const r2Storage: (config: R2S3StorageConfig) => StorageAdapterWith<
|
|
45
|
+
declare const r2Storage: (config: R2S3StorageConfig) => StorageAdapterWith<S3StorageOperations>;
|
|
40
46
|
//#endregion
|
|
41
47
|
export { D1DatabaseConfig, D1ExecutionError, type R2S3StorageConfig, R2StorageConfig, d1Database, r2Storage };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { StorageAdapterWith, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
|
-
import { S3ClientConfig } from "@
|
|
1
|
+
import { Lazy, StorageAdapterWith, ToolingDatabase } from "@hot-updater/plugin-core";
|
|
2
|
+
import { S3ClientConfig, S3CredentialsOption, S3StorageOperations } from "@hot-updater/storage-s3";
|
|
3
3
|
//#region src/d1Rest.d.ts
|
|
4
4
|
interface D1RestConfig {
|
|
5
5
|
readonly databaseId: string;
|
|
6
6
|
readonly accountId: string;
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* An API token with D1 edit permission, or a function that returns it,
|
|
9
|
+
* such as `secret("<name>")` in `hot-updater.config.ts`: called on the
|
|
10
|
+
* first query, so a config loads without the token.
|
|
11
|
+
*/
|
|
12
|
+
readonly cloudflareApiToken: Lazy<string>;
|
|
8
13
|
}
|
|
9
14
|
//#endregion
|
|
10
15
|
//#region src/d1Executor.d.ts
|
|
@@ -26,16 +31,17 @@ type D1DatabaseConfig = D1RestConfig;
|
|
|
26
31
|
declare const d1Database: (config: D1DatabaseConfig) => ToolingDatabase;
|
|
27
32
|
//#endregion
|
|
28
33
|
//#region src/r2S3Storage.d.ts
|
|
29
|
-
interface R2S3StorageConfig extends S3ClientConfig {
|
|
34
|
+
interface R2S3StorageConfig extends Omit<S3ClientConfig, "credentials"> {
|
|
30
35
|
accountId: string;
|
|
31
36
|
bucketName: string;
|
|
32
|
-
credentials
|
|
37
|
+
/** The SDK's credentials, or an R2 access key whose fields are lazy. */
|
|
38
|
+
credentials: NonNullable<S3CredentialsOption>;
|
|
33
39
|
/** Base path where bundles will be stored in the bucket. */
|
|
34
40
|
basePath?: string;
|
|
35
41
|
}
|
|
36
42
|
//#endregion
|
|
37
43
|
//#region src/r2Storage.d.ts
|
|
38
44
|
type R2StorageConfig = R2S3StorageConfig;
|
|
39
|
-
declare const r2Storage: (config: R2S3StorageConfig) => StorageAdapterWith<
|
|
45
|
+
declare const r2Storage: (config: R2S3StorageConfig) => StorageAdapterWith<S3StorageOperations>;
|
|
40
46
|
//#endregion
|
|
41
47
|
export { D1DatabaseConfig, D1ExecutionError, type R2S3StorageConfig, R2StorageConfig, d1Database, r2Storage };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { WRITE_GUARD_TABLE, coreSettings, coreTarget, createEngineDatabase, createSqlAdapter,
|
|
1
|
+
import { WRITE_GUARD_TABLE, coreSettings, coreTarget, createEngineDatabase, createSqlAdapter, createTableStatements, generateEngineSql } from "@hot-updater/plugin-core";
|
|
2
2
|
import Cloudflare from "cloudflare";
|
|
3
|
-
import {
|
|
4
|
-
import { Upload } from "@aws-sdk/lib-storage";
|
|
5
|
-
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
3
|
+
import { createS3Storage } from "@hot-updater/storage-s3";
|
|
6
4
|
//#region src/d1Executor.ts
|
|
7
5
|
var D1ExecutionError = class extends Error {
|
|
8
6
|
name = "D1ExecutionError";
|
|
@@ -62,7 +60,12 @@ const encode = ({ sql, params }) => ({
|
|
|
62
60
|
* time, or a batch D1 runs in one transaction.
|
|
63
61
|
*/
|
|
64
62
|
const d1RestRunner = (config) => {
|
|
65
|
-
const
|
|
63
|
+
const { cloudflareApiToken } = config;
|
|
64
|
+
let client;
|
|
65
|
+
const connect = () => client ??= (async () => new Cloudflare({ apiToken: typeof cloudflareApiToken === "function" ? await cloudflareApiToken() : cloudflareApiToken }))().catch((error) => {
|
|
66
|
+
client = void 0;
|
|
67
|
+
throw error;
|
|
68
|
+
});
|
|
66
69
|
const batch = async (statements) => {
|
|
67
70
|
const [first] = statements;
|
|
68
71
|
if (first === void 0) return [];
|
|
@@ -73,7 +76,7 @@ const d1RestRunner = (config) => {
|
|
|
73
76
|
account_id: config.accountId,
|
|
74
77
|
batch: statements.map(encode)
|
|
75
78
|
};
|
|
76
|
-
const page = await
|
|
79
|
+
const page = await (await connect()).d1.database.query(config.databaseId, body);
|
|
77
80
|
const results = [];
|
|
78
81
|
for await (const resultPage of page.iterPages()) for (const result of resultPage.result) results.push(toSqlResult(result));
|
|
79
82
|
if (results.length !== statements.length) throw new D1ExecutionError();
|
|
@@ -128,94 +131,17 @@ const d1Database = (config) => ({
|
|
|
128
131
|
});
|
|
129
132
|
//#endregion
|
|
130
133
|
//#region src/r2S3Storage.ts
|
|
131
|
-
/** Devices download right after the update check that returns the URL. */
|
|
132
|
-
const PRESIGNED_URL_EXPIRES_IN_SECONDS = 3600;
|
|
133
|
-
const isObjectNotFoundError = (error) => {
|
|
134
|
-
if (error instanceof Error && (error.name === "NotFound" || error.name === "NoSuchKey")) return true;
|
|
135
|
-
return typeof error === "object" && error !== null && "$metadata" in error && error.$metadata?.httpStatusCode === 404;
|
|
136
|
-
};
|
|
137
134
|
const createR2S3Storage = (config) => {
|
|
138
|
-
const { accountId,
|
|
139
|
-
|
|
135
|
+
const { accountId, endpoint, forcePathStyle, region, ...s3Config } = config;
|
|
136
|
+
return createS3Storage({
|
|
137
|
+
name: "r2Storage",
|
|
138
|
+
protocol: "r2"
|
|
139
|
+
}, {
|
|
140
140
|
...s3Config,
|
|
141
141
|
endpoint: endpoint ?? `https://${accountId}.r2.cloudflarestorage.com`,
|
|
142
142
|
forcePathStyle: forcePathStyle ?? true,
|
|
143
143
|
region: region ?? "auto"
|
|
144
144
|
});
|
|
145
|
-
const getStorageKey = createStorageKeyBuilder(basePath);
|
|
146
|
-
const parseAndValidate = (storageUri) => {
|
|
147
|
-
const parsed = parseStorageUri(storageUri, "r2");
|
|
148
|
-
if (parsed.bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${parsed.bucket}".`);
|
|
149
|
-
return parsed;
|
|
150
|
-
};
|
|
151
|
-
return createStorageAdapter({
|
|
152
|
-
name: "r2Storage",
|
|
153
|
-
protocol: "r2",
|
|
154
|
-
async put({ key, body, contentLength, contentType }) {
|
|
155
|
-
const storageKey = getStorageKey(key);
|
|
156
|
-
await new Upload({
|
|
157
|
-
client,
|
|
158
|
-
params: {
|
|
159
|
-
Body: body,
|
|
160
|
-
Bucket: bucketName,
|
|
161
|
-
CacheControl: "max-age=31536000",
|
|
162
|
-
ContentLength: contentLength,
|
|
163
|
-
ContentType: contentType,
|
|
164
|
-
Key: storageKey
|
|
165
|
-
}
|
|
166
|
-
}).done();
|
|
167
|
-
return { storageUri: createStorageUri({
|
|
168
|
-
protocol: "r2",
|
|
169
|
-
bucket: bucketName,
|
|
170
|
-
key: storageKey
|
|
171
|
-
}) };
|
|
172
|
-
},
|
|
173
|
-
async get({ storageUri }) {
|
|
174
|
-
const { key } = parseAndValidate(storageUri);
|
|
175
|
-
try {
|
|
176
|
-
const response = await client.send(new GetObjectCommand({
|
|
177
|
-
Bucket: bucketName,
|
|
178
|
-
Key: key
|
|
179
|
-
}));
|
|
180
|
-
if (!response.Body) return { response: null };
|
|
181
|
-
const headers = new Headers();
|
|
182
|
-
if (response.ContentType) headers.set("content-type", response.ContentType);
|
|
183
|
-
if (response.ContentLength !== void 0) headers.set("content-length", String(response.ContentLength));
|
|
184
|
-
return { response: new Response(response.Body.transformToWebStream(), { headers }) };
|
|
185
|
-
} catch (error) {
|
|
186
|
-
if (isObjectNotFoundError(error)) return { response: null };
|
|
187
|
-
throw error;
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
async getDownloadUrl({ storageUri }) {
|
|
191
|
-
const { key } = parseAndValidate(storageUri);
|
|
192
|
-
return { url: await getSignedUrl(client, new GetObjectCommand({
|
|
193
|
-
Bucket: bucketName,
|
|
194
|
-
Key: key
|
|
195
|
-
}), { expiresIn: PRESIGNED_URL_EXPIRES_IN_SECONDS }) };
|
|
196
|
-
},
|
|
197
|
-
async exists({ storageUri }) {
|
|
198
|
-
const { key } = parseAndValidate(storageUri);
|
|
199
|
-
try {
|
|
200
|
-
await client.send(new HeadObjectCommand({
|
|
201
|
-
Bucket: bucketName,
|
|
202
|
-
Key: key
|
|
203
|
-
}));
|
|
204
|
-
return { exists: true };
|
|
205
|
-
} catch (error) {
|
|
206
|
-
if (isObjectNotFoundError(error)) return { exists: false };
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
async delete({ storageUri }) {
|
|
211
|
-
const { key } = parseAndValidate(storageUri);
|
|
212
|
-
await client.send(new DeleteObjectCommand({
|
|
213
|
-
Bucket: bucketName,
|
|
214
|
-
Key: key
|
|
215
|
-
}));
|
|
216
|
-
return { deleted: true };
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
145
|
};
|
|
220
146
|
//#endregion
|
|
221
147
|
//#region src/r2Storage.ts
|
package/dist/init/index.cjs
CHANGED
|
@@ -113,7 +113,12 @@ const encode = ({ sql, params }) => ({
|
|
|
113
113
|
* time, or a batch D1 runs in one transaction.
|
|
114
114
|
*/
|
|
115
115
|
const d1RestRunner = (config) => {
|
|
116
|
-
const
|
|
116
|
+
const { cloudflareApiToken } = config;
|
|
117
|
+
let client;
|
|
118
|
+
const connect = () => client ??= (async () => new cloudflare.default({ apiToken: typeof cloudflareApiToken === "function" ? await cloudflareApiToken() : cloudflareApiToken }))().catch((error) => {
|
|
119
|
+
client = void 0;
|
|
120
|
+
throw error;
|
|
121
|
+
});
|
|
117
122
|
const batch = async (statements) => {
|
|
118
123
|
const [first] = statements;
|
|
119
124
|
if (first === void 0) return [];
|
|
@@ -124,7 +129,7 @@ const d1RestRunner = (config) => {
|
|
|
124
129
|
account_id: config.accountId,
|
|
125
130
|
batch: statements.map(encode)
|
|
126
131
|
};
|
|
127
|
-
const page = await
|
|
132
|
+
const page = await (await connect()).d1.database.query(config.databaseId, body);
|
|
128
133
|
const results = [];
|
|
129
134
|
for await (const resultPage of page.iterPages()) for (const result of resultPage.result) results.push(toSqlResult(result));
|
|
130
135
|
if (results.length !== statements.length) throw new D1ExecutionError();
|
|
@@ -11320,7 +11325,12 @@ const initProvider = {
|
|
|
11320
11325
|
},
|
|
11321
11326
|
validate: (value) => value === "true" || value === "false"
|
|
11322
11327
|
}
|
|
11323
|
-
}
|
|
11328
|
+
},
|
|
11329
|
+
secrets: [
|
|
11330
|
+
"HOT_UPDATER_CLOUDFLARE_API_TOKEN",
|
|
11331
|
+
"HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID",
|
|
11332
|
+
"HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"
|
|
11333
|
+
]
|
|
11324
11334
|
};
|
|
11325
11335
|
//#endregion
|
|
11326
11336
|
//#region iac/cloudflareInitInputs.ts
|
|
@@ -11408,8 +11418,27 @@ const inputCloudflareInitSecrets = async ({ accountId, bucketName, apiToken, acc
|
|
|
11408
11418
|
};
|
|
11409
11419
|
//#endregion
|
|
11410
11420
|
//#region iac/configTemplate.ts
|
|
11411
|
-
|
|
11412
|
-
|
|
11421
|
+
/**
|
|
11422
|
+
* The config init writes. With the `resources` init set up, it names them,
|
|
11423
|
+
* and reads the API token and R2 keys with `secret()`, from the
|
|
11424
|
+
* environment and `.env.hotupdater`, then the config's `secrets` adapter.
|
|
11425
|
+
* Without them, as the agent scaffold writes it before the agent creates the
|
|
11426
|
+
* resources, it reads their IDs from the environment, where the agent
|
|
11427
|
+
* records them, and the credentials with `secret()` alike.
|
|
11428
|
+
*/
|
|
11429
|
+
const getConfigScaffold = (build, resources) => {
|
|
11430
|
+
const builder = new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setPlugins({
|
|
11431
|
+
imports: [{
|
|
11432
|
+
pkg: "hot-updater/plugins",
|
|
11433
|
+
named: [
|
|
11434
|
+
"apiKeys",
|
|
11435
|
+
"insights",
|
|
11436
|
+
"remoteConfig"
|
|
11437
|
+
]
|
|
11438
|
+
}],
|
|
11439
|
+
configString: "[apiKeys(), insights(), remoteConfig()]"
|
|
11440
|
+
});
|
|
11441
|
+
if (resources === void 0) return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(builder.setStorage({
|
|
11413
11442
|
imports: [{
|
|
11414
11443
|
pkg: "@hot-updater/cloudflare",
|
|
11415
11444
|
named: ["r2Storage"]
|
|
@@ -11418,8 +11447,8 @@ const getConfigScaffold = (build) => {
|
|
|
11418
11447
|
bucketName: process.env.HOT_UPDATER_CLOUDFLARE_R2_BUCKET_NAME!,
|
|
11419
11448
|
accountId: process.env.HOT_UPDATER_CLOUDFLARE_ACCOUNT_ID!,
|
|
11420
11449
|
credentials: {
|
|
11421
|
-
accessKeyId:
|
|
11422
|
-
secretAccessKey:
|
|
11450
|
+
accessKeyId: secret("HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID"),
|
|
11451
|
+
secretAccessKey: secret("HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"),
|
|
11423
11452
|
},
|
|
11424
11453
|
})`
|
|
11425
11454
|
}).setDatabase({
|
|
@@ -11430,18 +11459,41 @@ const getConfigScaffold = (build) => {
|
|
|
11430
11459
|
configString: `d1Database({
|
|
11431
11460
|
databaseId: process.env.HOT_UPDATER_CLOUDFLARE_D1_DATABASE_ID!,
|
|
11432
11461
|
accountId: process.env.HOT_UPDATER_CLOUDFLARE_ACCOUNT_ID!,
|
|
11433
|
-
cloudflareApiToken:
|
|
11462
|
+
cloudflareApiToken: secret("HOT_UPDATER_CLOUDFLARE_API_TOKEN"),
|
|
11434
11463
|
})`
|
|
11435
|
-
}).
|
|
11464
|
+
}).addImport({
|
|
11465
|
+
pkg: "hot-updater",
|
|
11466
|
+
named: ["secret"]
|
|
11467
|
+
}));
|
|
11468
|
+
const accountId = JSON.stringify(resources.accountId);
|
|
11469
|
+
const storageConfig = {
|
|
11436
11470
|
imports: [{
|
|
11437
|
-
pkg: "hot-updater/
|
|
11438
|
-
named: [
|
|
11439
|
-
"apiKeys",
|
|
11440
|
-
"insights",
|
|
11441
|
-
"remoteConfig"
|
|
11442
|
-
]
|
|
11471
|
+
pkg: "@hot-updater/cloudflare",
|
|
11472
|
+
named: ["r2Storage"]
|
|
11443
11473
|
}],
|
|
11444
|
-
configString:
|
|
11474
|
+
configString: `r2Storage({
|
|
11475
|
+
bucketName: ${JSON.stringify(resources.bucketName)},
|
|
11476
|
+
accountId: ${accountId},
|
|
11477
|
+
credentials: {
|
|
11478
|
+
accessKeyId: secret("HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID"),
|
|
11479
|
+
secretAccessKey: secret("HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"),
|
|
11480
|
+
},
|
|
11481
|
+
})`
|
|
11482
|
+
};
|
|
11483
|
+
const databaseConfig = {
|
|
11484
|
+
imports: [{
|
|
11485
|
+
pkg: "@hot-updater/cloudflare",
|
|
11486
|
+
named: ["d1Database"]
|
|
11487
|
+
}],
|
|
11488
|
+
configString: `d1Database({
|
|
11489
|
+
databaseId: ${JSON.stringify(resources.d1DatabaseId)},
|
|
11490
|
+
accountId: ${accountId},
|
|
11491
|
+
cloudflareApiToken: secret("HOT_UPDATER_CLOUDFLARE_API_TOKEN"),
|
|
11492
|
+
})`
|
|
11493
|
+
};
|
|
11494
|
+
return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(builder.setStorage(storageConfig).setDatabase(databaseConfig).addImport({
|
|
11495
|
+
pkg: "hot-updater",
|
|
11496
|
+
named: ["secret"]
|
|
11445
11497
|
}));
|
|
11446
11498
|
};
|
|
11447
11499
|
//#endregion
|
|
@@ -11514,10 +11566,10 @@ const deployWorker = async (apiToken, accountId, { credentialSource, d1DatabaseI
|
|
|
11514
11566
|
await removeTmpDir();
|
|
11515
11567
|
}
|
|
11516
11568
|
};
|
|
11517
|
-
const runInit = async ({ build, envFile }) => {
|
|
11569
|
+
const runInit = async ({ build, envFile, secretsEnv }) => {
|
|
11518
11570
|
const cwd = (0, _hot_updater_cli_tools.getCwd)();
|
|
11519
11571
|
const nonInteractive = envFile !== void 0;
|
|
11520
|
-
const initEnvSources = await (0, _hot_updater_cli_tools.readHotUpdaterInitEnv)(cwd, envFile);
|
|
11572
|
+
const initEnvSources = await (0, _hot_updater_cli_tools.readHotUpdaterInitEnv)(cwd, envFile, secretsEnv);
|
|
11521
11573
|
const { managedEnv } = initEnvSources;
|
|
11522
11574
|
const initInputEnv = (0, _hot_updater_cli_tools.getHotUpdaterInitInputEnv)(initEnvSources, nonInteractive);
|
|
11523
11575
|
const existingInputs = resolveCloudflareInitInputs(initInputEnv);
|
|
@@ -11867,7 +11919,11 @@ const runInit = async ({ build, envFile }) => {
|
|
|
11867
11919
|
await database.dispose?.();
|
|
11868
11920
|
}
|
|
11869
11921
|
_hot_updater_cli_tools.p.log.success("Generated '.env.hotupdater' file with Cloudflare settings.");
|
|
11870
|
-
await (0, _hot_updater_cli_tools.writeHotUpdaterFiles)(getConfigScaffold(build
|
|
11922
|
+
await (0, _hot_updater_cli_tools.writeHotUpdaterFiles)(getConfigScaffold(build, {
|
|
11923
|
+
accountId,
|
|
11924
|
+
bucketName: selectedBucketName,
|
|
11925
|
+
d1DatabaseId: selectedD1DatabaseId
|
|
11926
|
+
}), {
|
|
11871
11927
|
cwd,
|
|
11872
11928
|
settings: "Cloudflare"
|
|
11873
11929
|
});
|
package/dist/init/index.d.cts
CHANGED
|
@@ -82,9 +82,10 @@ declare const initProvider: {
|
|
|
82
82
|
readonly validate: (value: string | undefined) => value is "true" | "false";
|
|
83
83
|
};
|
|
84
84
|
};
|
|
85
|
+
readonly secrets: readonly ["HOT_UPDATER_CLOUDFLARE_API_TOKEN", "HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID", "HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"];
|
|
85
86
|
};
|
|
86
87
|
//#endregion
|
|
87
88
|
//#region iac/index.d.ts
|
|
88
|
-
declare const runInit: ({ build, envFile }: RunInitOptions) => Promise<void>;
|
|
89
|
+
declare const runInit: ({ build, envFile, secretsEnv }: RunInitOptions) => Promise<void>;
|
|
89
90
|
//#endregion
|
|
90
91
|
export { initProvider, runInit };
|
package/dist/init/index.d.mts
CHANGED
|
@@ -82,9 +82,10 @@ declare const initProvider: {
|
|
|
82
82
|
readonly validate: (value: string | undefined) => value is "true" | "false";
|
|
83
83
|
};
|
|
84
84
|
};
|
|
85
|
+
readonly secrets: readonly ["HOT_UPDATER_CLOUDFLARE_API_TOKEN", "HOT_UPDATER_CLOUDFLARE_R2_ACCESS_KEY_ID", "HOT_UPDATER_CLOUDFLARE_R2_SECRET_ACCESS_KEY"];
|
|
85
86
|
};
|
|
86
87
|
//#endregion
|
|
87
88
|
//#region iac/index.d.ts
|
|
88
|
-
declare const runInit: ({ build, envFile }: RunInitOptions) => Promise<void>;
|
|
89
|
+
declare const runInit: ({ build, envFile, secretsEnv }: RunInitOptions) => Promise<void>;
|
|
89
90
|
//#endregion
|
|
90
91
|
export { initProvider, runInit };
|