feeef 0.12.10 → 0.12.12

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.
@@ -1,13 +1,44 @@
1
1
  /**
2
- * Pure utility class for estimating AI generation costs client-side.
2
+ * Client-side AI cost estimator deterministic mirror of the backend engine
3
+ * in `backend/app/services/ai_calculator.ts`.
3
4
  *
4
- * Mirrors the backend `AiCalculator` in `backend/app/services/ai_calculator.ts`.
5
- * All methods are deterministic and require no network calls.
6
- * The backend quote is authoritative; this calculator is a deterministic
7
- * mirror for UX (showing estimated cost before the user clicks generate).
5
+ * The backend quote is always authoritative (it performs the wallet debit);
6
+ * this class exists so UIs can show "you will pay X DZD" before generating,
7
+ * with the SAME formulas and the SAME config inputs (`aiModels` + `models`
8
+ * catalog from the app-config endpoint). No network calls, no side effects.
8
9
  *
9
- * Canonical `aiModels.billing` keys keep in sync: backend `configs_controller.ts`,
10
- * feeef `lib/core/app_config.dart`, admins_dashboard `src/lib/hooks/useOptions.ts`.
10
+ * ## Money model (identical to backend)
11
+ *
12
+ * ```
13
+ * provider cost (USD) what the AI provider charges
14
+ * × exchangeRate → provider cost (DZD)
15
+ * × retailMarkup.multiplier → retail user cost (DZD)
16
+ * + flat retail add-ons (DZD) reference images, resolution tiers,
17
+ * feature add-ons, attachment surcharge…
18
+ * = userCostDzd
19
+ * ```
20
+ *
21
+ * Invariants:
22
+ * 1. `providerCostUsd`/`providerCostDzd` are ALWAYS the pre-markup provider
23
+ * cost; `0` when unknown (retail floors) — never back-computed from the
24
+ * retail price.
25
+ * 2. `userCostDzd` is the final retail amount, rounded to 3 decimals.
26
+ *
27
+ * ## Pricing precedence (identical to backend)
28
+ *
29
+ * - **Text** : legacy exact-id row (context tiers) → catalog
30
+ * `pricing.prompt/completion` → named default legacy row
31
+ * (`gemini-flash-lite-latest`) → free. Never `models[0]`.
32
+ * - **Image** : catalog (`image_output_per_size_usd` → `image_output`) →
33
+ * legacy exact-id `unit:'image'` row → `defaultImageCost` floor.
34
+ * Legacy `localCost` (DZD) stays an explicit retail override.
35
+ * - **Voice** : legacy row (`localCost` → flat `audio`/`voice` USD → `image`
36
+ * unit for voice-capable rows → `tokens` per-1M), floored by
37
+ * `voiceGeneration.minimumChargeUsd` unless `localCost` is set.
38
+ *
39
+ * Canonical `aiModels.billing` keys — keep in sync: backend
40
+ * `ai_models_billing.ts`, feeef.dart `ai_calculator.dart`, admins_dashboard
41
+ * `useOptions.ts`.
11
42
  */
12
43
  import { ModelsCatalogConfig } from '../core/models_catalog.js';
13
44
  /** Fallback DZD per USD when `aiModels.exchangeRate` is missing (mirror backend). */
@@ -107,6 +138,7 @@ export interface LegacyAiBillingFlat {
107
138
  VOICE_TTS_OUTPUT_TEXT_FACTOR: number;
108
139
  VOICE_TTS_TOKEN_CAP: number;
109
140
  }
141
+ /** @deprecated Prefer `mergeAiModelsBilling` + `ResolvedAiModelsBilling`. */
110
142
  export declare function getLegacyAiBillingFlat(exchangeRate: number, resolved?: ResolvedAiModelsBilling): LegacyAiBillingFlat;
111
143
  /**
112
144
  * @deprecated Prefer `mergeAiModelsBilling` + `ResolvedAiModelsBilling`.
@@ -114,15 +146,18 @@ export declare function getLegacyAiBillingFlat(exchangeRate: number, resolved?:
114
146
  */
115
147
  export declare const AI_BILLING: LegacyAiBillingFlat;
116
148
  export interface AiModelPricing {
149
+ /** USD per 1M tokens (`unit: 'tokens'`) — `input` prompt / `output` completion. */
117
150
  input?: number;
151
+ /** For `unit: 'image' | 'audio' | 'voice'`: USD per single generation. */
118
152
  output?: number;
119
153
  unit: string;
154
+ /** Optional context tier, e.g. `<=200K` / `>200K` (tokens unit only). */
120
155
  contextThreshold?: string;
121
156
  }
122
157
  /**
123
158
  * Optional operator overrides for Gemini image-generation Google Search grounding.
124
159
  * Shapes `aiModels.models[].tools` from the app config API — same as backend `AIModel.tools`.
125
- * Undefined keys mean use platform default for this model id (see backend `gemini_image_grounding`).
160
+ * Undefined keys mean "use platform default for this model id" (see backend `gemini_image_grounding`).
126
161
  */
127
162
  export interface AiModelTools {
128
163
  googleSearch?: boolean;
@@ -131,6 +166,7 @@ export interface AiModelTools {
131
166
  export interface AiModelConfig {
132
167
  id: string;
133
168
  pricing?: AiModelPricing[];
169
+ /** Explicit admin retail price (DZD) for one generation — overrides computed retail. */
134
170
  localCost?: number | null;
135
171
  /** From aiModels — used so TTS billing does not fall back to the first (often image) row. */
136
172
  capabilities?: string[];
@@ -138,15 +174,24 @@ export interface AiModelConfig {
138
174
  }
139
175
  export interface AiCalculatorConfig {
140
176
  exchangeRate?: number;
177
+ /** Floor retail-provider DZD for one image when no source prices the model. */
141
178
  defaultImageCost?: number;
179
+ /** Flat retail DZD per reference image. */
142
180
  referenceImageCost?: number;
181
+ /** Flat retail DZD per resolution tier (`MEDIA_RESOLUTION_LOW|MEDIUM|HIGH`). */
143
182
  resolutionCosts?: Record<string, number>;
183
+ /** Legacy `aiModels.models` rows (admin overrides). */
144
184
  models?: AiModelConfig[];
145
- /** Optional model catalog (`models` option): allows pricing.prompt/completion to price text models without aiModels rows. */
185
+ /** Multi-provider catalog (`models` option) preferred pricing source. */
146
186
  modelsCatalog?: ModelsCatalogConfig;
147
187
  /** Optional `aiModels.billing` overrides (merged over [mergeAiModelsBilling] defaults). */
148
188
  billing?: AIModelsBilling | null;
149
189
  }
190
+ /**
191
+ * Result of a cost estimation.
192
+ * `providerCostUsd`/`providerCostDzd` are pre-markup provider cost (0 when
193
+ * unknown); `userCostDzd` is the retail amount the wallet would be debited.
194
+ */
150
195
  export interface AiCostEstimate {
151
196
  providerCostUsd: number;
152
197
  providerCostDzd: number;
@@ -156,34 +201,92 @@ export interface AiCostEstimate {
156
201
  usedLocalCost: boolean;
157
202
  breakdown: Record<string, number | boolean>;
158
203
  }
159
- /** Keep in sync with backend `defaultVoiceTtsTokenEstimates` (default billing only). */
160
- export declare function defaultVoiceTtsTokenEstimates(scriptCharLength: number, attachmentCount: number): {
161
- promptTokens: number;
162
- outputTokens: number;
163
- };
204
+ /**
205
+ * Deterministic client-side mirror of the backend `AiCalculator`.
206
+ *
207
+ * ```ts
208
+ * const calc = new AiCalculator({ ...appConfig.aiModels, modelsCatalog: appConfig.models })
209
+ * const { userCostDzd } = calc.estimateImageGeneration({ modelId, imageSize: '2K' })
210
+ * ```
211
+ */
164
212
  export declare class AiCalculator {
165
213
  private config;
166
214
  constructor(config?: AiCalculatorConfig);
167
- /** TTS base DZD: localCost → flat USD row → tokens (per 1M) × estimates × rate × multiplier → floor. */
168
- private _voiceoverBaseUserCostDzd;
169
- private _attachmentExtraUserDzd;
215
+ /** Exact-id legacy row (namespace tolerant). NO `models[0]` fallback. */
216
+ private findLegacyModel;
217
+ private findCatalogRow;
218
+ private modelHasVoiceCapability;
219
+ /** Context-tier row from a legacy `tokens` pricing list (mirror backend). */
220
+ private pickLegacyTokenRow;
221
+ /** Catalog `pricing.prompt`/`completion` (USD per token) → USD per 1M. */
222
+ private pickCatalogTokenPricing;
223
+ /**
224
+ * USD-per-1M pricing: legacy exact-id → catalog → named default legacy row →
225
+ * `null` (free). Mirrors backend `resolveTextTokenPricing`.
226
+ */
227
+ private resolveTextTokenPricing;
228
+ /**
229
+ * Catalog per-image USD, preferring the per-tier map
230
+ * (`image_output_per_size_usd`: requested tier → 1K → 2K → 4K → first
231
+ * positive), then flat `image_output`.
232
+ */
233
+ private pickCatalogImageUsd;
234
+ /** Legacy exact-id `unit:'image'` row output (USD per image). */
235
+ private pickLegacyImageUsd;
236
+ /** Attachment surcharge (stores/products/audio context files) in retail DZD. */
237
+ private attachmentExtraUserDzd;
170
238
  /**
171
- * Estimate the cost of an image generation action.
172
- * Covers: image gen, logo gen, editOrGenerateSimpleImage.
239
+ * Flat DZD resolution extras ONE rule, mirror of backend
240
+ * `computeResolutionExtrasDzd`:
241
+ * - output extra only when an output size tier is requested (1K→LOW,
242
+ * 2K→MEDIUM, 4K→HIGH),
243
+ * - input extra only when an explicit input resolution is requested
244
+ * (`max(0, cost[resolution] − cost[LOW])`).
245
+ */
246
+ private resolutionExtrasDzd;
247
+ /** Voice row: exact id → named TTS default → any voice-capable row. */
248
+ private findVoiceModel;
249
+ /**
250
+ * Flat provider USD per TTS generation: `audio`/`voice` units; for
251
+ * voice-capable rows also the `image` unit (legacy admin editor artifact).
252
+ */
253
+ private pickTtsFlatUsd;
254
+ /**
255
+ * Base TTS pricing (mirror backend `computeBaseVoiceoverBilling`):
256
+ * `localCost` → flat USD → tokens per-1M → floor; non-localCost paths are
257
+ * floored by `voiceGeneration.minimumChargeUsd`. Provider cost is honest
258
+ * (0 when only a retail figure is known).
259
+ */
260
+ private voiceoverBase;
261
+ private ttsTokenEstimates;
262
+ /**
263
+ * Image generation cost (image studio, logo studio, landing-page image).
264
+ *
265
+ * `userCostDzd = base(model, tier) × iterations + referenceImages ×
266
+ * referenceImageCost + attachment surcharge + resolution extras + feature
267
+ * add-ons`. Base precedence: catalog → legacy `unit:'image'` row →
268
+ * `defaultImageCost` floor; legacy `localCost` overrides retail.
173
269
  */
174
270
  estimateImageGeneration(options?: {
175
271
  modelId?: string;
176
272
  attachmentCount?: number;
177
273
  attachmentResolution?: 'low' | 'medium' | 'high';
274
+ /** Explicit input/reference processing resolution (input extra). */
178
275
  resolution?: string;
276
+ /**
277
+ * Effective output size tier (`1K`/`2K`/`4K`). Pass only for models that
278
+ * support output tiers — the backend resolves it via `pickImageSize`.
279
+ */
179
280
  imageSize?: string;
180
281
  iterations?: number;
181
282
  referenceImageCount?: number;
283
+ /** Catalog-driven feature add-ons (DZD), e.g. transparent background. */
284
+ featureAddonsDzd?: number;
182
285
  }): AiCostEstimate;
183
286
  /**
184
- * Estimate the cost of a text generation action.
185
- * Covers: updateProductUsingAi, generateSimpleCode, generateCustomComponentCode.
186
- * Uses estimated tokens (exact cost billed post-generation).
287
+ * Text generation estimate (actual billing happens post-success from real
288
+ * token usage on the backend). Free when the model is unpriced everywhere
289
+ * or `promptTokens < freeTierMaxPromptTokens` (prompt tokens not total).
187
290
  */
188
291
  estimateTextGeneration(options?: {
189
292
  modelId?: string;
@@ -191,7 +294,10 @@ export declare class AiCalculator {
191
294
  estimatedOutputTokens?: number;
192
295
  }): AiCostEstimate;
193
296
  /**
194
- * Voiceover: base + attachment surcharge + optional script-enhancement add-on.
297
+ * Voiceover estimate: TTS base (heuristic tokens unless explicitly given) +
298
+ * attachment surcharge + optional script-enhancement add-on. The backend
299
+ * settles from ACTUAL usage (`computeVoiceoverSettlement`); this preview
300
+ * uses the same retail policy.
195
301
  */
196
302
  estimateVoiceover(options?: {
197
303
  modelId?: string;
@@ -202,6 +308,24 @@ export declare class AiCalculator {
202
308
  estimatedPromptTokens?: number;
203
309
  estimatedOutputTokens?: number;
204
310
  }): AiCostEstimate;
205
- /** Get the fixed cost for image landing page generation. */
206
- estimateImageLandingPage(): AiCostEstimate;
311
+ /**
312
+ * Landing-page image cost — identical formula to [estimateImageGeneration]
313
+ * (image-studio parity). Without an image model id, returns the fixed
314
+ * `billing.landingPageImage` charge (provider cost unknown → 0). A ≤ 0
315
+ * image quote also falls back to the fixed charge (zero-guard).
316
+ */
317
+ estimateImageLandingPage(options?: {
318
+ imageModelId?: string;
319
+ attachmentCount?: number;
320
+ attachmentResolution?: 'low' | 'medium' | 'high';
321
+ resolution?: string;
322
+ imageSize?: string;
323
+ referenceImageCount?: number;
324
+ featureAddonsDzd?: number;
325
+ }): AiCostEstimate;
207
326
  }
327
+ /** Heuristic TTS token counts using **default** billing only (keep in sync with backend). */
328
+ export declare function defaultVoiceTtsTokenEstimates(scriptCharLength: number, attachmentCount: number): {
329
+ promptTokens: number;
330
+ outputTokens: number;
331
+ };
@@ -3,6 +3,8 @@ export declare enum OrderStatus {
3
3
  pending = "pending",
4
4
  review = "review",
5
5
  accepted = "accepted",
6
+ /** Confirmed, but still needs merchant action before processing/completed. */
7
+ followup = "followup",
6
8
  processing = "processing",
7
9
  completed = "completed",
8
10
  cancelled = "cancelled"
@@ -303,6 +303,10 @@ export interface ProductUpdateInput {
303
303
  type?: ProductType;
304
304
  decoration?: ProductDecoration;
305
305
  integrationsData?: IntegrationsData;
306
+ /** Moderation (admin): ISO date to verify, null to unverify. */
307
+ verifiedAt?: string | null;
308
+ /** Moderation (admin): ISO date to block, null to unblock. */
309
+ blockedAt?: string | null;
306
310
  }
307
311
  /**
308
312
  * Product report/analytics data
@@ -48,7 +48,19 @@ export interface StoreEntity {
48
48
  /** Linked inventory project ID for stock management. */
49
49
  projectId?: string | null;
50
50
  }
51
- export declare const generatePublicStoreIntegrations: (integrations: StoreIntegrations | null | undefined) => PublicStoreIntegrations | null;
51
+ export declare const generatePublicStoreIntegrations: (integrations: StoreIntegrations | null | undefined,
52
+ /**
53
+ * Optional store configs — used to expose inventory storefront flags
54
+ * (`show_unavailable_on_frontend`) on {@link PublicInventoryIntegration}.
55
+ */
56
+ configs?: Pick<StoreConfigs, "inventory_integration"> | StoreConfigs | null) => PublicStoreIntegrations | null;
57
+ /**
58
+ * Public inventory module (no project credentials).
59
+ * Storefront OOS UI runs only when `active` and `showUnavailableOnFrontend`.
60
+ */
61
+ export declare const generatePublicStoreIntegrationInventory: (inventory: StoreInventoryIntegration | null | undefined, options?: {
62
+ showUnavailableOnFrontend?: boolean;
63
+ }) => PublicInventoryIntegration | null | undefined;
52
64
  /** Strips connector auth secrets from public store JSON. */
53
65
  export declare const generatePublicStoreIntegrationConnectors: (connectors: ConnectorsIntegration | null | undefined) => PublicConnectorsIntegration | null | undefined;
54
66
  export declare const generatePublicStoreIntegrationCustomFields: (customFields: any | null | undefined) => PublicCustomFieldsIntegration | null | undefined;
@@ -191,7 +203,24 @@ export interface PublicPaymentIntegration {
191
203
  methods: PublicPaymentMethod[];
192
204
  defaultMethod?: string;
193
205
  }
206
+ /**
207
+ * Public inventory module — no project / warehouse secrets.
208
+ * Combined with effective-active (entitlement) on store serialization.
209
+ *
210
+ * Storefront must only fetch/apply OOS when `active && showUnavailableOnFrontend`.
211
+ */
212
+ export interface PublicInventoryIntegration {
213
+ active: boolean;
214
+ /**
215
+ * When true, storefront shows unavailable variants (live qty / legacy stock).
216
+ * Opt-in via `configs.inventory_integration.show_unavailable_on_frontend`.
217
+ * @default false
218
+ */
219
+ showUnavailableOnFrontend: boolean;
220
+ }
194
221
  export interface PublicStoreIntegrations {
222
+ /** Global Meta integration; credentials and ad accounts never included. */
223
+ meta: PublicMetaIntegration | null;
195
224
  metaPixel: PublicMetaPixelIntegration | null;
196
225
  tiktokPixel: PublicTiktokPixelIntegration | null;
197
226
  googleAnalytics: PublicGoogleAnalyticsIntegration | null;
@@ -206,6 +235,11 @@ export interface PublicStoreIntegrations {
206
235
  customFields: PublicCustomFieldsIntegration | null;
207
236
  payment: PublicPaymentIntegration | null;
208
237
  connectors: PublicConnectorsIntegration | null;
238
+ /**
239
+ * Inventory module. Storefront OOS checks require `active` and
240
+ * `showUnavailableOnFrontend` (merchant opt-in).
241
+ */
242
+ inventory: PublicInventoryIntegration | null;
209
243
  }
210
244
  export declare enum StoreMemberRole {
211
245
  editor = "editor",
@@ -221,6 +255,12 @@ export interface StoreMember {
221
255
  createdAt: any;
222
256
  active: boolean;
223
257
  metadata: Record<string, any>;
258
+ /**
259
+ * Fine-grained RBAC scopes (e.g. `orders`, `products.read`, `store.integrations`).
260
+ * Empty/undefined = legacy unrestricted access for the member's role.
261
+ * Parent scopes imply `.read` children (`orders` ⇒ `orders.read`).
262
+ */
263
+ scopes?: string[];
224
264
  }
225
265
  export declare enum StoreInviteStatus {
226
266
  pending = "pending",
@@ -245,12 +285,16 @@ export interface StoreInvite {
245
285
  name: string;
246
286
  iconUrl?: string;
247
287
  };
288
+ /** RBAC scopes copied onto the member when the invite is accepted. */
289
+ scopes?: string[];
248
290
  }
249
291
  export interface CreateStoreInviteInput {
250
292
  email: string;
251
293
  role: StoreMemberRole;
252
294
  expiresAt?: string;
253
295
  metadata?: Record<string, any>;
296
+ /** RBAC scopes to grant on acceptance (see {@link StoreMember.scopes}). */
297
+ scopes?: string[];
254
298
  }
255
299
  /** How order sync handles line items with no inventory bucket for their SKU. */
256
300
  export type MissingInventoryBucketPolicy = 'ignore' | 'reject';
@@ -278,6 +322,12 @@ export interface InventoryIntegration {
278
322
  * @default true
279
323
  */
280
324
  allow_backorder?: boolean;
325
+ /**
326
+ * When true (and inventory public integration is active), the storefront
327
+ * fetches live availability and marks out-of-stock variants.
328
+ * @default false
329
+ */
330
+ show_unavailable_on_frontend?: boolean;
281
331
  }
282
332
  export type FinancePdfPaperSize = 'a4' | 'letter' | 'a5' | 'legal';
283
333
  /** Layout and content options for finance PDF documents. */
@@ -312,6 +362,7 @@ export interface StoreConfigs {
312
362
  customStatusMappings?: CustomStatusMapping[];
313
363
  /** Feature flag to enable custom statuses across the app */
314
364
  customStatusEnabled?: boolean;
365
+ confirmationQueue?: ConfirmationQueueConfig;
315
366
  inventory_integration?: InventoryIntegration;
316
367
  finance_integration?: FinanceIntegration;
317
368
  }
@@ -332,6 +383,42 @@ export interface CustomStatusMapping {
332
383
  paymentStatus?: PaymentStatus | null;
333
384
  /** Codes (or names) of other mappings suggested as the next workflow step */
334
385
  next?: string[];
386
+ /**
387
+ * Minutes to postpone the order when this status is set. The order's
388
+ * `scheduledAt` becomes `now + snoozeMinutes`, so it leaves the confirmation
389
+ * queue and re-enters it once the delay elapses (e.g. "not_respond_1" -> 180).
390
+ */
391
+ snoozeMinutes?: number | null;
392
+ /** Plain-text reason presets offered to the confirmer when this status is set. */
393
+ reasons?: string[];
394
+ /** Whether the confirmer may type a reason that is not in `reasons`. */
395
+ allowOtherReason?: boolean;
396
+ /**
397
+ * Whether a reason is mandatory. Always treated as `true` when `status` is
398
+ * `cancelled`, regardless of the stored value.
399
+ */
400
+ requiresReason?: boolean;
401
+ /** Whether orders carrying this status may be served by the confirmation queue. */
402
+ queueEligible?: boolean;
403
+ }
404
+ /** Store-level confirmation queue settings. */
405
+ export interface ConfirmationQueueConfig {
406
+ enabled?: boolean;
407
+ /**
408
+ * How long a `draft` order must age before it becomes eligible for
409
+ * confirmation. Gives the customer time to finish submitting.
410
+ */
411
+ draftDelayMinutes?: number;
412
+ /**
413
+ * After a confirmer skips, how long before the order is due again
414
+ * (`scheduled_at` soft-snooze). Default 15.
415
+ */
416
+ skipDeferMinutes?: number;
417
+ /**
418
+ * How long after `updated_at` a recent history order stays correctable
419
+ * in the confirmation feed. Default 5.
420
+ */
421
+ historyActionMinutes?: number;
335
422
  }
336
423
  export interface StoreCurrencyConfig {
337
424
  code: string;
@@ -439,6 +526,79 @@ export interface TiktokPixel {
439
526
  id: string;
440
527
  accessToken?: string;
441
528
  }
529
+ /**
530
+ * An ad account the merchant chose to manage from Feeef.
531
+ */
532
+ export interface MetaAdAccountRef {
533
+ /** Graph node id, `act_123`. */
534
+ id: string;
535
+ /** Bare numeric id, `123`. */
536
+ accountId: string;
537
+ name?: string;
538
+ currency?: string;
539
+ timezoneName?: string;
540
+ accountStatus?: number;
541
+ }
542
+ /** Everything ads-related on the Meta integration. */
543
+ export interface MetaAdsConfig {
544
+ active?: boolean;
545
+ adAccounts?: MetaAdAccountRef[];
546
+ defaultAdAccountId?: string | null;
547
+ /** Default insights window for the dashboard, e.g. `last_7d`. */
548
+ defaultDatePreset?: string | null;
549
+ /** Extra hosts that count as this store's storefront when matching ad links. */
550
+ extraStoreHosts?: string[];
551
+ metadata?: Record<string, any>;
552
+ }
553
+ /**
554
+ * Meta OAuth credentials.
555
+ *
556
+ * Server-side only — the token is encrypted at rest and written exclusively by
557
+ * the OAuth callback. It is stripped from every client-facing projection, and
558
+ * `mergeIntegrationsPatch` in the backend refuses to accept it from a client.
559
+ */
560
+ export interface MetaOAuthCredentials {
561
+ /** AES-encrypted access token. Never present in API responses. */
562
+ accessTokenEnc: string;
563
+ tokenType?: string;
564
+ expiresAt?: string;
565
+ /** Scopes Meta actually granted, from `debug_token`. */
566
+ scopes?: string[];
567
+ connectedAt?: string;
568
+ connectedByUserId?: string;
569
+ metaUserId?: string;
570
+ }
571
+ /**
572
+ * Global Meta integration (`store.integrations.meta`).
573
+ *
574
+ * Credentials live at the top level and are shared by every Meta feature.
575
+ * Ads live under `ads`; pixels remain on the legacy {@link MetaPixelIntegration}
576
+ * key for now and may move here later.
577
+ */
578
+ export interface MetaIntegration {
579
+ active: boolean;
580
+ oauth2?: MetaOAuthCredentials | null;
581
+ /** Meta identity the token belongs to, for display + reconnect detection. */
582
+ account?: {
583
+ id: string;
584
+ name?: string;
585
+ } | null;
586
+ ads?: MetaAdsConfig | null;
587
+ metadata?: Record<string, any>;
588
+ }
589
+ /** Storefront-safe Meta integration — credentials and ad accounts excluded. */
590
+ export interface PublicMetaIntegration {
591
+ active: boolean;
592
+ ads: {
593
+ active: boolean;
594
+ } | null;
595
+ }
596
+ /**
597
+ * Generates public Meta integration data.
598
+ * `oauth2`, `account`, and the ad-account list are intentionally excluded — none
599
+ * of it belongs on a storefront page.
600
+ */
601
+ export declare const generatePublicStoreIntegrationMeta: (meta: MetaIntegration | null | undefined) => PublicMetaIntegration | null;
442
602
  export interface MetaPixelIntegration {
443
603
  id: string;
444
604
  pixels: MetaPixel[];
@@ -484,6 +644,19 @@ export interface GoogleSheetsIntegration {
484
644
  metadata: Record<string, any>;
485
645
  simple?: boolean;
486
646
  columns?: GoogleSheetsColumn<any>[];
647
+ /**
648
+ * When true, draft (abandoned-cart) orders are written to a dedicated
649
+ * sheet tab (`draftSheetName`) instead of the main tab (`name`).
650
+ * When the order leaves the draft status (e.g. becomes pending), its row is
651
+ * removed from the draft tab and a fresh row is inserted into the main tab.
652
+ * Disabled by default.
653
+ */
654
+ draftSheetEnabled?: boolean;
655
+ /**
656
+ * Tab title used for draft orders when `draftSheetEnabled` is true.
657
+ * Falls back to the platform default ("الطلبات المتروكة") when empty.
658
+ */
659
+ draftSheetName?: string | null;
487
660
  }
488
661
  export interface GoogleTagsIntegration {
489
662
  id: string;
@@ -580,6 +753,30 @@ export interface ZrexpressIntegration {
580
753
  /** Additional metadata for the integration */
581
754
  metadata?: Record<string, any>;
582
755
  }
756
+ /**
757
+ * Codpilot mini-ERP — push Feeef orders for confirmation / COD ops.
758
+ *
759
+ * Auth: subdomain + apiId + Bearer apiToken.
760
+ * Docs: https://codpilot.gitbook.io/codpilot-api
761
+ * Sync state: `order.metadata.codpilot` (not a delivery carrier).
762
+ */
763
+ export interface CodpilotIntegration {
764
+ /** Business subdomain (`mystore` → mystore.codpilot.net) */
765
+ subdomain: string;
766
+ apiId: string;
767
+ apiToken: string;
768
+ active: boolean;
769
+ /**
770
+ * Auto-send when a status dimension transitions into `equals`.
771
+ * Default (client-seeded): `[{ id: 'default-pending', dimension: 'orderStatus', equals: 'pending' }]`.
772
+ */
773
+ statusRules?: Array<{
774
+ id: string;
775
+ dimension: 'orderStatus' | 'deliveryStatus' | 'paymentStatus' | 'customStatus';
776
+ equals: string;
777
+ }>;
778
+ metadata?: Record<string, any>;
779
+ }
583
780
  /**
584
781
  * MDM Express (api.mdm.express) — `x-api-key` and/or Bearer JWT, MDM store `trackingId` (`mdmStoreId` on orders),
585
782
  * and MDM seller id (`mdmSellerId`) for service-fees.
@@ -598,6 +795,29 @@ export interface MdmExpressIntegration {
598
795
  webhookSecret?: string | null;
599
796
  metadata?: Record<string, any>;
600
797
  }
798
+ /**
799
+ * Feeef Delivery (Near Delivery white-label). Merchants never hold Near API keys —
800
+ * enable via `POST .../integrations/feeefDelivery/enable`.
801
+ */
802
+ export interface FeeefDeliveryIntegration {
803
+ id: string;
804
+ active: boolean;
805
+ autoSend?: boolean;
806
+ /** Near sender user id — required when active. */
807
+ nearSenderUserId: number;
808
+ nearSenderUsername?: string | null;
809
+ nearSenderEmail?: string | null;
810
+ nearAccountType?: 'platform' | 'api' | 'both' | null;
811
+ /** 0 = address pickup, 1 = center pickup. */
812
+ pickupLocationType?: 0 | 1 | null;
813
+ pickupAddress?: string | null;
814
+ senderCenterId?: number | null;
815
+ defaultBuralistId?: number | null;
816
+ /** Prefer Feeef-branded PDF labels (default true). */
817
+ useFeeefLabel?: boolean | null;
818
+ webhookSecret?: string | null;
819
+ metadata?: Record<string, any>;
820
+ }
601
821
  export declare enum SecurityTreatment {
602
822
  block = "block",
603
823
  warning = "warning",
@@ -664,12 +884,15 @@ export interface PublicSecurityIntegration {
664
884
  options: PublicSecurityOptions;
665
885
  }
666
886
  /**
667
- * Webhook event types for order lifecycle
887
+ * Webhook event types for order and product lifecycle
668
888
  */
669
889
  export declare enum WebhookEvent {
670
890
  ORDER_CREATED = "orderCreated",
671
891
  ORDER_UPDATED = "orderUpdated",
672
- ORDER_DELETED = "orderDeleted"
892
+ ORDER_DELETED = "orderDeleted",
893
+ PRODUCT_CREATED = "productCreated",
894
+ PRODUCT_UPDATED = "productUpdated",
895
+ PRODUCT_DELETED = "productDeleted"
673
896
  }
674
897
  /**
675
898
  * Individual webhook configuration
@@ -693,7 +916,7 @@ export interface WebhookConfig {
693
916
  metadata: Record<string, any>;
694
917
  }
695
918
  /**
696
- * Webhooks integration configuration for real-time order notifications
919
+ * Webhooks integration configuration for real-time order and product notifications
697
920
  */
698
921
  export interface WebhooksIntegration {
699
922
  /** List of configured webhooks */
@@ -830,6 +1053,11 @@ export interface PublicConnectorsIntegration {
830
1053
  export interface StoreIntegrations {
831
1054
  [key: string]: any;
832
1055
  metadata?: Record<string, any>;
1056
+ /**
1057
+ * Global Meta integration — credentials shared by every Meta feature.
1058
+ * Ads live here today; pixels may move over from `metaPixel` later.
1059
+ */
1060
+ meta?: MetaIntegration;
833
1061
  metaPixel?: MetaPixelIntegration;
834
1062
  tiktokPixel?: TiktokPixelIntegration;
835
1063
  googleAnalytics?: GoogleAnalyticsIntegration;
@@ -852,6 +1080,9 @@ export interface StoreIntegrations {
852
1080
  zimou?: ZimouIntegration;
853
1081
  zrexpress?: ZrexpressIntegration;
854
1082
  mdmExpress?: MdmExpressIntegration;
1083
+ /** Feeef Delivery (Near white-label) — no merchant API keys. */
1084
+ feeefDelivery?: FeeefDeliveryIntegration;
1085
+ codpilot?: CodpilotIntegration;
855
1086
  security?: SecurityIntegration;
856
1087
  dispatcher?: DispatcherIntegration;
857
1088
  inventory?: StoreInventoryIntegration;
@@ -990,6 +1221,8 @@ export interface AddStoreMemberInput {
990
1221
  role: StoreMemberRole;
991
1222
  name?: string;
992
1223
  metadata?: Record<string, any>;
1224
+ /** RBAC scopes to grant (see {@link StoreMember.scopes}). Empty/undefined = unrestricted for the role. */
1225
+ scopes?: string[];
993
1226
  }
994
1227
  /**
995
1228
  * Input for updating a store member
@@ -998,4 +1231,6 @@ export interface UpdateStoreMemberInput {
998
1231
  role?: StoreMemberRole;
999
1232
  name?: string;
1000
1233
  metadata?: Record<string, any>;
1234
+ /** Replacement RBAC scopes (see {@link StoreMember.scopes}). Omit to keep current scopes. */
1235
+ scopes?: string[];
1001
1236
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * OAuth / member RBAC scope catalog — aligned with backend
3
+ * `app/oauth_scopes.ts` (`MEMBER_SCOPES` + `auth`, `apps`).
4
+ *
5
+ * Keep this list in sync when adding a store resource. Unknown strings are
6
+ * rejected by the API validators.
7
+ */
8
+ /** Store member RBAC scopes (parent implies `.read` child). */
9
+ export declare const MEMBER_SCOPES: readonly ["store", "store.read", "store.settings", "store.integrations", "store.members", "orders", "orders.read", "products", "products.read", "categories", "categories.read", "pages", "pages.read", "product_landing_pages", "product_landing_pages.read", "shipping_prices", "shipping_prices.read", "template_components", "template_components.read", "store_templates", "store_templates.read", "finance", "finance.read", "inventory", "inventory.read"];
10
+ export type MemberScope = (typeof MEMBER_SCOPES)[number];
11
+ /** Scopes for developer tooling / delegation (not store-specific RBAC). */
12
+ export declare const OAUTH_PLATFORM_SCOPES: readonly ["auth", "apps"];
13
+ /**
14
+ * Identity-only grant when an app is registered without scopes.
15
+ * Never `*` — empty registration must not escalate to full access.
16
+ */
17
+ export declare const DEFAULT_OAUTH_SCOPES: readonly ["auth"];
18
+ /** Every scope string allowed on OAuth apps and access tokens. */
19
+ export declare const OAUTH_SCOPES: readonly ["store", "store.read", "store.settings", "store.integrations", "store.members", "orders", "orders.read", "products", "products.read", "categories", "categories.read", "pages", "pages.read", "product_landing_pages", "product_landing_pages.read", "shipping_prices", "shipping_prices.read", "template_components", "template_components.read", "store_templates", "store_templates.read", "finance", "finance.read", "inventory", "inventory.read", "auth", "apps"];
20
+ export type OAuthScope = (typeof OAUTH_SCOPES)[number];