@joai/sdk 0.15.1 → 0.16.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.mts CHANGED
@@ -288,6 +288,9 @@ type Coupon = {
288
288
  percent: number;
289
289
  expiresAt: string | null;
290
290
  };
291
+ //#endregion
292
+ //#region src/team/types.d.ts
293
+ type TeamCategory = 'general' | 'appointment' | 'restaurant' | 'service' | 'fitness' | 'beauty' | 'consultation';
291
294
  type TeamFeature = 'shop' | 'appointments';
292
295
  type TeamMeta = {
293
296
  'extra.messages'?: number;
@@ -310,6 +313,7 @@ type Team = {
310
313
  slug: string;
311
314
  name: string;
312
315
  personal: boolean;
316
+ category?: TeamCategory;
313
317
  description: TranslatableValue | null;
314
318
  locale: WarpLocale;
315
319
  timezone: string;
@@ -1043,6 +1047,13 @@ type BrandSiteConfig = {
1043
1047
  };
1044
1048
  //#endregion
1045
1049
  //#region src/link/types.d.ts
1050
+ type LinkScanHistory = {
1051
+ daily: number[];
1052
+ geography: Record<string, number>;
1053
+ devices?: Record<string, number>;
1054
+ operatingSystems?: Record<string, number>;
1055
+ browsers?: Record<string, number>;
1056
+ };
1046
1057
  type Link = {
1047
1058
  id: string;
1048
1059
  url: string;
@@ -1050,18 +1061,49 @@ type Link = {
1050
1061
  status: 'active' | 'paused' | 'expired';
1051
1062
  title: string | null;
1052
1063
  scanCount: number;
1053
- scanHistory: number[];
1054
- scanGeography: Record<string, number>;
1064
+ scanHistory: LinkScanHistory;
1065
+ lastScannedAt: string | null;
1066
+ createdAt: string;
1067
+ updatedAt: string;
1068
+ };
1069
+ type LinkVariation = {
1070
+ id: string;
1071
+ linkId: string;
1072
+ title: string | null;
1073
+ values: Record<string, string>;
1074
+ url: string;
1075
+ shortUrl: string;
1076
+ status: 'active' | 'paused' | 'expired';
1077
+ scanCount: number;
1055
1078
  lastScannedAt: string | null;
1056
1079
  createdAt: string;
1057
1080
  updatedAt: string;
1058
1081
  };
1082
+ type LinkVariationCreatePayload = {
1083
+ title?: string | null;
1084
+ values: Record<string, string>;
1085
+ };
1086
+ type LinkVariationBatchCreatePayload = {
1087
+ placeholder: string;
1088
+ labelTemplate?: string | null;
1089
+ from?: number | null;
1090
+ to?: number | null;
1091
+ values?: Array<{
1092
+ value: string;
1093
+ label?: string | null;
1094
+ }>;
1095
+ };
1059
1096
  type LinkCreatePayload = {
1060
1097
  url: string;
1061
1098
  title: string;
1062
1099
  };
1063
1100
  type LinkUpdatePayload = Partial<LinkCreatePayload>;
1064
- //#endregion
1101
+ type LinkStats = {
1102
+ totalLinks: number;
1103
+ activeLinks: number;
1104
+ totalScans: number;
1105
+ scanHistory: LinkScanHistory;
1106
+ }; //#endregion
1065
1107
  //#region src/store/types.d.ts
1066
1108
  type StoreVisibility = 'private' | 'team' | 'public';
1067
1109
  type StoreEntry = {
@@ -1120,6 +1162,7 @@ type Update = {
1120
1162
  linkUrl: string | null;
1121
1163
  startsAt: string | null;
1122
1164
  endsAt: string | null;
1165
+ team?: Team;
1123
1166
  createdAt: string;
1124
1167
  updatedAt: string;
1125
1168
  };
@@ -1149,6 +1192,27 @@ type UpdateStats = {
1149
1192
  //#region src/swarm/types.d.ts
1150
1193
  //#endregion
1151
1194
  //#region src/resources/appointments.d.ts
1195
+ declare const WEEKDAYS: readonly ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
1196
+ type Weekday = typeof WEEKDAYS[number];
1197
+ type OpeningHoursRange = string | {
1198
+ start: string;
1199
+ end: string;
1200
+ };
1201
+ type OpeningHoursAvailability = Partial<Record<Weekday | string, OpeningHoursRange[] | null | undefined>> | null | undefined;
1202
+ type OpeningHoursEntry = {
1203
+ days: string;
1204
+ time: string;
1205
+ };
1206
+ type OpeningHoursFormatOptions = {
1207
+ locale?: string;
1208
+ dayFormat?: 'narrow' | 'short' | 'long';
1209
+ dayLabels?: Partial<Record<Weekday, string>>;
1210
+ dayRangeSeparator?: string;
1211
+ dayListSeparator?: string;
1212
+ lastDayListSeparator?: string;
1213
+ timeRangeSeparator?: string;
1214
+ };
1215
+ declare const formatOpeningHours: (availability: OpeningHoursAvailability, options?: OpeningHoursFormatOptions) => OpeningHoursEntry[];
1152
1216
  declare class AppointmentsResource {
1153
1217
  private readonly http;
1154
1218
  private readonly config;
@@ -1425,11 +1489,17 @@ type MediaUploadType = 'brand' | 'reference' | 'template' | 'output';
1425
1489
  declare class MediaResource {
1426
1490
  private readonly http;
1427
1491
  constructor(http: IHttpService);
1492
+ listPublic(params?: {
1493
+ tags?: string;
1494
+ team?: string;
1495
+ mime?: string;
1496
+ }): Promise<IAppResponse<Media[]>>;
1428
1497
  upload(data: {
1429
1498
  team: string;
1430
1499
  file: File;
1431
1500
  type: MediaUploadType;
1432
1501
  label?: string;
1502
+ tags?: string[];
1433
1503
  }): Promise<IAppResponse<Media>>;
1434
1504
  }
1435
1505
  //#endregion
@@ -1634,6 +1704,15 @@ declare class LinksResource {
1634
1704
  create(payload: LinkCreatePayload): Promise<IAppResponse<Link>>;
1635
1705
  update(id: string, payload: LinkUpdatePayload): Promise<IAppResponse<Link>>;
1636
1706
  delete(id: string): Promise<IAppResponse<unknown>>;
1707
+ stats(): Promise<IAppResponse<LinkStats>>;
1708
+ variations(linkId: string): Promise<IAppResponse<{
1709
+ data: LinkVariation[];
1710
+ }>>;
1711
+ createVariation(linkId: string, payload: LinkVariationCreatePayload): Promise<IAppResponse<LinkVariation>>;
1712
+ createVariationBatch(linkId: string, payload: LinkVariationBatchCreatePayload): Promise<IAppResponse<{
1713
+ data: LinkVariation[];
1714
+ }>>;
1715
+ deleteVariation(linkId: string, variationId: string): Promise<IAppResponse<unknown>>;
1637
1716
  }
1638
1717
  //#endregion
1639
1718
  //#region src/resources/warps.d.ts
@@ -1773,4 +1852,4 @@ declare class DistributionResource {
1773
1852
  private fetchDistribution;
1774
1853
  }
1775
1854
  //#endregion
1776
- export { AppointmentsResource, AuthResource, type AuthSendCodeRequest, type AuthVerifyResponse, type BackendWarp, type BackendWarpBrand, BlueprintsResource, type CacheConfig, CachedHttpService, CartsResource, ContactsResource, DistributionResource, FlowsResource, IngestionsResource, JoAiClient, type JoAiClientConfig, MarketplaceResource, MeetingsResource, type Order, OrdersResource, type Product, type ProductVariation, ProductsResource, ServicesResource, SitesResource, SkillsResource, StoresResource, SubscriptionsResource, WarpsResource, createClient };
1855
+ export { AppointmentsResource, AuthResource, type AuthSendCodeRequest, type AuthVerifyResponse, type BackendWarp, type BackendWarpBrand, BlueprintsResource, type CacheConfig, CachedHttpService, CartsResource, ContactsResource, DistributionResource, FlowsResource, IngestionsResource, JoAiClient, type JoAiClientConfig, LinksResource, MarketplaceResource, MeetingsResource, type OpeningHoursEntry, type OpeningHoursFormatOptions, type Order, OrdersResource, type Product, type ProductVariation, ProductsResource, ServicesResource, SitesResource, SkillsResource, StoresResource, SubscriptionsResource, WarpsResource, createClient, formatOpeningHours };
package/dist/index.mjs CHANGED
@@ -111,6 +111,83 @@ var HttpService = class {
111
111
  };
112
112
  //#endregion
113
113
  //#region src/resources/appointments.ts
114
+ const WEEKDAYS = [
115
+ "monday",
116
+ "tuesday",
117
+ "wednesday",
118
+ "thursday",
119
+ "friday",
120
+ "saturday",
121
+ "sunday"
122
+ ];
123
+ const WEEKDAY_DATES = [
124
+ "2024-01-01",
125
+ "2024-01-02",
126
+ "2024-01-03",
127
+ "2024-01-04",
128
+ "2024-01-05",
129
+ "2024-01-06",
130
+ "2024-01-07"
131
+ ];
132
+ const formatTimeRange = (range, separator) => {
133
+ if (typeof range === "string") return range.replace(/\s*-\s*/, ` ${separator} `);
134
+ return `${range.start} ${separator} ${range.end}`;
135
+ };
136
+ const labelForDay = (day, options) => {
137
+ if (options.dayLabels?.[day]) return options.dayLabels[day];
138
+ const date = /* @__PURE__ */ new Date(`${WEEKDAY_DATES[WEEKDAYS.indexOf(day)]}T12:00:00Z`);
139
+ return new Intl.DateTimeFormat(options.locale, {
140
+ weekday: options.dayFormat,
141
+ timeZone: "UTC"
142
+ }).format(date).replace(/\.$/, "");
143
+ };
144
+ const formatDayIndexes = (indexes, options) => {
145
+ const ranges = [];
146
+ let start = indexes[0];
147
+ let previous = indexes[0];
148
+ for (const index of indexes.slice(1)) {
149
+ if (index === previous + 1) {
150
+ previous = index;
151
+ continue;
152
+ }
153
+ ranges.push(start === previous ? labelForDay(WEEKDAYS[start], options) : `${labelForDay(WEEKDAYS[start], options)} ${options.dayRangeSeparator} ${labelForDay(WEEKDAYS[previous], options)}`);
154
+ start = index;
155
+ previous = index;
156
+ }
157
+ ranges.push(start === previous ? labelForDay(WEEKDAYS[start], options) : `${labelForDay(WEEKDAYS[start], options)} ${options.dayRangeSeparator} ${labelForDay(WEEKDAYS[previous], options)}`);
158
+ if (ranges.length <= 1) return ranges[0] ?? "";
159
+ return `${ranges.slice(0, -1).join(options.dayListSeparator)}${options.lastDayListSeparator}${ranges.at(-1)}`;
160
+ };
161
+ const formatOpeningHours = (availability, options = {}) => {
162
+ if (!availability) return [];
163
+ const resolvedOptions = {
164
+ locale: options.locale ?? "en",
165
+ dayFormat: options.dayFormat ?? "short",
166
+ dayLabels: options.dayLabels ?? {},
167
+ dayRangeSeparator: options.dayRangeSeparator ?? "–",
168
+ dayListSeparator: options.dayListSeparator ?? ", ",
169
+ lastDayListSeparator: options.lastDayListSeparator ?? " & ",
170
+ timeRangeSeparator: options.timeRangeSeparator ?? "–"
171
+ };
172
+ const lines = [];
173
+ for (const [dayIndex, day] of WEEKDAYS.entries()) {
174
+ const ranges = availability[day];
175
+ if (!ranges?.length) continue;
176
+ for (const range of ranges) {
177
+ const time = formatTimeRange(range, resolvedOptions.timeRangeSeparator);
178
+ const existing = lines.find((line) => line.time === time);
179
+ if (existing) existing.dayIndexes.push(dayIndex);
180
+ else lines.push({
181
+ dayIndexes: [dayIndex],
182
+ time
183
+ });
184
+ }
185
+ }
186
+ return lines.map((line) => ({
187
+ days: formatDayIndexes(line.dayIndexes, resolvedOptions),
188
+ time: line.time
189
+ }));
190
+ };
114
191
  var AppointmentsResource = class {
115
192
  constructor(http, config) {
116
193
  this.http = http;
@@ -467,11 +544,20 @@ var MediaResource = class {
467
544
  constructor(http) {
468
545
  this.http = http;
469
546
  }
547
+ listPublic(params) {
548
+ const query = new URLSearchParams();
549
+ if (params?.tags) query.set("tags", params.tags);
550
+ if (params?.team) query.set("team", params.team);
551
+ if (params?.mime) query.set("mime", params.mime);
552
+ const qs = query.toString();
553
+ return this.http.get(`media/public${qs ? "?" + qs : ""}`);
554
+ }
470
555
  upload(data) {
471
556
  const formData = new FormData();
472
557
  formData.append("file", data.file, data.file.name);
473
558
  formData.append("type", data.type);
474
559
  if (data.label) formData.append("label", data.label);
560
+ if (data.tags) data.tags.forEach((t) => formData.append("tags[]", t));
475
561
  return this.http.post("media", formData, { headers: { "X-Team": data.team } });
476
562
  }
477
563
  };
@@ -735,6 +821,21 @@ var LinksResource = class {
735
821
  delete(id) {
736
822
  return this.http.delete(`links/${id}`);
737
823
  }
824
+ stats() {
825
+ return this.http.get("links/stats");
826
+ }
827
+ variations(linkId) {
828
+ return this.http.get(`links/${linkId}/variations`);
829
+ }
830
+ createVariation(linkId, payload) {
831
+ return this.http.post(`links/${linkId}/variations`, payload);
832
+ }
833
+ createVariationBatch(linkId, payload) {
834
+ return this.http.post(`links/${linkId}/variations/batch`, payload);
835
+ }
836
+ deleteVariation(linkId, variationId) {
837
+ return this.http.delete(`links/${linkId}/variations/${variationId}`);
838
+ }
738
839
  };
739
840
  //#endregion
740
841
  //#region src/resources/warps.ts
@@ -979,4 +1080,4 @@ var DistributionResource = class {
979
1080
  }
980
1081
  };
981
1082
  //#endregion
982
- export { AppointmentsResource, AuthResource, BlueprintsResource, CachedHttpService, CartsResource, ContactsResource, DistributionResource, FlowsResource, IngestionsResource, JoAiClient, MarketplaceResource, MeetingsResource, OrdersResource, ProductsResource, ServicesResource, SitesResource, SkillsResource, StoresResource, SubscriptionsResource, WarpsResource, createClient };
1083
+ export { AppointmentsResource, AuthResource, BlueprintsResource, CachedHttpService, CartsResource, ContactsResource, DistributionResource, FlowsResource, IngestionsResource, JoAiClient, LinksResource, MarketplaceResource, MeetingsResource, OrdersResource, ProductsResource, ServicesResource, SitesResource, SkillsResource, StoresResource, SubscriptionsResource, WarpsResource, createClient, formatOpeningHours };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joai/sdk",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "JoAi public API SDK — build with your AI agents",
5
5
  "license": "MIT",
6
6
  "type": "module",