feeef 0.9.0 → 0.9.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/build/index.js CHANGED
@@ -2213,6 +2213,140 @@ var ImageGenerationsRepository = class {
2213
2213
  }
2214
2214
  };
2215
2215
 
2216
+ // src/feeef/repositories/template_components.ts
2217
+ function normalizeFilterator(value) {
2218
+ if (value === void 0 || value === null) return void 0;
2219
+ if (typeof value === "string") return value;
2220
+ return JSON.stringify(value);
2221
+ }
2222
+ function toListResponse2(value) {
2223
+ if (Array.isArray(value)) {
2224
+ return { data: value };
2225
+ }
2226
+ const record = value && typeof value === "object" ? value : {};
2227
+ const meta = record.meta && typeof record.meta === "object" ? record.meta : {};
2228
+ return {
2229
+ data: Array.isArray(record.data) ? record.data : [],
2230
+ total: Number(meta.total ?? 0) || void 0,
2231
+ page: Number(meta.current_page ?? meta.currentPage ?? 0) || void 0,
2232
+ limit: Number(meta.per_page ?? meta.perPage ?? 0) || void 0
2233
+ };
2234
+ }
2235
+ var TemplateComponentsRepository = class extends ModelRepository {
2236
+ constructor(client) {
2237
+ super("template_components", client);
2238
+ }
2239
+ /**
2240
+ * Override `list` to expose the full search/filter surface and accept
2241
+ * either the structured options or a raw `filterator` payload.
2242
+ */
2243
+ async list(options) {
2244
+ const { page, offset, limit, params, filterator, ...filters } = options || {};
2245
+ const res = await this.client.get(`/${this.resource}`, {
2246
+ params: {
2247
+ page,
2248
+ offset,
2249
+ limit,
2250
+ ...filters.storeId ? { storeId: filters.storeId } : {},
2251
+ ...filters.q ? { q: filters.q } : {},
2252
+ ...filters.search ? { search: filters.search } : {},
2253
+ ...filters.policy ? { policy: filters.policy } : {},
2254
+ ...filters.category ? { category: filters.category } : {},
2255
+ ...filters.tags ? { tags: filters.tags } : {},
2256
+ ...filters.parentId ? { parentId: filters.parentId } : {},
2257
+ ...filters.orderBy ? { orderBy: filters.orderBy } : {},
2258
+ ...filterator ? { filterator: normalizeFilterator(filterator) } : {},
2259
+ ...params
2260
+ }
2261
+ });
2262
+ return toListResponse2(res.data);
2263
+ }
2264
+ /**
2265
+ * Fork an existing entry into a target store.
2266
+ *
2267
+ * Always called against the **source** entry's id (`fromId`). The
2268
+ * destination store must be one the caller can `create` in. The new
2269
+ * entry starts in `private` — surfacing it requires a follow-up
2270
+ * `update`. `parentId` of the fork points at `fromId`, preserving the
2271
+ * fork tree for analytics/audit.
2272
+ *
2273
+ * Optional `title` lets the caller rename at fork time so multiple
2274
+ * forks of the same source can coexist in the destination library
2275
+ * without collision in the picker.
2276
+ */
2277
+ async fork(options) {
2278
+ const res = await this.client.post(`/${this.resource}/${options.fromId}/fork`, {
2279
+ storeId: options.storeId,
2280
+ ...options.title ? { title: options.title } : {}
2281
+ });
2282
+ return res.data;
2283
+ }
2284
+ };
2285
+
2286
+ // src/feeef/repositories/store_templates.ts
2287
+ function normalizeFilterator2(value) {
2288
+ if (value === void 0 || value === null) return void 0;
2289
+ if (typeof value === "string") return value;
2290
+ return JSON.stringify(value);
2291
+ }
2292
+ function toListResponse3(value) {
2293
+ if (Array.isArray(value)) {
2294
+ return { data: value };
2295
+ }
2296
+ const record = value && typeof value === "object" ? value : {};
2297
+ const meta = record.meta && typeof record.meta === "object" ? record.meta : {};
2298
+ return {
2299
+ data: Array.isArray(record.data) ? record.data : [],
2300
+ total: Number(meta.total ?? 0) || void 0,
2301
+ page: Number(meta.current_page ?? meta.currentPage ?? 0) || void 0,
2302
+ limit: Number(meta.per_page ?? meta.perPage ?? 0) || void 0
2303
+ };
2304
+ }
2305
+ var StoreTemplatesRepository = class extends ModelRepository {
2306
+ constructor(client) {
2307
+ super("store_templates", client);
2308
+ }
2309
+ async list(options) {
2310
+ const { page, offset, limit, params, filterator, ...filters } = options || {};
2311
+ const res = await this.client.get(`/${this.resource}`, {
2312
+ params: {
2313
+ page,
2314
+ offset,
2315
+ limit,
2316
+ ...filters.storeId ? { storeId: filters.storeId } : {},
2317
+ ...filters.q ? { q: filters.q } : {},
2318
+ ...filters.search ? { search: filters.search } : {},
2319
+ ...filters.policy ? { policy: filters.policy } : {},
2320
+ ...filters.category ? { category: filters.category } : {},
2321
+ ...filters.tags ? { tags: filters.tags } : {},
2322
+ ...filters.parentId ? { parentId: filters.parentId } : {},
2323
+ ...filters.orderBy ? { orderBy: filters.orderBy } : {},
2324
+ ...filterator ? { filterator: normalizeFilterator2(filterator) } : {},
2325
+ ...params
2326
+ }
2327
+ });
2328
+ return toListResponse3(res.data);
2329
+ }
2330
+ async fork(options) {
2331
+ const res = await this.client.post(`/${this.resource}/${options.fromId}/fork`, {
2332
+ storeId: options.storeId,
2333
+ ...options.title ? { title: options.title } : {}
2334
+ });
2335
+ return res.data;
2336
+ }
2337
+ /**
2338
+ * Set `stores.template_id` to this template (same row in `store_templates`)
2339
+ * and copy `data` into `store.metadata.templateData`. Does not create a new
2340
+ * `store_templates` row — use [fork] to duplicate a template into a store.
2341
+ */
2342
+ async install(options) {
2343
+ const res = await this.client.post(`/${this.resource}/${options.fromId}/install`, {
2344
+ storeId: options.storeId
2345
+ });
2346
+ return res.data;
2347
+ }
2348
+ };
2349
+
2216
2350
  // src/core/entities/order.ts
2217
2351
  var OrderStatus = /* @__PURE__ */ ((OrderStatus2) => {
2218
2352
  OrderStatus2["draft"] = "draft";
@@ -2378,6 +2512,25 @@ var CartService = class extends NotifiableService {
2378
2512
  cachedSubtotal = null;
2379
2513
  // Cache for subtotal to avoid redundant calculations
2380
2514
  currentItem = null;
2515
+ /**
2516
+ * Monotonic counter bumped in {@link CartService.notify} for React
2517
+ * `useSyncExternalStore` — lets storefront UI subscribe to cart changes
2518
+ * without re-rendering unrelated provider subtrees (see Lithium FeeefCartProvider).
2519
+ */
2520
+ _reactSnapshotVersion = 0;
2521
+ /**
2522
+ * @override
2523
+ */
2524
+ notify() {
2525
+ this._reactSnapshotVersion++;
2526
+ super.notify();
2527
+ }
2528
+ /**
2529
+ * Snapshot for React `useSyncExternalStore` (increments on every cart mutation).
2530
+ */
2531
+ getReactSnapshot() {
2532
+ return this._reactSnapshotVersion;
2533
+ }
2381
2534
  /**
2382
2535
  * Generates a unique key for a cart item based on product ID, variant path, offer code, and addons
2383
2536
  * @param item - The cart item to generate a key for
@@ -3155,6 +3308,39 @@ var ActionsService = class {
3155
3308
  storeId: response.data.storeId
3156
3309
  };
3157
3310
  }
3311
+ /**
3312
+ * Resolve a batch of library `template_components` by id for the
3313
+ * storefront / editor renderer.
3314
+ *
3315
+ * Used by SSR pages that walk the template tree, gather every
3316
+ * `reference`-typed placement's `refId`, and need the renderable
3317
+ * `{ code, propsSchema, slotsSchema, defaults }` payload before the
3318
+ * page can be rendered.
3319
+ *
3320
+ * Authorization is per-id and happens server-side: same-store entries
3321
+ * are always returned; cross-store entries must be `policy in
3322
+ * (public, deprecated)`. Anything else is silently dropped into
3323
+ * `missing` so the page can render with a fallback (typically a
3324
+ * no-op or a "This component is unavailable" placeholder).
3325
+ *
3326
+ * The response is cached server-side per `(storeId, version)` for 24h
3327
+ * and the cache is invalidated automatically on any
3328
+ * `template_components` mutation or `Store` update — clients can call
3329
+ * this as often as they like without extra coordination.
3330
+ *
3331
+ * @param storeId - The store identifying the rendering context.
3332
+ * @param ids - Library entry ids to resolve. Deduplicated server-side.
3333
+ */
3334
+ async resolveComponents({
3335
+ storeId,
3336
+ ids
3337
+ }) {
3338
+ const response = await this.client.post(
3339
+ "/actions/resolveComponents",
3340
+ { storeId, ids }
3341
+ );
3342
+ return response.data;
3343
+ }
3158
3344
  };
3159
3345
 
3160
3346
  // src/feeef/services/notifications.ts
@@ -3697,6 +3883,19 @@ var FeeeF = class {
3697
3883
  * The repository for managing async image generations.
3698
3884
  */
3699
3885
  imageGenerations;
3886
+ /**
3887
+ * The repository for the per-store **library of reusable custom
3888
+ * components** + the cross-store **marketplace**. Components live in
3889
+ * `template_components` and are referenced from store templateData by
3890
+ * `refId` so a single source can power many placements.
3891
+ *
3892
+ * @see ResolveComponentsResponse for the storefront resolver path.
3893
+ */
3894
+ templateComponents;
3895
+ /**
3896
+ * Full-site template library rows (`store_templates`) + marketplace.
3897
+ */
3898
+ storeTemplates;
3700
3899
  /**
3701
3900
  * The repository for managing users.
3702
3901
  */
@@ -3798,6 +3997,8 @@ var FeeeF = class {
3798
3997
  this.productLandingPageTemplates = new ProductLandingPageTemplatesRepository(this.client);
3799
3998
  this.imagePromptTemplates = new ImagePromptTemplatesRepository(this.client);
3800
3999
  this.imageGenerations = new ImageGenerationsRepository(this.client);
4000
+ this.templateComponents = new TemplateComponentsRepository(this.client);
4001
+ this.storeTemplates = new StoreTemplatesRepository(this.client);
3801
4002
  this.users = new UserRepository(this.client);
3802
4003
  this.apps = new AppRepository(this.client);
3803
4004
  this.oauth = new OAuthRepository(this.client);
@@ -4127,6 +4328,15 @@ function formatProductLandingPageOrderReference(landingPageId) {
4127
4328
  return `product_landing_page:${landingPageId}`;
4128
4329
  }
4129
4330
 
4331
+ // src/core/entities/template_component.ts
4332
+ var TemplateComponentPolicy = /* @__PURE__ */ ((TemplateComponentPolicy2) => {
4333
+ TemplateComponentPolicy2["private"] = "private";
4334
+ TemplateComponentPolicy2["unlisted"] = "unlisted";
4335
+ TemplateComponentPolicy2["public"] = "public";
4336
+ TemplateComponentPolicy2["deprecated"] = "deprecated";
4337
+ return TemplateComponentPolicy2;
4338
+ })(TemplateComponentPolicy || {});
4339
+
4130
4340
  // src/core/entities/feedback.ts
4131
4341
  var FeedbackStatus = /* @__PURE__ */ ((FeedbackStatus2) => {
4132
4342
  FeedbackStatus2["open"] = "open";
@@ -4505,7 +4715,7 @@ var AiCalculator = class {
4505
4715
  }
4506
4716
  const outputResExtraDzd = supportsImageSize ? roundMoney(this.config.resolutionCosts[outputResKey] ?? 0) : 0;
4507
4717
  let referenceResolutionExtraDzd = 0;
4508
- if (referenceImageCount > 0 && resolution) {
4718
+ if (resolution) {
4509
4719
  const low = this.config.resolutionCosts.MEDIA_RESOLUTION_LOW ?? 0;
4510
4720
  const tier = this.config.resolutionCosts[resolution] ?? 0;
4511
4721
  referenceResolutionExtraDzd = roundMoney(Math.max(0, tier - low));
@@ -4783,7 +4993,11 @@ export {
4783
4993
  StoreRepository,
4784
4994
  StoreSubscriptionStatus,
4785
4995
  StoreSubscriptionType,
4996
+ TemplateComponentPolicy as StoreTemplatePolicy,
4997
+ StoreTemplatesRepository,
4786
4998
  Subscription,
4999
+ TemplateComponentPolicy,
5000
+ TemplateComponentsRepository,
4787
5001
  TiktokPixelEvent,
4788
5002
  TransferRepository,
4789
5003
  Transmit2 as Transmit,