@getjack/jack 0.1.33 → 0.1.35

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 (94) hide show
  1. package/README.md +6 -6
  2. package/package.json +1 -1
  3. package/src/commands/down.ts +39 -7
  4. package/src/commands/link.ts +2 -4
  5. package/src/commands/logs.ts +2 -4
  6. package/src/commands/mcp.ts +12 -10
  7. package/src/commands/secrets.ts +3 -1
  8. package/src/commands/services.ts +4 -2
  9. package/src/commands/sync.ts +5 -6
  10. package/src/lib/auth/client.ts +5 -2
  11. package/src/lib/binding-validator.ts +39 -3
  12. package/src/lib/build-helper.ts +18 -19
  13. package/src/lib/control-plane.ts +1 -0
  14. package/src/lib/crypto.ts +84 -0
  15. package/src/lib/deploy-upload.ts +7 -3
  16. package/src/lib/do-config.ts +110 -0
  17. package/src/lib/do-export-validator.ts +26 -0
  18. package/src/lib/hooks.ts +1 -2
  19. package/src/lib/jsonc-edit.ts +292 -0
  20. package/src/lib/managed-deploy.ts +36 -1
  21. package/src/lib/project-link.ts +37 -0
  22. package/src/lib/project-operations.ts +37 -46
  23. package/src/lib/prompts.ts +2 -2
  24. package/src/lib/resources.ts +4 -5
  25. package/src/lib/schema.ts +8 -12
  26. package/src/lib/services/db-create.ts +2 -2
  27. package/src/lib/services/db-execute.ts +9 -6
  28. package/src/lib/services/db-list.ts +6 -4
  29. package/src/lib/services/endpoint-test.ts +275 -0
  30. package/src/lib/services/project-delete.ts +190 -0
  31. package/src/lib/services/project-environment.ts +457 -0
  32. package/src/lib/services/storage-config.ts +7 -309
  33. package/src/lib/services/storage-create.ts +2 -1
  34. package/src/lib/services/storage-delete.ts +3 -2
  35. package/src/lib/services/storage-info.ts +2 -1
  36. package/src/lib/services/storage-list.ts +6 -3
  37. package/src/lib/services/vectorize-config.ts +7 -264
  38. package/src/lib/services/vectorize-create.ts +2 -1
  39. package/src/lib/services/vectorize-delete.ts +6 -4
  40. package/src/lib/services/vectorize-list.ts +6 -3
  41. package/src/lib/storage/index.ts +21 -23
  42. package/src/lib/telemetry.ts +1 -0
  43. package/src/lib/wrangler-config.ts +43 -312
  44. package/src/lib/zip-packager.ts +28 -0
  45. package/src/mcp/test-utils.ts +31 -0
  46. package/src/mcp/tools/index.ts +271 -0
  47. package/src/templates/index.ts +5 -0
  48. package/src/templates/types.ts +4 -0
  49. package/templates/AI-BINDINGS.md +34 -76
  50. package/templates/CLAUDE.md +22 -1
  51. package/templates/ai-chat/src/index.ts +7 -14
  52. package/templates/ai-chat/src/jack-ai.ts +0 -6
  53. package/templates/chat/.jack.json +45 -0
  54. package/templates/chat/bun.lock +1588 -0
  55. package/templates/chat/components.json +23 -0
  56. package/templates/chat/index.html +12 -0
  57. package/templates/chat/package.json +41 -0
  58. package/templates/chat/src/chat-agent.ts +61 -0
  59. package/templates/chat/src/client/app.tsx +189 -0
  60. package/templates/chat/src/client/chat.tsx +222 -0
  61. package/templates/chat/src/client/components/prompt-kit/chat-container.tsx +47 -0
  62. package/templates/chat/src/client/components/prompt-kit/loader.tsx +33 -0
  63. package/templates/chat/src/client/components/prompt-kit/markdown.tsx +84 -0
  64. package/templates/chat/src/client/components/prompt-kit/message.tsx +54 -0
  65. package/templates/chat/src/client/components/prompt-kit/prompt-suggestion.tsx +20 -0
  66. package/templates/chat/src/client/components/prompt-kit/reasoning.tsx +134 -0
  67. package/templates/chat/src/client/components/prompt-kit/scroll-button.tsx +28 -0
  68. package/templates/chat/src/client/components/ui/button.tsx +38 -0
  69. package/templates/chat/src/client/lib/utils.ts +6 -0
  70. package/templates/chat/src/client/main.tsx +11 -0
  71. package/templates/chat/src/client/styles.css +125 -0
  72. package/templates/chat/src/index.ts +25 -0
  73. package/templates/chat/src/jack-ai.ts +94 -0
  74. package/templates/chat/tsconfig.json +18 -0
  75. package/templates/chat/vite.config.ts +14 -0
  76. package/templates/chat/wrangler.jsonc +18 -0
  77. package/templates/cron/.jack.json +18 -28
  78. package/templates/cron/schema.sql +10 -20
  79. package/templates/cron/src/admin.ts +321 -0
  80. package/templates/cron/src/index.ts +151 -81
  81. package/templates/cron/src/monitor.ts +124 -0
  82. package/templates/nextjs-clerk/app/layout.tsx +2 -0
  83. package/templates/semantic-search/src/index.ts +5 -43
  84. package/templates/semantic-search/src/jack-ai.ts +0 -6
  85. package/templates/telegram-bot/.jack.json +56 -0
  86. package/templates/telegram-bot/bun.lock +41 -0
  87. package/templates/telegram-bot/package.json +16 -0
  88. package/templates/telegram-bot/src/index.ts +236 -0
  89. package/templates/telegram-bot/src/jack-ai.ts +100 -0
  90. package/templates/telegram-bot/tsconfig.json +11 -0
  91. package/templates/telegram-bot/wrangler.jsonc +8 -0
  92. package/templates/cron/src/jobs.ts +0 -139
  93. package/templates/cron/src/webhooks.ts +0 -95
  94. package/templates/semantic-search/src/jack-vectorize.ts +0 -169
@@ -3,6 +3,12 @@
3
3
  */
4
4
 
5
5
  import { existsSync } from "node:fs";
6
+ import {
7
+ addSectionBeforeClosingBrace,
8
+ findLastObjectEndInArray,
9
+ findMatchingBracket,
10
+ isOnlyCommentsAndWhitespace,
11
+ } from "../jsonc-edit.ts";
6
12
  import { parseJsonc } from "../jsonc.ts";
7
13
 
8
14
  export interface R2BindingConfig {
@@ -167,315 +173,7 @@ function appendToR2BucketsArray(content: string, bindingJson: string): string {
167
173
  * Inserts before the final closing brace.
168
174
  */
169
175
  function addR2BucketsSection(content: string, bindingJson: string): string {
170
- // Find the last closing brace in the file
171
- const lastBraceIndex = content.lastIndexOf("}");
172
- if (lastBraceIndex === -1) {
173
- throw new Error("Invalid JSON: no closing brace found");
174
- }
175
-
176
- // Check what comes before the last brace to determine if we need a comma
177
- const beforeBrace = content.slice(0, lastBraceIndex);
178
- const needsComma = shouldAddCommaBefore(beforeBrace);
179
-
180
- // Build the r2_buckets section
181
- const r2Section = `"r2_buckets": [
182
- ${bindingJson}
183
- ]`;
184
-
185
- // Find proper insertion point - look for last non-whitespace content
186
- const trimmedBefore = beforeBrace.trimEnd();
187
-
188
- let insertion: string;
189
- if (needsComma) {
190
- insertion = `,\n\t${r2Section}`;
191
- } else {
192
- insertion = `\n\t${r2Section}`;
193
- }
194
-
195
- // Reconstruct: content before + insertion + newline + closing brace
196
- return trimmedBefore + insertion + "\n" + content.slice(lastBraceIndex);
197
- }
198
-
199
- /**
200
- * Find the matching closing bracket/brace for an opening one
201
- */
202
- function findMatchingBracket(
203
- content: string,
204
- startIndex: number,
205
- openChar: string,
206
- closeChar: string,
207
- ): number {
208
- let depth = 0;
209
- let inString = false;
210
- let stringChar = "";
211
- let escaped = false;
212
- let inLineComment = false;
213
- let inBlockComment = false;
214
-
215
- for (let i = startIndex; i < content.length; i++) {
216
- const char = content[i] ?? "";
217
- const next = content[i + 1] ?? "";
218
-
219
- // Handle line comments
220
- if (inLineComment) {
221
- if (char === "\n") {
222
- inLineComment = false;
223
- }
224
- continue;
225
- }
226
-
227
- // Handle block comments
228
- if (inBlockComment) {
229
- if (char === "*" && next === "/") {
230
- inBlockComment = false;
231
- i++;
232
- }
233
- continue;
234
- }
235
-
236
- // Handle strings
237
- if (inString) {
238
- if (escaped) {
239
- escaped = false;
240
- continue;
241
- }
242
- if (char === "\\") {
243
- escaped = true;
244
- continue;
245
- }
246
- if (char === stringChar) {
247
- inString = false;
248
- stringChar = "";
249
- }
250
- continue;
251
- }
252
-
253
- // Check for comment start
254
- if (char === "/" && next === "/") {
255
- inLineComment = true;
256
- i++;
257
- continue;
258
- }
259
- if (char === "/" && next === "*") {
260
- inBlockComment = true;
261
- i++;
262
- continue;
263
- }
264
-
265
- // Check for string start
266
- if (char === '"' || char === "'") {
267
- inString = true;
268
- stringChar = char;
269
- continue;
270
- }
271
-
272
- // Track bracket depth
273
- if (char === openChar) {
274
- depth++;
275
- } else if (char === closeChar) {
276
- depth--;
277
- if (depth === 0) {
278
- return i;
279
- }
280
- }
281
- }
282
-
283
- return -1;
284
- }
285
-
286
- /**
287
- * Check if content is only whitespace and comments
288
- */
289
- function isOnlyCommentsAndWhitespace(content: string): boolean {
290
- let inLineComment = false;
291
- let inBlockComment = false;
292
-
293
- for (let i = 0; i < content.length; i++) {
294
- const char = content[i] ?? "";
295
- const next = content[i + 1] ?? "";
296
-
297
- if (inLineComment) {
298
- if (char === "\n") {
299
- inLineComment = false;
300
- }
301
- continue;
302
- }
303
-
304
- if (inBlockComment) {
305
- if (char === "*" && next === "/") {
306
- inBlockComment = false;
307
- i++;
308
- }
309
- continue;
310
- }
311
-
312
- if (char === "/" && next === "/") {
313
- inLineComment = true;
314
- i++;
315
- continue;
316
- }
317
-
318
- if (char === "/" && next === "*") {
319
- inBlockComment = true;
320
- i++;
321
- continue;
322
- }
323
-
324
- if (!/\s/.test(char)) {
325
- return false;
326
- }
327
- }
328
-
329
- return true;
330
- }
331
-
332
- /**
333
- * Find the last closing brace of an object within an array range
334
- */
335
- function findLastObjectEndInArray(content: string, startIndex: number, endIndex: number): number {
336
- let lastBraceIndex = -1;
337
- let inString = false;
338
- let stringChar = "";
339
- let escaped = false;
340
- let inLineComment = false;
341
- let inBlockComment = false;
342
-
343
- for (let i = startIndex; i < endIndex; i++) {
344
- const char = content[i] ?? "";
345
- const next = content[i + 1] ?? "";
346
-
347
- if (inLineComment) {
348
- if (char === "\n") {
349
- inLineComment = false;
350
- }
351
- continue;
352
- }
353
-
354
- if (inBlockComment) {
355
- if (char === "*" && next === "/") {
356
- inBlockComment = false;
357
- i++;
358
- }
359
- continue;
360
- }
361
-
362
- if (inString) {
363
- if (escaped) {
364
- escaped = false;
365
- continue;
366
- }
367
- if (char === "\\") {
368
- escaped = true;
369
- continue;
370
- }
371
- if (char === stringChar) {
372
- inString = false;
373
- stringChar = "";
374
- }
375
- continue;
376
- }
377
-
378
- if (char === "/" && next === "/") {
379
- inLineComment = true;
380
- i++;
381
- continue;
382
- }
383
-
384
- if (char === "/" && next === "*") {
385
- inBlockComment = true;
386
- i++;
387
- continue;
388
- }
389
-
390
- if (char === '"' || char === "'") {
391
- inString = true;
392
- stringChar = char;
393
- continue;
394
- }
395
-
396
- if (char === "}") {
397
- lastBraceIndex = i;
398
- }
399
- }
400
-
401
- return lastBraceIndex;
402
- }
403
-
404
- /**
405
- * Determine if we need to add a comma before new content.
406
- * Looks at the last non-whitespace, non-comment character.
407
- */
408
- function shouldAddCommaBefore(content: string): boolean {
409
- // Strip trailing comments and whitespace to find last meaningful char
410
- let i = content.length - 1;
411
-
412
- // First pass: find where any trailing line comment starts
413
- for (let j = content.length - 1; j >= 0; j--) {
414
- if (content[j] === "\n") {
415
- // Check if there's a // comment on this line
416
- const lineStart = content.lastIndexOf("\n", j - 1) + 1;
417
- const line = content.slice(lineStart, j);
418
- const commentIndex = findLineCommentStart(line);
419
- if (commentIndex !== -1) {
420
- i = lineStart + commentIndex - 1;
421
- }
422
- break;
423
- }
424
- }
425
-
426
- // Skip whitespace
427
- while (i >= 0 && /\s/.test(content[i] ?? "")) {
428
- i--;
429
- }
430
-
431
- if (i < 0) return false;
432
-
433
- const lastChar = content[i];
434
- // Need comma if last char is }, ], ", number, or identifier char
435
- // Don't need comma if last char is { or [ or ,
436
- return lastChar !== "{" && lastChar !== "[" && lastChar !== ",";
437
- }
438
-
439
- /**
440
- * Find the start of a line comment (//) in a string, respecting strings
441
- */
442
- function findLineCommentStart(line: string): number {
443
- let inString = false;
444
- let stringChar = "";
445
- let escaped = false;
446
-
447
- for (let i = 0; i < line.length - 1; i++) {
448
- const char = line[i] ?? "";
449
- const next = line[i + 1] ?? "";
450
-
451
- if (inString) {
452
- if (escaped) {
453
- escaped = false;
454
- continue;
455
- }
456
- if (char === "\\") {
457
- escaped = true;
458
- continue;
459
- }
460
- if (char === stringChar) {
461
- inString = false;
462
- stringChar = "";
463
- }
464
- continue;
465
- }
466
-
467
- if (char === '"' || char === "'") {
468
- inString = true;
469
- stringChar = char;
470
- continue;
471
- }
472
-
473
- if (char === "/" && next === "/") {
474
- return i;
475
- }
476
- }
477
-
478
- return -1;
176
+ return addSectionBeforeClosingBrace(content, `"r2_buckets": [\n\t\t${bindingJson}\n\t]`);
479
177
  }
480
178
 
481
179
  /**
@@ -9,6 +9,7 @@ import { $ } from "bun";
9
9
  import { createProjectResource } from "../control-plane.ts";
10
10
  import { readProjectLink } from "../project-link.ts";
11
11
  import { getProjectNameFromDir } from "../storage/index.ts";
12
+ import { findWranglerConfig } from "../wrangler-config.ts";
12
13
  import {
13
14
  addR2Binding,
14
15
  generateBucketName,
@@ -103,7 +104,7 @@ export async function createStorageBucket(
103
104
  const projectName = await getProjectNameFromDir(projectDir);
104
105
 
105
106
  // Get existing R2 bindings to determine naming
106
- const wranglerPath = join(projectDir, "wrangler.jsonc");
107
+ const wranglerPath = findWranglerConfig(projectDir) ?? join(projectDir, "wrangler.jsonc");
107
108
  const existingBindings = await getExistingR2Bindings(wranglerPath);
108
109
  const existingCount = existingBindings.length;
109
110
 
@@ -8,6 +8,7 @@ import { join } from "node:path";
8
8
  import { $ } from "bun";
9
9
  import { deleteProjectResource, fetchProjectResources } from "../control-plane.ts";
10
10
  import { readProjectLink } from "../project-link.ts";
11
+ import { findWranglerConfig } from "../wrangler-config.ts";
11
12
  import { getExistingR2Bindings, removeR2Binding } from "./storage-config.ts";
12
13
 
13
14
  export interface DeleteStorageBucketResult {
@@ -49,9 +50,9 @@ export async function deleteStorageBucket(
49
50
  throw new Error("Not in a jack project. Run 'jack new' to create a project.");
50
51
  }
51
52
 
52
- const wranglerPath = join(projectDir, "wrangler.jsonc");
53
+ const wranglerPath = findWranglerConfig(projectDir) ?? join(projectDir, "wrangler.jsonc");
53
54
 
54
- // Verify bucket exists in wrangler.jsonc
55
+ // Verify bucket exists in wrangler config
55
56
  const bindings = await getExistingR2Bindings(wranglerPath);
56
57
  const binding = bindings.find((b) => b.bucket_name === bucketName);
57
58
 
@@ -9,6 +9,7 @@ import { join } from "node:path";
9
9
  import { $ } from "bun";
10
10
  import { fetchProjectResources } from "../control-plane.ts";
11
11
  import { readProjectLink } from "../project-link.ts";
12
+ import { findWranglerConfig } from "../wrangler-config.ts";
12
13
  import { getExistingR2Bindings } from "./storage-config.ts";
13
14
 
14
15
  export interface StorageBucketInfo {
@@ -46,7 +47,7 @@ export async function getStorageBucketInfo(
46
47
  projectDir: string,
47
48
  bucketName?: string,
48
49
  ): Promise<StorageBucketInfo | null> {
49
- const wranglerPath = join(projectDir, "wrangler.jsonc");
50
+ const wranglerPath = findWranglerConfig(projectDir) ?? join(projectDir, "wrangler.jsonc");
50
51
 
51
52
  // Read deploy mode from .jack/project.json
52
53
  const link = await readProjectLink(projectDir);
@@ -5,7 +5,7 @@
5
5
  * For managed projects, fetches metadata via control plane instead of wrangler.
6
6
  */
7
7
 
8
- import { join } from "node:path";
8
+ import { findWranglerConfig } from "../wrangler-config.ts";
9
9
  import { getExistingR2Bindings } from "./storage-config.ts";
10
10
 
11
11
  export interface StorageBucketListEntry {
@@ -23,9 +23,12 @@ export interface StorageBucketListEntry {
23
23
  * the configured bindings. For detailed info, use storage info.
24
24
  */
25
25
  export async function listStorageBuckets(projectDir: string): Promise<StorageBucketListEntry[]> {
26
- const wranglerPath = join(projectDir, "wrangler.jsonc");
26
+ const wranglerPath = findWranglerConfig(projectDir);
27
+ if (!wranglerPath) {
28
+ return [];
29
+ }
27
30
 
28
- // Get existing R2 bindings from wrangler.jsonc
31
+ // Get existing R2 bindings from wrangler config
29
32
  const bindings = await getExistingR2Bindings(wranglerPath);
30
33
 
31
34
  if (bindings.length === 0) {
@@ -3,6 +3,12 @@
3
3
  */
4
4
 
5
5
  import { existsSync } from "node:fs";
6
+ import {
7
+ addSectionBeforeClosingBrace,
8
+ findLastObjectEndInArray,
9
+ findMatchingBracket,
10
+ isOnlyCommentsAndWhitespace,
11
+ } from "../jsonc-edit.ts";
6
12
  import { parseJsonc } from "../jsonc.ts";
7
13
 
8
14
  export interface VectorizeBindingConfig {
@@ -132,28 +138,7 @@ function appendToVectorizeArray(content: string, bindingJson: string): string {
132
138
  * Add a new vectorize section to the config.
133
139
  */
134
140
  function addVectorizeSection(content: string, bindingJson: string): string {
135
- const lastBraceIndex = content.lastIndexOf("}");
136
- if (lastBraceIndex === -1) {
137
- throw new Error("Invalid JSON: no closing brace found");
138
- }
139
-
140
- const beforeBrace = content.slice(0, lastBraceIndex);
141
- const needsComma = shouldAddCommaBefore(beforeBrace);
142
-
143
- const vecSection = `"vectorize": [
144
- ${bindingJson}
145
- ]`;
146
-
147
- const trimmedBefore = beforeBrace.trimEnd();
148
-
149
- let insertion: string;
150
- if (needsComma) {
151
- insertion = `,\n\t${vecSection}`;
152
- } else {
153
- insertion = `\n\t${vecSection}`;
154
- }
155
-
156
- return trimmedBefore + insertion + "\n" + content.slice(lastBraceIndex);
141
+ return addSectionBeforeClosingBrace(content, `"vectorize": [\n\t\t${bindingJson}\n\t]`);
157
142
  }
158
143
 
159
144
  /**
@@ -276,248 +261,6 @@ function removeVectorizeProperty(content: string, propertyStart: number, arrayEn
276
261
  return content.slice(0, removeStart) + content.slice(removeEnd);
277
262
  }
278
263
 
279
- // Helper functions (same as in wrangler-config.ts)
280
-
281
- function findMatchingBracket(
282
- content: string,
283
- startIndex: number,
284
- openChar: string,
285
- closeChar: string,
286
- ): number {
287
- let depth = 0;
288
- let inString = false;
289
- let stringChar = "";
290
- let escaped = false;
291
- let inLineComment = false;
292
- let inBlockComment = false;
293
-
294
- for (let i = startIndex; i < content.length; i++) {
295
- const char = content[i] ?? "";
296
- const next = content[i + 1] ?? "";
297
-
298
- if (inLineComment) {
299
- if (char === "\n") inLineComment = false;
300
- continue;
301
- }
302
-
303
- if (inBlockComment) {
304
- if (char === "*" && next === "/") {
305
- inBlockComment = false;
306
- i++;
307
- }
308
- continue;
309
- }
310
-
311
- if (inString) {
312
- if (escaped) {
313
- escaped = false;
314
- continue;
315
- }
316
- if (char === "\\") {
317
- escaped = true;
318
- continue;
319
- }
320
- if (char === stringChar) {
321
- inString = false;
322
- stringChar = "";
323
- }
324
- continue;
325
- }
326
-
327
- if (char === "/" && next === "/") {
328
- inLineComment = true;
329
- i++;
330
- continue;
331
- }
332
- if (char === "/" && next === "*") {
333
- inBlockComment = true;
334
- i++;
335
- continue;
336
- }
337
-
338
- if (char === '"' || char === "'") {
339
- inString = true;
340
- stringChar = char;
341
- continue;
342
- }
343
-
344
- if (char === openChar) {
345
- depth++;
346
- } else if (char === closeChar) {
347
- depth--;
348
- if (depth === 0) return i;
349
- }
350
- }
351
-
352
- return -1;
353
- }
354
-
355
- function isOnlyCommentsAndWhitespace(content: string): boolean {
356
- let inLineComment = false;
357
- let inBlockComment = false;
358
-
359
- for (let i = 0; i < content.length; i++) {
360
- const char = content[i] ?? "";
361
- const next = content[i + 1] ?? "";
362
-
363
- if (inLineComment) {
364
- if (char === "\n") inLineComment = false;
365
- continue;
366
- }
367
-
368
- if (inBlockComment) {
369
- if (char === "*" && next === "/") {
370
- inBlockComment = false;
371
- i++;
372
- }
373
- continue;
374
- }
375
-
376
- if (char === "/" && next === "/") {
377
- inLineComment = true;
378
- i++;
379
- continue;
380
- }
381
-
382
- if (char === "/" && next === "*") {
383
- inBlockComment = true;
384
- i++;
385
- continue;
386
- }
387
-
388
- if (!/\s/.test(char)) return false;
389
- }
390
-
391
- return true;
392
- }
393
-
394
- function findLastObjectEndInArray(content: string, startIndex: number, endIndex: number): number {
395
- let lastBraceIndex = -1;
396
- let inString = false;
397
- let stringChar = "";
398
- let escaped = false;
399
- let inLineComment = false;
400
- let inBlockComment = false;
401
-
402
- for (let i = startIndex; i < endIndex; i++) {
403
- const char = content[i] ?? "";
404
- const next = content[i + 1] ?? "";
405
-
406
- if (inLineComment) {
407
- if (char === "\n") inLineComment = false;
408
- continue;
409
- }
410
-
411
- if (inBlockComment) {
412
- if (char === "*" && next === "/") {
413
- inBlockComment = false;
414
- i++;
415
- }
416
- continue;
417
- }
418
-
419
- if (inString) {
420
- if (escaped) {
421
- escaped = false;
422
- continue;
423
- }
424
- if (char === "\\") {
425
- escaped = true;
426
- continue;
427
- }
428
- if (char === stringChar) {
429
- inString = false;
430
- stringChar = "";
431
- }
432
- continue;
433
- }
434
-
435
- if (char === "/" && next === "/") {
436
- inLineComment = true;
437
- i++;
438
- continue;
439
- }
440
-
441
- if (char === "/" && next === "*") {
442
- inBlockComment = true;
443
- i++;
444
- continue;
445
- }
446
-
447
- if (char === '"' || char === "'") {
448
- inString = true;
449
- stringChar = char;
450
- continue;
451
- }
452
-
453
- if (char === "}") lastBraceIndex = i;
454
- }
455
-
456
- return lastBraceIndex;
457
- }
458
-
459
- function shouldAddCommaBefore(content: string): boolean {
460
- let i = content.length - 1;
461
-
462
- for (let j = content.length - 1; j >= 0; j--) {
463
- if (content[j] === "\n") {
464
- const lineStart = content.lastIndexOf("\n", j - 1) + 1;
465
- const line = content.slice(lineStart, j);
466
- const commentIndex = findLineCommentStart(line);
467
- if (commentIndex !== -1) {
468
- i = lineStart + commentIndex - 1;
469
- }
470
- break;
471
- }
472
- }
473
-
474
- while (i >= 0 && /\s/.test(content[i] ?? "")) {
475
- i--;
476
- }
477
-
478
- if (i < 0) return false;
479
-
480
- const lastChar = content[i];
481
- return lastChar !== "{" && lastChar !== "[" && lastChar !== ",";
482
- }
483
-
484
- function findLineCommentStart(line: string): number {
485
- let inString = false;
486
- let stringChar = "";
487
- let escaped = false;
488
-
489
- for (let i = 0; i < line.length - 1; i++) {
490
- const char = line[i] ?? "";
491
- const next = line[i + 1] ?? "";
492
-
493
- if (inString) {
494
- if (escaped) {
495
- escaped = false;
496
- continue;
497
- }
498
- if (char === "\\") {
499
- escaped = true;
500
- continue;
501
- }
502
- if (char === stringChar) {
503
- inString = false;
504
- stringChar = "";
505
- }
506
- continue;
507
- }
508
-
509
- if (char === '"' || char === "'") {
510
- inString = true;
511
- stringChar = char;
512
- continue;
513
- }
514
-
515
- if (char === "/" && next === "/") return i;
516
- }
517
-
518
- return -1;
519
- }
520
-
521
264
  function findObjectStartBefore(content: string, fromPos: number): number {
522
265
  let depth = 0;
523
266
  for (let i = fromPos; i >= 0; i--) {
@@ -7,6 +7,7 @@
7
7
  import { join } from "node:path";
8
8
  import { $ } from "bun";
9
9
  import { getProjectNameFromDir } from "../storage/index.ts";
10
+ import { findWranglerConfig } from "../wrangler-config.ts";
10
11
  import { addVectorizeBinding, getExistingVectorizeBindings } from "./vectorize-config.ts";
11
12
 
12
13
  export type VectorizeMetric = "cosine" | "euclidean" | "dot-product";
@@ -128,7 +129,7 @@ export async function createVectorizeIndex(
128
129
  const projectName = await getProjectNameFromDir(projectDir);
129
130
 
130
131
  // Get existing Vectorize bindings to determine naming
131
- const wranglerPath = join(projectDir, "wrangler.jsonc");
132
+ const wranglerPath = findWranglerConfig(projectDir) ?? join(projectDir, "wrangler.jsonc");
132
133
  const existingBindings = await getExistingVectorizeBindings(wranglerPath);
133
134
  const existingCount = existingBindings.length;
134
135