@authrim/setup 0.1.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.
Files changed (78) hide show
  1. package/README.md +303 -0
  2. package/dist/__tests__/config.test.d.ts +5 -0
  3. package/dist/__tests__/config.test.d.ts.map +1 -0
  4. package/dist/__tests__/config.test.js +115 -0
  5. package/dist/__tests__/config.test.js.map +1 -0
  6. package/dist/__tests__/keys.test.d.ts +5 -0
  7. package/dist/__tests__/keys.test.d.ts.map +1 -0
  8. package/dist/__tests__/keys.test.js +87 -0
  9. package/dist/__tests__/keys.test.js.map +1 -0
  10. package/dist/__tests__/naming.test.d.ts +5 -0
  11. package/dist/__tests__/naming.test.d.ts.map +1 -0
  12. package/dist/__tests__/naming.test.js +84 -0
  13. package/dist/__tests__/naming.test.js.map +1 -0
  14. package/dist/cli/commands/config.d.ts +13 -0
  15. package/dist/cli/commands/config.d.ts.map +1 -0
  16. package/dist/cli/commands/config.js +231 -0
  17. package/dist/cli/commands/config.js.map +1 -0
  18. package/dist/cli/commands/deploy.d.ts +21 -0
  19. package/dist/cli/commands/deploy.d.ts.map +1 -0
  20. package/dist/cli/commands/deploy.js +304 -0
  21. package/dist/cli/commands/deploy.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts +14 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -0
  24. package/dist/cli/commands/init.js +1248 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/core/admin.d.ts +64 -0
  27. package/dist/core/admin.d.ts.map +1 -0
  28. package/dist/core/admin.js +247 -0
  29. package/dist/core/admin.js.map +1 -0
  30. package/dist/core/cloudflare.d.ts +157 -0
  31. package/dist/core/cloudflare.d.ts.map +1 -0
  32. package/dist/core/cloudflare.js +452 -0
  33. package/dist/core/cloudflare.js.map +1 -0
  34. package/dist/core/config.d.ts +891 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +208 -0
  37. package/dist/core/config.js.map +1 -0
  38. package/dist/core/deploy.d.ts +81 -0
  39. package/dist/core/deploy.d.ts.map +1 -0
  40. package/dist/core/deploy.js +389 -0
  41. package/dist/core/deploy.js.map +1 -0
  42. package/dist/core/keys.d.ts +111 -0
  43. package/dist/core/keys.d.ts.map +1 -0
  44. package/dist/core/keys.js +287 -0
  45. package/dist/core/keys.js.map +1 -0
  46. package/dist/core/lock.d.ts +220 -0
  47. package/dist/core/lock.d.ts.map +1 -0
  48. package/dist/core/lock.js +230 -0
  49. package/dist/core/lock.js.map +1 -0
  50. package/dist/core/naming.d.ts +151 -0
  51. package/dist/core/naming.d.ts.map +1 -0
  52. package/dist/core/naming.js +209 -0
  53. package/dist/core/naming.js.map +1 -0
  54. package/dist/core/source.d.ts +68 -0
  55. package/dist/core/source.d.ts.map +1 -0
  56. package/dist/core/source.js +285 -0
  57. package/dist/core/source.js.map +1 -0
  58. package/dist/core/wrangler.d.ts +87 -0
  59. package/dist/core/wrangler.d.ts.map +1 -0
  60. package/dist/core/wrangler.js +398 -0
  61. package/dist/core/wrangler.js.map +1 -0
  62. package/dist/index.d.ts +11 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +117 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/web/api.d.ts +21 -0
  67. package/dist/web/api.d.ts.map +1 -0
  68. package/dist/web/api.js +423 -0
  69. package/dist/web/api.js.map +1 -0
  70. package/dist/web/server.d.ts +12 -0
  71. package/dist/web/server.d.ts.map +1 -0
  72. package/dist/web/server.js +112 -0
  73. package/dist/web/server.js.map +1 -0
  74. package/dist/web/ui.d.ts +7 -0
  75. package/dist/web/ui.d.ts.map +1 -0
  76. package/dist/web/ui.js +765 -0
  77. package/dist/web/ui.js.map +1 -0
  78. package/package.json +61 -0
@@ -0,0 +1,452 @@
1
+ /**
2
+ * Cloudflare API Integration Module
3
+ *
4
+ * Provides programmatic access to Cloudflare resources via wrangler CLI.
5
+ * Used for provisioning D1 databases, KV namespaces, and other resources.
6
+ */
7
+ import { execa } from 'execa';
8
+ import { getD1DatabaseName, getKVNamespaceName, getQueueName, D1_DATABASES, KV_NAMESPACES, } from './naming.js';
9
+ // =============================================================================
10
+ // Wrangler Wrapper
11
+ // =============================================================================
12
+ /**
13
+ * Execute a wrangler command
14
+ */
15
+ async function wrangler(args, options = {}) {
16
+ try {
17
+ const result = await execa('wrangler', args, {
18
+ cwd: options.cwd,
19
+ env: { ...process.env, ...options.env },
20
+ reject: false,
21
+ });
22
+ return {
23
+ stdout: result.stdout,
24
+ stderr: result.stderr,
25
+ };
26
+ }
27
+ catch (error) {
28
+ const execaError = error;
29
+ throw new Error(`Wrangler command failed: ${execaError.message}`);
30
+ }
31
+ }
32
+ /**
33
+ * Check if wrangler is installed
34
+ */
35
+ export async function isWranglerInstalled() {
36
+ try {
37
+ await execa('wrangler', ['--version']);
38
+ return true;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * Check if user is authenticated with Cloudflare
46
+ */
47
+ export async function checkAuth() {
48
+ try {
49
+ const { stdout } = await wrangler(['whoami']);
50
+ // Parse output to extract account info
51
+ const emailMatch = stdout.match(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/);
52
+ const accountMatch = stdout.match(/account ID[:\s]+([a-f0-9]{32})/i);
53
+ return {
54
+ isLoggedIn: !stdout.includes('not logged in'),
55
+ email: emailMatch?.[1],
56
+ accountId: accountMatch?.[1],
57
+ };
58
+ }
59
+ catch {
60
+ return { isLoggedIn: false };
61
+ }
62
+ }
63
+ /**
64
+ * Get account ID from wrangler
65
+ */
66
+ export async function getAccountId() {
67
+ const auth = await checkAuth();
68
+ if (auth.accountId)
69
+ return auth.accountId;
70
+ // Try to get from wrangler.toml or env
71
+ try {
72
+ const { stdout } = await wrangler(['whoami', '--verbose']);
73
+ const match = stdout.match(/([a-f0-9]{32})/);
74
+ return match?.[1] || null;
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ // =============================================================================
81
+ // D1 Database Operations
82
+ // =============================================================================
83
+ /**
84
+ * List all D1 databases
85
+ * @throws Error if wrangler command fails (caller should handle)
86
+ */
87
+ export async function listD1Databases() {
88
+ try {
89
+ const { stdout, stderr } = await wrangler(['d1', 'list', '--json']);
90
+ // Check for auth errors
91
+ if (stderr && stderr.includes('not logged in')) {
92
+ throw new Error('Not logged in to Cloudflare. Run: wrangler login');
93
+ }
94
+ const databases = JSON.parse(stdout);
95
+ return databases.map((db) => ({
96
+ name: db.name,
97
+ uuid: db.uuid,
98
+ }));
99
+ }
100
+ catch (error) {
101
+ // Re-throw with context
102
+ if (error instanceof SyntaxError) {
103
+ throw new Error('Failed to parse D1 database list - wrangler output was not valid JSON');
104
+ }
105
+ throw error;
106
+ }
107
+ }
108
+ /**
109
+ * Check if a D1 database exists
110
+ */
111
+ export async function d1DatabaseExists(name) {
112
+ const databases = await listD1Databases();
113
+ const db = databases.find((d) => d.name === name);
114
+ return { exists: !!db, id: db?.uuid };
115
+ }
116
+ /**
117
+ * Create a D1 database
118
+ */
119
+ export async function createD1Database(name) {
120
+ // Check if already exists
121
+ const existing = await d1DatabaseExists(name);
122
+ if (existing.exists && existing.id) {
123
+ return { id: existing.id, name };
124
+ }
125
+ // Create new database
126
+ const { stdout, stderr } = await wrangler(['d1', 'create', name]);
127
+ // Extract database ID from output
128
+ const idMatch = stdout.match(/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/);
129
+ if (!idMatch) {
130
+ // Try to get ID from list (in case creation message format changed)
131
+ const databases = await listD1Databases();
132
+ const db = databases.find((d) => d.name === name);
133
+ if (db) {
134
+ return { id: db.uuid, name };
135
+ }
136
+ throw new Error(`Failed to create D1 database: ${stderr || stdout}`);
137
+ }
138
+ return { id: idMatch[1], name };
139
+ }
140
+ /**
141
+ * Delete a D1 database
142
+ */
143
+ export async function deleteD1Database(name) {
144
+ try {
145
+ await wrangler(['d1', 'delete', name, '--skip-confirmation']);
146
+ return true;
147
+ }
148
+ catch {
149
+ return false;
150
+ }
151
+ }
152
+ // =============================================================================
153
+ // KV Namespace Operations
154
+ // =============================================================================
155
+ /**
156
+ * List all KV namespaces
157
+ * @throws Error if wrangler command fails (caller should handle)
158
+ */
159
+ export async function listKVNamespaces() {
160
+ try {
161
+ const { stdout, stderr } = await wrangler(['kv', 'namespace', 'list']);
162
+ // Check for auth errors
163
+ if (stderr && stderr.includes('not logged in')) {
164
+ throw new Error('Not logged in to Cloudflare. Run: wrangler login');
165
+ }
166
+ // wrangler kv namespace list outputs JSON
167
+ const namespaces = JSON.parse(stdout);
168
+ return namespaces.map((ns) => ({
169
+ title: ns.title,
170
+ id: ns.id,
171
+ }));
172
+ }
173
+ catch (error) {
174
+ // Re-throw with context
175
+ if (error instanceof SyntaxError) {
176
+ throw new Error('Failed to parse KV namespace list - wrangler output was not valid JSON');
177
+ }
178
+ throw error;
179
+ }
180
+ }
181
+ /**
182
+ * Check if a KV namespace exists
183
+ */
184
+ export async function kvNamespaceExists(title) {
185
+ const namespaces = await listKVNamespaces();
186
+ const ns = namespaces.find((n) => n.title === title);
187
+ return { exists: !!ns, id: ns?.id };
188
+ }
189
+ /**
190
+ * Create a KV namespace
191
+ */
192
+ export async function createKVNamespace(name, preview = false) {
193
+ const args = ['kv', 'namespace', 'create', name];
194
+ if (preview) {
195
+ args.push('--preview');
196
+ }
197
+ const { stdout, stderr } = await wrangler(args);
198
+ // Extract ID from output
199
+ // Format: "id": "abc123..." or "preview_id": "abc123..."
200
+ const idKey = preview ? 'preview_id' : 'id';
201
+ const idMatch = stdout.match(new RegExp(`"${idKey}"\\s*:\\s*"([a-f0-9]{32})"`));
202
+ if (!idMatch) {
203
+ // Check if namespace already exists
204
+ const existing = await kvNamespaceExists(name);
205
+ if (existing.exists && existing.id) {
206
+ return { id: existing.id, name };
207
+ }
208
+ // Try preview namespace name format
209
+ if (preview) {
210
+ const previewExisting = await kvNamespaceExists(`${name}_preview`);
211
+ if (previewExisting.exists && previewExisting.id) {
212
+ return { id: previewExisting.id, name: `${name}_preview` };
213
+ }
214
+ }
215
+ throw new Error(`Failed to create KV namespace: ${stderr || stdout}`);
216
+ }
217
+ return { id: idMatch[1], name };
218
+ }
219
+ /**
220
+ * Delete a KV namespace
221
+ */
222
+ export async function deleteKVNamespace(namespaceId) {
223
+ try {
224
+ await wrangler(['kv', 'namespace', 'delete', '--namespace-id', namespaceId]);
225
+ return true;
226
+ }
227
+ catch {
228
+ return false;
229
+ }
230
+ }
231
+ /**
232
+ * Put a value in KV
233
+ */
234
+ export async function kvPut(namespaceId, key, value, options = {}) {
235
+ try {
236
+ const args = ['kv', 'key', 'put', key, value, '--namespace-id', namespaceId];
237
+ if (options.expirationTtl) {
238
+ args.push('--expiration-ttl', options.expirationTtl.toString());
239
+ }
240
+ await wrangler(args);
241
+ return true;
242
+ }
243
+ catch {
244
+ return false;
245
+ }
246
+ }
247
+ // =============================================================================
248
+ // Queue Operations
249
+ // =============================================================================
250
+ /**
251
+ * Create a Queue
252
+ */
253
+ export async function createQueue(name) {
254
+ try {
255
+ const { stdout } = await wrangler(['queues', 'create', name]);
256
+ // Extract queue ID (format varies)
257
+ const idMatch = stdout.match(/"id"\s*:\s*"([^"]+)"/);
258
+ return {
259
+ id: idMatch?.[1] || name, // Use name as fallback ID
260
+ name,
261
+ };
262
+ }
263
+ catch (error) {
264
+ // Queue might already exist
265
+ return { id: name, name };
266
+ }
267
+ }
268
+ // =============================================================================
269
+ // R2 Bucket Operations
270
+ // =============================================================================
271
+ /**
272
+ * Create an R2 bucket
273
+ */
274
+ export async function createR2Bucket(name) {
275
+ try {
276
+ await wrangler(['r2', 'bucket', 'create', name]);
277
+ return { name };
278
+ }
279
+ catch (error) {
280
+ // Bucket might already exist
281
+ return { name };
282
+ }
283
+ }
284
+ // =============================================================================
285
+ // Secrets Operations
286
+ // =============================================================================
287
+ /**
288
+ * Upload a secret to Cloudflare
289
+ */
290
+ export async function uploadSecret(workerName, secretName, secretValue, env) {
291
+ try {
292
+ const args = ['secret', 'put', secretName, '--name', workerName];
293
+ if (env) {
294
+ args.push('--env', env);
295
+ }
296
+ // Use stdin to pass the secret value
297
+ await execa('wrangler', args, {
298
+ input: secretValue,
299
+ });
300
+ return true;
301
+ }
302
+ catch {
303
+ return false;
304
+ }
305
+ }
306
+ // =============================================================================
307
+ // Validation Helpers
308
+ // =============================================================================
309
+ /**
310
+ * Validate environment name to prevent injection attacks
311
+ */
312
+ function validateEnvName(env) {
313
+ if (!/^[a-z][a-z0-9-]*$/.test(env)) {
314
+ throw new Error('Invalid environment name: must start with lowercase letter and contain only lowercase alphanumeric and hyphens');
315
+ }
316
+ if (env.length > 32) {
317
+ throw new Error('Invalid environment name: must be 32 characters or less');
318
+ }
319
+ }
320
+ /**
321
+ * Sanitize error message to prevent path/secret exposure
322
+ */
323
+ function sanitizeError(error) {
324
+ const message = error instanceof Error ? error.message : String(error);
325
+ // Remove potential file paths
326
+ return message
327
+ .replace(/\/[^\s:]+/g, '[path]')
328
+ .replace(/\\[^\s:]+/g, '[path]')
329
+ .replace(/[a-f0-9]{32,}/gi, '[id]'); // Obscure long hex strings that might be IDs/secrets
330
+ }
331
+ // =============================================================================
332
+ // Provisioning
333
+ // =============================================================================
334
+ /**
335
+ * Provision all required Cloudflare resources for an environment
336
+ */
337
+ export async function provisionResources(options) {
338
+ const { env, onProgress = console.log } = options;
339
+ // Security: Validate environment name
340
+ validateEnvName(env);
341
+ const resources = {
342
+ d1: [],
343
+ kv: [],
344
+ queues: [],
345
+ r2: [],
346
+ };
347
+ // Provision D1 databases
348
+ if (options.createD1 !== false) {
349
+ for (const db of D1_DATABASES) {
350
+ const dbName = getD1DatabaseName(env, db.dbType);
351
+ onProgress(`Creating D1 database: ${dbName}`);
352
+ try {
353
+ const result = await createD1Database(dbName);
354
+ resources.d1.push({
355
+ binding: db.binding,
356
+ name: result.name,
357
+ id: result.id,
358
+ });
359
+ onProgress(` ✓ ${dbName} created`);
360
+ }
361
+ catch (error) {
362
+ onProgress(` ✗ Failed to create ${dbName}: ${sanitizeError(error)}`);
363
+ throw new Error(`Failed to create D1 database ${dbName}`);
364
+ }
365
+ }
366
+ }
367
+ // Provision KV namespaces
368
+ if (options.createKV !== false) {
369
+ for (const kvName of KV_NAMESPACES) {
370
+ const nsName = getKVNamespaceName(env, kvName);
371
+ onProgress(`Creating KV namespace: ${nsName}`);
372
+ try {
373
+ const result = await createKVNamespace(nsName);
374
+ const previewResult = await createKVNamespace(nsName, true);
375
+ resources.kv.push({
376
+ binding: kvName,
377
+ name: result.name,
378
+ id: result.id,
379
+ previewId: previewResult.id,
380
+ });
381
+ onProgress(` ✓ ${nsName} created`);
382
+ }
383
+ catch (error) {
384
+ onProgress(` ✗ Failed to create ${nsName}: ${sanitizeError(error)}`);
385
+ throw new Error(`Failed to create KV namespace ${nsName}`);
386
+ }
387
+ }
388
+ }
389
+ // Provision Queues (optional)
390
+ if (options.createQueues) {
391
+ const queueName = getQueueName(env, 'audit-queue');
392
+ onProgress(`Creating Queue: ${queueName}`);
393
+ try {
394
+ const result = await createQueue(queueName);
395
+ resources.queues.push({
396
+ binding: 'AUDIT_QUEUE',
397
+ name: result.name,
398
+ id: result.id,
399
+ });
400
+ onProgress(` ✓ ${queueName} created`);
401
+ }
402
+ catch (error) {
403
+ onProgress(` ✗ Failed to create ${queueName}: ${sanitizeError(error)}`);
404
+ }
405
+ }
406
+ // Provision R2 buckets (optional)
407
+ if (options.createR2) {
408
+ const bucketName = `${env}-authrim-avatars`;
409
+ onProgress(`Creating R2 bucket: ${bucketName}`);
410
+ try {
411
+ const result = await createR2Bucket(bucketName);
412
+ resources.r2.push({
413
+ binding: 'AVATARS',
414
+ name: result.name,
415
+ });
416
+ onProgress(` ✓ ${bucketName} created`);
417
+ }
418
+ catch (error) {
419
+ onProgress(` ✗ Failed to create ${bucketName}: ${sanitizeError(error)}`);
420
+ }
421
+ }
422
+ return resources;
423
+ }
424
+ /**
425
+ * Convert provisioned resources to ResourceIds format for wrangler.ts
426
+ */
427
+ export function toResourceIds(resources) {
428
+ const result = {
429
+ d1: {},
430
+ kv: {},
431
+ };
432
+ for (const db of resources.d1) {
433
+ result.d1[db.binding] = { id: db.id, name: db.name };
434
+ }
435
+ for (const kv of resources.kv) {
436
+ result.kv[kv.binding] = { id: kv.id, name: kv.name };
437
+ }
438
+ if (resources.queues.length > 0) {
439
+ result.queues = {};
440
+ for (const q of resources.queues) {
441
+ result.queues[q.binding] = { id: q.id, name: q.name };
442
+ }
443
+ }
444
+ if (resources.r2.length > 0) {
445
+ result.r2 = {};
446
+ for (const r of resources.r2) {
447
+ result.r2[r.binding] = { name: r.name };
448
+ }
449
+ }
450
+ return result;
451
+ }
452
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/core/cloudflare.ts"],"names":[],"mappings":"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"}