alchemy 0.85.0 → 0.85.2

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 (84) hide show
  1. package/bin/alchemy.js +32 -23
  2. package/lib/cloudflare/account-api-token.d.ts +5 -0
  3. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  4. package/lib/cloudflare/account-api-token.js +13 -2
  5. package/lib/cloudflare/account-api-token.js.map +1 -1
  6. package/lib/cloudflare/ai-crawler.d.ts +27 -0
  7. package/lib/cloudflare/ai-crawler.d.ts.map +1 -0
  8. package/lib/cloudflare/ai-crawler.js +75 -0
  9. package/lib/cloudflare/ai-crawler.js.map +1 -0
  10. package/lib/cloudflare/ai-search-token.d.ts +150 -0
  11. package/lib/cloudflare/ai-search-token.d.ts.map +1 -0
  12. package/lib/cloudflare/ai-search-token.js +171 -0
  13. package/lib/cloudflare/ai-search-token.js.map +1 -0
  14. package/lib/cloudflare/ai-search.d.ts +397 -0
  15. package/lib/cloudflare/ai-search.d.ts.map +1 -0
  16. package/lib/cloudflare/ai-search.js +307 -0
  17. package/lib/cloudflare/ai-search.js.map +1 -0
  18. package/lib/cloudflare/auth.d.ts +3 -2
  19. package/lib/cloudflare/auth.d.ts.map +1 -1
  20. package/lib/cloudflare/auth.js +17 -14
  21. package/lib/cloudflare/auth.js.map +1 -1
  22. package/lib/cloudflare/bucket-custom-domain.d.ts.map +1 -1
  23. package/lib/cloudflare/bucket-custom-domain.js +4 -2
  24. package/lib/cloudflare/bucket-custom-domain.js.map +1 -1
  25. package/lib/cloudflare/bucket.d.ts.map +1 -1
  26. package/lib/cloudflare/bucket.js +8 -2
  27. package/lib/cloudflare/bucket.js.map +1 -1
  28. package/lib/cloudflare/index.d.ts +3 -0
  29. package/lib/cloudflare/index.d.ts.map +1 -1
  30. package/lib/cloudflare/index.js +3 -0
  31. package/lib/cloudflare/index.js.map +1 -1
  32. package/lib/cloudflare/permission-groups.d.ts +5 -0
  33. package/lib/cloudflare/permission-groups.d.ts.map +1 -1
  34. package/lib/cloudflare/permission-groups.js +6 -0
  35. package/lib/cloudflare/permission-groups.js.map +1 -1
  36. package/lib/cloudflare/sveltekit/plugin.d.ts.map +1 -1
  37. package/lib/cloudflare/sveltekit/plugin.js +11 -5
  38. package/lib/cloudflare/sveltekit/plugin.js.map +1 -1
  39. package/lib/cloudflare/vite/vite.d.ts.map +1 -1
  40. package/lib/cloudflare/vite/vite.js +2 -1
  41. package/lib/cloudflare/vite/vite.js.map +1 -1
  42. package/lib/docker/api.d.ts +33 -2
  43. package/lib/docker/api.d.ts.map +1 -1
  44. package/lib/docker/api.js +8 -4
  45. package/lib/docker/api.js.map +1 -1
  46. package/lib/docker/container.d.ts +1 -1
  47. package/lib/docker/container.d.ts.map +1 -1
  48. package/lib/docker/container.js +244 -15
  49. package/lib/docker/container.js.map +1 -1
  50. package/lib/scope.d.ts +1 -1
  51. package/lib/scope.d.ts.map +1 -1
  52. package/lib/scope.js +10 -5
  53. package/lib/scope.js.map +1 -1
  54. package/lib/test/bun.d.ts +17 -0
  55. package/lib/test/bun.d.ts.map +1 -1
  56. package/lib/test/bun.js +2 -1
  57. package/lib/test/bun.js.map +1 -1
  58. package/lib/test/vitest.d.ts +17 -0
  59. package/lib/test/vitest.d.ts.map +1 -1
  60. package/lib/test/vitest.js +4 -1
  61. package/lib/test/vitest.js.map +1 -1
  62. package/lib/util/snake-to-camel.d.ts +21 -0
  63. package/lib/util/snake-to-camel.d.ts.map +1 -0
  64. package/lib/util/snake-to-camel.js +34 -0
  65. package/lib/util/snake-to-camel.js.map +1 -0
  66. package/package.json +1 -1
  67. package/src/cloudflare/account-api-token.ts +23 -6
  68. package/src/cloudflare/ai-crawler.ts +89 -0
  69. package/src/cloudflare/ai-search-token.ts +324 -0
  70. package/src/cloudflare/ai-search.ts +952 -0
  71. package/src/cloudflare/auth.ts +17 -14
  72. package/src/cloudflare/bucket-custom-domain.ts +4 -1
  73. package/src/cloudflare/bucket.ts +9 -2
  74. package/src/cloudflare/index.ts +3 -0
  75. package/src/cloudflare/permission-groups.ts +6 -0
  76. package/src/cloudflare/sveltekit/plugin.ts +17 -8
  77. package/src/cloudflare/vite/vite.ts +4 -2
  78. package/src/docker/api.ts +47 -4
  79. package/src/docker/container.ts +318 -18
  80. package/src/scope.ts +14 -5
  81. package/src/test/bun.ts +26 -1
  82. package/src/test/vitest.ts +34 -1
  83. package/src/util/snake-to-camel.ts +59 -0
  84. package/workers/tunnel-proxy.js +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/test/vitest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAOpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,OAAO;QACf,IAAI,EAAE,OAAO,IAAI,CAAC;KACnB;CACF;AAOD;;GAEG;AACH,KAAK,IAAI,GAAG;IACV;;;;;OAKG;IACH,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3E;;;;;;OAMG;IACH,CACE,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IAER;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAEjC,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvE,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtE;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,UAAU,EAChB,cAAc,GAAE,WAEf,GACA,IAAI,CA6GN"}
1
+ {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/test/vitest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAOpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,OAAO;QACf,IAAI,EAAE,OAAO,IAAI,CAAC;KACnB;CACF;AAOD;;GAEG;AACH,KAAK,IAAI,GAAG;IACV;;;;;OAKG;IACH,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3E;;;;;;OAMG;IACH,CACE,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IAER;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE;QACJ;;;;;WAKG;QACH,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAE3E;;;;;;WAMG;QACH,CACE,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;KACT,CAAC;IAEF,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvE,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtE;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,UAAU,EAChB,cAAc,GAAE,WAEf,GACA,IAAI,CAuHN"}
@@ -59,6 +59,9 @@ export function test(meta, defaultOptions = {
59
59
  }
60
60
  return test;
61
61
  };
62
+ test.skip = (...args
63
+ // @ts-expect-error
64
+ ) => it.skip(...args);
62
65
  const scope = new Scope({
63
66
  parent: undefined,
64
67
  scopeName: `${defaultOptions.prefix ? `${defaultOptions.prefix}-` : ""}${path.basename(meta.filename)}`,
@@ -81,7 +84,7 @@ export function test(meta, defaultOptions = {
81
84
  const _options = typeof args[1] === "object" ? args[1] : undefined;
82
85
  const timeout = typeof args[args.length - 1] === "number"
83
86
  ? args[args.length - 1]
84
- : 120000;
87
+ : 150000;
85
88
  const spread = (obj) => obj && typeof obj === "object"
86
89
  ? Object.fromEntries(Object.entries(obj).flatMap(([k, v]) => v !== undefined ? [[k, v]] : []))
87
90
  : {};
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/test/vitest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/test/vitest.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAY3B;;GAEG;AACH,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;AAmEpB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,IAAI,CAClB,IAAgB,EAChB,iBAA8B;IAC5B,KAAK,EAAE,IAAI;CACZ;IAED,IAAI,CAAC,CAAC,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC;QACjC,cAAc,CAAC,KAAK,GAAG,IAAI,CAAC;IAC9B,CAAC;IACD,cAAc,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,EAAE;QACtC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAClD,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,IAAI;gBACP,OAAO,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACzC,KAAK,IAAI;gBACP,OAAO,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACzC,KAAK,IAAI;gBACP,OAAO,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;YACjC;gBACE,OAAO,IAAI,gBAAgB,CAAC,KAAK,EAAE;oBACjC,QAAQ,EAAE,IAAI,CAAC,IAAI,CACjB,KAAK,CAAC,UAAU,EAChB,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CACxD;iBACF,CAAC,CAAC;QACP,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,MAAM,GAAG,CAAC,SAAkB,EAAE,EAAE;QACnC,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,KAAY,EAAE,EAAE,GAAE,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,GAAG,CACV,GAAG,IAMoD;IACvD,mBAAmB;MACnB,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAEtB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,GACT,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EACxD,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACjC,UAAU,EAAE,cAAc,EAAE,UAAU;QACtC,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,cAAc,CAAC,KAAK;QAC3B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;QACtC,KAAK,EAAE,cAAc,CAAC,KAAK;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,GAAG,CAAC,EAAmC,EAAE,OAAgB,EAAE,EAAE;QACzE,OAAO,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAmC,EAAE,OAAgB,EAAE,EAAE;QACxE,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,OAAO,IAAY,CAAC;IAEpB,SAAS,IAAI,CACX,GAAG,IAMoD;QAEvD,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,MAAM,OAAO,GACX,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ;YACvC,CAAC,CAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAY;YACnC,CAAC,CAAC,MAAM,CAAC;QACb,MAAM,MAAM,GAAG,CAAC,GAAQ,EAAE,EAAE,CAC1B,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAC5B,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CACrC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAChC,CACF;YACH,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,OAAO,GAAgB;YAC3B,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,KAAK;YACrC,QAAQ,EAAE,eAAe;YACzB,GAAG,MAAM,CAAC,cAAc,CAAC;YACzB,GAAG,MAAM,CAAC,QAAQ,CAAC;SACpB,CAAC;QAEF,MAAM,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;QAE9D,OAAO,EAAE,CACP,QAAQ,EACR,CAAC,GAAG,EAAE,EAAE;YACN,4DAA4D;YAC5D,IAAI,iBAAiB,GAAG,EAAE,CAAC;YAC3B,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;gBAC3B,iBAAiB,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;YAChD,CAAC;YAED,OAAO,OAAO,CAAC,GAAG,CAChB,GAAG,iBAAiB,GAAG,QAAQ,EAAE,EACjC;gBACE,GAAG,OAAO;gBACV,MAAM,EAAE,KAAK;aACd,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;gBACd,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACnC,CAAC,CACF,CAAC;QACJ,CAAC,EACD,OAAO,CACR,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Convert a snake_case string to camelCase.
3
+ * @example "account_id" -> "accountId", "created_at" -> "createdAt"
4
+ */
5
+ export declare function snakeToCamelString(s: string): string;
6
+ /**
7
+ * Recursively convert an object's keys from snake_case to camelCase.
8
+ * Arrays and nested objects are traversed; primitives, Date, and RegExp are returned as-is.
9
+ */
10
+ export declare function snakeToCamelObjectDeep<T>(obj: T): SnakeToCamel<T>;
11
+ /**
12
+ * Convert a snake_case string to camelCase at the type level.
13
+ */
14
+ export type SnakeToCamelString<S extends string> = S extends `${infer A}_${infer B}` ? `${A}${Capitalize<SnakeToCamelString<B>>}` : S;
15
+ /**
16
+ * Recursively convert an object type's keys from snake_case to camelCase.
17
+ */
18
+ export type SnakeToCamel<T> = T extends object ? T extends Array<infer U> ? Array<SnakeToCamel<U>> : T extends Date | RegExp | Function ? T : {
19
+ [K in keyof T as K extends string ? SnakeToCamelString<K> : K]: SnakeToCamel<T[K]>;
20
+ } : T;
21
+ //# sourceMappingURL=snake-to-camel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snake-to-camel.d.ts","sourceRoot":"","sources":["../../src/util/snake-to-camel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAuBjE;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAC7C,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,GAC7B,GAAG,CAAC,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,GAC1C,CAAC,CAAC;AAER;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAC1C,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GACtB,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GACtB,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,QAAQ,GAChC,CAAC,GACD;KACG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,MAAM,GAC7B,kBAAkB,CAAC,CAAC,CAAC,GACrB,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3B,GACL,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Convert a snake_case string to camelCase.
3
+ * @example "account_id" -> "accountId", "created_at" -> "createdAt"
4
+ */
5
+ export function snakeToCamelString(s) {
6
+ return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
7
+ }
8
+ /**
9
+ * Recursively convert an object's keys from snake_case to camelCase.
10
+ * Arrays and nested objects are traversed; primitives, Date, and RegExp are returned as-is.
11
+ */
12
+ export function snakeToCamelObjectDeep(obj) {
13
+ if (obj === undefined || obj === null) {
14
+ return obj;
15
+ }
16
+ if (typeof obj !== "object") {
17
+ return obj;
18
+ }
19
+ if (obj instanceof RegExp || obj instanceof Date) {
20
+ return obj;
21
+ }
22
+ if (Array.isArray(obj)) {
23
+ return obj.map(snakeToCamelObjectDeep);
24
+ }
25
+ return Object.fromEntries(Object.entries(obj).map(([key, value]) => [
26
+ snakeToCamelString(key),
27
+ typeof value === "object" && value !== null && !Array.isArray(value)
28
+ ? snakeToCamelObjectDeep(value)
29
+ : Array.isArray(value)
30
+ ? value.map(snakeToCamelObjectDeep)
31
+ : value,
32
+ ]));
33
+ }
34
+ //# sourceMappingURL=snake-to-camel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snake-to-camel.js","sourceRoot":"","sources":["../../src/util/snake-to-camel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAI,GAAM;IAC9C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO,GAAsB,CAAC;IAChC,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAsB,CAAC;IAChC,CAAC;IACD,IAAI,GAAG,YAAY,MAAM,IAAI,GAAG,YAAY,IAAI,EAAE,CAAC;QACjD,OAAO,GAAsB,CAAC;IAChC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAoB,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QACxC,kBAAkB,CAAC,GAAG,CAAC;QACvB,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAClE,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC;YAC/B,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACpB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC;gBACnC,CAAC,CAAC,KAAK;KACZ,CAAC,CACgB,CAAC;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.85.0",
3
+ "version": "0.85.2",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Sam Goodwin <sam@alchemy.run>",
6
6
  "homepage": "https://alchemy.run",
@@ -109,6 +109,12 @@ export interface AccountApiTokenProps extends CloudflareApiOptions {
109
109
  * Optional conditions for token use (like IP restrictions)
110
110
  */
111
111
  condition?: TokenCondition;
112
+
113
+ /**
114
+ * Whether to delete the token when removed from Alchemy
115
+ * @default true
116
+ */
117
+ delete?: boolean;
112
118
  }
113
119
 
114
120
  /**
@@ -261,7 +267,7 @@ export const AccountApiToken = Resource(
261
267
 
262
268
  if (this.phase === "delete") {
263
269
  // Delete token if we have an ID
264
- if (this.output?.id) {
270
+ if (this.output?.id && props.delete !== false) {
265
271
  try {
266
272
  const deleteResponse = await api.delete(
267
273
  `/accounts/${api.accountId}/tokens/${this.output.id}`,
@@ -360,11 +366,22 @@ export const AccountApiToken = Resource(
360
366
  }));
361
367
 
362
368
  throw new Error(
363
- `Error ${
364
- this.phase === "update" ? "updating" : "creating"
365
- } token '${tokenName}': ${
366
- errorData.errors?.[0]?.message || response.statusText
367
- }`,
369
+ [
370
+ `Error ${
371
+ this.phase === "update" ? "updating" : "creating"
372
+ } token '${tokenName}' (${response.status}): ${
373
+ errorData.errors?.[0]?.message || response.statusText
374
+ }`,
375
+ ...(api.credentials.type !== "api-key"
376
+ ? [
377
+ `\nTo create an Account API Token, you must use a Global API Key or an API Token with the "Account API Tokens Write" permission.`,
378
+ ]
379
+ : []),
380
+ ...(api.credentials.type === "oauth"
381
+ ? ["OAuth credentials are not supported."]
382
+ : []),
383
+ "See https://alchemy.run/guides/cloudflare/ for more details.",
384
+ ].join("\n"),
368
385
  );
369
386
  }
370
387
 
@@ -0,0 +1,89 @@
1
+ import type { AiSearchWebCrawlerSource } from "./ai-search.ts";
2
+
3
+ /**
4
+ * Parse a URL and extract the domain and path
5
+ */
6
+ function parseUrl(url: string): { domain: string; path: string } {
7
+ // Handle URLs with or without protocol
8
+ let normalized = url;
9
+ if (!normalized.includes("://")) {
10
+ normalized = `https://${normalized}`;
11
+ }
12
+
13
+ const parsed = new URL(normalized);
14
+ return {
15
+ domain: parsed.hostname,
16
+ path: parsed.pathname,
17
+ };
18
+ }
19
+
20
+ /**
21
+ * Convert a path to a glob pattern for path filtering
22
+ */
23
+ function pathToGlobPattern(path: string): string {
24
+ // Remove leading slash for pattern
25
+ const cleanPath = path.replace(/^\//, "");
26
+
27
+ if (!cleanPath || cleanPath === "/") {
28
+ // Root path - no filtering needed
29
+ return "**";
30
+ }
31
+
32
+ // Create a pattern that matches this path and its children
33
+ return `**/${cleanPath}**`;
34
+ }
35
+
36
+ /**
37
+ * Builds an AiSearchWebCrawlerSource configuration from URLs.
38
+ *
39
+ * This is a convenience helper that parses URLs and extracts the domain
40
+ * and path filters for use with AiSearch.
41
+ *
42
+ * @example
43
+ * // Crawl an entire domain
44
+ * const search = await AiSearch("docs-search", {
45
+ * source: AiCrawler(["https://docs.example.com"]),
46
+ * });
47
+ *
48
+ * @example
49
+ * // Crawl specific paths on a domain
50
+ * const search = await AiSearch("blog-search", {
51
+ * source: AiCrawler([
52
+ * "https://example.com/blog",
53
+ * "https://example.com/news",
54
+ * ]),
55
+ * });
56
+ *
57
+ * @param urls - URLs to crawl. All URLs must be from the same domain.
58
+ * @returns An AiSearchWebCrawlerSource configuration object
59
+ */
60
+ export function AiCrawler(urls: string[]): AiSearchWebCrawlerSource {
61
+ if (!urls || urls.length === 0) {
62
+ throw new Error("AiCrawler requires at least one URL");
63
+ }
64
+
65
+ // Parse all URLs
66
+ const parsed = urls.map(parseUrl);
67
+
68
+ // Verify all URLs are from the same domain
69
+ const domains = new Set(parsed.map((p) => p.domain));
70
+ if (domains.size > 1) {
71
+ throw new Error(
72
+ `All URLs must be from the same domain. Found: ${[...domains].join(", ")}`,
73
+ );
74
+ }
75
+
76
+ const domain = parsed[0].domain;
77
+
78
+ // Build include paths from URL paths
79
+ // Only add path filters if we have specific paths (not just root)
80
+ const paths = parsed.map((p) => p.path).filter((p) => p && p !== "/");
81
+ const includePaths =
82
+ paths.length > 0 ? paths.map(pathToGlobPattern) : undefined;
83
+
84
+ return {
85
+ type: "web-crawler",
86
+ domain,
87
+ includePaths,
88
+ };
89
+ }
@@ -0,0 +1,324 @@
1
+ import { alchemy } from "../alchemy.ts";
2
+ import type { Context } from "../context.ts";
3
+ import { Resource, ResourceKind } from "../resource.ts";
4
+ import type { Secret } from "../secret.ts";
5
+ import { AccountApiToken } from "./account-api-token.ts";
6
+ import { CloudflareApiError } from "./api-error.ts";
7
+ import { extractCloudflareResult } from "./api-response.ts";
8
+ import {
9
+ CloudflareApi,
10
+ createCloudflareApi,
11
+ type CloudflareApiOptions,
12
+ } from "./api.ts";
13
+
14
+ /**
15
+ * Properties for creating an AI Search Token
16
+ */
17
+ export interface AiSearchTokenProps extends CloudflareApiOptions {
18
+ /**
19
+ * Name of the token
20
+ * @default Uses the resource ID
21
+ */
22
+ name?: string;
23
+
24
+ /**
25
+ * Whether to adopt an existing token if one with the same name exists
26
+ * @default false
27
+ */
28
+ adopt?: boolean;
29
+
30
+ /**
31
+ * Whether to delete the token when removed from Alchemy
32
+ * @default true
33
+ */
34
+ delete?: boolean;
35
+ }
36
+
37
+ /**
38
+ * AI Search Token output
39
+ */
40
+ export type AiSearchToken = {
41
+ /**
42
+ * Resource type identifier for binding
43
+ * @internal
44
+ */
45
+ type: "ai_search_token";
46
+
47
+ /**
48
+ * The AI Search token ID (UUID)
49
+ */
50
+ tokenId: string;
51
+
52
+ /**
53
+ * The underlying account API token ID (for lifecycle management)
54
+ */
55
+ accountTokenId: string;
56
+
57
+ /**
58
+ * The account ID
59
+ */
60
+ accountId: string;
61
+
62
+ /**
63
+ * The account tag
64
+ */
65
+ accountTag: string;
66
+
67
+ /**
68
+ * Name of the token
69
+ */
70
+ name: string;
71
+
72
+ /**
73
+ * The CF API ID for this token
74
+ */
75
+ cfApiId: string;
76
+
77
+ /**
78
+ * The CF API key for this token (stored as Secret)
79
+ */
80
+ cfApiKey: Secret;
81
+
82
+ /**
83
+ * Whether the token is enabled
84
+ */
85
+ enabled: boolean;
86
+
87
+ /**
88
+ * When the token was created
89
+ */
90
+ createdAt: string;
91
+
92
+ /**
93
+ * When the token was last modified
94
+ */
95
+ modifiedAt: string;
96
+ };
97
+
98
+ /**
99
+ * API response for AI Search token
100
+ * @internal
101
+ */
102
+ interface AiSearchTokenApiResponse {
103
+ id: string;
104
+ account_id: string;
105
+ account_tag: string;
106
+ name: string;
107
+ cf_api_id: string;
108
+ cf_api_key: string;
109
+ enabled: boolean;
110
+ legacy: boolean;
111
+ created_at: string;
112
+ modified_at: string;
113
+ }
114
+
115
+ /**
116
+ * Type guard for AiSearchToken
117
+ */
118
+ export function isAiSearchToken(resource: unknown): resource is AiSearchToken {
119
+ return (
120
+ typeof resource === "object" &&
121
+ resource !== null &&
122
+ ((resource as any)[ResourceKind] === "cloudflare::AiSearchToken" ||
123
+ (resource as any).type === "ai_search_token")
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Creates an AI Search token for accessing AI Search instances.
129
+ *
130
+ * AI Search tokens are used to authenticate with the AI Search API and provide
131
+ * access to R2 buckets or other data sources for indexing.
132
+ *
133
+ * This resource automatically:
134
+ * 1. Creates an account API token with AI Search Index Engine and R2 Storage Write permissions
135
+ * 2. Registers that token with the AI Search service
136
+ *
137
+ * @example
138
+ * // Create an AI Search token
139
+ * const token = await AiSearchToken("my-token", {
140
+ * name: "docs-search-token",
141
+ * });
142
+ *
143
+ * // Use the token with an AI Search instance
144
+ * const search = await AiSearch("docs-search", {
145
+ * source: {
146
+ * type: "r2",
147
+ * bucket: myBucket,
148
+ * token: token,
149
+ * },
150
+ * });
151
+ *
152
+ * @example
153
+ * // Let AiSearch auto-create a token (recommended)
154
+ * const search = await AiSearch("docs-search", {
155
+ * source: {
156
+ * type: "r2",
157
+ * bucket: myBucket,
158
+ * },
159
+ * });
160
+ */
161
+ export const AiSearchToken = Resource(
162
+ "cloudflare::AiSearchToken",
163
+ async function (
164
+ this: Context<AiSearchToken>,
165
+ id: string,
166
+ props: AiSearchTokenProps,
167
+ ): Promise<AiSearchToken> {
168
+ const api = await createCloudflareApi(props);
169
+ const tokenName = props.name ?? this.scope.createPhysicalName(id);
170
+
171
+ if (this.phase === "delete") {
172
+ if (this.output?.tokenId && props.delete !== false) {
173
+ await deleteAiSearchToken(api, this.output.tokenId);
174
+ }
175
+
176
+ // The AccountApiToken will be cleaned up automatically by Alchemy's
177
+ // resource lifecycle management since it's a child resource
178
+
179
+ return this.destroy();
180
+ }
181
+
182
+ // For update, we can't really update tokens - just return existing
183
+ if (this.phase === "update" && this.output?.tokenId) {
184
+ return this.output;
185
+ }
186
+
187
+ // Create an account API token with AI Search + R2 permissions
188
+ const accountToken = await AccountApiToken("account-token", {
189
+ name: `${tokenName} (AI Search Service Token)`,
190
+ policies: [
191
+ {
192
+ effect: "allow",
193
+ permissionGroups: [
194
+ "AI Search Index Engine",
195
+ "Workers R2 Storage Write",
196
+ ],
197
+ resources: {
198
+ "com.cloudflare.api.account": "*",
199
+ },
200
+ },
201
+ ],
202
+ baseUrl: props.baseUrl,
203
+ profile: props.profile,
204
+ apiKey: props.apiKey,
205
+ apiToken: props.apiToken,
206
+ accountId: props.accountId,
207
+ email: props.email,
208
+ delete: props.delete,
209
+ });
210
+
211
+ if (!accountToken.value) {
212
+ throw new Error(
213
+ "Failed to create account API token for AI Search - no token value returned",
214
+ );
215
+ }
216
+
217
+ const cfApiId = accountToken.id;
218
+ const cfApiKey = accountToken.value.unencrypted;
219
+
220
+ // Register the token with AI Search
221
+ try {
222
+ const result = await createAiSearchToken(api, {
223
+ name: tokenName,
224
+ cf_api_id: cfApiId,
225
+ cf_api_key: cfApiKey,
226
+ });
227
+
228
+ return {
229
+ type: "ai_search_token" as const,
230
+ tokenId: result.id,
231
+ accountTokenId: accountToken.id,
232
+ accountId: result.account_id,
233
+ accountTag: result.account_tag,
234
+ name: result.name,
235
+ cfApiId: result.cf_api_id,
236
+ cfApiKey: alchemy.secret(cfApiKey),
237
+ enabled: result.enabled,
238
+ createdAt: result.created_at,
239
+ modifiedAt: result.modified_at,
240
+ };
241
+ } catch (error) {
242
+ // Check if token already exists and we should adopt it
243
+ if (error instanceof CloudflareApiError && props.adopt) {
244
+ // List tokens and find by name
245
+ const tokens = await listAiSearchTokens(api);
246
+ const existing = tokens.find((t) => t.name === tokenName);
247
+ if (existing) {
248
+ return {
249
+ type: "ai_search_token" as const,
250
+ tokenId: existing.id,
251
+ accountTokenId: accountToken.id,
252
+ accountId: existing.account_id,
253
+ accountTag: existing.account_tag,
254
+ name: existing.name,
255
+ cfApiId: existing.cf_api_id,
256
+ cfApiKey: alchemy.secret(cfApiKey),
257
+ enabled: existing.enabled,
258
+ createdAt: existing.created_at,
259
+ modifiedAt: existing.modified_at,
260
+ };
261
+ }
262
+ }
263
+ throw error;
264
+ }
265
+ },
266
+ );
267
+
268
+ /**
269
+ * Create an AI Search token
270
+ */
271
+ export async function createAiSearchToken(
272
+ api: CloudflareApi,
273
+ payload: { name: string; cf_api_id: string; cf_api_key: string },
274
+ ): Promise<AiSearchTokenApiResponse> {
275
+ return await extractCloudflareResult<AiSearchTokenApiResponse>(
276
+ `create AI Search token "${payload.name}"`,
277
+ api.post(`/accounts/${api.accountId}/ai-search/tokens`, payload),
278
+ );
279
+ }
280
+
281
+ /**
282
+ * List all AI Search tokens in an account
283
+ */
284
+ export async function listAiSearchTokens(
285
+ api: CloudflareApi,
286
+ ): Promise<AiSearchTokenApiResponse[]> {
287
+ return await extractCloudflareResult<AiSearchTokenApiResponse[]>(
288
+ `list AI Search tokens`,
289
+ api.get(`/accounts/${api.accountId}/ai-search/tokens`),
290
+ );
291
+ }
292
+
293
+ /**
294
+ * Delete an AI Search token
295
+ */
296
+ export async function deleteAiSearchToken(
297
+ api: CloudflareApi,
298
+ tokenId: string,
299
+ ): Promise<void> {
300
+ try {
301
+ await extractCloudflareResult(
302
+ `delete AI Search token "${tokenId}"`,
303
+ api.delete(`/accounts/${api.accountId}/ai-search/tokens/${tokenId}`),
304
+ );
305
+ } catch (error) {
306
+ if (error instanceof CloudflareApiError && error.status === 404) {
307
+ return;
308
+ }
309
+ throw error;
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Get an AI Search token
315
+ */
316
+ export async function getAiSearchToken(
317
+ api: CloudflareApi,
318
+ tokenId: string,
319
+ ): Promise<AiSearchTokenApiResponse> {
320
+ return await extractCloudflareResult<AiSearchTokenApiResponse>(
321
+ `get AI Search token "${tokenId}"`,
322
+ api.get(`/accounts/${api.accountId}/ai-search/tokens/${tokenId}`),
323
+ );
324
+ }