@callimacus/thamyr-core 4.11.1 → 4.13.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.
@@ -476,6 +476,21 @@ type WhisperPayload = {
476
476
  generated_at: number;
477
477
  ttl_ms: number;
478
478
  };
479
+ type ShopifyStorefrontSettings = {
480
+ /**
481
+ * The store’s primary domain: the host the Storefront API is called on.
482
+ */
483
+ domain: string | null;
484
+ storefrontToken: string | null;
485
+ sourceName: string | null;
486
+ /**
487
+ * Site locale → the buyer’s country (ISO 3166-1 alpha-2).
488
+ */
489
+ countries: {
490
+ [key: string]: string;
491
+ };
492
+ cartEnabled: boolean;
493
+ };
479
494
  type SkesisItemPage = {
480
495
  /**
481
496
  * The canonical page path, `/map/{locale}/{slug}/{id}`, as the sitemap lists it
@@ -817,6 +832,30 @@ type BlockPatchOutput = {
817
832
  */
818
833
  fire: Array<string>;
819
834
  };
835
+ type CartCommandOutput = {
836
+ storyId: string;
837
+ chapterId: string;
838
+ command: 'shopify-add';
839
+ /**
840
+ * The Shopify product variant to add.
841
+ */
842
+ variantId: string;
843
+ quantity: number;
844
+ item: {
845
+ /**
846
+ * The item the chat showed (`shopify:product:<gid>`).
847
+ */
848
+ id: string;
849
+ name: string;
850
+ /**
851
+ * The options that tell the variant apart, for the notice.
852
+ */
853
+ options: Array<{
854
+ name: string;
855
+ value: string;
856
+ }>;
857
+ };
858
+ };
820
859
  type BlockOutput = LegacyBlockOutput | CustomBlockOutput;
821
860
  type ChapterOutput = {
822
861
  id: string;
@@ -894,6 +933,10 @@ type CreateRoundContextOutput = {
894
933
  * Ask for the round's `outline`: the blocks it will show, in page order, sent before their contents are ready. Without it, no outline is sent.
895
934
  */
896
935
  outline?: boolean;
936
+ /**
937
+ * The client runs a Shopify cart in the shopper's browser: the chat may then answer an add to the bag with a `cart-command`. Without it, an add to the bag shows the item's details.
938
+ */
939
+ shopifyCart?: boolean;
897
940
  [key: string]: unknown;
898
941
  };
899
942
  type CustomBlockOutput = {
@@ -1271,6 +1314,9 @@ type ThamyrResponse$1 = {
1271
1314
  } | {
1272
1315
  type: 'block-patch';
1273
1316
  data: BlockPatchOutput;
1317
+ } | {
1318
+ type: 'cart-command';
1319
+ data: CartCommandOutput;
1274
1320
  };
1275
1321
  type UserInteraction$1 = {
1276
1322
  type: 'get-story';
@@ -2991,6 +3037,30 @@ type CartUpdateProductQuantityResponses = {
2991
3037
  */
2992
3038
  200: Basket;
2993
3039
  };
3040
+ type ShopifyGetStorefrontSettingsErrors = {
3041
+ /**
3042
+ * Validation error
3043
+ */
3044
+ 400: unknown;
3045
+ /**
3046
+ * Missing or invalid access token
3047
+ */
3048
+ 401: unknown;
3049
+ /**
3050
+ * The caller is not permitted to perform this operation
3051
+ */
3052
+ 403: PinaxForbidden;
3053
+ /**
3054
+ * The project has no store connected from Studio
3055
+ */
3056
+ 404: PublicError;
3057
+ };
3058
+ type ShopifyGetStorefrontSettingsResponses = {
3059
+ /**
3060
+ * Success
3061
+ */
3062
+ 200: ShopifyStorefrontSettings;
3063
+ };
2994
3064
  type SkesisSimilarErrors = {
2995
3065
  /**
2996
3066
  * Validation error
@@ -3261,6 +3331,14 @@ declare class Cart extends HeyApiClient {
3261
3331
  quantity: number;
3262
3332
  }, options?: Options<never, ThrowOnError>): RequestResult<CartUpdateProductQuantityResponses, CartUpdateProductQuantityErrors, ThrowOnError>;
3263
3333
  }
3334
+ declare class Shopify extends HeyApiClient {
3335
+ /**
3336
+ * Get the Shopify cart settings
3337
+ *
3338
+ * The store’s primary domain, its storefront token and channel source name (null until the store is a sales channel), the buyer’s country for each site locale, and whether the cart is on. The cart is off on the site’s preview and once the store uninstalled the app. Not found while the project has no store connected: the SDK then keeps its own config.
3339
+ */
3340
+ getStorefrontSettings<ThrowOnError extends boolean = false>(options?: Options<never, ThrowOnError>): RequestResult<ShopifyGetStorefrontSettingsResponses, ShopifyGetStorefrontSettingsErrors, ThrowOnError>;
3341
+ }
3264
3342
  declare class Skesis extends HeyApiClient {
3265
3343
  /**
3266
3344
  * Similar items
@@ -3308,6 +3386,8 @@ declare class CallimacusApi extends HeyApiClient {
3308
3386
  get analytics(): Analytics;
3309
3387
  private _cart?;
3310
3388
  get cart(): Cart;
3389
+ private _shopify?;
3390
+ get shopify(): Shopify;
3311
3391
  private _skesis?;
3312
3392
  get skesis(): Skesis;
3313
3393
  }
@@ -3370,6 +3450,13 @@ type ThamyrResponse = ThamyrResponse$1;
3370
3450
  declares in `patchOn` re-set its animation in place. Apply it with `applyBlockPatch`.
3371
3451
  */
3372
3452
  type BlockPatch = BlockPatchOutput;
3453
+ /**
3454
+ An add to the bag the chat asks the shopper's browser to make in its Shopify cart,
3455
+ at most once: it comes only on the socket whose round asked for it, only to a client
3456
+ that declared `context.shopifyCart`, and is never stored with the round, so a replay
3457
+ never sends it again. Run it with the Shopify cart (`@callimacus/thamyr-react` does).
3458
+ */
3459
+ type CartCommand = CartCommandOutput;
3373
3460
  /**
3374
3461
  What a Rive animation exposes to be set: the `properties` of a `rive` document section.
3375
3462
  */
@@ -3383,6 +3470,7 @@ declare const ThamyrResponseType: {
3383
3470
  readonly STORY_CREATED: "story-created";
3384
3471
  readonly STORY_SHARED: "story-shared";
3385
3472
  readonly BLOCK_PATCH: "block-patch";
3473
+ readonly CART_COMMAND: "cart-command";
3386
3474
  };
3387
3475
  type ThamyrResponseType = Values<typeof ThamyrResponseType>;
3388
3476
  /**
@@ -3499,6 +3587,10 @@ type InteractionContext = {
3499
3587
  The page title, carried in a delivered interaction's envelope.
3500
3588
  */
3501
3589
  title?: string;
3590
+ /**
3591
+ The client runs a Shopify cart (`useShopifyCart`): a round that declares it may get the chat's add to the bag as a `cart-command`.
3592
+ */
3593
+ shopifyCart?: boolean;
3502
3594
  };
3503
3595
  type UiObserverConfig = {
3504
3596
  enabled?: boolean;
@@ -4146,6 +4238,250 @@ declare function deliverResultOf(block: {
4146
4238
  data?: unknown;
4147
4239
  }): DeliverResult | undefined;
4148
4240
 
4241
+ /**
4242
+ The Shopify settings a site passes at init (`shopify` in the init config).
4243
+ */
4244
+ type ShopifyConfig = {
4245
+ /**
4246
+ The store's domain (its primary domain, or `brand.myshopify.com`): the cart calls the Storefront API there.
4247
+ */
4248
+ storeDomain: string;
4249
+ /**
4250
+ A public Storefront API token. Without one the cart uses Shopify's tokenless access.
4251
+ */
4252
+ storefrontToken?: string;
4253
+ /**
4254
+ The buyer's country (ISO 3166 alpha-2) when core names none for the site's locale.
4255
+ */
4256
+ country?: string;
4257
+ };
4258
+ /**
4259
+ What core's `GET /api/v3/shopify/storefront` answers once a store is connected.
4260
+ */
4261
+ type ShopifyStorefront = {
4262
+ domain: string | null;
4263
+ storefrontToken: string | null;
4264
+ sourceName: string | null;
4265
+ /**
4266
+ Site locale → the buyer's country, e.g. `{"it-IT": "IT", "en": "US"}`.
4267
+ */
4268
+ countries: Record<string, string>;
4269
+ /**
4270
+ Off on the site's preview, and once the store uninstalled the app.
4271
+ */
4272
+ cartEnabled: boolean;
4273
+ };
4274
+ /**
4275
+ The settings of the page: core's values where it has them, the init config's elsewhere.
4276
+ */
4277
+ type ShopifySettings = {
4278
+ cartEnabled: boolean;
4279
+ storeDomain?: string;
4280
+ storefrontToken?: string;
4281
+ sourceName?: string;
4282
+ countries: Record<string, string>;
4283
+ /**
4284
+ The config's country, for a locale `countries` does not name.
4285
+ */
4286
+ country?: string;
4287
+ };
4288
+ /**
4289
+ What one cart call runs with: the settings, with the buyer's country resolved for the site's current locale.
4290
+ */
4291
+ type ShopifyCartSettings = Omit<ShopifySettings, 'countries'>;
4292
+ /**
4293
+ Merges core's answer over the init config, field by field: core's domain, token
4294
+ and source name win when present, the config's token stays in use while core's
4295
+ is null, and a cart core turned off stays off whatever the config says. No
4296
+ answer (a 404: no store connected yet) leaves the config as it is.
4297
+ */
4298
+ declare function mergeShopifySettings(storefront: ShopifyStorefront | undefined, config?: ShopifyConfig): ShopifySettings;
4299
+ /**
4300
+ Reads core's Shopify settings for the site and merges them over the init
4301
+ config. Never rejects: a 404 means no store is connected yet, and any other
4302
+ failure (network, a 5xx, a malformed body) also leaves the config in charge —
4303
+ core is not in the cart path, so its outage must not take the cart down. Read
4304
+ it once per page load: the answer is `private, no-store`.
4305
+ @param client - The contract client every `/api/v3` call goes through (`createContractClient`).
4306
+ @param config - The init config's `shopify`.
4307
+ */
4308
+ declare function readShopifySettings(client: ContractClient, config?: ShopifyConfig): Promise<ShopifySettings>;
4309
+ /**
4310
+ The settings one cart call runs with: the buyer's country is the one core names for `locale`, else the config's.
4311
+ @param settings - What {@link readShopifySettings} resolved.
4312
+ @param locale - The site's current locale (`it-IT`, `en`).
4313
+ */
4314
+ declare function cartSettingsFor(settings: ShopifySettings, locale: string | undefined): ShopifyCartSettings;
4315
+
4316
+ /**
4317
+ The Storefront API version the cart is written against.
4318
+ */
4319
+ declare const STOREFRONT_API_VERSION = "2026-10";
4320
+ type ShopifyMoney = {
4321
+ amount: string;
4322
+ currencyCode: string;
4323
+ };
4324
+ type ShopifyCartLine = {
4325
+ id: string;
4326
+ quantity: number;
4327
+ merchandise: {
4328
+ id: string;
4329
+ title: string;
4330
+ product: {
4331
+ title: string;
4332
+ handle: string;
4333
+ };
4334
+ image: {
4335
+ url: string;
4336
+ altText: string | null;
4337
+ } | null;
4338
+ price: ShopifyMoney;
4339
+ selectedOptions: Array<{
4340
+ name: string;
4341
+ value: string;
4342
+ }>;
4343
+ };
4344
+ cost: {
4345
+ totalAmount: ShopifyMoney;
4346
+ };
4347
+ };
4348
+ /**
4349
+ Shopify's refusal of a cart change (`CartUserError`): sold out, not published to the channel, a quantity rule.
4350
+ `message` is written for the shopper.
4351
+ */
4352
+ type ShopifyUserError = {
4353
+ code: string | null;
4354
+ field: string[] | null;
4355
+ message: string;
4356
+ };
4357
+ type ShopifyCart = {
4358
+ id: string;
4359
+ checkoutUrl: string;
4360
+ totalQuantity: number;
4361
+ cost: {
4362
+ subtotalAmount: ShopifyMoney;
4363
+ totalAmount: ShopifyMoney;
4364
+ };
4365
+ lines: ShopifyCartLine[];
4366
+ };
4367
+ /**
4368
+ What Shopify did other than asked (`CartWarning`), e.g. `MERCHANDISE_NOT_ENOUGH_STOCK`: it added what it had.
4369
+ */
4370
+ type ShopifyCartWarning = {
4371
+ code: string;
4372
+ message: string;
4373
+ target: string;
4374
+ };
4375
+ /**
4376
+ - `cart_disabled`: the cart is off (the site's preview, or the store uninstalled the app).
4377
+ - `cart_unavailable`: no store is set up, or the store refuses the call (its storefront password, a revoked token).
4378
+ - `invalid_input`: not a product variant id, or not a whole quantity.
4379
+ - `refused`: Shopify said no; its reasons are in `userErrors`. A sold-out add is refused too, with Shopify's warning as the message.
4380
+ - `no_cart`: nothing to change or check out.
4381
+ - `throttled`: Shopify is rate limiting (HTTP 430 or 429).
4382
+ - `busy`: another tab held the cart creation for too long.
4383
+ - `network`: no answer, or none in time.
4384
+ - `http`: any other failed status. `graphql`: the API answered errors only.
4385
+ */
4386
+ type ShopifyCartErrorCode = 'cart_disabled' | 'cart_unavailable' | 'invalid_input' | 'refused' | 'no_cart' | 'throttled' | 'busy' | 'network' | 'http' | 'graphql';
4387
+ type ShopifyCartError = {
4388
+ code: ShopifyCartErrorCode;
4389
+ message: string;
4390
+ /**
4391
+ The HTTP status, when the store answered with one.
4392
+ */
4393
+ status?: number;
4394
+ userErrors?: ShopifyUserError[];
4395
+ };
4396
+ /**
4397
+ What a cart method resolves, never rejects with. `data` is the cart (`undefined`:
4398
+ none yet), or the checkout URL for `checkout`. On `error`, `data` is the cart as
4399
+ it stands when Shopify sent it along (a refused add leaves it unchanged).
4400
+ `warnings` is always there, empty when Shopify had nothing to say.
4401
+ */
4402
+ type ShopifyCartResult<T = ShopifyCart | undefined> = {
4403
+ data: T;
4404
+ error?: undefined;
4405
+ warnings: ShopifyCartWarning[];
4406
+ } | {
4407
+ data?: T;
4408
+ error: ShopifyCartError;
4409
+ warnings: ShopifyCartWarning[];
4410
+ };
4411
+ /**
4412
+ The slice of `localStorage` the cart uses.
4413
+ */
4414
+ type CartStorage = Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>;
4415
+ /**
4416
+ Runs `task` while no other tab runs one under the same `name`; rejects when the lock is not granted in time.
4417
+ */
4418
+ type CartLock = <T>(name: string, task: () => Promise<T>) => Promise<T>;
4419
+ type ShopifyCartClientOptions = {
4420
+ /**
4421
+ The store and the buyer, asked before every call: memoize what it fetches.
4422
+ */
4423
+ settings: () => Promise<ShopifyCartSettings>;
4424
+ /**
4425
+ Defaults to the global `fetch`.
4426
+ */
4427
+ fetch?: (input: string, init: RequestInit) => Promise<Response>;
4428
+ /**
4429
+ Defaults to `localStorage`, or memory where the browser refuses it.
4430
+ */
4431
+ storage?: CartStorage;
4432
+ /**
4433
+ Defaults to `navigator.locks`, or a lease kept in `storage` where there is none.
4434
+ */
4435
+ lock?: CartLock;
4436
+ /**
4437
+ Sends the shopper to checkout. Defaults to `location.assign`.
4438
+ */
4439
+ navigate?: (url: string) => void;
4440
+ };
4441
+ type ShopifyCartClient = {
4442
+ /**
4443
+ The cart as Shopify has it now; `data: undefined` when there is none yet, and the store is not asked then.
4444
+ */
4445
+ getCart: () => Promise<ShopifyCartResult>;
4446
+ /**
4447
+ Adds `quantity` (default 1) of a variant (`gid://shopify/ProductVariant/<id>`, or the bare number); creates the cart on the first add.
4448
+ */
4449
+ addItem: (variantId: string, quantity?: number) => Promise<ShopifyCartResult>;
4450
+ /**
4451
+ Removes a line (`ShopifyCartLine.id`).
4452
+ */
4453
+ removeItem: (lineId: string) => Promise<ShopifyCartResult>;
4454
+ /**
4455
+ Sets a line's quantity; 0 removes it, as in Shopify.
4456
+ */
4457
+ updateQuantity: (lineId: string, quantity: number) => Promise<ShopifyCartResult>;
4458
+ /**
4459
+ Sends the shopper to Shopify's checkout for the cart, and resolves its URL. An empty cart goes nowhere (`no_cart`).
4460
+ */
4461
+ checkout: () => Promise<ShopifyCartResult<string>>;
4462
+ };
4463
+ /**
4464
+ Whether `variantId` is a Shopify product variant gid (`gid://shopify/ProductVariant/123`).
4465
+ */
4466
+ declare const isVariantGid: (variantId: string) => boolean;
4467
+ /**
4468
+ The browser's storage, or one kept in memory where the browser refuses it. Pass the same one to every
4469
+ cart client of a page, so they share the cart id even where the browser keeps nothing.
4470
+ */
4471
+ declare function createPageStorage(): CartStorage;
4472
+ /**
4473
+ The Shopify cart in the shopper's browser, on the Storefront API (version
4474
+ {@link STOREFRONT_API_VERSION}) of the store the settings name, tokenless
4475
+ until a storefront token exists. Every method resolves a
4476
+ {@link ShopifyCartResult} and never rejects.
4477
+ @example
4478
+ ```ts
4479
+ const cart = createShopifyCart({settings: async () => ({cartEnabled: true, storeDomain: 'brand.com', country: 'IT'})});
4480
+ const {data, error, warnings} = await cart.addItem('gid://shopify/ProductVariant/123', 1);
4481
+ ```
4482
+ */
4483
+ declare function createShopifyCart(options: ShopifyCartClientOptions): ShopifyCartClient;
4484
+
4149
4485
  /**
4150
4486
  Logger utility for Thamyr SDK
4151
4487
  Provides configurable logging that can be enabled/disabled to avoid console spam
@@ -4297,5 +4633,5 @@ declare function ensureIntentSessionId(): void;
4297
4633
  declare function clearIntentSessionId(): void;
4298
4634
  declare function setIntentSessionMaxAge(_seconds: number): void;
4299
4635
 
4300
- export { ACTION_TYPES, ADD_TO_CART_RESULT_BLOCK, CallimacusApi, CallimacusEvent, CallimacusService, ChapterStatus, ClientEvents, DELIVER_RESULT_BLOCK, GalleryMode, LANDING_VALUE_MAX_LENGTH, MAX_HANDSHAKE_RETRIES, SLInputEventType, ServerEvents, ThamyrHttpError, ThamyrResponseType, UserInteractionType, actionOf, addToCartResultOf, applyBlockPatch, blockKeyOf, callimacusService, classifyConnectError, clearIntentSessionId, createContractClient, deliverResultOf, ensureIntentSessionId, extractTtsAudio, fieldsOf, getIntentSessionId, initIntent, interactionRound, isCustomBlock, isMasterProduct, isSetProduct, landingRound, logger, parseConnectRejection, parseMapPath, randomUuid, receptorsOf, resolveMapPage, setConsent, setDebug, setDebugPanel, setGeo, setIntentSessionMaxAge, shouldRetryHandshake, transformImageUrl };
4301
- export type { Action, ActionType, AddToCartResult, BCProduct, Basket, Block, BlockPatch, BoundingBox, CallimacusErrorMessage, Chapter, ClientInfo, ConnectRejection, ConnectionStatusCallback, ContractClient, CustomBlock, DeliverResult, DocumentIndexEntry, ErrorCallback, ErrorMessage, Gallery, GenericProduct, HomePage, Image, ImageEdits, ImageFormatEdit, ImageResizeEdit, InitOptions, InteractionContext, InteractionId, InteractionOptions, InteractionPayload, InteractionPayloadMap, LegacyBlock, LocalizedEPArtwork, LocalizedEPChapter, LogLevel, LoggerConfig, MapPage, MapPath, MasterProduct, MasterProductWithVariationGroup, OptionItem, ProductItem, ProductMatch, RecommendationsResponse, RiveManifest, RoundOptions, SLDocument, SLDocumentSection, SLInputEvent, ServerResponseCallback, SetProduct, SkesisItem, SkesisItemPage, SkesisRelatedResponse, SkesisSimilarResponse, Story, SuggestPayload, Suggestions, ThamyrInteractionMap, ThamyrResponse, Topic, TopicContentsPage, TopicSummary, TtsAudio, UiElement, UiObserverConfig, UiSnapshot, UserInteraction, Variant, VariationAttribute, VariationGroup, Video, WhisperPayload };
4636
+ export { ACTION_TYPES, ADD_TO_CART_RESULT_BLOCK, CallimacusApi, CallimacusEvent, CallimacusService, ChapterStatus, ClientEvents, DELIVER_RESULT_BLOCK, GalleryMode, LANDING_VALUE_MAX_LENGTH, MAX_HANDSHAKE_RETRIES, SLInputEventType, STOREFRONT_API_VERSION, ServerEvents, ThamyrHttpError, ThamyrResponseType, UserInteractionType, actionOf, addToCartResultOf, applyBlockPatch, blockKeyOf, callimacusService, cartSettingsFor, classifyConnectError, clearIntentSessionId, createContractClient, createPageStorage, createShopifyCart, deliverResultOf, ensureIntentSessionId, extractTtsAudio, fieldsOf, getIntentSessionId, initIntent, interactionRound, isCustomBlock, isMasterProduct, isSetProduct, isVariantGid, landingRound, logger, mergeShopifySettings, parseConnectRejection, parseMapPath, randomUuid, readShopifySettings, receptorsOf, resolveMapPage, setConsent, setDebug, setDebugPanel, setGeo, setIntentSessionMaxAge, shouldRetryHandshake, transformImageUrl };
4637
+ export type { Action, ActionType, AddToCartResult, BCProduct, Basket, Block, BlockPatch, BoundingBox, CallimacusErrorMessage, CartCommand, CartLock, CartStorage, Chapter, ClientInfo, ConnectRejection, ConnectionStatusCallback, ContractClient, CustomBlock, DeliverResult, DocumentIndexEntry, ErrorCallback, ErrorMessage, Gallery, GenericProduct, HomePage, Image, ImageEdits, ImageFormatEdit, ImageResizeEdit, InitOptions, InteractionContext, InteractionId, InteractionOptions, InteractionPayload, InteractionPayloadMap, LegacyBlock, LocalizedEPArtwork, LocalizedEPChapter, LogLevel, LoggerConfig, MapPage, MapPath, MasterProduct, MasterProductWithVariationGroup, OptionItem, ProductItem, ProductMatch, RecommendationsResponse, RiveManifest, RoundOptions, SLDocument, SLDocumentSection, SLInputEvent, ServerResponseCallback, SetProduct, ShopifyCart, ShopifyCartClient, ShopifyCartClientOptions, ShopifyCartError, ShopifyCartErrorCode, ShopifyCartLine, ShopifyCartResult, ShopifyCartSettings, ShopifyCartWarning, ShopifyConfig, ShopifyMoney, ShopifySettings, ShopifyStorefront, ShopifyUserError, SkesisItem, SkesisItemPage, SkesisRelatedResponse, SkesisSimilarResponse, Story, SuggestPayload, Suggestions, ThamyrInteractionMap, ThamyrResponse, Topic, TopicContentsPage, TopicSummary, TtsAudio, UiElement, UiObserverConfig, UiSnapshot, UserInteraction, Variant, VariationAttribute, VariationGroup, Video, WhisperPayload };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callimacus/thamyr-core",
3
- "version": "4.11.1",
3
+ "version": "4.13.0",
4
4
  "private": false,
5
5
  "description": "Core package for Thamyr",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -35,7 +35,7 @@
35
35
  "build": "rollup -c",
36
36
  "dev": "rollup -c -w",
37
37
  "clean": "rm -rf dist",
38
- "test": "node --experimental-strip-types --test test/**/*.test.ts",
38
+ "test": "node --experimental-strip-types --test 'test/**/*.test.ts'",
39
39
  "lint": "eslint src"
40
40
  },
41
41
  "dependencies": {