@foxscheduling/shared 0.1.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,56 +1,74 @@
1
1
  # @foxscheduling/shared
2
2
 
3
- Shared utilities and interfaces for FoxScheduling backend and frontend.
3
+ Shared TypeScript types and utilities for the [Fox Scheduling](https://foxscheduling.com) platform.
4
4
 
5
- ## Installation
5
+ This package is the companion to [`@foxscheduling/sdk`](https://www.npmjs.com/package/@foxscheduling/sdk). It contains the data types (DTOs, enums, webhook payloads) and helper functions used across Fox Scheduling, so you can share strong typing between your code and the API.
6
6
 
7
- With npm workspaces (already configured in the root `package.json`):
7
+ > If you just want to call the Partner API, install `@foxscheduling/sdk` — it re-exports the types you need from this package.
8
8
 
9
- ```bash
10
- # From project root
11
- npm install
12
- ```
13
-
14
- Then add the dependency to your backend or frontend:
9
+ ## Installation
15
10
 
16
11
  ```bash
17
- # In backend or frontend directory
18
12
  npm install @foxscheduling/shared
19
13
  ```
20
14
 
21
- Or add to `package.json`:
15
+ ```bash
16
+ pnpm add @foxscheduling/shared
17
+ ```
22
18
 
23
- ```json
24
- {
25
- "dependencies": {
26
- "@foxscheduling/shared": "file:../shared-library"
27
- }
28
- }
19
+ ```bash
20
+ yarn add @foxscheduling/shared
29
21
  ```
30
22
 
31
- (Use `workspace:*` if using pnpm or yarn workspaces.)
23
+ Requires Node.js 18+. Ships with both ESM and CommonJS builds and bundled type declarations.
32
24
 
33
25
  ## Usage
34
26
 
35
27
  ```ts
36
- // Import everything
37
- import { formatCurrency, type CDKConfig, type DeploymentEnvironments } from "@foxscheduling/shared";
28
+ import {
29
+ type BusinessProfileDto,
30
+ type PartnerBookingDto,
31
+ type PartnerEmbedOptions,
32
+ type PartnerWebhookEvent,
33
+ isValidYearMonth,
34
+ partnerPaginate,
35
+ } from "@foxscheduling/shared";
36
+
37
+ // Validate a booking month before querying
38
+ if (!isValidYearMonth("2026-06")) {
39
+ throw new Error("month must be YYYY-MM");
40
+ }
41
+ ```
42
+
43
+ CommonJS works too:
38
44
 
39
- // Or import subpaths
40
- import { formatCurrency } from "@foxscheduling/shared/utils";
41
- import type { CDKConfig } from "@foxscheduling/shared/types";
45
+ ```js
46
+ const { isValidYearMonth } = require("@foxscheduling/shared");
42
47
  ```
43
48
 
44
- ## Development
49
+ ### Subpath imports
45
50
 
46
- ```bash
47
- cd src/v1/shared-library
48
- npm run build # Build once
49
- npm run dev # Watch mode
51
+ For smaller imports you can target a subpath directly:
52
+
53
+ ```ts
54
+ import { isValidYearMonth } from "@foxscheduling/shared/types";
55
+ import { buildBookingEmbedUrl } from "@foxscheduling/shared/utils/bookingEmbed";
50
56
  ```
51
57
 
52
- ## Structure
58
+ | Entry point | Contents |
59
+ | -------------------------------------- | ----------------------------------------- |
60
+ | `@foxscheduling/shared` | Everything (types + utils) |
61
+ | `@foxscheduling/shared/types` | Type and interface definitions |
62
+ | `@foxscheduling/shared/utils` | Utility functions |
63
+ | `@foxscheduling/shared/utils/bookingEmbed` | Booking embed URL and snippet builders |
64
+
65
+ ## What's inside
66
+
67
+ - **Partner API types** — `BusinessProfileDto`, `PartnerBookingDto`, `PartnerServiceDto`, `PartnerCustomerDto`, `PartnerStaffDto`, `PartnerPage<T>`, and more.
68
+ - **Webhooks** — `PartnerWebhookEvent` and the `PARTNER_WEBHOOK_EVENTS` list.
69
+ - **Embedding** — `PartnerEmbedOptions` plus `buildBookingEmbedUrl`, `buildInlineIframeEmbedCode`, and `buildWidgetScriptSnippet` for rendering booking widgets.
70
+ - **Helpers** — pagination (`partnerPaginate`, `resolvePartnerPageParams`), validation (`isValidYearMonth`), formatting utilities, and shared enums.
71
+
72
+ ## License
53
73
 
54
- - `src/types/` - Shared interfaces and type definitions
55
- - `src/utils/` - Shared utility functions
56
- - `src/index.ts` - Main entry point (re-exports all)
74
+ Proprietary © Fox Scheduling.
@@ -7,4 +7,5 @@ exports.PARTNER_WEBHOOK_EVENTS = [
7
7
  "booking.cancelled",
8
8
  "customer.created",
9
9
  "customer.updated",
10
+ "business.booking_url.updated",
10
11
  ];
@@ -1,5 +1,5 @@
1
1
  import { DBRecord } from "./db.js";
2
- export declare const PARTNER_WEBHOOK_EVENTS: readonly ["booking.created", "booking.updated", "booking.cancelled", "customer.created", "customer.updated"];
2
+ export declare const PARTNER_WEBHOOK_EVENTS: readonly ["booking.created", "booking.updated", "booking.cancelled", "customer.created", "customer.updated", "business.booking_url.updated"];
3
3
  export type PartnerWebhookEvent = (typeof PARTNER_WEBHOOK_EVENTS)[number];
4
4
  export interface WebhookSubscription extends DBRecord {
5
5
  recordType: "WEBHOOK_SUBSCRIPTION";
@@ -1 +1 @@
1
- {"version":3,"file":"db.webhook.d.ts","sourceRoot":"","sources":["../../../src/types/db.webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,eAAO,MAAM,sBAAsB,8GAMzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,UAAU,EAAE,sBAAsB,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"db.webhook.d.ts","sourceRoot":"","sources":["../../../src/types/db.webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,eAAO,MAAM,sBAAsB,8IAOzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,UAAU,EAAE,sBAAsB,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB"}
@@ -1,2 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PARTNER_DEFAULT_PAGE_SIZE = exports.PARTNER_MAX_PAGE_SIZE = void 0;
4
+ exports.resolvePartnerPageParams = resolvePartnerPageParams;
5
+ exports.partnerPaginate = partnerPaginate;
6
+ exports.isValidYearMonth = isValidYearMonth;
7
+ /** Maximum number of items the Partner API returns in a single list page. */
8
+ exports.PARTNER_MAX_PAGE_SIZE = 100;
9
+ /** Default page size when no limit is supplied. */
10
+ exports.PARTNER_DEFAULT_PAGE_SIZE = 100;
11
+ function toBoundedInt(value, fallback, min, max) {
12
+ const parsed = typeof value === "string" ? Number.parseInt(value, 10) : value ?? fallback;
13
+ const n = Number.isFinite(parsed) ? Math.floor(parsed) : fallback;
14
+ return Math.min(Math.max(min, n), max);
15
+ }
16
+ /** Clamp raw pagination params to valid bounds (limit 1–100, offset >= 0). */
17
+ function resolvePartnerPageParams(input) {
18
+ const limit = toBoundedInt(input?.limit, exports.PARTNER_DEFAULT_PAGE_SIZE, 1, exports.PARTNER_MAX_PAGE_SIZE);
19
+ const offset = toBoundedInt(input?.offset, 0, 0, Number.MAX_SAFE_INTEGER);
20
+ return { limit, offset };
21
+ }
22
+ /** Slice a full array into a typed {@link PartnerPage}, enforcing the max page size. */
23
+ function partnerPaginate(items, input) {
24
+ const { limit, offset } = resolvePartnerPageParams(input);
25
+ const slice = items.slice(offset, offset + limit);
26
+ return {
27
+ items: slice,
28
+ total: items.length,
29
+ limit,
30
+ offset,
31
+ hasMore: offset + slice.length < items.length,
32
+ };
33
+ }
34
+ const YEAR_MONTH_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
35
+ /** True when `value` matches the `YYYY-MM` format (e.g. "2026-06"). */
36
+ function isValidYearMonth(value) {
37
+ return typeof value === "string" && YEAR_MONTH_PATTERN.test(value);
38
+ }
@@ -66,4 +66,106 @@ export interface CreatePartnerApiKeyResponseDto {
66
66
  key: PartnerApiKeyPublicDto;
67
67
  api_key: string;
68
68
  }
69
+ /** Maximum number of items the Partner API returns in a single list page. */
70
+ export declare const PARTNER_MAX_PAGE_SIZE = 100;
71
+ /** Default page size when no limit is supplied. */
72
+ export declare const PARTNER_DEFAULT_PAGE_SIZE = 100;
73
+ /** A single page of Partner API list results. */
74
+ export interface PartnerPage<T> {
75
+ /** Items in this page (never more than {@link PARTNER_MAX_PAGE_SIZE}). */
76
+ items: T[];
77
+ /** Total number of items available across all pages. */
78
+ total: number;
79
+ /** Effective page size used for this response. */
80
+ limit: number;
81
+ /** Offset used for this response. */
82
+ offset: number;
83
+ /** True when more items exist beyond this page. */
84
+ hasMore: boolean;
85
+ }
86
+ /** Raw pagination inputs (query strings or numbers). */
87
+ export interface PartnerPaginationInput {
88
+ limit?: number | string;
89
+ offset?: number | string;
90
+ }
91
+ /** Clamp raw pagination params to valid bounds (limit 1–100, offset >= 0). */
92
+ export declare function resolvePartnerPageParams(input?: PartnerPaginationInput): {
93
+ limit: number;
94
+ offset: number;
95
+ };
96
+ /** Slice a full array into a typed {@link PartnerPage}, enforcing the max page size. */
97
+ export declare function partnerPaginate<T>(items: T[], input?: PartnerPaginationInput): PartnerPage<T>;
98
+ /** True when `value` matches the `YYYY-MM` format (e.g. "2026-06"). */
99
+ export declare function isValidYearMonth(value: string | undefined | null): boolean;
100
+ /** Color theme for an embedded booking page. */
101
+ export type PartnerEmbedTheme = "light" | "dark" | "auto";
102
+ /** How the popup widget opens the booking page. */
103
+ export type PartnerEmbedOpenMode = "popup" | "newTab";
104
+ /**
105
+ * Whether the popup widget renders its own button (`create`) or attaches to an
106
+ * existing element already on the host page (`existing`).
107
+ */
108
+ export type PartnerEmbedButtonMode = "create" | "existing";
109
+ /** Options for {@link PartnerEmbedCodeDto} generation. */
110
+ export interface PartnerEmbedOptions {
111
+ /** Book a specific service path/slug instead of the business landing page. */
112
+ servicePath?: string;
113
+ /** Color theme. Defaults to "auto". */
114
+ theme?: PartnerEmbedTheme;
115
+ /** Hide the business header/details inside the embed. Defaults to false. */
116
+ hidePageDetails?: boolean;
117
+ /** Show the light/dark toggle. Defaults to true. */
118
+ showThemeToggle?: boolean;
119
+ /** Inline iframe height in px. Defaults to 760. */
120
+ heightPx?: number;
121
+ /** Inline iframe border-radius key (none|sm|medium|lg|xl|2xl). Defaults to "medium". */
122
+ iframeBorderRadius?: string;
123
+ /** Popup vs new tab for the script widget. Defaults to "popup". */
124
+ openMode?: PartnerEmbedOpenMode;
125
+ /**
126
+ * Render a generated button (`create`, default) or wire the widget to an
127
+ * element already on your site (`existing`). When `existing`, set
128
+ * {@link triggerId} and the button styling fields are ignored.
129
+ */
130
+ buttonMode?: PartnerEmbedButtonMode;
131
+ /**
132
+ * HTML id (without the leading `#`) of an existing element on the host page
133
+ * that should open the booking popup. Required when `buttonMode` is
134
+ * `existing`, e.g. `book-appointment` for `<button id="book-appointment">`.
135
+ */
136
+ triggerId?: string;
137
+ /** Popup button text. Defaults to "Book now". */
138
+ buttonText?: string;
139
+ /** Popup button background color (hex). */
140
+ buttonBackgroundColor?: string;
141
+ /** Popup button text color (hex). */
142
+ buttonTextColor?: string;
143
+ /** Popup button border radius in px. */
144
+ buttonBorderRadiusPx?: number;
145
+ }
146
+ /** Resolved embed options actually applied (after defaults). */
147
+ export interface PartnerEmbedAppliedOptions {
148
+ servicePath?: string;
149
+ theme: PartnerEmbedTheme;
150
+ hidePageDetails: boolean;
151
+ showThemeToggle: boolean;
152
+ heightPx: number;
153
+ iframeBorderRadius: string;
154
+ openMode: PartnerEmbedOpenMode;
155
+ /** Whether a button was generated or an existing element is used. */
156
+ buttonMode: PartnerEmbedButtonMode;
157
+ /** The existing element id wired to the popup, when `buttonMode` is `existing`. */
158
+ triggerId?: string;
159
+ }
160
+ /** Booking embed code for a business (iframe + popup script + raw URL). */
161
+ export interface PartnerEmbedCodeDto {
162
+ /** Fully-qualified booking URL with the chosen options applied. */
163
+ bookingUrl: string;
164
+ /** Inline iframe HTML snippet. */
165
+ iframe: string;
166
+ /** Popup widget `<script>` snippet. */
167
+ popupScript: string;
168
+ /** The options actually applied after defaults. */
169
+ appliedOptions: PartnerEmbedAppliedOptions;
170
+ }
69
171
  //# sourceMappingURL=partnerDto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"partnerDto.d.ts","sourceRoot":"","sources":["../../../src/types/partnerDto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC;AACxC,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC;AACpC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uDAAuD;AACvD,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,sBAAsB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"partnerDto.d.ts","sourceRoot":"","sources":["../../../src/types/partnerDto.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { DBRecord } from "./db.js";
2
- export declare const PARTNER_WEBHOOK_EVENTS: readonly ["booking.created", "booking.updated", "booking.cancelled", "customer.created", "customer.updated"];
2
+ export declare const PARTNER_WEBHOOK_EVENTS: readonly ["booking.created", "booking.updated", "booking.cancelled", "customer.created", "customer.updated", "business.booking_url.updated"];
3
3
  export type PartnerWebhookEvent = (typeof PARTNER_WEBHOOK_EVENTS)[number];
4
4
  export interface WebhookSubscription extends DBRecord {
5
5
  recordType: "WEBHOOK_SUBSCRIPTION";
@@ -1 +1 @@
1
- {"version":3,"file":"db.webhook.d.ts","sourceRoot":"","sources":["../../src/types/db.webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,eAAO,MAAM,sBAAsB,8GAMzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,UAAU,EAAE,sBAAsB,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"db.webhook.d.ts","sourceRoot":"","sources":["../../src/types/db.webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,eAAO,MAAM,sBAAsB,8IAOzB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,UAAU,EAAE,sBAAsB,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB"}
@@ -4,4 +4,5 @@ export const PARTNER_WEBHOOK_EVENTS = [
4
4
  "booking.cancelled",
5
5
  "customer.created",
6
6
  "customer.updated",
7
+ "business.booking_url.updated",
7
8
  ];
@@ -66,4 +66,106 @@ export interface CreatePartnerApiKeyResponseDto {
66
66
  key: PartnerApiKeyPublicDto;
67
67
  api_key: string;
68
68
  }
69
+ /** Maximum number of items the Partner API returns in a single list page. */
70
+ export declare const PARTNER_MAX_PAGE_SIZE = 100;
71
+ /** Default page size when no limit is supplied. */
72
+ export declare const PARTNER_DEFAULT_PAGE_SIZE = 100;
73
+ /** A single page of Partner API list results. */
74
+ export interface PartnerPage<T> {
75
+ /** Items in this page (never more than {@link PARTNER_MAX_PAGE_SIZE}). */
76
+ items: T[];
77
+ /** Total number of items available across all pages. */
78
+ total: number;
79
+ /** Effective page size used for this response. */
80
+ limit: number;
81
+ /** Offset used for this response. */
82
+ offset: number;
83
+ /** True when more items exist beyond this page. */
84
+ hasMore: boolean;
85
+ }
86
+ /** Raw pagination inputs (query strings or numbers). */
87
+ export interface PartnerPaginationInput {
88
+ limit?: number | string;
89
+ offset?: number | string;
90
+ }
91
+ /** Clamp raw pagination params to valid bounds (limit 1–100, offset >= 0). */
92
+ export declare function resolvePartnerPageParams(input?: PartnerPaginationInput): {
93
+ limit: number;
94
+ offset: number;
95
+ };
96
+ /** Slice a full array into a typed {@link PartnerPage}, enforcing the max page size. */
97
+ export declare function partnerPaginate<T>(items: T[], input?: PartnerPaginationInput): PartnerPage<T>;
98
+ /** True when `value` matches the `YYYY-MM` format (e.g. "2026-06"). */
99
+ export declare function isValidYearMonth(value: string | undefined | null): boolean;
100
+ /** Color theme for an embedded booking page. */
101
+ export type PartnerEmbedTheme = "light" | "dark" | "auto";
102
+ /** How the popup widget opens the booking page. */
103
+ export type PartnerEmbedOpenMode = "popup" | "newTab";
104
+ /**
105
+ * Whether the popup widget renders its own button (`create`) or attaches to an
106
+ * existing element already on the host page (`existing`).
107
+ */
108
+ export type PartnerEmbedButtonMode = "create" | "existing";
109
+ /** Options for {@link PartnerEmbedCodeDto} generation. */
110
+ export interface PartnerEmbedOptions {
111
+ /** Book a specific service path/slug instead of the business landing page. */
112
+ servicePath?: string;
113
+ /** Color theme. Defaults to "auto". */
114
+ theme?: PartnerEmbedTheme;
115
+ /** Hide the business header/details inside the embed. Defaults to false. */
116
+ hidePageDetails?: boolean;
117
+ /** Show the light/dark toggle. Defaults to true. */
118
+ showThemeToggle?: boolean;
119
+ /** Inline iframe height in px. Defaults to 760. */
120
+ heightPx?: number;
121
+ /** Inline iframe border-radius key (none|sm|medium|lg|xl|2xl). Defaults to "medium". */
122
+ iframeBorderRadius?: string;
123
+ /** Popup vs new tab for the script widget. Defaults to "popup". */
124
+ openMode?: PartnerEmbedOpenMode;
125
+ /**
126
+ * Render a generated button (`create`, default) or wire the widget to an
127
+ * element already on your site (`existing`). When `existing`, set
128
+ * {@link triggerId} and the button styling fields are ignored.
129
+ */
130
+ buttonMode?: PartnerEmbedButtonMode;
131
+ /**
132
+ * HTML id (without the leading `#`) of an existing element on the host page
133
+ * that should open the booking popup. Required when `buttonMode` is
134
+ * `existing`, e.g. `book-appointment` for `<button id="book-appointment">`.
135
+ */
136
+ triggerId?: string;
137
+ /** Popup button text. Defaults to "Book now". */
138
+ buttonText?: string;
139
+ /** Popup button background color (hex). */
140
+ buttonBackgroundColor?: string;
141
+ /** Popup button text color (hex). */
142
+ buttonTextColor?: string;
143
+ /** Popup button border radius in px. */
144
+ buttonBorderRadiusPx?: number;
145
+ }
146
+ /** Resolved embed options actually applied (after defaults). */
147
+ export interface PartnerEmbedAppliedOptions {
148
+ servicePath?: string;
149
+ theme: PartnerEmbedTheme;
150
+ hidePageDetails: boolean;
151
+ showThemeToggle: boolean;
152
+ heightPx: number;
153
+ iframeBorderRadius: string;
154
+ openMode: PartnerEmbedOpenMode;
155
+ /** Whether a button was generated or an existing element is used. */
156
+ buttonMode: PartnerEmbedButtonMode;
157
+ /** The existing element id wired to the popup, when `buttonMode` is `existing`. */
158
+ triggerId?: string;
159
+ }
160
+ /** Booking embed code for a business (iframe + popup script + raw URL). */
161
+ export interface PartnerEmbedCodeDto {
162
+ /** Fully-qualified booking URL with the chosen options applied. */
163
+ bookingUrl: string;
164
+ /** Inline iframe HTML snippet. */
165
+ iframe: string;
166
+ /** Popup widget `<script>` snippet. */
167
+ popupScript: string;
168
+ /** The options actually applied after defaults. */
169
+ appliedOptions: PartnerEmbedAppliedOptions;
170
+ }
69
171
  //# sourceMappingURL=partnerDto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"partnerDto.d.ts","sourceRoot":"","sources":["../../src/types/partnerDto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC;AACxC,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC;AACpC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uDAAuD;AACvD,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,sBAAsB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"partnerDto.d.ts","sourceRoot":"","sources":["../../src/types/partnerDto.ts"],"names":[],"mappings":"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"}
@@ -1 +1,32 @@
1
- export {};
1
+ /** Maximum number of items the Partner API returns in a single list page. */
2
+ export const PARTNER_MAX_PAGE_SIZE = 100;
3
+ /** Default page size when no limit is supplied. */
4
+ export const PARTNER_DEFAULT_PAGE_SIZE = 100;
5
+ function toBoundedInt(value, fallback, min, max) {
6
+ const parsed = typeof value === "string" ? Number.parseInt(value, 10) : value ?? fallback;
7
+ const n = Number.isFinite(parsed) ? Math.floor(parsed) : fallback;
8
+ return Math.min(Math.max(min, n), max);
9
+ }
10
+ /** Clamp raw pagination params to valid bounds (limit 1–100, offset >= 0). */
11
+ export function resolvePartnerPageParams(input) {
12
+ const limit = toBoundedInt(input?.limit, PARTNER_DEFAULT_PAGE_SIZE, 1, PARTNER_MAX_PAGE_SIZE);
13
+ const offset = toBoundedInt(input?.offset, 0, 0, Number.MAX_SAFE_INTEGER);
14
+ return { limit, offset };
15
+ }
16
+ /** Slice a full array into a typed {@link PartnerPage}, enforcing the max page size. */
17
+ export function partnerPaginate(items, input) {
18
+ const { limit, offset } = resolvePartnerPageParams(input);
19
+ const slice = items.slice(offset, offset + limit);
20
+ return {
21
+ items: slice,
22
+ total: items.length,
23
+ limit,
24
+ offset,
25
+ hasMore: offset + slice.length < items.length,
26
+ };
27
+ }
28
+ const YEAR_MONTH_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
29
+ /** True when `value` matches the `YYYY-MM` format (e.g. "2026-06"). */
30
+ export function isValidYearMonth(value) {
31
+ return typeof value === "string" && YEAR_MONTH_PATTERN.test(value);
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxscheduling/shared",
3
- "version": "0.1.0",
3
+ "version": "0.2.2",
4
4
  "description": "Shared utilities and interfaces for FoxScheduling backend and frontend",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,12 @@
31
31
  "default": "./dist/types/index.js"
32
32
  }
33
33
  },
34
- "files": ["dist"],
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
35
40
  "scripts": {
36
41
  "build": "tsc && tsc -p tsconfig.cjs.json && node scripts/rename-cjs.mjs",
37
42
  "dev": "tsc --watch",
@@ -43,4 +48,4 @@
43
48
  "dependencies": {
44
49
  "dayjs": "^1.11.19"
45
50
  }
46
- }
51
+ }