@eide/foir-cli 0.4.8 → 0.4.10

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/cli.js CHANGED
@@ -4810,6 +4810,14 @@ async function reconcileOperations(client, configId, operations, operationBaseUr
4810
4810
  for (const op of operations) {
4811
4811
  if (!op.key || !op.name) continue;
4812
4812
  manifestKeys.add(op.key);
4813
+ if (op.precondition) {
4814
+ const pre = op.precondition;
4815
+ const isSegment = "segmentKey" in pre && typeof pre.segmentKey === "string";
4816
+ const isExpression = "type" in pre && (pre.type === "condition" || pre.type === "group");
4817
+ if (!isSegment && !isExpression) {
4818
+ console.warn(`\u26A0 operation "${op.key}": precondition has unknown shape \u2014 expected {segmentKey, message} or {type: "condition"|"group", ...}`);
4819
+ }
4820
+ }
4813
4821
  const ex = existingByKey.get(op.key);
4814
4822
  const endpoint = resolveEndpoint(op.endpoint, operationBaseUrl);
4815
4823
  if (ex) {
@@ -4906,10 +4914,17 @@ async function reconcileHooks(client, configId, hooks, summary) {
4906
4914
  }
4907
4915
  }
4908
4916
  async function reconcileSegments(client, configId, segments, summary) {
4909
- const existing = await client.segments.listSegments({ configId, limit: 200 });
4910
- const existingByKey = new Map(
4911
- (existing.segments ?? []).map((s) => [s.key, s])
4912
- );
4917
+ const [scoped, all] = await Promise.all([
4918
+ client.segments.listSegments({ configId, limit: 200 }),
4919
+ client.segments.listSegments({ limit: 200 })
4920
+ ]);
4921
+ const existingByKey = /* @__PURE__ */ new Map();
4922
+ for (const s of all.segments ?? []) {
4923
+ existingByKey.set(s.key, s);
4924
+ }
4925
+ for (const s of scoped.segments ?? []) {
4926
+ existingByKey.set(s.key, s);
4927
+ }
4913
4928
  const manifestKeys = /* @__PURE__ */ new Set();
4914
4929
  for (const seg of segments) {
4915
4930
  if (!seg.key || !seg.name) continue;
@@ -4938,11 +4953,12 @@ async function reconcileSegments(client, configId, segments, summary) {
4938
4953
  summary.segments.created++;
4939
4954
  }
4940
4955
  }
4941
- for (const [key, ex] of existingByKey) {
4956
+ const scopedByKey = new Map(
4957
+ (scoped.segments ?? []).map((s) => [s.key, s])
4958
+ );
4959
+ for (const [key, ex] of scopedByKey) {
4942
4960
  if (!manifestKeys.has(key)) {
4943
- await client.segments.deleteSegment(
4944
- ex.id
4945
- );
4961
+ await client.segments.deleteSegment(ex.id);
4946
4962
  summary.segments.deleted++;
4947
4963
  }
4948
4964
  }
@@ -52,7 +52,24 @@ interface QuotaRule {
52
52
  condition?: Record<string, unknown>;
53
53
  /** Optional expiry — rule is ignored after this date (ISO 8601). */
54
54
  expiresAt?: string;
55
+ /** Custom message returned when this rule's quota is exhausted (e.g., upgrade CTA). */
56
+ message?: string;
55
57
  }
58
+ /** Segment-based precondition: blocks execution unless the customer belongs to the segment. */
59
+ interface SegmentPrecondition {
60
+ /** Key of the segment the customer must belong to. */
61
+ segmentKey: string;
62
+ /** Error message returned when the precondition fails (e.g., upgrade CTA). */
63
+ message?: string;
64
+ }
65
+ /** Rule-expression precondition: blocks execution unless the expression evaluates to true. */
66
+ interface ExpressionPrecondition {
67
+ /** Expression type — "condition" for a single rule, "group" for AND/OR groups. */
68
+ type: 'condition' | 'group';
69
+ [key: string]: unknown;
70
+ }
71
+ /** A precondition that must be met before an operation can execute. */
72
+ type Precondition = SegmentPrecondition | ExpressionPrecondition;
56
73
  interface ApplyConfigOperationInput {
57
74
  key: string;
58
75
  name: string;
@@ -76,7 +93,7 @@ interface ApplyConfigOperationInput {
76
93
  /** Roles allowed to execute this operation. */
77
94
  allowedRoles?: string[];
78
95
  /** Precondition that must be met before execution (e.g., segment membership). */
79
- precondition?: Record<string, unknown>;
96
+ precondition?: Precondition;
80
97
  }
81
98
  interface ApplyConfigSegmentInput {
82
99
  key: string;
@@ -187,4 +204,4 @@ declare function defineHook(hook: ApplyConfigHookInput): ApplyConfigHookInput;
187
204
  /** Define an editor placement (sidebar or main-editor tab). */
188
205
  declare function definePlacement(placement: ApplyConfigPlacementInput): ApplyConfigPlacementInput;
189
206
 
190
- export { type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type FieldDefinitionInput, type QuotaRule, defineAuthProvider, defineConfig, defineExtension, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
207
+ export { type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type ExpressionPrecondition, type FieldDefinitionInput, type Precondition, type QuotaRule, type SegmentPrecondition, defineAuthProvider, defineConfig, defineExtension, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eide/foir-cli",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Universal platform CLI for Foir platform",
5
5
  "type": "module",
6
6
  "publishConfig": {