@nfcard/validation 0.19.0 → 0.21.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { z } from 'zod';
1
+ import * as _nfcard_types from '@nfcard/types';
2
2
  import { CardAsset, CardElement, ElementTransform } from '@nfcard/types';
3
+ import { z } from 'zod';
3
4
 
4
5
  /**
5
6
  * Manufacturing-printability envelope for the free-transform element layer
@@ -5181,6 +5182,24 @@ declare const ctaButtonsSchema: z.ZodEffects<z.ZodArray<z.ZodObject<{
5181
5182
  url?: string | undefined;
5182
5183
  label?: string | undefined;
5183
5184
  }[]>;
5185
+ declare const tipJarSchema: z.ZodEffects<z.ZodUnknown, {
5186
+ provider: _nfcard_types.TipProviderId;
5187
+ handle: string;
5188
+ label: string;
5189
+ } | {
5190
+ provider: _nfcard_types.TipProviderId;
5191
+ handle: string;
5192
+ label?: undefined;
5193
+ } | undefined, unknown>;
5194
+ declare const bookingSchema: z.ZodEffects<z.ZodUnknown, {
5195
+ provider: _nfcard_types.BookingProviderId;
5196
+ handle: string;
5197
+ label: string;
5198
+ } | {
5199
+ provider: _nfcard_types.BookingProviderId;
5200
+ handle: string;
5201
+ label?: undefined;
5202
+ } | undefined, unknown>;
5184
5203
  declare const digitalConfigSchema: z.ZodObject<{
5185
5204
  templateId: z.ZodEnum<["minimal", "bold", "card", "aurora", "classic", "spotlight", "marquee", "riso"]>;
5186
5205
  accentColor: z.ZodString;
@@ -5268,6 +5287,24 @@ declare const digitalConfigSchema: z.ZodObject<{
5268
5287
  url?: string | undefined;
5269
5288
  label?: string | undefined;
5270
5289
  }[]>>;
5290
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
5291
+ provider: _nfcard_types.TipProviderId;
5292
+ handle: string;
5293
+ label: string;
5294
+ } | {
5295
+ provider: _nfcard_types.TipProviderId;
5296
+ handle: string;
5297
+ label?: undefined;
5298
+ } | undefined, unknown>>;
5299
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
5300
+ provider: _nfcard_types.BookingProviderId;
5301
+ handle: string;
5302
+ label: string;
5303
+ } | {
5304
+ provider: _nfcard_types.BookingProviderId;
5305
+ handle: string;
5306
+ label?: undefined;
5307
+ } | undefined, unknown>>;
5271
5308
  }, "strip", z.ZodTypeAny, {
5272
5309
  fontKey: string;
5273
5310
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -5303,6 +5340,24 @@ declare const digitalConfigSchema: z.ZodObject<{
5303
5340
  url: string;
5304
5341
  label: string;
5305
5342
  }[] | undefined;
5343
+ tipJar?: {
5344
+ provider: _nfcard_types.TipProviderId;
5345
+ handle: string;
5346
+ label: string;
5347
+ } | {
5348
+ provider: _nfcard_types.TipProviderId;
5349
+ handle: string;
5350
+ label?: undefined;
5351
+ } | undefined;
5352
+ booking?: {
5353
+ provider: _nfcard_types.BookingProviderId;
5354
+ handle: string;
5355
+ label: string;
5356
+ } | {
5357
+ provider: _nfcard_types.BookingProviderId;
5358
+ handle: string;
5359
+ label?: undefined;
5360
+ } | undefined;
5306
5361
  }, {
5307
5362
  fontKey: string;
5308
5363
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -5338,6 +5393,8 @@ declare const digitalConfigSchema: z.ZodObject<{
5338
5393
  url?: string | undefined;
5339
5394
  label?: string | undefined;
5340
5395
  }[] | undefined;
5396
+ tipJar?: unknown;
5397
+ booking?: unknown;
5341
5398
  }>;
5342
5399
  declare const entrySourceSchema: z.ZodObject<{
5343
5400
  output: z.ZodOptional<z.ZodEnum<["with-card", "digital-only"]>>;
@@ -8831,6 +8888,24 @@ declare const configurationCreateSchema: z.ZodObject<{
8831
8888
  url?: string | undefined;
8832
8889
  label?: string | undefined;
8833
8890
  }[]>>;
8891
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
8892
+ provider: _nfcard_types.TipProviderId;
8893
+ handle: string;
8894
+ label: string;
8895
+ } | {
8896
+ provider: _nfcard_types.TipProviderId;
8897
+ handle: string;
8898
+ label?: undefined;
8899
+ } | undefined, unknown>>;
8900
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
8901
+ provider: _nfcard_types.BookingProviderId;
8902
+ handle: string;
8903
+ label: string;
8904
+ } | {
8905
+ provider: _nfcard_types.BookingProviderId;
8906
+ handle: string;
8907
+ label?: undefined;
8908
+ } | undefined, unknown>>;
8834
8909
  }, "strip", z.ZodTypeAny, {
8835
8910
  fontKey: string;
8836
8911
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -8866,6 +8941,24 @@ declare const configurationCreateSchema: z.ZodObject<{
8866
8941
  url: string;
8867
8942
  label: string;
8868
8943
  }[] | undefined;
8944
+ tipJar?: {
8945
+ provider: _nfcard_types.TipProviderId;
8946
+ handle: string;
8947
+ label: string;
8948
+ } | {
8949
+ provider: _nfcard_types.TipProviderId;
8950
+ handle: string;
8951
+ label?: undefined;
8952
+ } | undefined;
8953
+ booking?: {
8954
+ provider: _nfcard_types.BookingProviderId;
8955
+ handle: string;
8956
+ label: string;
8957
+ } | {
8958
+ provider: _nfcard_types.BookingProviderId;
8959
+ handle: string;
8960
+ label?: undefined;
8961
+ } | undefined;
8869
8962
  }, {
8870
8963
  fontKey: string;
8871
8964
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -8901,6 +8994,8 @@ declare const configurationCreateSchema: z.ZodObject<{
8901
8994
  url?: string | undefined;
8902
8995
  label?: string | undefined;
8903
8996
  }[] | undefined;
8997
+ tipJar?: unknown;
8998
+ booking?: unknown;
8904
8999
  }>;
8905
9000
  quantity: z.ZodDefault<z.ZodNumber>;
8906
9001
  existingProfileId: z.ZodOptional<z.ZodString>;
@@ -9285,6 +9380,24 @@ declare const configurationCreateSchema: z.ZodObject<{
9285
9380
  url: string;
9286
9381
  label: string;
9287
9382
  }[] | undefined;
9383
+ tipJar?: {
9384
+ provider: _nfcard_types.TipProviderId;
9385
+ handle: string;
9386
+ label: string;
9387
+ } | {
9388
+ provider: _nfcard_types.TipProviderId;
9389
+ handle: string;
9390
+ label?: undefined;
9391
+ } | undefined;
9392
+ booking?: {
9393
+ provider: _nfcard_types.BookingProviderId;
9394
+ handle: string;
9395
+ label: string;
9396
+ } | {
9397
+ provider: _nfcard_types.BookingProviderId;
9398
+ handle: string;
9399
+ label?: undefined;
9400
+ } | undefined;
9288
9401
  };
9289
9402
  quantity: number;
9290
9403
  existingProfileId?: string | undefined;
@@ -9651,6 +9764,8 @@ declare const configurationCreateSchema: z.ZodObject<{
9651
9764
  url?: string | undefined;
9652
9765
  label?: string | undefined;
9653
9766
  }[] | undefined;
9767
+ tipJar?: unknown;
9768
+ booking?: unknown;
9654
9769
  };
9655
9770
  quantity?: number | undefined;
9656
9771
  existingProfileId?: string | undefined;
@@ -13129,6 +13244,24 @@ declare const configurationUpdateSchema: z.ZodObject<{
13129
13244
  url?: string | undefined;
13130
13245
  label?: string | undefined;
13131
13246
  }[]>>;
13247
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
13248
+ provider: _nfcard_types.TipProviderId;
13249
+ handle: string;
13250
+ label: string;
13251
+ } | {
13252
+ provider: _nfcard_types.TipProviderId;
13253
+ handle: string;
13254
+ label?: undefined;
13255
+ } | undefined, unknown>>;
13256
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
13257
+ provider: _nfcard_types.BookingProviderId;
13258
+ handle: string;
13259
+ label: string;
13260
+ } | {
13261
+ provider: _nfcard_types.BookingProviderId;
13262
+ handle: string;
13263
+ label?: undefined;
13264
+ } | undefined, unknown>>;
13132
13265
  }, "strip", z.ZodTypeAny, {
13133
13266
  fontKey: string;
13134
13267
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -13164,6 +13297,24 @@ declare const configurationUpdateSchema: z.ZodObject<{
13164
13297
  url: string;
13165
13298
  label: string;
13166
13299
  }[] | undefined;
13300
+ tipJar?: {
13301
+ provider: _nfcard_types.TipProviderId;
13302
+ handle: string;
13303
+ label: string;
13304
+ } | {
13305
+ provider: _nfcard_types.TipProviderId;
13306
+ handle: string;
13307
+ label?: undefined;
13308
+ } | undefined;
13309
+ booking?: {
13310
+ provider: _nfcard_types.BookingProviderId;
13311
+ handle: string;
13312
+ label: string;
13313
+ } | {
13314
+ provider: _nfcard_types.BookingProviderId;
13315
+ handle: string;
13316
+ label?: undefined;
13317
+ } | undefined;
13167
13318
  }, {
13168
13319
  fontKey: string;
13169
13320
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -13199,6 +13350,8 @@ declare const configurationUpdateSchema: z.ZodObject<{
13199
13350
  url?: string | undefined;
13200
13351
  label?: string | undefined;
13201
13352
  }[] | undefined;
13353
+ tipJar?: unknown;
13354
+ booking?: unknown;
13202
13355
  }>>;
13203
13356
  quantity: z.ZodOptional<z.ZodNumber>;
13204
13357
  existingProfileId: z.ZodOptional<z.ZodString>;
@@ -13554,6 +13707,24 @@ declare const configurationUpdateSchema: z.ZodObject<{
13554
13707
  url: string;
13555
13708
  label: string;
13556
13709
  }[] | undefined;
13710
+ tipJar?: {
13711
+ provider: _nfcard_types.TipProviderId;
13712
+ handle: string;
13713
+ label: string;
13714
+ } | {
13715
+ provider: _nfcard_types.TipProviderId;
13716
+ handle: string;
13717
+ label?: undefined;
13718
+ } | undefined;
13719
+ booking?: {
13720
+ provider: _nfcard_types.BookingProviderId;
13721
+ handle: string;
13722
+ label: string;
13723
+ } | {
13724
+ provider: _nfcard_types.BookingProviderId;
13725
+ handle: string;
13726
+ label?: undefined;
13727
+ } | undefined;
13557
13728
  } | undefined;
13558
13729
  quantity?: number | undefined;
13559
13730
  existingProfileId?: string | undefined;
@@ -13909,6 +14080,8 @@ declare const configurationUpdateSchema: z.ZodObject<{
13909
14080
  url?: string | undefined;
13910
14081
  label?: string | undefined;
13911
14082
  }[] | undefined;
14083
+ tipJar?: unknown;
14084
+ booking?: unknown;
13912
14085
  } | undefined;
13913
14086
  quantity?: number | undefined;
13914
14087
  existingProfileId?: string | undefined;
@@ -14015,6 +14188,24 @@ declare const cardUpdateSchema: z.ZodObject<{
14015
14188
  url?: string | undefined;
14016
14189
  label?: string | undefined;
14017
14190
  }[]>>>>;
14191
+ tipJar: z.ZodOptional<z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
14192
+ provider: _nfcard_types.TipProviderId;
14193
+ handle: string;
14194
+ label: string;
14195
+ } | {
14196
+ provider: _nfcard_types.TipProviderId;
14197
+ handle: string;
14198
+ label?: undefined;
14199
+ } | undefined, unknown>>>>;
14200
+ booking: z.ZodOptional<z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
14201
+ provider: _nfcard_types.BookingProviderId;
14202
+ handle: string;
14203
+ label: string;
14204
+ } | {
14205
+ provider: _nfcard_types.BookingProviderId;
14206
+ handle: string;
14207
+ label?: undefined;
14208
+ } | undefined, unknown>>>>;
14018
14209
  profilePhotoUrl: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>>;
14019
14210
  companyLogoUrl: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>>;
14020
14211
  }, "strip", z.ZodTypeAny, {
@@ -14054,6 +14245,24 @@ declare const cardUpdateSchema: z.ZodObject<{
14054
14245
  url: string;
14055
14246
  label: string;
14056
14247
  }[] | undefined;
14248
+ tipJar?: {
14249
+ provider: _nfcard_types.TipProviderId;
14250
+ handle: string;
14251
+ label: string;
14252
+ } | {
14253
+ provider: _nfcard_types.TipProviderId;
14254
+ handle: string;
14255
+ label?: undefined;
14256
+ } | undefined;
14257
+ booking?: {
14258
+ provider: _nfcard_types.BookingProviderId;
14259
+ handle: string;
14260
+ label: string;
14261
+ } | {
14262
+ provider: _nfcard_types.BookingProviderId;
14263
+ handle: string;
14264
+ label?: undefined;
14265
+ } | undefined;
14057
14266
  }, {
14058
14267
  profilePhotoUrl?: string | undefined;
14059
14268
  companyLogoUrl?: string | undefined;
@@ -14091,6 +14300,8 @@ declare const cardUpdateSchema: z.ZodObject<{
14091
14300
  url?: string | undefined;
14092
14301
  label?: string | undefined;
14093
14302
  }[] | undefined;
14303
+ tipJar?: unknown;
14304
+ booking?: unknown;
14094
14305
  }>>;
14095
14306
  status: z.ZodOptional<z.ZodEnum<["active", "suspended", "archived"]>>;
14096
14307
  }, "strip", z.ZodTypeAny, {
@@ -14132,6 +14343,24 @@ declare const cardUpdateSchema: z.ZodObject<{
14132
14343
  url: string;
14133
14344
  label: string;
14134
14345
  }[] | undefined;
14346
+ tipJar?: {
14347
+ provider: _nfcard_types.TipProviderId;
14348
+ handle: string;
14349
+ label: string;
14350
+ } | {
14351
+ provider: _nfcard_types.TipProviderId;
14352
+ handle: string;
14353
+ label?: undefined;
14354
+ } | undefined;
14355
+ booking?: {
14356
+ provider: _nfcard_types.BookingProviderId;
14357
+ handle: string;
14358
+ label: string;
14359
+ } | {
14360
+ provider: _nfcard_types.BookingProviderId;
14361
+ handle: string;
14362
+ label?: undefined;
14363
+ } | undefined;
14135
14364
  } | undefined;
14136
14365
  }, {
14137
14366
  status?: "active" | "suspended" | "archived" | undefined;
@@ -14172,6 +14401,8 @@ declare const cardUpdateSchema: z.ZodObject<{
14172
14401
  url?: string | undefined;
14173
14402
  label?: string | undefined;
14174
14403
  }[] | undefined;
14404
+ tipJar?: unknown;
14405
+ booking?: unknown;
14175
14406
  } | undefined;
14176
14407
  }>;
14177
14408
  declare const adminCardCreateSchema: z.ZodObject<{
@@ -14351,6 +14582,24 @@ declare const adminCardCreateSchema: z.ZodObject<{
14351
14582
  url?: string | undefined;
14352
14583
  label?: string | undefined;
14353
14584
  }[]>>;
14585
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
14586
+ provider: _nfcard_types.TipProviderId;
14587
+ handle: string;
14588
+ label: string;
14589
+ } | {
14590
+ provider: _nfcard_types.TipProviderId;
14591
+ handle: string;
14592
+ label?: undefined;
14593
+ } | undefined, unknown>>;
14594
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
14595
+ provider: _nfcard_types.BookingProviderId;
14596
+ handle: string;
14597
+ label: string;
14598
+ } | {
14599
+ provider: _nfcard_types.BookingProviderId;
14600
+ handle: string;
14601
+ label?: undefined;
14602
+ } | undefined, unknown>>;
14354
14603
  }, "strip", z.ZodTypeAny, {
14355
14604
  fontKey: string;
14356
14605
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -14386,6 +14635,24 @@ declare const adminCardCreateSchema: z.ZodObject<{
14386
14635
  url: string;
14387
14636
  label: string;
14388
14637
  }[] | undefined;
14638
+ tipJar?: {
14639
+ provider: _nfcard_types.TipProviderId;
14640
+ handle: string;
14641
+ label: string;
14642
+ } | {
14643
+ provider: _nfcard_types.TipProviderId;
14644
+ handle: string;
14645
+ label?: undefined;
14646
+ } | undefined;
14647
+ booking?: {
14648
+ provider: _nfcard_types.BookingProviderId;
14649
+ handle: string;
14650
+ label: string;
14651
+ } | {
14652
+ provider: _nfcard_types.BookingProviderId;
14653
+ handle: string;
14654
+ label?: undefined;
14655
+ } | undefined;
14389
14656
  }, {
14390
14657
  fontKey: string;
14391
14658
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -14421,6 +14688,8 @@ declare const adminCardCreateSchema: z.ZodObject<{
14421
14688
  url?: string | undefined;
14422
14689
  label?: string | undefined;
14423
14690
  }[] | undefined;
14691
+ tipJar?: unknown;
14692
+ booking?: unknown;
14424
14693
  }>;
14425
14694
  physicalConfig: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodObject<{
14426
14695
  material: z.ZodEnum<["plastic", "3dprint_standard", "metal", "bamboo"]>;
@@ -17769,6 +18038,24 @@ declare const adminCardCreateSchema: z.ZodObject<{
17769
18038
  url: string;
17770
18039
  label: string;
17771
18040
  }[] | undefined;
18041
+ tipJar?: {
18042
+ provider: _nfcard_types.TipProviderId;
18043
+ handle: string;
18044
+ label: string;
18045
+ } | {
18046
+ provider: _nfcard_types.TipProviderId;
18047
+ handle: string;
18048
+ label?: undefined;
18049
+ } | undefined;
18050
+ booking?: {
18051
+ provider: _nfcard_types.BookingProviderId;
18052
+ handle: string;
18053
+ label: string;
18054
+ } | {
18055
+ provider: _nfcard_types.BookingProviderId;
18056
+ handle: string;
18057
+ label?: undefined;
18058
+ } | undefined;
17772
18059
  };
17773
18060
  targetUserId: string;
17774
18061
  physicalConfig?: {
@@ -18122,6 +18409,8 @@ declare const adminCardCreateSchema: z.ZodObject<{
18122
18409
  url?: string | undefined;
18123
18410
  label?: string | undefined;
18124
18411
  }[] | undefined;
18412
+ tipJar?: unknown;
18413
+ booking?: unknown;
18125
18414
  };
18126
18415
  targetUserId: string;
18127
18416
  physicalConfig?: {
@@ -18686,6 +18975,24 @@ declare const profileCreateSchema: z.ZodObject<{
18686
18975
  url?: string | undefined;
18687
18976
  label?: string | undefined;
18688
18977
  }[]>>;
18978
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
18979
+ provider: _nfcard_types.TipProviderId;
18980
+ handle: string;
18981
+ label: string;
18982
+ } | {
18983
+ provider: _nfcard_types.TipProviderId;
18984
+ handle: string;
18985
+ label?: undefined;
18986
+ } | undefined, unknown>>;
18987
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
18988
+ provider: _nfcard_types.BookingProviderId;
18989
+ handle: string;
18990
+ label: string;
18991
+ } | {
18992
+ provider: _nfcard_types.BookingProviderId;
18993
+ handle: string;
18994
+ label?: undefined;
18995
+ } | undefined, unknown>>;
18689
18996
  }, "strip", z.ZodTypeAny, {
18690
18997
  fontKey: string;
18691
18998
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -18721,6 +19028,24 @@ declare const profileCreateSchema: z.ZodObject<{
18721
19028
  url: string;
18722
19029
  label: string;
18723
19030
  }[] | undefined;
19031
+ tipJar?: {
19032
+ provider: _nfcard_types.TipProviderId;
19033
+ handle: string;
19034
+ label: string;
19035
+ } | {
19036
+ provider: _nfcard_types.TipProviderId;
19037
+ handle: string;
19038
+ label?: undefined;
19039
+ } | undefined;
19040
+ booking?: {
19041
+ provider: _nfcard_types.BookingProviderId;
19042
+ handle: string;
19043
+ label: string;
19044
+ } | {
19045
+ provider: _nfcard_types.BookingProviderId;
19046
+ handle: string;
19047
+ label?: undefined;
19048
+ } | undefined;
18724
19049
  }, {
18725
19050
  fontKey: string;
18726
19051
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -18756,6 +19081,8 @@ declare const profileCreateSchema: z.ZodObject<{
18756
19081
  url?: string | undefined;
18757
19082
  label?: string | undefined;
18758
19083
  }[] | undefined;
19084
+ tipJar?: unknown;
19085
+ booking?: unknown;
18759
19086
  }>;
18760
19087
  visibility: z.ZodDefault<z.ZodEnum<["public", "private", "link_only"]>>;
18761
19088
  accessPin: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
@@ -18820,6 +19147,24 @@ declare const profileCreateSchema: z.ZodObject<{
18820
19147
  url: string;
18821
19148
  label: string;
18822
19149
  }[] | undefined;
19150
+ tipJar?: {
19151
+ provider: _nfcard_types.TipProviderId;
19152
+ handle: string;
19153
+ label: string;
19154
+ } | {
19155
+ provider: _nfcard_types.TipProviderId;
19156
+ handle: string;
19157
+ label?: undefined;
19158
+ } | undefined;
19159
+ booking?: {
19160
+ provider: _nfcard_types.BookingProviderId;
19161
+ handle: string;
19162
+ label: string;
19163
+ } | {
19164
+ provider: _nfcard_types.BookingProviderId;
19165
+ handle: string;
19166
+ label?: undefined;
19167
+ } | undefined;
18823
19168
  };
18824
19169
  label?: string | undefined;
18825
19170
  cardId?: string | undefined;
@@ -18885,6 +19230,8 @@ declare const profileCreateSchema: z.ZodObject<{
18885
19230
  url?: string | undefined;
18886
19231
  label?: string | undefined;
18887
19232
  }[] | undefined;
19233
+ tipJar?: unknown;
19234
+ booking?: unknown;
18888
19235
  };
18889
19236
  label?: string | undefined;
18890
19237
  visibility?: "public" | "private" | "link_only" | undefined;
@@ -19077,6 +19424,24 @@ declare const signupWithProfileSchema: z.ZodObject<{
19077
19424
  url?: string | undefined;
19078
19425
  label?: string | undefined;
19079
19426
  }[]>>;
19427
+ tipJar: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
19428
+ provider: _nfcard_types.TipProviderId;
19429
+ handle: string;
19430
+ label: string;
19431
+ } | {
19432
+ provider: _nfcard_types.TipProviderId;
19433
+ handle: string;
19434
+ label?: undefined;
19435
+ } | undefined, unknown>>;
19436
+ booking: z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
19437
+ provider: _nfcard_types.BookingProviderId;
19438
+ handle: string;
19439
+ label: string;
19440
+ } | {
19441
+ provider: _nfcard_types.BookingProviderId;
19442
+ handle: string;
19443
+ label?: undefined;
19444
+ } | undefined, unknown>>;
19080
19445
  }, "strip", z.ZodTypeAny, {
19081
19446
  fontKey: string;
19082
19447
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -19112,6 +19477,24 @@ declare const signupWithProfileSchema: z.ZodObject<{
19112
19477
  url: string;
19113
19478
  label: string;
19114
19479
  }[] | undefined;
19480
+ tipJar?: {
19481
+ provider: _nfcard_types.TipProviderId;
19482
+ handle: string;
19483
+ label: string;
19484
+ } | {
19485
+ provider: _nfcard_types.TipProviderId;
19486
+ handle: string;
19487
+ label?: undefined;
19488
+ } | undefined;
19489
+ booking?: {
19490
+ provider: _nfcard_types.BookingProviderId;
19491
+ handle: string;
19492
+ label: string;
19493
+ } | {
19494
+ provider: _nfcard_types.BookingProviderId;
19495
+ handle: string;
19496
+ label?: undefined;
19497
+ } | undefined;
19115
19498
  }, {
19116
19499
  fontKey: string;
19117
19500
  templateId: "minimal" | "bold" | "card" | "aurora" | "classic" | "spotlight" | "marquee" | "riso";
@@ -19147,6 +19530,8 @@ declare const signupWithProfileSchema: z.ZodObject<{
19147
19530
  url?: string | undefined;
19148
19531
  label?: string | undefined;
19149
19532
  }[] | undefined;
19533
+ tipJar?: unknown;
19534
+ booking?: unknown;
19150
19535
  }>;
19151
19536
  }, "strip", z.ZodTypeAny, {
19152
19537
  email: string;
@@ -19209,6 +19594,24 @@ declare const signupWithProfileSchema: z.ZodObject<{
19209
19594
  url: string;
19210
19595
  label: string;
19211
19596
  }[] | undefined;
19597
+ tipJar?: {
19598
+ provider: _nfcard_types.TipProviderId;
19599
+ handle: string;
19600
+ label: string;
19601
+ } | {
19602
+ provider: _nfcard_types.TipProviderId;
19603
+ handle: string;
19604
+ label?: undefined;
19605
+ } | undefined;
19606
+ booking?: {
19607
+ provider: _nfcard_types.BookingProviderId;
19608
+ handle: string;
19609
+ label: string;
19610
+ } | {
19611
+ provider: _nfcard_types.BookingProviderId;
19612
+ handle: string;
19613
+ label?: undefined;
19614
+ } | undefined;
19212
19615
  };
19213
19616
  password: string;
19214
19617
  acceptedTerms: true;
@@ -19278,6 +19681,8 @@ declare const signupWithProfileSchema: z.ZodObject<{
19278
19681
  url?: string | undefined;
19279
19682
  label?: string | undefined;
19280
19683
  }[] | undefined;
19684
+ tipJar?: unknown;
19685
+ booking?: unknown;
19281
19686
  };
19282
19687
  password: string;
19283
19688
  acceptedTerms: true;
@@ -19466,6 +19871,24 @@ declare const profileUpdateSchema: z.ZodObject<{
19466
19871
  url?: string | undefined;
19467
19872
  label?: string | undefined;
19468
19873
  }[]>>>>;
19874
+ tipJar: z.ZodOptional<z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
19875
+ provider: _nfcard_types.TipProviderId;
19876
+ handle: string;
19877
+ label: string;
19878
+ } | {
19879
+ provider: _nfcard_types.TipProviderId;
19880
+ handle: string;
19881
+ label?: undefined;
19882
+ } | undefined, unknown>>>>;
19883
+ booking: z.ZodOptional<z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnknown, {
19884
+ provider: _nfcard_types.BookingProviderId;
19885
+ handle: string;
19886
+ label: string;
19887
+ } | {
19888
+ provider: _nfcard_types.BookingProviderId;
19889
+ handle: string;
19890
+ label?: undefined;
19891
+ } | undefined, unknown>>>>;
19469
19892
  profilePhotoUrl: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>>;
19470
19893
  companyLogoUrl: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>>;
19471
19894
  }, "strip", z.ZodTypeAny, {
@@ -19505,6 +19928,24 @@ declare const profileUpdateSchema: z.ZodObject<{
19505
19928
  url: string;
19506
19929
  label: string;
19507
19930
  }[] | undefined;
19931
+ tipJar?: {
19932
+ provider: _nfcard_types.TipProviderId;
19933
+ handle: string;
19934
+ label: string;
19935
+ } | {
19936
+ provider: _nfcard_types.TipProviderId;
19937
+ handle: string;
19938
+ label?: undefined;
19939
+ } | undefined;
19940
+ booking?: {
19941
+ provider: _nfcard_types.BookingProviderId;
19942
+ handle: string;
19943
+ label: string;
19944
+ } | {
19945
+ provider: _nfcard_types.BookingProviderId;
19946
+ handle: string;
19947
+ label?: undefined;
19948
+ } | undefined;
19508
19949
  }, {
19509
19950
  profilePhotoUrl?: string | undefined;
19510
19951
  companyLogoUrl?: string | undefined;
@@ -19542,6 +19983,8 @@ declare const profileUpdateSchema: z.ZodObject<{
19542
19983
  url?: string | undefined;
19543
19984
  label?: string | undefined;
19544
19985
  }[] | undefined;
19986
+ tipJar?: unknown;
19987
+ booking?: unknown;
19545
19988
  }>>;
19546
19989
  visibility: z.ZodOptional<z.ZodEnum<["public", "private", "link_only"]>>;
19547
19990
  accessPin: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
@@ -19609,6 +20052,24 @@ declare const profileUpdateSchema: z.ZodObject<{
19609
20052
  url: string;
19610
20053
  label: string;
19611
20054
  }[] | undefined;
20055
+ tipJar?: {
20056
+ provider: _nfcard_types.TipProviderId;
20057
+ handle: string;
20058
+ label: string;
20059
+ } | {
20060
+ provider: _nfcard_types.TipProviderId;
20061
+ handle: string;
20062
+ label?: undefined;
20063
+ } | undefined;
20064
+ booking?: {
20065
+ provider: _nfcard_types.BookingProviderId;
20066
+ handle: string;
20067
+ label: string;
20068
+ } | {
20069
+ provider: _nfcard_types.BookingProviderId;
20070
+ handle: string;
20071
+ label?: undefined;
20072
+ } | undefined;
19612
20073
  } | undefined;
19613
20074
  icon?: string | undefined;
19614
20075
  accessPin?: string | undefined;
@@ -19676,6 +20137,8 @@ declare const profileUpdateSchema: z.ZodObject<{
19676
20137
  url?: string | undefined;
19677
20138
  label?: string | undefined;
19678
20139
  }[] | undefined;
20140
+ tipJar?: unknown;
20141
+ booking?: unknown;
19679
20142
  } | undefined;
19680
20143
  icon?: string | undefined;
19681
20144
  accessPin?: string | undefined;
@@ -19824,4 +20287,4 @@ declare function validatePhysicalConfig(data: unknown): ValidationResult<z.infer
19824
20287
  declare function validateDigitalConfig(data: unknown): ValidationResult<z.infer<typeof digitalConfigSchema>>;
19825
20288
  declare function validateConfiguration(data: unknown): ValidationResult<z.infer<typeof configurationCreateSchema>>;
19826
20289
 
19827
- export { ADVANCE_FALLBACK_EM, CARD_H_MM, CARD_W_MM, CHIP_RADIUS_MM, CHIP_SCALE_FLOOR, type ChipAxis, EDGE_MARGIN_MM, EMPTY_TEXT_FLOOR_EM, ITALIC_OVERHANG_EM, MAX_CTA_BUTTONS, MIN_WALL_MM, NFC_COIL_DIAMETER_MM, NFC_RADIAL_CLEARANCE_MM, type PrintabilityCtx, type Pt, QR_MATRIX_CELLS, QR_MIN_SIZE_MM, QR_MODULE_MIN_MM, TEXT_LINE_FACTOR_EM, TEXT_MIN_EM_MM, type ValidationResult, type Violation, adminCardCreateSchema, cardAssetSchema, cardDesignMaterialSchema, cardDesignPatternSchema, cardDesignSchema, cardElementSchema, cardElementsSchema, cardProfileUpdateSchema, cardUpdateSchema, chipAnchorToMm, chipPlacementMaxXY, comboIdSchema, configurationCreateSchema, configurationUpdateSchema, contactDetailTogglesSchema, contactExchangeSchema, cornersOnCard, createOrderSchema, ctaButtonSchema, ctaButtonsSchema, digitalConfigSchema, digitalVisibilitySchema, elementPrintability, elementTransformSchema, entrySourceSchema, footprintOf, hubConfigSchema, hubProfilesUpdateSchema, isFiniteTransform, materialSchema, mmToNearestChipAnchor, obbCorners, patternFamilySchema, physicalConfigSchema, physicalContentOverridesSchema, profileAccessTokenCreateSchema, profileCreateSchema, profilePinVerifySchema, profileUpdateSchema, profileUserDataSchema, profileVisibilitySchema, sanitizeHttpUrl, sanitizeText, signupWithProfileSchema, socialLinksSchema, socialOverridesSchema, textAdvanceEm, userDataSchema, validateConfiguration, validateDigitalConfig, validatePhysicalConfig, validateUserData, webAddressSchema };
20290
+ export { ADVANCE_FALLBACK_EM, CARD_H_MM, CARD_W_MM, CHIP_RADIUS_MM, CHIP_SCALE_FLOOR, type ChipAxis, EDGE_MARGIN_MM, EMPTY_TEXT_FLOOR_EM, ITALIC_OVERHANG_EM, MAX_CTA_BUTTONS, MIN_WALL_MM, NFC_COIL_DIAMETER_MM, NFC_RADIAL_CLEARANCE_MM, type PrintabilityCtx, type Pt, QR_MATRIX_CELLS, QR_MIN_SIZE_MM, QR_MODULE_MIN_MM, TEXT_LINE_FACTOR_EM, TEXT_MIN_EM_MM, type ValidationResult, type Violation, adminCardCreateSchema, bookingSchema, cardAssetSchema, cardDesignMaterialSchema, cardDesignPatternSchema, cardDesignSchema, cardElementSchema, cardElementsSchema, cardProfileUpdateSchema, cardUpdateSchema, chipAnchorToMm, chipPlacementMaxXY, comboIdSchema, configurationCreateSchema, configurationUpdateSchema, contactDetailTogglesSchema, contactExchangeSchema, cornersOnCard, createOrderSchema, ctaButtonSchema, ctaButtonsSchema, digitalConfigSchema, digitalVisibilitySchema, elementPrintability, elementTransformSchema, entrySourceSchema, footprintOf, hubConfigSchema, hubProfilesUpdateSchema, isFiniteTransform, materialSchema, mmToNearestChipAnchor, obbCorners, patternFamilySchema, physicalConfigSchema, physicalContentOverridesSchema, profileAccessTokenCreateSchema, profileCreateSchema, profilePinVerifySchema, profileUpdateSchema, profileUserDataSchema, profileVisibilitySchema, sanitizeHttpUrl, sanitizeText, signupWithProfileSchema, socialLinksSchema, socialOverridesSchema, textAdvanceEm, tipJarSchema, userDataSchema, validateConfiguration, validateDigitalConfig, validatePhysicalConfig, validateUserData, webAddressSchema };
package/dist/index.js CHANGED
@@ -1,5 +1,11 @@
1
1
  // src/index.ts
2
2
  import { z } from "zod";
3
+ import {
4
+ isTipProviderId,
5
+ normalizeTipHandle,
6
+ isBookingProviderId,
7
+ normalizeBookingHandle
8
+ } from "@nfcard/types";
3
9
 
4
10
  // src/printability.ts
5
11
  var CARD_W_MM = 85.6;
@@ -735,6 +741,24 @@ var ctaButtonSchema = z.object({
735
741
  var ctaButtonsSchema = z.array(ctaButtonSchema).max(50).transform(
736
742
  (arr) => arr.filter((b) => b.url !== "" && b.label !== "").slice(0, MAX_CTA_BUTTONS)
737
743
  );
744
+ var tipJarSchema = z.unknown().transform((raw) => {
745
+ if (!raw || typeof raw !== "object") return void 0;
746
+ const rec = raw;
747
+ if (!isTipProviderId(rec.provider)) return void 0;
748
+ const handle = normalizeTipHandle(rec.provider, rec.handle);
749
+ if (!handle) return void 0;
750
+ const label = typeof rec.label === "string" ? sanitizeText(rec.label, 40) : "";
751
+ return label ? { provider: rec.provider, handle, label } : { provider: rec.provider, handle };
752
+ });
753
+ var bookingSchema = z.unknown().transform((raw) => {
754
+ if (!raw || typeof raw !== "object") return void 0;
755
+ const rec = raw;
756
+ if (!isBookingProviderId(rec.provider)) return void 0;
757
+ const handle = normalizeBookingHandle(rec.provider, rec.handle);
758
+ if (!handle) return void 0;
759
+ const label = typeof rec.label === "string" ? sanitizeText(rec.label, 40) : "";
760
+ return label ? { provider: rec.provider, handle, label } : { provider: rec.provider, handle };
761
+ });
738
762
  var digitalConfigSchema = z.object({
739
763
  templateId: z.enum(["minimal", "bold", "card", "aurora", "classic", "spotlight", "marquee", "riso"]),
740
764
  accentColor: z.string().regex(/^#[0-9A-Fa-f]{6}$/),
@@ -753,7 +777,9 @@ var digitalConfigSchema = z.object({
753
777
  // NFCARD-211 — Pro-only custom CTA buttons. Sanitised + capped here; the
754
778
  // public renderer additionally gates them on the owner's tier (free →
755
779
  // none). Optional, so existing profiles/configs validate unchanged.
756
- ctaButtons: ctaButtonsSchema.optional()
780
+ ctaButtons: ctaButtonsSchema.optional(),
781
+ tipJar: tipJarSchema.optional(),
782
+ booking: bookingSchema.optional()
757
783
  });
758
784
  var entrySourceSchema = z.object({
759
785
  output: z.enum(["with-card", "digital-only"]).optional(),
@@ -965,6 +991,7 @@ export {
965
991
  TEXT_LINE_FACTOR_EM,
966
992
  TEXT_MIN_EM_MM,
967
993
  adminCardCreateSchema,
994
+ bookingSchema,
968
995
  cardAssetSchema,
969
996
  cardDesignMaterialSchema,
970
997
  cardDesignPatternSchema,
@@ -1011,6 +1038,7 @@ export {
1011
1038
  socialLinksSchema,
1012
1039
  socialOverridesSchema,
1013
1040
  textAdvanceEm,
1041
+ tipJarSchema,
1014
1042
  userDataSchema,
1015
1043
  validateConfiguration,
1016
1044
  validateDigitalConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nfcard/validation",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "description": "Shared Zod validation schemas for the NFCard product family.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "zod": "^3.24.0",
20
- "@nfcard/types": "0.13.2"
20
+ "@nfcard/types": "0.15.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "tsup": "^8.0.0"
@@ -0,0 +1,85 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { bookingSchema, digitalConfigSchema } from './index'
3
+
4
+ const baseConfig = {
5
+ templateId: 'classic' as const,
6
+ accentColor: '#123456',
7
+ fontKey: 'inter',
8
+ showAvatar: true,
9
+ }
10
+
11
+ describe('bookingSchema', () => {
12
+ it('accepts a valid provider + handle and stores only { provider, handle }', () => {
13
+ expect(bookingSchema.parse({ provider: 'salonic', handle: 'kiss-fodraszat' })).toEqual({
14
+ provider: 'salonic',
15
+ handle: 'kiss-fodraszat',
16
+ })
17
+ })
18
+
19
+ it('normalizes a pasted booking-page URL down to the subdomain handle', () => {
20
+ expect(
21
+ bookingSchema.parse({
22
+ provider: 'salonic',
23
+ handle: 'https://kiss-fodraszat.salonic.hu/booking?x=1',
24
+ }),
25
+ ).toEqual({ provider: 'salonic', handle: 'kiss-fodraszat' })
26
+ })
27
+
28
+ it('lowercases the handle', () => {
29
+ expect(bookingSchema.parse({ provider: 'reservio', handle: 'HighBrow' })).toEqual({
30
+ provider: 'reservio',
31
+ handle: 'highbrow',
32
+ })
33
+ })
34
+
35
+ it('keeps a sanitized custom label, capped at 40 chars', () => {
36
+ const out = bookingSchema.parse({
37
+ provider: 'salonic',
38
+ handle: 'kiss-fodraszat',
39
+ label: '<b>Foglalj</b> ' + 'x'.repeat(60),
40
+ })
41
+ expect(out?.provider).toBe('salonic')
42
+ expect(out?.label).not.toContain('<')
43
+ expect((out?.label ?? '').length).toBeLessThanOrEqual(40)
44
+ })
45
+
46
+ it('drops everything invalid to undefined instead of throwing (never 400)', () => {
47
+ expect(bookingSchema.parse(undefined)).toBeUndefined()
48
+ expect(bookingSchema.parse(null)).toBeUndefined()
49
+ expect(bookingSchema.parse('nonsense')).toBeUndefined()
50
+ expect(bookingSchema.parse({})).toBeUndefined()
51
+ expect(bookingSchema.parse({ provider: 'booksy', handle: 'szalon' })).toBeUndefined()
52
+ expect(bookingSchema.parse({ provider: 'salonic', handle: 'www' })).toBeUndefined() // reserved
53
+ expect(bookingSchema.parse({ provider: 'salonic', handle: '-bad' })).toBeUndefined() // bad DNS label
54
+ expect(
55
+ bookingSchema.parse({ provider: 'salonic', handle: 'https://evil.com/szalon' }),
56
+ ).toBeUndefined()
57
+ expect(
58
+ bookingSchema.parse({ provider: 'salonic', handle: 'javascript:alert(1)' }),
59
+ ).toBeUndefined()
60
+ expect(bookingSchema.parse({ provider: 'salonic', handle: 123 })).toBeUndefined()
61
+ })
62
+ })
63
+
64
+ describe('digitalConfigSchema — booking field', () => {
65
+ it('round-trips a valid booking', () => {
66
+ const parsed = digitalConfigSchema.parse({
67
+ ...baseConfig,
68
+ booking: { provider: 'salonic', handle: 'kiss-fodraszat' },
69
+ })
70
+ expect(parsed.booking).toEqual({ provider: 'salonic', handle: 'kiss-fodraszat' })
71
+ })
72
+
73
+ it('drops an invalid booking without failing the whole config save', () => {
74
+ const parsed = digitalConfigSchema.parse({
75
+ ...baseConfig,
76
+ booking: { provider: 'salonic', handle: 'https://evil.com/x' },
77
+ })
78
+ expect(parsed.booking).toBeUndefined()
79
+ })
80
+
81
+ it('is optional — a config without a booking parses fine', () => {
82
+ const parsed = digitalConfigSchema.parse(baseConfig)
83
+ expect(parsed.booking).toBeUndefined()
84
+ })
85
+ })
package/src/index.ts CHANGED
Binary file
@@ -0,0 +1,77 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { tipJarSchema, digitalConfigSchema } from './index'
3
+
4
+ const baseConfig = {
5
+ templateId: 'classic' as const,
6
+ accentColor: '#123456',
7
+ fontKey: 'inter',
8
+ showAvatar: true,
9
+ }
10
+
11
+ describe('tipJarSchema', () => {
12
+ it('accepts a valid provider + handle and stores only { provider, handle }', () => {
13
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 'ricsi' })).toEqual({
14
+ provider: 'kofi',
15
+ handle: 'ricsi',
16
+ })
17
+ })
18
+
19
+ it('normalizes a pasted full URL down to the handle', () => {
20
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 'https://ko-fi.com/ricsi?x=1' })).toEqual(
21
+ { provider: 'kofi', handle: 'ricsi' },
22
+ )
23
+ })
24
+
25
+ it('lowercases revolut handles', () => {
26
+ expect(tipJarSchema.parse({ provider: 'revolut', handle: 'RicSi' })).toEqual({
27
+ provider: 'revolut',
28
+ handle: 'ricsi',
29
+ })
30
+ })
31
+
32
+ it('keeps a sanitized custom label, capped at 40 chars', () => {
33
+ const out = tipJarSchema.parse({
34
+ provider: 'kofi',
35
+ handle: 'ricsi',
36
+ label: '<b>Támogass</b> ' + 'x'.repeat(60),
37
+ })
38
+ expect(out?.provider).toBe('kofi')
39
+ expect(out?.label).not.toContain('<')
40
+ expect((out?.label ?? '').length).toBeLessThanOrEqual(40)
41
+ })
42
+
43
+ it('drops everything invalid to undefined instead of throwing (never 400)', () => {
44
+ expect(tipJarSchema.parse(undefined)).toBeUndefined()
45
+ expect(tipJarSchema.parse(null)).toBeUndefined()
46
+ expect(tipJarSchema.parse('nonsense')).toBeUndefined()
47
+ expect(tipJarSchema.parse({})).toBeUndefined()
48
+ expect(tipJarSchema.parse({ provider: 'stripe', handle: 'ricsi' })).toBeUndefined()
49
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 'x' })).toBeUndefined() // too short
50
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 'https://evil.com/ricsi' })).toBeUndefined()
51
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 'javascript:alert(1)' })).toBeUndefined()
52
+ expect(tipJarSchema.parse({ provider: 'kofi', handle: 123 })).toBeUndefined()
53
+ })
54
+ })
55
+
56
+ describe('digitalConfigSchema — tipJar field', () => {
57
+ it('round-trips a valid tipJar', () => {
58
+ const parsed = digitalConfigSchema.parse({
59
+ ...baseConfig,
60
+ tipJar: { provider: 'revolut', handle: 'ricsi' },
61
+ })
62
+ expect(parsed.tipJar).toEqual({ provider: 'revolut', handle: 'ricsi' })
63
+ })
64
+
65
+ it('drops an invalid tipJar without failing the whole config save', () => {
66
+ const parsed = digitalConfigSchema.parse({
67
+ ...baseConfig,
68
+ tipJar: { provider: 'kofi', handle: 'https://evil.com/x' },
69
+ })
70
+ expect(parsed.tipJar).toBeUndefined()
71
+ })
72
+
73
+ it('is optional — a config without a tipJar parses fine', () => {
74
+ const parsed = digitalConfigSchema.parse(baseConfig)
75
+ expect(parsed.tipJar).toBeUndefined()
76
+ })
77
+ })