@01.software/sdk 0.1.3 → 0.1.5

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.
@@ -139,9 +139,7 @@ interface Config {
139
139
  globals: {};
140
140
  globalsSelect: {};
141
141
  locale: null;
142
- user: User & {
143
- collection: 'users';
144
- };
142
+ user: User;
145
143
  jobs: {
146
144
  tasks: unknown;
147
145
  workflows: unknown;
@@ -232,6 +230,7 @@ interface User {
232
230
  expiresAt: string;
233
231
  }[] | null;
234
232
  password?: string | null;
233
+ collection: 'users';
235
234
  }
236
235
  /**
237
236
  * This interface was referenced by `Config`'s JSON-Schema
@@ -591,6 +590,16 @@ interface TenantOgImage {
591
590
  height?: number | null;
592
591
  focalX?: number | null;
593
592
  focalY?: number | null;
593
+ sizes?: {
594
+ '1200'?: {
595
+ url?: string | null;
596
+ width?: number | null;
597
+ height?: number | null;
598
+ mimeType?: string | null;
599
+ filesize?: number | null;
600
+ filename?: string | null;
601
+ };
602
+ };
594
603
  }
595
604
  /**
596
605
  * This interface was referenced by `Config`'s JSON-Schema
@@ -621,6 +630,64 @@ interface TenantLogo {
621
630
  height?: number | null;
622
631
  focalX?: number | null;
623
632
  focalY?: number | null;
633
+ sizes?: {
634
+ '16'?: {
635
+ url?: string | null;
636
+ width?: number | null;
637
+ height?: number | null;
638
+ mimeType?: string | null;
639
+ filesize?: number | null;
640
+ filename?: string | null;
641
+ };
642
+ '32'?: {
643
+ url?: string | null;
644
+ width?: number | null;
645
+ height?: number | null;
646
+ mimeType?: string | null;
647
+ filesize?: number | null;
648
+ filename?: string | null;
649
+ };
650
+ '64'?: {
651
+ url?: string | null;
652
+ width?: number | null;
653
+ height?: number | null;
654
+ mimeType?: string | null;
655
+ filesize?: number | null;
656
+ filename?: string | null;
657
+ };
658
+ '128'?: {
659
+ url?: string | null;
660
+ width?: number | null;
661
+ height?: number | null;
662
+ mimeType?: string | null;
663
+ filesize?: number | null;
664
+ filename?: string | null;
665
+ };
666
+ '180'?: {
667
+ url?: string | null;
668
+ width?: number | null;
669
+ height?: number | null;
670
+ mimeType?: string | null;
671
+ filesize?: number | null;
672
+ filename?: string | null;
673
+ };
674
+ '192'?: {
675
+ url?: string | null;
676
+ width?: number | null;
677
+ height?: number | null;
678
+ mimeType?: string | null;
679
+ filesize?: number | null;
680
+ filename?: string | null;
681
+ };
682
+ '512'?: {
683
+ url?: string | null;
684
+ width?: number | null;
685
+ height?: number | null;
686
+ mimeType?: string | null;
687
+ filesize?: number | null;
688
+ filename?: string | null;
689
+ };
690
+ };
624
691
  }
625
692
  /**
626
693
  * This interface was referenced by `Config`'s JSON-Schema
@@ -898,6 +965,7 @@ interface ProductCategory {
898
965
  description?: string | null;
899
966
  image?: (number | null) | ProductImage;
900
967
  parent?: (number | null) | ProductCategory;
968
+ color?: string | null;
901
969
  updatedAt: string;
902
970
  createdAt: string;
903
971
  }
@@ -916,6 +984,9 @@ interface ProductTag {
916
984
  generateSlug?: boolean | null;
917
985
  slug?: string | null;
918
986
  description?: string | null;
987
+ image?: (number | null) | ProductImage;
988
+ parent?: (number | null) | ProductTag;
989
+ color?: string | null;
919
990
  updatedAt: string;
920
991
  createdAt: string;
921
992
  }
@@ -972,6 +1043,7 @@ interface ProductVariant {
972
1043
  * Override price (uses product price if empty)
973
1044
  */
974
1045
  price?: number | null;
1046
+ isSoldOut?: boolean | null;
975
1047
  images?: (number | ProductImage)[] | null;
976
1048
  productOptions?: {
977
1049
  docs?: (number | ProductOption)[];
@@ -1265,7 +1337,9 @@ interface PostCategory {
1265
1337
  generateSlug?: boolean | null;
1266
1338
  slug?: string | null;
1267
1339
  description?: string | null;
1340
+ image?: (number | null) | PostImage;
1268
1341
  parent?: (number | null) | PostCategory;
1342
+ color?: string | null;
1269
1343
  updatedAt: string;
1270
1344
  createdAt: string;
1271
1345
  }
@@ -1284,6 +1358,9 @@ interface PostTag {
1284
1358
  generateSlug?: boolean | null;
1285
1359
  slug?: string | null;
1286
1360
  description?: string | null;
1361
+ image?: (number | null) | PostImage;
1362
+ parent?: (number | null) | PostTag;
1363
+ color?: string | null;
1287
1364
  updatedAt: string;
1288
1365
  createdAt: string;
1289
1366
  }
@@ -1365,6 +1442,9 @@ interface DocumentCategory {
1365
1442
  generateSlug?: boolean | null;
1366
1443
  slug?: string | null;
1367
1444
  description?: string | null;
1445
+ image?: (number | null) | DocumentImage;
1446
+ parent?: (number | null) | DocumentCategory;
1447
+ color?: string | null;
1368
1448
  updatedAt: string;
1369
1449
  createdAt: string;
1370
1450
  }
@@ -2122,6 +2202,64 @@ interface TenantLogosSelect<T extends boolean = true> {
2122
2202
  height?: T;
2123
2203
  focalX?: T;
2124
2204
  focalY?: T;
2205
+ sizes?: T | {
2206
+ '16'?: T | {
2207
+ url?: T;
2208
+ width?: T;
2209
+ height?: T;
2210
+ mimeType?: T;
2211
+ filesize?: T;
2212
+ filename?: T;
2213
+ };
2214
+ '32'?: T | {
2215
+ url?: T;
2216
+ width?: T;
2217
+ height?: T;
2218
+ mimeType?: T;
2219
+ filesize?: T;
2220
+ filename?: T;
2221
+ };
2222
+ '64'?: T | {
2223
+ url?: T;
2224
+ width?: T;
2225
+ height?: T;
2226
+ mimeType?: T;
2227
+ filesize?: T;
2228
+ filename?: T;
2229
+ };
2230
+ '128'?: T | {
2231
+ url?: T;
2232
+ width?: T;
2233
+ height?: T;
2234
+ mimeType?: T;
2235
+ filesize?: T;
2236
+ filename?: T;
2237
+ };
2238
+ '180'?: T | {
2239
+ url?: T;
2240
+ width?: T;
2241
+ height?: T;
2242
+ mimeType?: T;
2243
+ filesize?: T;
2244
+ filename?: T;
2245
+ };
2246
+ '192'?: T | {
2247
+ url?: T;
2248
+ width?: T;
2249
+ height?: T;
2250
+ mimeType?: T;
2251
+ filesize?: T;
2252
+ filename?: T;
2253
+ };
2254
+ '512'?: T | {
2255
+ url?: T;
2256
+ width?: T;
2257
+ height?: T;
2258
+ mimeType?: T;
2259
+ filesize?: T;
2260
+ filename?: T;
2261
+ };
2262
+ };
2125
2263
  }
2126
2264
  /**
2127
2265
  * This interface was referenced by `Config`'s JSON-Schema
@@ -2151,6 +2289,16 @@ interface TenantOgImagesSelect<T extends boolean = true> {
2151
2289
  height?: T;
2152
2290
  focalX?: T;
2153
2291
  focalY?: T;
2292
+ sizes?: T | {
2293
+ '1200'?: T | {
2294
+ url?: T;
2295
+ width?: T;
2296
+ height?: T;
2297
+ mimeType?: T;
2298
+ filesize?: T;
2299
+ filename?: T;
2300
+ };
2301
+ };
2154
2302
  }
2155
2303
  /**
2156
2304
  * This interface was referenced by `Config`'s JSON-Schema
@@ -2273,6 +2421,7 @@ interface ProductVariantsSelect<T extends boolean = true> {
2273
2421
  title?: T;
2274
2422
  sku?: T;
2275
2423
  price?: T;
2424
+ isSoldOut?: T;
2276
2425
  images?: T;
2277
2426
  productOptions?: T;
2278
2427
  updatedAt?: T;
@@ -2309,6 +2458,7 @@ interface ProductCategoriesSelect<T extends boolean = true> {
2309
2458
  description?: T;
2310
2459
  image?: T;
2311
2460
  parent?: T;
2461
+ color?: T;
2312
2462
  updatedAt?: T;
2313
2463
  createdAt?: T;
2314
2464
  }
@@ -2323,6 +2473,9 @@ interface ProductTagsSelect<T extends boolean = true> {
2323
2473
  generateSlug?: T;
2324
2474
  slug?: T;
2325
2475
  description?: T;
2476
+ image?: T;
2477
+ parent?: T;
2478
+ color?: T;
2326
2479
  updatedAt?: T;
2327
2480
  createdAt?: T;
2328
2481
  }
@@ -2607,7 +2760,9 @@ interface PostCategoriesSelect<T extends boolean = true> {
2607
2760
  generateSlug?: T;
2608
2761
  slug?: T;
2609
2762
  description?: T;
2763
+ image?: T;
2610
2764
  parent?: T;
2765
+ color?: T;
2611
2766
  updatedAt?: T;
2612
2767
  createdAt?: T;
2613
2768
  }
@@ -2622,6 +2777,9 @@ interface PostTagsSelect<T extends boolean = true> {
2622
2777
  generateSlug?: T;
2623
2778
  slug?: T;
2624
2779
  description?: T;
2780
+ image?: T;
2781
+ parent?: T;
2782
+ color?: T;
2625
2783
  updatedAt?: T;
2626
2784
  createdAt?: T;
2627
2785
  }
@@ -2726,6 +2884,9 @@ interface DocumentCategoriesSelect<T extends boolean = true> {
2726
2884
  generateSlug?: T;
2727
2885
  slug?: T;
2728
2886
  description?: T;
2887
+ image?: T;
2888
+ parent?: T;
2889
+ color?: T;
2729
2890
  updatedAt?: T;
2730
2891
  createdAt?: T;
2731
2892
  }
@@ -139,9 +139,7 @@ interface Config {
139
139
  globals: {};
140
140
  globalsSelect: {};
141
141
  locale: null;
142
- user: User & {
143
- collection: 'users';
144
- };
142
+ user: User;
145
143
  jobs: {
146
144
  tasks: unknown;
147
145
  workflows: unknown;
@@ -232,6 +230,7 @@ interface User {
232
230
  expiresAt: string;
233
231
  }[] | null;
234
232
  password?: string | null;
233
+ collection: 'users';
235
234
  }
236
235
  /**
237
236
  * This interface was referenced by `Config`'s JSON-Schema
@@ -591,6 +590,16 @@ interface TenantOgImage {
591
590
  height?: number | null;
592
591
  focalX?: number | null;
593
592
  focalY?: number | null;
593
+ sizes?: {
594
+ '1200'?: {
595
+ url?: string | null;
596
+ width?: number | null;
597
+ height?: number | null;
598
+ mimeType?: string | null;
599
+ filesize?: number | null;
600
+ filename?: string | null;
601
+ };
602
+ };
594
603
  }
595
604
  /**
596
605
  * This interface was referenced by `Config`'s JSON-Schema
@@ -621,6 +630,64 @@ interface TenantLogo {
621
630
  height?: number | null;
622
631
  focalX?: number | null;
623
632
  focalY?: number | null;
633
+ sizes?: {
634
+ '16'?: {
635
+ url?: string | null;
636
+ width?: number | null;
637
+ height?: number | null;
638
+ mimeType?: string | null;
639
+ filesize?: number | null;
640
+ filename?: string | null;
641
+ };
642
+ '32'?: {
643
+ url?: string | null;
644
+ width?: number | null;
645
+ height?: number | null;
646
+ mimeType?: string | null;
647
+ filesize?: number | null;
648
+ filename?: string | null;
649
+ };
650
+ '64'?: {
651
+ url?: string | null;
652
+ width?: number | null;
653
+ height?: number | null;
654
+ mimeType?: string | null;
655
+ filesize?: number | null;
656
+ filename?: string | null;
657
+ };
658
+ '128'?: {
659
+ url?: string | null;
660
+ width?: number | null;
661
+ height?: number | null;
662
+ mimeType?: string | null;
663
+ filesize?: number | null;
664
+ filename?: string | null;
665
+ };
666
+ '180'?: {
667
+ url?: string | null;
668
+ width?: number | null;
669
+ height?: number | null;
670
+ mimeType?: string | null;
671
+ filesize?: number | null;
672
+ filename?: string | null;
673
+ };
674
+ '192'?: {
675
+ url?: string | null;
676
+ width?: number | null;
677
+ height?: number | null;
678
+ mimeType?: string | null;
679
+ filesize?: number | null;
680
+ filename?: string | null;
681
+ };
682
+ '512'?: {
683
+ url?: string | null;
684
+ width?: number | null;
685
+ height?: number | null;
686
+ mimeType?: string | null;
687
+ filesize?: number | null;
688
+ filename?: string | null;
689
+ };
690
+ };
624
691
  }
625
692
  /**
626
693
  * This interface was referenced by `Config`'s JSON-Schema
@@ -898,6 +965,7 @@ interface ProductCategory {
898
965
  description?: string | null;
899
966
  image?: (number | null) | ProductImage;
900
967
  parent?: (number | null) | ProductCategory;
968
+ color?: string | null;
901
969
  updatedAt: string;
902
970
  createdAt: string;
903
971
  }
@@ -916,6 +984,9 @@ interface ProductTag {
916
984
  generateSlug?: boolean | null;
917
985
  slug?: string | null;
918
986
  description?: string | null;
987
+ image?: (number | null) | ProductImage;
988
+ parent?: (number | null) | ProductTag;
989
+ color?: string | null;
919
990
  updatedAt: string;
920
991
  createdAt: string;
921
992
  }
@@ -972,6 +1043,7 @@ interface ProductVariant {
972
1043
  * Override price (uses product price if empty)
973
1044
  */
974
1045
  price?: number | null;
1046
+ isSoldOut?: boolean | null;
975
1047
  images?: (number | ProductImage)[] | null;
976
1048
  productOptions?: {
977
1049
  docs?: (number | ProductOption)[];
@@ -1265,7 +1337,9 @@ interface PostCategory {
1265
1337
  generateSlug?: boolean | null;
1266
1338
  slug?: string | null;
1267
1339
  description?: string | null;
1340
+ image?: (number | null) | PostImage;
1268
1341
  parent?: (number | null) | PostCategory;
1342
+ color?: string | null;
1269
1343
  updatedAt: string;
1270
1344
  createdAt: string;
1271
1345
  }
@@ -1284,6 +1358,9 @@ interface PostTag {
1284
1358
  generateSlug?: boolean | null;
1285
1359
  slug?: string | null;
1286
1360
  description?: string | null;
1361
+ image?: (number | null) | PostImage;
1362
+ parent?: (number | null) | PostTag;
1363
+ color?: string | null;
1287
1364
  updatedAt: string;
1288
1365
  createdAt: string;
1289
1366
  }
@@ -1365,6 +1442,9 @@ interface DocumentCategory {
1365
1442
  generateSlug?: boolean | null;
1366
1443
  slug?: string | null;
1367
1444
  description?: string | null;
1445
+ image?: (number | null) | DocumentImage;
1446
+ parent?: (number | null) | DocumentCategory;
1447
+ color?: string | null;
1368
1448
  updatedAt: string;
1369
1449
  createdAt: string;
1370
1450
  }
@@ -2122,6 +2202,64 @@ interface TenantLogosSelect<T extends boolean = true> {
2122
2202
  height?: T;
2123
2203
  focalX?: T;
2124
2204
  focalY?: T;
2205
+ sizes?: T | {
2206
+ '16'?: T | {
2207
+ url?: T;
2208
+ width?: T;
2209
+ height?: T;
2210
+ mimeType?: T;
2211
+ filesize?: T;
2212
+ filename?: T;
2213
+ };
2214
+ '32'?: T | {
2215
+ url?: T;
2216
+ width?: T;
2217
+ height?: T;
2218
+ mimeType?: T;
2219
+ filesize?: T;
2220
+ filename?: T;
2221
+ };
2222
+ '64'?: T | {
2223
+ url?: T;
2224
+ width?: T;
2225
+ height?: T;
2226
+ mimeType?: T;
2227
+ filesize?: T;
2228
+ filename?: T;
2229
+ };
2230
+ '128'?: T | {
2231
+ url?: T;
2232
+ width?: T;
2233
+ height?: T;
2234
+ mimeType?: T;
2235
+ filesize?: T;
2236
+ filename?: T;
2237
+ };
2238
+ '180'?: T | {
2239
+ url?: T;
2240
+ width?: T;
2241
+ height?: T;
2242
+ mimeType?: T;
2243
+ filesize?: T;
2244
+ filename?: T;
2245
+ };
2246
+ '192'?: T | {
2247
+ url?: T;
2248
+ width?: T;
2249
+ height?: T;
2250
+ mimeType?: T;
2251
+ filesize?: T;
2252
+ filename?: T;
2253
+ };
2254
+ '512'?: T | {
2255
+ url?: T;
2256
+ width?: T;
2257
+ height?: T;
2258
+ mimeType?: T;
2259
+ filesize?: T;
2260
+ filename?: T;
2261
+ };
2262
+ };
2125
2263
  }
2126
2264
  /**
2127
2265
  * This interface was referenced by `Config`'s JSON-Schema
@@ -2151,6 +2289,16 @@ interface TenantOgImagesSelect<T extends boolean = true> {
2151
2289
  height?: T;
2152
2290
  focalX?: T;
2153
2291
  focalY?: T;
2292
+ sizes?: T | {
2293
+ '1200'?: T | {
2294
+ url?: T;
2295
+ width?: T;
2296
+ height?: T;
2297
+ mimeType?: T;
2298
+ filesize?: T;
2299
+ filename?: T;
2300
+ };
2301
+ };
2154
2302
  }
2155
2303
  /**
2156
2304
  * This interface was referenced by `Config`'s JSON-Schema
@@ -2273,6 +2421,7 @@ interface ProductVariantsSelect<T extends boolean = true> {
2273
2421
  title?: T;
2274
2422
  sku?: T;
2275
2423
  price?: T;
2424
+ isSoldOut?: T;
2276
2425
  images?: T;
2277
2426
  productOptions?: T;
2278
2427
  updatedAt?: T;
@@ -2309,6 +2458,7 @@ interface ProductCategoriesSelect<T extends boolean = true> {
2309
2458
  description?: T;
2310
2459
  image?: T;
2311
2460
  parent?: T;
2461
+ color?: T;
2312
2462
  updatedAt?: T;
2313
2463
  createdAt?: T;
2314
2464
  }
@@ -2323,6 +2473,9 @@ interface ProductTagsSelect<T extends boolean = true> {
2323
2473
  generateSlug?: T;
2324
2474
  slug?: T;
2325
2475
  description?: T;
2476
+ image?: T;
2477
+ parent?: T;
2478
+ color?: T;
2326
2479
  updatedAt?: T;
2327
2480
  createdAt?: T;
2328
2481
  }
@@ -2607,7 +2760,9 @@ interface PostCategoriesSelect<T extends boolean = true> {
2607
2760
  generateSlug?: T;
2608
2761
  slug?: T;
2609
2762
  description?: T;
2763
+ image?: T;
2610
2764
  parent?: T;
2765
+ color?: T;
2611
2766
  updatedAt?: T;
2612
2767
  createdAt?: T;
2613
2768
  }
@@ -2622,6 +2777,9 @@ interface PostTagsSelect<T extends boolean = true> {
2622
2777
  generateSlug?: T;
2623
2778
  slug?: T;
2624
2779
  description?: T;
2780
+ image?: T;
2781
+ parent?: T;
2782
+ color?: T;
2625
2783
  updatedAt?: T;
2626
2784
  createdAt?: T;
2627
2785
  }
@@ -2726,6 +2884,9 @@ interface DocumentCategoriesSelect<T extends boolean = true> {
2726
2884
  generateSlug?: T;
2727
2885
  slug?: T;
2728
2886
  description?: T;
2887
+ image?: T;
2888
+ parent?: T;
2889
+ color?: T;
2729
2890
  updatedAt?: T;
2730
2891
  createdAt?: T;
2731
2892
  }
@@ -1,4 +1,4 @@
1
- import { C as Config } from './payload-types-D-pPck9V.js';
1
+ import { C as Config } from './payload-types-BAZCcssT.js';
2
2
 
3
3
  /**
4
4
  * Collection type derived from Payload Config.
@@ -1,4 +1,4 @@
1
- import { C as Config } from './payload-types-D-pPck9V.cjs';
1
+ import { C as Config } from './payload-types-BAZCcssT.cjs';
2
2
 
3
3
  /**
4
4
  * Collection type derived from Payload Config.
package/dist/webhook.cjs CHANGED
@@ -64,10 +64,10 @@ function verifySignature(payload, secret, signature) {
64
64
  );
65
65
  const sig = yield crypto.subtle.sign("HMAC", key, encoder.encode(payload));
66
66
  const expected = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
67
- if (expected.length !== signature.length) return false;
68
- let result = 0;
69
- for (let i = 0; i < expected.length; i++) {
70
- result |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
67
+ let result = expected.length !== signature.length ? 1 : 0;
68
+ const len = Math.max(expected.length, signature.length);
69
+ for (let i = 0; i < len; i++) {
70
+ result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0);
71
71
  }
72
72
  return result === 0;
73
73
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.tsx"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n isValidWebhookEvent,\n} from './core/webhook'\nexport type {\n WebhookEvent,\n WebhookHandler,\n WebhookOperation,\n WebhookOptions,\n} from './core/webhook'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n if (expected.length !== signature.length) return false\n let result = 0\n for (let i = 0; i < expected.length; i++) {\n result |= expected.charCodeAt(i) ^ signature.charCodeAt(i)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const valid = await verifySignature(rawBody, options.secret, signature)\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(\n JSON.stringify({\n error: 'Internal server error',\n message: error instanceof Error ? error.message : 'Unknown error',\n }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(`Expected collection \"${collection}\", got \"${event.collection}\"`)\n }\n return handler(event)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmBO,SAAS,oBAAoB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,eAAe,aACzB,IAAI,cAAc,YAAY,IAAI,cAAc,aACjD,OAAO,IAAI,SAAS,YACpB,IAAI,SAAS;AAEjB;AAEA,SAAe,gBACb,SACA,QACA,WACkB;AAAA;AAClB,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,MAAM,MAAM,OAAO,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ,OAAO,MAAM;AAAA,MACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC;AAAA,MACA,CAAC,MAAM;AAAA,IACT;AACA,UAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC;AACzE,UAAM,WAAW,MAAM,KAAK,IAAI,WAAW,GAAG,CAAC,EAC5C,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AAEV,QAAI,SAAS,WAAW,UAAU,OAAQ,QAAO;AACjD,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,gBAAU,SAAS,WAAW,CAAC,IAAI,UAAU,WAAW,CAAC;AAAA,IAC3D;AACA,WAAO,WAAW;AAAA,EACpB;AAAA;AAEA,SAAsB,cACpB,SACA,SACA,SACmB;AAAA;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,UAAI,mCAAS,QAAQ;AACnB,cAAM,YAAY,QAAQ,QAAQ,IAAI,qBAAqB,KAAK;AAChE,cAAM,QAAQ,MAAM,gBAAgB,SAAS,QAAQ,QAAQ,SAAS;AACtE,YAAI,CAAC,OAAO;AACV,iBAAO,IAAI;AAAA,YACT,KAAK,UAAU,EAAE,OAAO,4BAA4B,CAAC;AAAA,YACrD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,UAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,eAAO,IAAI;AAAA,UACT,KAAK,UAAU,EAAE,OAAO,+BAA+B,CAAC;AAAA,UACxD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,QACjE;AAAA,MACF;AAEA,YAAM,QAAQ,IAAuB;AAErC,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,SAAS,MAAM,SAAS,oBAAoB,CAAC;AAAA,QAC9D,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAEhD,aAAO,IAAI;AAAA,QACT,KAAK,UAAU;AAAA,UACb,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD,CAAC;AAAA,QACD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAEO,SAAS,0BACd,YACA,SACmB;AACnB,SAAO,CAAO,UAA2B;AACvC,QAAI,MAAM,eAAe,YAAY;AACnC,YAAM,IAAI,MAAM,wBAAwB,UAAU,WAAW,MAAM,UAAU,GAAG;AAAA,IAClF;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/webhook.ts","../src/core/webhook/index.tsx"],"sourcesContent":["export {\n handleWebhook,\n createTypedWebhookHandler,\n isValidWebhookEvent,\n} from './core/webhook'\nexport type {\n WebhookEvent,\n WebhookHandler,\n WebhookOperation,\n WebhookOptions,\n} from './core/webhook'\n","import type { Collection } from '../client/types'\nimport type { CollectionType } from '../collection/types'\n\nexport type WebhookOperation = 'create' | 'update'\n\nexport interface WebhookEvent<T extends Collection = Collection> {\n collection: T\n operation: WebhookOperation\n data: CollectionType<T>\n}\n\nexport type WebhookHandler<T extends Collection = Collection> = (\n event: WebhookEvent<T>,\n) => Promise<void> | void\n\nexport interface WebhookOptions {\n secret?: string\n}\n\nexport function isValidWebhookEvent(data: unknown): data is WebhookEvent {\n if (typeof data !== 'object' || data === null) return false\n const obj = data as Record<string, unknown>\n return (\n typeof obj.collection === 'string' &&\n (obj.operation === 'create' || obj.operation === 'update') &&\n typeof obj.data === 'object' &&\n obj.data !== null\n )\n}\n\nasync function verifySignature(\n payload: string,\n secret: string,\n signature: string,\n): Promise<boolean> {\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(payload))\n const expected = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n // Constant-time comparison to prevent timing attacks\n let result = expected.length !== signature.length ? 1 : 0\n const len = Math.max(expected.length, signature.length)\n for (let i = 0; i < len; i++) {\n result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0)\n }\n return result === 0\n}\n\nexport async function handleWebhook<T extends Collection = Collection>(\n request: Request,\n handler: WebhookHandler<T>,\n options?: WebhookOptions,\n): Promise<Response> {\n try {\n const rawBody = await request.text()\n\n if (options?.secret) {\n const signature = request.headers.get('x-webhook-signature') || ''\n const valid = await verifySignature(rawBody, options.secret, signature)\n if (!valid) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook signature' }),\n { status: 401, headers: { 'Content-Type': 'application/json' } },\n )\n }\n }\n\n const body = JSON.parse(rawBody)\n\n if (!isValidWebhookEvent(body)) {\n return new Response(\n JSON.stringify({ error: 'Invalid webhook event format' }),\n { status: 400, headers: { 'Content-Type': 'application/json' } },\n )\n }\n\n await handler(body as WebhookEvent<T>)\n\n return new Response(\n JSON.stringify({ success: true, message: 'Webhook processed' }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n )\n } catch (error) {\n console.error('Webhook processing error:', error)\n\n return new Response(\n JSON.stringify({\n error: 'Internal server error',\n message: error instanceof Error ? error.message : 'Unknown error',\n }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n}\n\nexport function createTypedWebhookHandler<T extends Collection>(\n collection: T,\n handler: (event: WebhookEvent<T>) => Promise<void> | void,\n): WebhookHandler<T> {\n return async (event: WebhookEvent<T>) => {\n if (event.collection !== collection) {\n throw new Error(`Expected collection \"${collection}\", got \"${event.collection}\"`)\n }\n return handler(event)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmBO,SAAS,oBAAoB,MAAqC;AACvE,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,eAAe,aACzB,IAAI,cAAc,YAAY,IAAI,cAAc,aACjD,OAAO,IAAI,SAAS,YACpB,IAAI,SAAS;AAEjB;AAEA,SAAe,gBACb,SACA,QACA,WACkB;AAAA;AAClB,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,MAAM,MAAM,OAAO,OAAO;AAAA,MAC9B;AAAA,MACA,QAAQ,OAAO,MAAM;AAAA,MACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC;AAAA,MACA,CAAC,MAAM;AAAA,IACT;AACA,UAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC;AACzE,UAAM,WAAW,MAAM,KAAK,IAAI,WAAW,GAAG,CAAC,EAC5C,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AAEV,QAAI,SAAS,SAAS,WAAW,UAAU,SAAS,IAAI;AACxD,UAAM,MAAM,KAAK,IAAI,SAAS,QAAQ,UAAU,MAAM;AACtD,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,iBAAW,SAAS,WAAW,CAAC,KAAK,MAAM,UAAU,WAAW,CAAC,KAAK;AAAA,IACxE;AACA,WAAO,WAAW;AAAA,EACpB;AAAA;AAEA,SAAsB,cACpB,SACA,SACA,SACmB;AAAA;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,QAAQ,KAAK;AAEnC,UAAI,mCAAS,QAAQ;AACnB,cAAM,YAAY,QAAQ,QAAQ,IAAI,qBAAqB,KAAK;AAChE,cAAM,QAAQ,MAAM,gBAAgB,SAAS,QAAQ,QAAQ,SAAS;AACtE,YAAI,CAAC,OAAO;AACV,iBAAO,IAAI;AAAA,YACT,KAAK,UAAU,EAAE,OAAO,4BAA4B,CAAC;AAAA,YACrD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,UAAI,CAAC,oBAAoB,IAAI,GAAG;AAC9B,eAAO,IAAI;AAAA,UACT,KAAK,UAAU,EAAE,OAAO,+BAA+B,CAAC;AAAA,UACxD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,QACjE;AAAA,MACF;AAEA,YAAM,QAAQ,IAAuB;AAErC,aAAO,IAAI;AAAA,QACT,KAAK,UAAU,EAAE,SAAS,MAAM,SAAS,oBAAoB,CAAC;AAAA,QAC9D,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAEhD,aAAO,IAAI;AAAA,QACT,KAAK,UAAU;AAAA,UACb,OAAO;AAAA,UACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACpD,CAAC;AAAA,QACD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAEO,SAAS,0BACd,YACA,SACmB;AACnB,SAAO,CAAO,UAA2B;AACvC,QAAI,MAAM,eAAe,YAAY;AACnC,YAAM,IAAI,MAAM,wBAAwB,UAAU,WAAW,MAAM,UAAU,GAAG;AAAA,IAClF;AACA,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;","names":[]}
@@ -1,2 +1,2 @@
1
- export { c as WebhookEvent, d as WebhookHandler, W as WebhookOperation, e as WebhookOptions, f as createTypedWebhookHandler, h as handleWebhook, i as isValidWebhookEvent } from './webhook-CeKIz4r5.cjs';
2
- import './payload-types-D-pPck9V.cjs';
1
+ export { c as WebhookEvent, d as WebhookHandler, W as WebhookOperation, e as WebhookOptions, f as createTypedWebhookHandler, h as handleWebhook, i as isValidWebhookEvent } from './webhook-DdNkaI-f.cjs';
2
+ import './payload-types-BAZCcssT.cjs';
package/dist/webhook.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { c as WebhookEvent, d as WebhookHandler, W as WebhookOperation, e as WebhookOptions, f as createTypedWebhookHandler, h as handleWebhook, i as isValidWebhookEvent } from './webhook-CC3SGR_a.js';
2
- import './payload-types-D-pPck9V.js';
1
+ export { c as WebhookEvent, d as WebhookHandler, W as WebhookOperation, e as WebhookOptions, f as createTypedWebhookHandler, h as handleWebhook, i as isValidWebhookEvent } from './webhook-CYJ0OPds.js';
2
+ import './payload-types-BAZCcssT.js';
package/dist/webhook.js CHANGED
@@ -37,10 +37,10 @@ function verifySignature(payload, secret, signature) {
37
37
  );
38
38
  const sig = yield crypto.subtle.sign("HMAC", key, encoder.encode(payload));
39
39
  const expected = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
40
- if (expected.length !== signature.length) return false;
41
- let result = 0;
42
- for (let i = 0; i < expected.length; i++) {
43
- result |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
40
+ let result = expected.length !== signature.length ? 1 : 0;
41
+ const len = Math.max(expected.length, signature.length);
42
+ for (let i = 0; i < len; i++) {
43
+ result |= (expected.charCodeAt(i) || 0) ^ (signature.charCodeAt(i) || 0);
44
44
  }
45
45
  return result === 0;
46
46
  });