@lockerverse/sdk 0.1.0-alpha.1

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.
@@ -0,0 +1,2 @@
1
+ import{n as e}from"./types.js";const t=/\/+$/,n=new Set([`localhost`,`127.0.0.1`,`[::1]`]),r={development:{sentryDsn:`https://1977371f7bc44480935a7bc9726ca296@o1338376.ingest.sentry.io/6631829`},production:{sentryDsn:`https://c87cbc682ff0422eab5a4714acb95fd1@o1338376.ingest.sentry.io/6662564`}};function i(e){if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(`Expected an object.`);return e}function a(e){if(e===`development`||e===`production`)return e;throw TypeError(`environment must be either development or production.`)}function o(e,r){if(typeof e!=`string`)throw TypeError(`apiBaseUrl must be a valid HTTP or HTTPS URL.`);let i;try{i=new URL(e)}catch{throw TypeError(`apiBaseUrl must be a valid HTTP or HTTPS URL.`)}if(i.protocol!==`http:`&&i.protocol!==`https:`)throw TypeError(`apiBaseUrl must be a valid HTTP or HTTPS URL.`);if(i.username||i.password)throw TypeError(`apiBaseUrl must not include credentials.`);if(i.search||i.hash)throw TypeError(`apiBaseUrl must not include a query or fragment.`);if(i.protocol!==`https:`&&!(r===`development`&&n.has(i.hostname)))throw TypeError(`apiBaseUrl must use HTTPS except for development loopback endpoints.`);return i.pathname=i.pathname.replace(t,``),i.toString().replace(t,``)}function s(e,t){if(typeof e!=`string`||e.trim().length===0)throw TypeError(`${t} must be a non-empty string.`);return e}function c(e,t){let n=i(e),c=n.environment;if(n.apiBaseUrl!==void 0&&c===void 0)throw TypeError(`environment is required when apiBaseUrl is provided.`);if(n.apiBaseUrl===void 0&&c===`development`)throw TypeError(`apiBaseUrl is required when environment is development.`);let l=c===void 0?`production`:a(c),u=s(n.communitySlug,`communitySlug`),d=s(n[t],t);if(n.fetch!==void 0&&typeof n.fetch!=`function`)throw TypeError(`fetch must be a function when provided.`);if(n.onError!==void 0&&typeof n.onError!=`function`)throw TypeError(`onError must be a function when provided.`);if(n.sentryDsn!==void 0&&n.sentryDsn!==null&&typeof n.sentryDsn!=`string`)throw TypeError(`sentryDsn must be a string or null when provided.`);let f=n.fetch??globalThis.fetch,p=n.apiBaseUrl===void 0?`https://portal.lockerverse.com/api`:o(n.apiBaseUrl,l),m=r[l],h=n.sentryDsn,g=h===null?null:h??m.sentryDsn;return{apiBaseUrl:p,communitySlug:encodeURIComponent(u),communitySlugValue:u,environment:l,fetchImplementation:f,onError:n.onError,resourceSlug:encodeURIComponent(d),resourceSlugValue:d,sentryDsn:g}}function l(e){let t=c(e,`signupSlug`);return{...t,signupSlug:t.resourceSlug,signupSlugValue:t.resourceSlugValue}}function u(e){if(typeof e!=`object`||!e||Object.isFrozen(e))return e;for(let t of Object.values(e))u(t);return Object.freeze(e)}function d({communitySlug:e,environment:t,getContext:n,onError:r,resourceContextName:i,sentryDsn:a}){let o=null;return function(s){try{r?.(s)}catch{}if(s.reportable&&a&&typeof window<`u`){let r=o??import(`./telemetry.js`);o=r;let c={communitySlug:e,...n()};s.status!==void 0&&(c.status=s.status),r.then(({captureSdkError:e})=>e({context:c,contextName:i,dsn:a,environment:t,error:s})).catch(()=>{o===r&&(o=null)})}return s}}function f(e){if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(`Expected an object.`);return e}function p(e){if(typeof e!=`string`)throw TypeError(`Expected a string.`);return e}function m(e){let t=p(e);if(t.trim().length===0)throw TypeError(`Expected a non-empty string.`);return t}function h(e,t){return e===void 0?t:p(e)}function g(e){return e===null?null:p(e)}function _(e,t){return e===void 0?t:g(e)}function v(e){if(typeof e!=`boolean`)throw TypeError(`Expected a boolean.`);return e}function y(e,t){return e===void 0?t:v(e)}function b(e){return e!=null&&m(e).length>0}function x(e){if(!Array.isArray(e))throw TypeError(`Expected a custom field option array.`);let t=new Set,n=[];for(let r of e){let e=f(r);if(b(e.archivedAt))continue;let i=m(e.id);if(t.has(i))throw TypeError(`Expected unique custom field option IDs.`);t.add(i),n.push({id:i,label:m(e.label)})}if(n.length<2)throw TypeError(`Expected at least two active custom field options.`);return n}function S(e){if(e===void 0)return[];if(!Array.isArray(e))throw TypeError(`Expected a custom field array.`);let t=new Set,n=[];for(let r of e){let e=f(r);if(b(e.archivedAt))continue;let i=m(e.id);if(t.has(i))throw TypeError(`Expected unique custom field IDs.`);t.add(i);let a={id:i,label:m(e.label),required:v(e.required)};if(e.type===`text`||e.type===`textarea`)n.push({...a,type:e.type});else if(e.type===`radio`||e.type===`select`)n.push({...a,options:x(e.options),type:e.type});else if(e.type===`checkboxes`||e.type===`multi_select`)n.push({...a,options:x(e.options),type:e.type});else throw TypeError(`Expected a supported custom field type.`)}return n}function C(e){let t=u(e),n=new Set;return{commit(e){t=u(e);for(let e of[...n])try{e(t)}catch{}},getState(){return t},subscribe(e){n.add(e);try{e(t)}catch{}return()=>{n.delete(e)}}}}function w(t,n){async function r(r,i,a){try{return await t(r,i)}catch{let t=new e({code:a.code,message:a.message,operation:a.operation,reportable:!0});throw a.report===!1?t:n(t)}}async function i(t,r,i){try{return r(await t.json())}catch{let t=new e({code:i.code,message:i.message,operation:i.operation,reportable:!0});throw i.report===!1?t:n(t)}}return{fetchResponse:r,parseResponseJson:i}}export{m as a,_ as c,d,u as f,S as i,h as l,l as m,C as n,g as o,c as p,v as r,y as s,w as t,f as u};
2
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","names":["parseRecord"],"sources":["../src/environment.ts","../src/deep-freeze.ts","../src/error-reporting.ts","../src/parsing.ts","../src/state.ts","../src/transport.ts"],"sourcesContent":["import type { CreateLockerverseSignupOptions } from \"./signup-types.ts\";\nimport type { LockerverseEnvironment, LockerverseSdkError } from \"./types.ts\";\n\nconst DEFAULT_API_BASE_URL = \"https://portal.lockerverse.com/api\";\nconst TRAILING_SLASHES = /\\/+$/;\nconst LOOPBACK_HOSTNAMES = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"]);\nconst ENVIRONMENT_CONFIG = {\n development: {\n sentryDsn:\n \"https://1977371f7bc44480935a7bc9726ca296@o1338376.ingest.sentry.io/6631829\",\n },\n production: {\n sentryDsn:\n \"https://c87cbc682ff0422eab5a4714acb95fd1@o1338376.ingest.sentry.io/6662564\",\n },\n} as const;\n\nfunction parseRecord(value: unknown): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"Expected an object.\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction parseEnvironment(value: unknown): LockerverseEnvironment {\n if (value === \"development\" || value === \"production\") {\n return value;\n }\n throw new TypeError(\"environment must be either development or production.\");\n}\n\nfunction parseApiBaseUrl(value: unknown, environment: LockerverseEnvironment) {\n if (typeof value !== \"string\") {\n throw new TypeError(\"apiBaseUrl must be a valid HTTP or HTTPS URL.\");\n }\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n // biome-ignore lint/style/useErrorCause: The URL parser error can contain the rejected endpoint or credentials.\n throw new TypeError(\"apiBaseUrl must be a valid HTTP or HTTPS URL.\");\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new TypeError(\"apiBaseUrl must be a valid HTTP or HTTPS URL.\");\n }\n if (url.username || url.password) {\n throw new TypeError(\"apiBaseUrl must not include credentials.\");\n }\n if (url.search || url.hash) {\n throw new TypeError(\"apiBaseUrl must not include a query or fragment.\");\n }\n if (\n url.protocol !== \"https:\" &&\n !(environment === \"development\" && LOOPBACK_HOSTNAMES.has(url.hostname))\n ) {\n throw new TypeError(\n \"apiBaseUrl must use HTTPS except for development loopback endpoints.\"\n );\n }\n url.pathname = url.pathname.replace(TRAILING_SLASHES, \"\");\n return url.toString().replace(TRAILING_SLASHES, \"\");\n}\n\nfunction parseSlug(value: unknown, name: string) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new TypeError(`${name} must be a non-empty string.`);\n }\n return value;\n}\n\nexport function resolveResourceEnvironment(\n options: unknown,\n resourceSlugKey: string\n) {\n const runtimeOptions = parseRecord(options);\n const requestedEnvironment = runtimeOptions.environment;\n if (\n runtimeOptions.apiBaseUrl !== undefined &&\n requestedEnvironment === undefined\n ) {\n throw new TypeError(\"environment is required when apiBaseUrl is provided.\");\n }\n if (\n runtimeOptions.apiBaseUrl === undefined &&\n requestedEnvironment === \"development\"\n ) {\n throw new TypeError(\n \"apiBaseUrl is required when environment is development.\"\n );\n }\n\n const environment =\n requestedEnvironment === undefined\n ? \"production\"\n : parseEnvironment(requestedEnvironment);\n const communitySlugValue = parseSlug(\n runtimeOptions.communitySlug,\n \"communitySlug\"\n );\n const resourceSlugValue = parseSlug(\n runtimeOptions[resourceSlugKey],\n resourceSlugKey\n );\n if (\n runtimeOptions.fetch !== undefined &&\n typeof runtimeOptions.fetch !== \"function\"\n ) {\n throw new TypeError(\"fetch must be a function when provided.\");\n }\n if (\n runtimeOptions.onError !== undefined &&\n typeof runtimeOptions.onError !== \"function\"\n ) {\n throw new TypeError(\"onError must be a function when provided.\");\n }\n if (\n runtimeOptions.sentryDsn !== undefined &&\n runtimeOptions.sentryDsn !== null &&\n typeof runtimeOptions.sentryDsn !== \"string\"\n ) {\n throw new TypeError(\"sentryDsn must be a string or null when provided.\");\n }\n\n const fetchImplementation =\n (runtimeOptions.fetch as typeof globalThis.fetch | undefined) ??\n globalThis.fetch;\n const apiBaseUrl =\n runtimeOptions.apiBaseUrl === undefined\n ? DEFAULT_API_BASE_URL\n : parseApiBaseUrl(runtimeOptions.apiBaseUrl, environment);\n const environmentConfig = ENVIRONMENT_CONFIG[environment];\n const configuredSentryDsn = runtimeOptions.sentryDsn as\n | string\n | null\n | undefined;\n const sentryDsn =\n configuredSentryDsn === null\n ? null\n : (configuredSentryDsn ?? environmentConfig.sentryDsn);\n\n return {\n apiBaseUrl,\n communitySlug: encodeURIComponent(communitySlugValue),\n communitySlugValue,\n environment,\n fetchImplementation,\n onError: runtimeOptions.onError as\n | ((error: LockerverseSdkError) => void)\n | undefined,\n resourceSlug: encodeURIComponent(resourceSlugValue),\n resourceSlugValue,\n sentryDsn,\n };\n}\n\nexport function resolveSignupEnvironment(\n options: CreateLockerverseSignupOptions\n) {\n const runtime = resolveResourceEnvironment(options, \"signupSlug\");\n return {\n ...runtime,\n signupSlug: runtime.resourceSlug,\n signupSlugValue: runtime.resourceSlugValue,\n };\n}\n","export function deepFreeze<T>(value: T): T {\n if (typeof value !== \"object\" || value === null || Object.isFrozen(value)) {\n return value;\n }\n for (const nestedValue of Object.values(value)) {\n deepFreeze(nestedValue);\n }\n return Object.freeze(value);\n}\n","import type { LockerverseEnvironment, LockerverseSdkError } from \"./types.ts\";\n\ntype TelemetryValue = boolean | number | string | null;\n\nexport function createSdkErrorReporter({\n communitySlug,\n environment,\n getContext,\n onError,\n resourceContextName,\n sentryDsn,\n}: {\n communitySlug: string;\n environment: LockerverseEnvironment;\n getContext: () => Record<string, TelemetryValue>;\n onError: ((error: LockerverseSdkError) => void) | undefined;\n resourceContextName: string;\n sentryDsn: string | null;\n}) {\n let telemetryModulePromise: Promise<typeof import(\"./telemetry.ts\")> | null =\n null;\n\n return function reportError(error: LockerverseSdkError) {\n try {\n onError?.(error);\n } catch {\n // Host error reporting must never interrupt an SDK workflow.\n }\n\n if (error.reportable && sentryDsn && typeof window !== \"undefined\") {\n const telemetryPromise =\n telemetryModulePromise ?? import(\"./telemetry.ts\");\n telemetryModulePromise = telemetryPromise;\n const context: Record<string, TelemetryValue> = {\n communitySlug,\n ...getContext(),\n };\n if (error.status !== undefined) {\n context.status = error.status;\n }\n telemetryPromise\n .then(({ captureSdkError }) =>\n captureSdkError({\n context,\n contextName: resourceContextName,\n dsn: sentryDsn,\n environment,\n error,\n })\n )\n .catch(() => {\n if (telemetryModulePromise === telemetryPromise) {\n telemetryModulePromise = null;\n }\n });\n }\n\n return error;\n };\n}\n","import type {\n LockerverseCustomField,\n LockerverseCustomFieldOption,\n} from \"./types.ts\";\n\nexport function parseRecord(value: unknown): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"Expected an object.\");\n }\n\n return value as Record<string, unknown>;\n}\n\nfunction parseString(value: unknown): string {\n if (typeof value !== \"string\") {\n throw new TypeError(\"Expected a string.\");\n }\n\n return value;\n}\n\nexport function parseNonEmptyString(value: unknown): string {\n const parsed = parseString(value);\n if (parsed.trim().length === 0) {\n throw new TypeError(\"Expected a non-empty string.\");\n }\n\n return parsed;\n}\n\nexport function parseOptionalString(value: unknown, fallback: string): string {\n return value === undefined ? fallback : parseString(value);\n}\n\nexport function parseNullableString(value: unknown): string | null {\n return value === null ? null : parseString(value);\n}\n\nexport function parseOptionalNullableString(\n value: unknown,\n fallback: string | null\n): string | null {\n if (value === undefined) {\n return fallback;\n }\n return parseNullableString(value);\n}\n\nexport function parseBoolean(value: unknown): boolean {\n if (typeof value !== \"boolean\") {\n throw new TypeError(\"Expected a boolean.\");\n }\n\n return value;\n}\n\nexport function parseOptionalBoolean(\n value: unknown,\n fallback: boolean\n): boolean {\n return value === undefined ? fallback : parseBoolean(value);\n}\n\nfunction parseArchived(value: unknown): boolean {\n if (value === undefined || value === null) {\n return false;\n }\n return parseNonEmptyString(value).length > 0;\n}\n\nfunction parseCustomFieldOptions(\n value: unknown\n): LockerverseCustomFieldOption[] {\n if (!Array.isArray(value)) {\n throw new TypeError(\"Expected a custom field option array.\");\n }\n const optionIds = new Set<string>();\n const options: LockerverseCustomFieldOption[] = [];\n for (const optionValue of value) {\n const option = parseRecord(optionValue);\n if (parseArchived(option.archivedAt)) {\n continue;\n }\n const id = parseNonEmptyString(option.id);\n if (optionIds.has(id)) {\n throw new TypeError(\"Expected unique custom field option IDs.\");\n }\n optionIds.add(id);\n options.push({ id, label: parseNonEmptyString(option.label) });\n }\n if (options.length < 2) {\n throw new TypeError(\"Expected at least two active custom field options.\");\n }\n return options;\n}\n\nexport function parseCustomFields(value: unknown): LockerverseCustomField[] {\n if (value === undefined) {\n return [];\n }\n if (!Array.isArray(value)) {\n throw new TypeError(\"Expected a custom field array.\");\n }\n const fieldIds = new Set<string>();\n const fields: LockerverseCustomField[] = [];\n for (const fieldValue of value) {\n const field = parseRecord(fieldValue);\n if (parseArchived(field.archivedAt)) {\n continue;\n }\n const id = parseNonEmptyString(field.id);\n if (fieldIds.has(id)) {\n throw new TypeError(\"Expected unique custom field IDs.\");\n }\n fieldIds.add(id);\n const base = {\n id,\n label: parseNonEmptyString(field.label),\n required: parseBoolean(field.required),\n };\n if (field.type === \"text\" || field.type === \"textarea\") {\n fields.push({ ...base, type: field.type });\n } else if (field.type === \"radio\" || field.type === \"select\") {\n fields.push({\n ...base,\n options: parseCustomFieldOptions(field.options),\n type: field.type,\n });\n } else if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n fields.push({\n ...base,\n options: parseCustomFieldOptions(field.options),\n type: field.type,\n });\n } else {\n throw new TypeError(\"Expected a supported custom field type.\");\n }\n }\n return fields;\n}\n","import { deepFreeze } from \"./deep-freeze.ts\";\n\nexport function createStateStore<State>(initialState: State) {\n let state = deepFreeze(initialState);\n const listeners = new Set<(nextState: State) => void>();\n\n return {\n commit(nextState: State) {\n state = deepFreeze(nextState);\n for (const listener of [...listeners]) {\n try {\n listener(state);\n } catch {\n // Host listeners cannot interrupt SDK state transitions.\n }\n }\n },\n getState() {\n return state;\n },\n subscribe(listener: (nextState: State) => void) {\n listeners.add(listener);\n try {\n listener(state);\n } catch {\n // A failing initial render must not prevent subscription or checkout.\n }\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n","import {\n LockerverseSdkError,\n type LockerverseSdkErrorCode,\n type LockerverseSdkOperation,\n} from \"./types.ts\";\n\ntype ErrorContext = {\n code: LockerverseSdkErrorCode;\n message: string;\n operation: LockerverseSdkOperation;\n report?: boolean;\n};\n\ntype ReportError = (error: LockerverseSdkError) => LockerverseSdkError;\n\nexport function createTransport(\n fetchImplementation: typeof globalThis.fetch,\n reportError: ReportError\n) {\n async function fetchResponse(\n input: string,\n init: RequestInit | undefined,\n context: ErrorContext\n ) {\n try {\n return await fetchImplementation(input, init);\n } catch {\n const error = new LockerverseSdkError({\n code: context.code,\n message: context.message,\n operation: context.operation,\n reportable: true,\n });\n // biome-ignore lint/style/useErrorCause: Raw host network errors are intentionally excluded from public SDK errors and telemetry.\n throw context.report === false ? error : reportError(error);\n }\n }\n\n async function parseResponseJson<T>(\n response: Response,\n parser: (value: unknown) => T,\n context: ErrorContext\n ) {\n try {\n const value: unknown = await response.json();\n return parser(value);\n } catch {\n const error = new LockerverseSdkError({\n code: context.code,\n message: context.message,\n operation: context.operation,\n reportable: true,\n });\n // biome-ignore lint/style/useErrorCause: Raw parse and validation errors must not escape the SDK boundary.\n throw context.report === false ? error : reportError(error);\n }\n }\n\n return { fetchResponse, parseResponseJson };\n}\n"],"mappings":"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"}
@@ -0,0 +1,247 @@
1
+ //#region src/types.d.ts
2
+ type LockerversePaymentOption = "one-time" | "monthly" | "annually";
3
+ type LockerverseEnvironment = "development" | "production";
4
+ declare const LOCKERVERSE_SDK_VERSION: string;
5
+ type LockerverseProduct = {
6
+ id: string;
7
+ listingId: string;
8
+ slug: string;
9
+ name: string;
10
+ description: string | null;
11
+ pricingMode: "fixed" | "custom";
12
+ paymentOption: LockerversePaymentOption;
13
+ amountCents: number | null;
14
+ minimumAmountCents: number | null;
15
+ minimumQuantity: number | null;
16
+ maximumQuantity: number | null;
17
+ inventoryQuantity: number | null;
18
+ acceptsDiscounts: boolean;
19
+ };
20
+ type LockerverseCatalog = {
21
+ payment: LockerversePaymentConfiguration;
22
+ pricingPolicy: LockerverseCheckoutPricingPolicy;
23
+ products: LockerverseProduct[];
24
+ widget: LockerverseWidgetConfiguration;
25
+ };
26
+ type LockerverseCheckoutPricingPolicy = {
27
+ currency: "usd";
28
+ serviceFeeRateBasisPoints: number;
29
+ };
30
+ type LockerversePaymentConfiguration = {
31
+ currency: "usd";
32
+ publishableKey: string;
33
+ };
34
+ type LockerverseCheckoutPaymentConfiguration = LockerversePaymentConfiguration & {
35
+ connectedAccountId: string | null;
36
+ };
37
+ type LockerverseWidgetFields = {
38
+ memberId: boolean;
39
+ merchSize: boolean;
40
+ phone: boolean;
41
+ promoCode: boolean;
42
+ serviceFee: boolean;
43
+ shipping: boolean;
44
+ tipping: boolean;
45
+ };
46
+ type LockerverseCustomFieldOption = {
47
+ id: string;
48
+ label: string;
49
+ };
50
+ type LockerverseCustomFieldBase = {
51
+ id: string;
52
+ label: string;
53
+ required: boolean;
54
+ };
55
+ type LockerverseTextCustomField = LockerverseCustomFieldBase & {
56
+ type: "text" | "textarea";
57
+ };
58
+ type LockerverseSingleOptionCustomField = LockerverseCustomFieldBase & {
59
+ options: LockerverseCustomFieldOption[];
60
+ type: "radio" | "select";
61
+ };
62
+ type LockerverseMultiOptionCustomField = LockerverseCustomFieldBase & {
63
+ options: LockerverseCustomFieldOption[];
64
+ type: "checkboxes" | "multi_select";
65
+ };
66
+ type LockerverseCustomField = LockerverseTextCustomField | LockerverseSingleOptionCustomField | LockerverseMultiOptionCustomField;
67
+ type LockerverseCustomFieldAnswerValue<Field extends LockerverseCustomField> = Field extends LockerverseMultiOptionCustomField ? string[] : string;
68
+ type LockerverseCustomFieldAnswer<Field extends LockerverseCustomField = LockerverseCustomField> = Field extends LockerverseCustomField ? {
69
+ fieldId: Field["id"];
70
+ value: LockerverseCustomFieldAnswerValue<Field>;
71
+ } : never;
72
+ type LockerverseWidgetConfiguration = {
73
+ customFields: LockerverseCustomField[];
74
+ description: string | null;
75
+ fields: LockerverseWidgetFields;
76
+ id: string;
77
+ name: string;
78
+ showCommunityBranding: boolean;
79
+ title: string | null;
80
+ };
81
+ type LockerverseSdkErrorCode = "widget_load_failed" | "signup_load_failed" | "signup_submit_failed" | "total_calculation_failed" | "payment_submit_failed" | "payment_status_failed" | "invalid_selection";
82
+ type LockerverseSdkOperation = "load_widget" | "load_signup" | "submit_signup" | "calculate_total" | "submit_payment" | "get_payment_status" | "update_selection";
83
+ declare class LockerverseSdkError extends Error {
84
+ readonly code: LockerverseSdkErrorCode;
85
+ readonly operation: LockerverseSdkOperation;
86
+ readonly reportable: boolean;
87
+ readonly sdkVersion: string;
88
+ readonly status: number | undefined;
89
+ constructor({ code, message, operation, reportable, status }: {
90
+ code: LockerverseSdkErrorCode;
91
+ message: string;
92
+ operation: LockerverseSdkOperation;
93
+ reportable: boolean;
94
+ status?: number;
95
+ });
96
+ }
97
+ type LockerverseCheckoutLineItem = {
98
+ productId: string;
99
+ productName: string;
100
+ listingId: string;
101
+ listingSlug: string;
102
+ acceptsDiscounts: boolean;
103
+ pricingMode: "fixed" | "custom";
104
+ paymentOption: LockerversePaymentOption;
105
+ quantity: number;
106
+ unitAmountCents: number;
107
+ subtotalCents: number;
108
+ };
109
+ type LockerverseAppliedDiscount = {
110
+ percentageOff: number;
111
+ source: "email_list" | "promo_code";
112
+ };
113
+ type LockerverseCheckoutAmounts = {
114
+ amountCents: number;
115
+ discountableSubtotalCents: number;
116
+ discountCents: number;
117
+ serviceFeeCents: number;
118
+ subtotalCents: number;
119
+ tipCents: number;
120
+ totalCents: number;
121
+ };
122
+ type LockerverseCheckoutQuote = LockerverseCheckoutAmounts & {
123
+ appliedDiscount: LockerverseAppliedDiscount | null;
124
+ authoritative: true;
125
+ paymentReference: string;
126
+ payment: LockerverseCheckoutPaymentConfiguration;
127
+ paymentOption: "one-time";
128
+ lineItems: LockerverseCheckoutLineItem[];
129
+ };
130
+ type LockerverseCheckoutTotal = LockerverseCheckoutQuote;
131
+ type LockerverseCheckoutPricingInput = {
132
+ email?: string;
133
+ includeServiceFee?: boolean;
134
+ promoCode?: string;
135
+ tipCents?: number;
136
+ };
137
+ type LockerverseCheckoutPreview = LockerverseCheckoutAmounts & {
138
+ appliedDiscount: null;
139
+ authoritative: false;
140
+ };
141
+ type LockerversePaymentStatus = "action_required" | "failed" | "pending" | "success";
142
+ type LockerversePaymentResult = {
143
+ checkoutId: string;
144
+ paymentReference: string;
145
+ checkoutStatus: LockerversePaymentStatus;
146
+ clientSecret: string | null;
147
+ requiresAction: boolean;
148
+ status: string | null;
149
+ };
150
+ type LockerversePaymentSubmission = {
151
+ confirmationToken: string;
152
+ customFieldAnswers?: LockerverseCustomFieldAnswer[];
153
+ email: string;
154
+ memberId?: string;
155
+ merchSize?: "XS" | "S" | "M" | "L" | "XL" | "XXL" | "XXXL";
156
+ metadata?: Record<string, string>;
157
+ phone?: string;
158
+ };
159
+ type LockerverseWidgetState = {
160
+ phase: "idle";
161
+ selection: LockerverseSelection;
162
+ } | {
163
+ phase: "loading";
164
+ selection: LockerverseSelection;
165
+ } | {
166
+ phase: "ready";
167
+ catalog: LockerverseCatalog;
168
+ selection: LockerverseSelection;
169
+ preview: LockerverseCheckoutPreview | null;
170
+ } | {
171
+ phase: "quoting";
172
+ catalog: LockerverseCatalog;
173
+ selection: LockerverseSelection;
174
+ preview: LockerverseCheckoutPreview;
175
+ } | {
176
+ phase: "quoted";
177
+ catalog: LockerverseCatalog;
178
+ selection: LockerverseSelection;
179
+ preview: LockerverseCheckoutPreview;
180
+ quote: LockerverseCheckoutTotal;
181
+ } | {
182
+ phase: "submitting";
183
+ catalog: LockerverseCatalog;
184
+ selection: LockerverseSelection;
185
+ preview: LockerverseCheckoutPreview;
186
+ quote: LockerverseCheckoutTotal;
187
+ } | {
188
+ phase: "recovering";
189
+ catalog: LockerverseCatalog | null;
190
+ selection: LockerverseSelection;
191
+ paymentReference: string;
192
+ } | {
193
+ phase: "payment";
194
+ catalog: LockerverseCatalog | null;
195
+ selection: LockerverseSelection;
196
+ quote: LockerverseCheckoutTotal | null;
197
+ payment: LockerversePaymentResult;
198
+ } | {
199
+ phase: "error";
200
+ catalog: LockerverseCatalog | null;
201
+ selection: LockerverseSelection;
202
+ error: LockerverseSdkError;
203
+ recoverablePaymentReference: string | null;
204
+ };
205
+ type LockerverseSelectionItem = {
206
+ productId: string;
207
+ productSlug: string;
208
+ quantity: number;
209
+ } | {
210
+ productId: string;
211
+ productSlug: string;
212
+ amountCents: number;
213
+ };
214
+ type LockerverseSelection = {
215
+ items: LockerverseSelectionItem[];
216
+ };
217
+ type CreateLockerverseWidgetBaseOptions = {
218
+ communitySlug: string;
219
+ fetch?: typeof globalThis.fetch;
220
+ onError?: (error: LockerverseSdkError) => void;
221
+ sentryDsn?: string | null;
222
+ widgetSlug: string;
223
+ };
224
+ type CreateLockerverseWidgetOptions = CreateLockerverseWidgetBaseOptions & ({
225
+ apiBaseUrl: string;
226
+ environment: LockerverseEnvironment;
227
+ } | {
228
+ apiBaseUrl?: undefined;
229
+ environment?: "production";
230
+ });
231
+ type LockerverseWidget = {
232
+ calculateTotal: (input?: LockerverseCheckoutPricingInput) => Promise<LockerverseCheckoutQuote>;
233
+ clear: () => void;
234
+ getSelection: () => LockerverseSelection;
235
+ getState: () => LockerverseWidgetState;
236
+ getPaymentStatus: (paymentReference?: string) => Promise<LockerversePaymentResult>;
237
+ load: () => Promise<LockerverseCatalog>;
238
+ previewTotal: (input?: LockerverseCheckoutPricingInput) => LockerverseCheckoutPreview;
239
+ remove: (productSlug: string) => void;
240
+ setAmount: (productSlug: string, amountCents: number) => void;
241
+ setQuantity: (productSlug: string, quantity: number) => void;
242
+ submitPayment: (submission: LockerversePaymentSubmission) => Promise<LockerversePaymentResult>;
243
+ subscribe: (listener: (state: LockerverseWidgetState) => void) => () => void;
244
+ };
245
+ //#endregion
246
+ export { LockerverseSingleOptionCustomField as A, LockerversePaymentSubmission as C, LockerverseSdkOperation as D, LockerverseSdkErrorCode as E, LockerverseWidgetState as F, LockerverseWidget as M, LockerverseWidgetConfiguration as N, LockerverseSelection as O, LockerverseWidgetFields as P, LockerversePaymentStatus as S, LockerverseSdkError as T, LockerverseEnvironment as _, LockerverseCheckoutAmounts as a, LockerversePaymentOption as b, LockerverseCheckoutPreview as c, LockerverseCheckoutQuote as d, LockerverseCheckoutTotal as f, LockerverseCustomFieldOption as g, LockerverseCustomFieldAnswerValue as h, LockerverseCatalog as i, LockerverseTextCustomField as j, LockerverseSelectionItem as k, LockerverseCheckoutPricingInput as l, LockerverseCustomFieldAnswer as m, LOCKERVERSE_SDK_VERSION as n, LockerverseCheckoutLineItem as o, LockerverseCustomField as p, LockerverseAppliedDiscount as r, LockerverseCheckoutPaymentConfiguration as s, CreateLockerverseWidgetOptions as t, LockerverseCheckoutPricingPolicy as u, LockerverseMultiOptionCustomField as v, LockerverseProduct as w, LockerversePaymentResult as x, LockerversePaymentConfiguration as y };
247
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";KAEY;KACA;cAEC;KAED;EACV;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV,SAAS;EACT,eAAe;EACf,UAAU;EACV,QAAQ;;KAGE;EACV;EACA;;KAGU;EACV;EACA;;KAGU,0CACV;EACE;;KAGQ;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU;EAAiC;EAAY;;KAEpD;EACH;EACA;EACA;;KAGU,6BAA6B;EACvC;;KAGU,qCAAqC;EAC/C,SAAS;EACT;;KAGU,oCAAoC;EAC9C,SAAS;EACT;;KAGU,yBACR,6BACA,qCACA;KAEQ,kCACV,cAAc,0BACZ,cAAc;KAEN,6BACV,cAAc,yBAAyB,0BACrC,cAAc;EACZ,SAAS;EAAa,OAAO,kCAAkC;;KAGzD;EACV,cAAc;EACd;EACA,QAAQ;EACR;EACA;EACA;EACA;;KAGU;KASA;cASC,4BAA4B;WAC9B,MAAM;WACN,WAAW;WACX;WACA;WACA;EAEG,cACV,MACA,SACA,WACA,YACA;IAEA,MAAM;IACN;IACA,WAAW;IACX;IACA;;;KAYQ;EACV;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf;EACA;EACA;;KAGU;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU,2BAA2B;EACrC,iBAAiB;EACjB;EACA;EACA,SAAS;EACT;EACA,WAAW;;KAGD,2BAA2B;KAE3B;EACV;EACA;EACA;EACA;;KAGU,6BAA6B;EACvC;EACA;;KAGU;KAMA;EACV;EACA;EACA,gBAAgB;EAChB;EACA;EACA;;KAGU;EACV;EACA,qBAAqB;EACrB;EACA;EACA;EACA,WAAW;EACX;;KAGU;EACN;EAAe,WAAW;;EAC1B;EAAkB,WAAW;;EAE7B;EACA,SAAS;EACT,WAAW;EACX,SAAS;;EAGT;EACA,SAAS;EACT,WAAW;EACX,SAAS;;EAGT;EACA,SAAS;EACT,WAAW;EACX,SAAS;EACT,OAAO;;EAGP;EACA,SAAS;EACT,WAAW;EACX,SAAS;EACT,OAAO;;EAGP;EACA,SAAS;EACT,WAAW;EACX;;EAGA;EACA,SAAS;EACT,WAAW;EACX,OAAO;EACP,SAAS;;EAGT;EACA,SAAS;EACT,WAAW;EACX,OAAO;EACP;;KAGM;EACN;EAAmB;EAAqB;;EACxC;EAAmB;EAAqB;;KAElC;EACV,OAAO;;KAGJ;EACH;EACA,eAAe,WAAW;EAC1B,WAAW,OAAO;EAClB;EACA;;KAGU,iCACV;EAGQ;EACA,aAAa;;EAGb;EACA;;KAIE;EACV,iBACE,QAAQ,oCACL,QAAQ;EACb;EACA,oBAAoB;EACpB,gBAAgB;EAChB,mBACE,8BACG,QAAQ;EACb,YAAY,QAAQ;EACpB,eACE,QAAQ,oCACL;EACL,SAAS;EACT,YAAY,qBAAqB;EACjC,cAAc,qBAAqB;EACnC,gBACE,YAAY,iCACT,QAAQ;EACb,YAAY,WAAW,OAAO"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ const e=`0.1.0-alpha.1`;var t=class extends Error{code;operation;reportable;sdkVersion;status;constructor({code:t,message:n,operation:r,reportable:i,status:a}){super(n),this.name=`LockerverseSdkError`,this.code=t,this.operation=r,this.reportable=i,this.sdkVersion=e,this.status=a}};export{t as n,e as t};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":["packageMetadata.version"],"sources":["../package.json","../src/types.ts"],"sourcesContent":["","import packageMetadata from \"../package.json\" with { type: \"json\" };\n\nexport type LockerversePaymentOption = \"one-time\" | \"monthly\" | \"annually\";\nexport type LockerverseEnvironment = \"development\" | \"production\";\n\nexport const LOCKERVERSE_SDK_VERSION = packageMetadata.version;\n\nexport type LockerverseProduct = {\n id: string;\n listingId: string;\n slug: string;\n name: string;\n description: string | null;\n pricingMode: \"fixed\" | \"custom\";\n paymentOption: LockerversePaymentOption;\n amountCents: number | null;\n minimumAmountCents: number | null;\n minimumQuantity: number | null;\n maximumQuantity: number | null;\n inventoryQuantity: number | null;\n acceptsDiscounts: boolean;\n};\n\nexport type LockerverseCatalog = {\n payment: LockerversePaymentConfiguration;\n pricingPolicy: LockerverseCheckoutPricingPolicy;\n products: LockerverseProduct[];\n widget: LockerverseWidgetConfiguration;\n};\n\nexport type LockerverseCheckoutPricingPolicy = {\n currency: \"usd\";\n serviceFeeRateBasisPoints: number;\n};\n\nexport type LockerversePaymentConfiguration = {\n currency: \"usd\";\n publishableKey: string;\n};\n\nexport type LockerverseCheckoutPaymentConfiguration =\n LockerversePaymentConfiguration & {\n connectedAccountId: string | null;\n };\n\nexport type LockerverseWidgetFields = {\n memberId: boolean;\n merchSize: boolean;\n phone: boolean;\n promoCode: boolean;\n serviceFee: boolean;\n shipping: boolean;\n tipping: boolean;\n};\n\nexport type LockerverseCustomFieldOption = { id: string; label: string };\n\ntype LockerverseCustomFieldBase = {\n id: string;\n label: string;\n required: boolean;\n};\n\nexport type LockerverseTextCustomField = LockerverseCustomFieldBase & {\n type: \"text\" | \"textarea\";\n};\n\nexport type LockerverseSingleOptionCustomField = LockerverseCustomFieldBase & {\n options: LockerverseCustomFieldOption[];\n type: \"radio\" | \"select\";\n};\n\nexport type LockerverseMultiOptionCustomField = LockerverseCustomFieldBase & {\n options: LockerverseCustomFieldOption[];\n type: \"checkboxes\" | \"multi_select\";\n};\n\nexport type LockerverseCustomField =\n | LockerverseTextCustomField\n | LockerverseSingleOptionCustomField\n | LockerverseMultiOptionCustomField;\n\nexport type LockerverseCustomFieldAnswerValue<\n Field extends LockerverseCustomField,\n> = Field extends LockerverseMultiOptionCustomField ? string[] : string;\n\nexport type LockerverseCustomFieldAnswer<\n Field extends LockerverseCustomField = LockerverseCustomField,\n> = Field extends LockerverseCustomField\n ? { fieldId: Field[\"id\"]; value: LockerverseCustomFieldAnswerValue<Field> }\n : never;\n\nexport type LockerverseWidgetConfiguration = {\n customFields: LockerverseCustomField[];\n description: string | null;\n fields: LockerverseWidgetFields;\n id: string;\n name: string;\n showCommunityBranding: boolean;\n title: string | null;\n};\n\nexport type LockerverseSdkErrorCode =\n | \"widget_load_failed\"\n | \"signup_load_failed\"\n | \"signup_submit_failed\"\n | \"total_calculation_failed\"\n | \"payment_submit_failed\"\n | \"payment_status_failed\"\n | \"invalid_selection\";\n\nexport type LockerverseSdkOperation =\n | \"load_widget\"\n | \"load_signup\"\n | \"submit_signup\"\n | \"calculate_total\"\n | \"submit_payment\"\n | \"get_payment_status\"\n | \"update_selection\";\n\nexport class LockerverseSdkError extends Error {\n readonly code: LockerverseSdkErrorCode;\n readonly operation: LockerverseSdkOperation;\n readonly reportable: boolean;\n readonly sdkVersion: string;\n readonly status: number | undefined;\n\n constructor({\n code,\n message,\n operation,\n reportable,\n status,\n }: {\n code: LockerverseSdkErrorCode;\n message: string;\n operation: LockerverseSdkOperation;\n reportable: boolean;\n status?: number;\n }) {\n super(message);\n this.name = \"LockerverseSdkError\";\n this.code = code;\n this.operation = operation;\n this.reportable = reportable;\n this.sdkVersion = LOCKERVERSE_SDK_VERSION;\n this.status = status;\n }\n}\n\nexport type LockerverseCheckoutLineItem = {\n productId: string;\n productName: string;\n listingId: string;\n listingSlug: string;\n acceptsDiscounts: boolean;\n pricingMode: \"fixed\" | \"custom\";\n paymentOption: LockerversePaymentOption;\n quantity: number;\n unitAmountCents: number;\n subtotalCents: number;\n};\n\nexport type LockerverseAppliedDiscount = {\n percentageOff: number;\n source: \"email_list\" | \"promo_code\";\n};\n\nexport type LockerverseCheckoutAmounts = {\n amountCents: number;\n discountableSubtotalCents: number;\n discountCents: number;\n serviceFeeCents: number;\n subtotalCents: number;\n tipCents: number;\n totalCents: number;\n};\n\nexport type LockerverseCheckoutQuote = LockerverseCheckoutAmounts & {\n appliedDiscount: LockerverseAppliedDiscount | null;\n authoritative: true;\n paymentReference: string;\n payment: LockerverseCheckoutPaymentConfiguration;\n paymentOption: \"one-time\";\n lineItems: LockerverseCheckoutLineItem[];\n};\n\nexport type LockerverseCheckoutTotal = LockerverseCheckoutQuote;\n\nexport type LockerverseCheckoutPricingInput = {\n email?: string;\n includeServiceFee?: boolean;\n promoCode?: string;\n tipCents?: number;\n};\n\nexport type LockerverseCheckoutPreview = LockerverseCheckoutAmounts & {\n appliedDiscount: null;\n authoritative: false;\n};\n\nexport type LockerversePaymentStatus =\n | \"action_required\"\n | \"failed\"\n | \"pending\"\n | \"success\";\n\nexport type LockerversePaymentResult = {\n checkoutId: string;\n paymentReference: string;\n checkoutStatus: LockerversePaymentStatus;\n clientSecret: string | null;\n requiresAction: boolean;\n status: string | null;\n};\n\nexport type LockerversePaymentSubmission = {\n confirmationToken: string;\n customFieldAnswers?: LockerverseCustomFieldAnswer[];\n email: string;\n memberId?: string;\n merchSize?: \"XS\" | \"S\" | \"M\" | \"L\" | \"XL\" | \"XXL\" | \"XXXL\";\n metadata?: Record<string, string>;\n phone?: string;\n};\n\nexport type LockerverseWidgetState =\n | { phase: \"idle\"; selection: LockerverseSelection }\n | { phase: \"loading\"; selection: LockerverseSelection }\n | {\n phase: \"ready\";\n catalog: LockerverseCatalog;\n selection: LockerverseSelection;\n preview: LockerverseCheckoutPreview | null;\n }\n | {\n phase: \"quoting\";\n catalog: LockerverseCatalog;\n selection: LockerverseSelection;\n preview: LockerverseCheckoutPreview;\n }\n | {\n phase: \"quoted\";\n catalog: LockerverseCatalog;\n selection: LockerverseSelection;\n preview: LockerverseCheckoutPreview;\n quote: LockerverseCheckoutTotal;\n }\n | {\n phase: \"submitting\";\n catalog: LockerverseCatalog;\n selection: LockerverseSelection;\n preview: LockerverseCheckoutPreview;\n quote: LockerverseCheckoutTotal;\n }\n | {\n phase: \"recovering\";\n catalog: LockerverseCatalog | null;\n selection: LockerverseSelection;\n paymentReference: string;\n }\n | {\n phase: \"payment\";\n catalog: LockerverseCatalog | null;\n selection: LockerverseSelection;\n quote: LockerverseCheckoutTotal | null;\n payment: LockerversePaymentResult;\n }\n | {\n phase: \"error\";\n catalog: LockerverseCatalog | null;\n selection: LockerverseSelection;\n error: LockerverseSdkError;\n recoverablePaymentReference: string | null;\n };\n\nexport type LockerverseSelectionItem =\n | { productId: string; productSlug: string; quantity: number }\n | { productId: string; productSlug: string; amountCents: number };\n\nexport type LockerverseSelection = {\n items: LockerverseSelectionItem[];\n};\n\ntype CreateLockerverseWidgetBaseOptions = {\n communitySlug: string;\n fetch?: typeof globalThis.fetch;\n onError?: (error: LockerverseSdkError) => void;\n sentryDsn?: string | null;\n widgetSlug: string;\n};\n\nexport type CreateLockerverseWidgetOptions =\n CreateLockerverseWidgetBaseOptions &\n (\n | {\n apiBaseUrl: string;\n environment: LockerverseEnvironment;\n }\n | {\n apiBaseUrl?: undefined;\n environment?: \"production\";\n }\n );\n\nexport type LockerverseWidget = {\n calculateTotal: (\n input?: LockerverseCheckoutPricingInput\n ) => Promise<LockerverseCheckoutQuote>;\n clear: () => void;\n getSelection: () => LockerverseSelection;\n getState: () => LockerverseWidgetState;\n getPaymentStatus: (\n paymentReference?: string\n ) => Promise<LockerversePaymentResult>;\n load: () => Promise<LockerverseCatalog>;\n previewTotal: (\n input?: LockerverseCheckoutPricingInput\n ) => LockerverseCheckoutPreview;\n remove: (productSlug: string) => void;\n setAmount: (productSlug: string, amountCents: number) => void;\n setQuantity: (productSlug: string, quantity: number) => void;\n submitPayment: (\n submission: LockerversePaymentSubmission\n ) => Promise<LockerversePaymentResult>;\n subscribe: (listener: (state: LockerverseWidgetState) => void) => () => void;\n};\n"],"mappings":"ACKA,MAAa,EAA0BA,gBAmHvC,IAAa,EAAb,cAAyC,KAAM,CAC7C,KACA,UACA,WACA,WACA,OAEA,YAAY,CACV,OACA,UACA,YACA,aACA,UAOC,CACD,MAAM,CAAO,EACb,KAAK,KAAO,sBACZ,KAAK,KAAO,EACZ,KAAK,UAAY,EACjB,KAAK,WAAa,EAClB,KAAK,WAAa,EAClB,KAAK,OAAS,CAChB,CACF"}
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@lockerverse/sdk",
3
+ "version": "0.1.0-alpha.1",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/Lockerverse/lockerverse-sdk.git",
7
+ "directory": "packages/sdk"
8
+ },
9
+ "sideEffects": false,
10
+ "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./checkout": {
18
+ "types": "./dist/checkout.d.ts",
19
+ "import": "./dist/checkout.js",
20
+ "default": "./dist/checkout.js"
21
+ },
22
+ "./signup": {
23
+ "types": "./dist/signup.d.ts",
24
+ "import": "./dist/signup.js",
25
+ "default": "./dist/signup.js"
26
+ }
27
+ },
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "files": [
31
+ "dist",
32
+ "README.md"
33
+ ],
34
+ "devDependencies": {
35
+ "@arethetypeswrong/core": "0.18.5",
36
+ "@sentry/browser": "10.69.0",
37
+ "@size-limit/file": "13.0.3",
38
+ "@types/node": "24.10.0",
39
+ "@vitest/browser-playwright": "4.1.10",
40
+ "playwright": "1.62.1",
41
+ "publint": "0.3.22",
42
+ "size-limit": "13.0.3",
43
+ "tsdown": "0.22.14",
44
+ "typescript": "5.9.3",
45
+ "vitest": "4.1.10"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "provenance": false
50
+ },
51
+ "size-limit": [
52
+ {
53
+ "name": "checkout core",
54
+ "limit": "7 kB",
55
+ "path": [
56
+ "dist/checkout.js",
57
+ "dist/transport.js",
58
+ "dist/types.js"
59
+ ]
60
+ },
61
+ {
62
+ "name": "signup core",
63
+ "limit": "5 kB",
64
+ "path": [
65
+ "dist/signup.js",
66
+ "dist/transport.js",
67
+ "dist/types.js"
68
+ ]
69
+ },
70
+ {
71
+ "name": "failure-only telemetry",
72
+ "limit": "20 kB",
73
+ "path": "dist/telemetry.js"
74
+ }
75
+ ],
76
+ "scripts": {
77
+ "build": "tsdown",
78
+ "contract:backend": "node test/contract/verify-backend-contract.mjs",
79
+ "dev": "tsdown --watch",
80
+ "pack:check": "node ../../scripts/verify-package.mjs",
81
+ "size": "size-limit",
82
+ "smoke:dev": "node test/contract/live-dev-smoke.mjs",
83
+ "smoke:dev:signup": "node test/contract/live-dev-signup-smoke.mjs",
84
+ "test": "pnpm test:unit && pnpm test:browser",
85
+ "test:browser": "vitest run --config vitest.browser.config.ts",
86
+ "test:unit": "vitest run --config vitest.config.ts",
87
+ "test:watch": "vitest",
88
+ "typecheck": "tsc -p tsconfig.json --noEmit"
89
+ }
90
+ }