@schematichq/schematic-react 1.9.0 → 1.10.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/README.md +37 -0
- package/dist/schematic-react.cjs.js +182 -5
- package/dist/schematic-react.d.ts +184 -0
- package/dist/schematic-react.esm.js +182 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -280,6 +280,43 @@ const CreditMeter = () => {
|
|
|
280
280
|
|
|
281
281
|
While `creditId` is `undefined`, the hook reports the client's loading state and a balance of `0`.
|
|
282
282
|
|
|
283
|
+
### Credit spend policies
|
|
284
|
+
|
|
285
|
+
To show the spend limits that bind the current company and user, use the `useSchematicCreditSpendPolicies` hook. It updates over the DataStream, so a policy edited or deleted in the dashboard reaches the component without a refetch:
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { useSchematicCreditSpendPolicies } from "@schematichq/schematic-react";
|
|
289
|
+
|
|
290
|
+
const SpendLimits = () => {
|
|
291
|
+
const { policies, isLoading } = useSchematicCreditSpendPolicies();
|
|
292
|
+
|
|
293
|
+
if (isLoading) {
|
|
294
|
+
return <div>Loading…</div>;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
<ul>
|
|
299
|
+
{policies.map((policy) => (
|
|
300
|
+
<li key={policy.id}>
|
|
301
|
+
{policy.kind === "window" && policy.window
|
|
302
|
+
? `${policy.scope} limit: ${policy.consumed} of ${policy.limit} credits used this ${policy.window.unit}`
|
|
303
|
+
: `${policy.scope} limit: ${policy.limit} credits per request`}
|
|
304
|
+
</li>
|
|
305
|
+
))}
|
|
306
|
+
</ul>
|
|
307
|
+
);
|
|
308
|
+
};
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
| Property | Type | Description |
|
|
312
|
+
| --- | --- | --- |
|
|
313
|
+
| `policies` | `CreditSpendPolicies` | Company-scope policies first, then the user's own; empty when none bind |
|
|
314
|
+
| `isLoading` | `boolean` | `true` while the policies are still loading and nothing has arrived yet |
|
|
315
|
+
|
|
316
|
+
A `per_draw` policy caps a single draw. A `window` policy caps what can be spent in one period: `consumed` is what the current period has spent, `resetsAt` is when the period ends, and `window` names the period. Each new spend sends an updated `consumed`. Once `resetsAt` has passed, read `consumed` as `0` until the next update arrives.
|
|
317
|
+
|
|
318
|
+
The policies are advisory for display: the server and the flag check enforce them.
|
|
319
|
+
|
|
283
320
|
## Fallback Behavior
|
|
284
321
|
|
|
285
322
|
The SDK includes built-in fallback behavior you can use to ensure your application continues to function even when unable to reach Schematic (e.g., during service disruptions or network issues).
|
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
useSchematic: () => useSchematic,
|
|
52
52
|
useSchematicContext: () => useSchematicContext,
|
|
53
53
|
useSchematicCreditBalance: () => useSchematicCreditBalance,
|
|
54
|
+
useSchematicCreditSpendPolicies: () => useSchematicCreditSpendPolicies,
|
|
54
55
|
useSchematicEntitlement: () => useSchematicEntitlement,
|
|
55
56
|
useSchematicEvents: () => useSchematicEvents,
|
|
56
57
|
useSchematicFlag: () => useSchematicFlag,
|
|
@@ -65,7 +66,7 @@ __export(index_exports, {
|
|
|
65
66
|
});
|
|
66
67
|
module.exports = __toCommonJS(index_exports);
|
|
67
68
|
|
|
68
|
-
// node_modules/.pnpm/@schematichq+schematic-js@1.
|
|
69
|
+
// node_modules/.pnpm/@schematichq+schematic-js@1.10.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
|
|
69
70
|
var __create2 = Object.create;
|
|
70
71
|
var __defProp2 = Object.defineProperty;
|
|
71
72
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
@@ -1061,6 +1062,43 @@ function DatastreamCompanyPlanFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
1061
1062
|
trialStatus: json["trial_status"] == null ? void 0 : TrialStatusFromJSON(json["trial_status"])
|
|
1062
1063
|
};
|
|
1063
1064
|
}
|
|
1065
|
+
function CreditSpendPolicyScopeFromJSON(json) {
|
|
1066
|
+
return CreditSpendPolicyScopeFromJSONTyped(json, false);
|
|
1067
|
+
}
|
|
1068
|
+
function CreditSpendPolicyScopeFromJSONTyped(json, ignoreDiscriminator) {
|
|
1069
|
+
return json;
|
|
1070
|
+
}
|
|
1071
|
+
function CreditSpendWindowFromJSON(json) {
|
|
1072
|
+
return CreditSpendWindowFromJSONTyped(json, false);
|
|
1073
|
+
}
|
|
1074
|
+
function CreditSpendWindowFromJSONTyped(json, ignoreDiscriminator) {
|
|
1075
|
+
if (json == null) {
|
|
1076
|
+
return json;
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
count: json["count"],
|
|
1080
|
+
unit: json["unit"]
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function CreditSpendPolicyFromJSON(json) {
|
|
1084
|
+
return CreditSpendPolicyFromJSONTyped(json, false);
|
|
1085
|
+
}
|
|
1086
|
+
function CreditSpendPolicyFromJSONTyped(json, ignoreDiscriminator) {
|
|
1087
|
+
if (json == null) {
|
|
1088
|
+
return json;
|
|
1089
|
+
}
|
|
1090
|
+
return {
|
|
1091
|
+
consumed: json["consumed"] == null ? void 0 : json["consumed"],
|
|
1092
|
+
creditId: json["credit_id"],
|
|
1093
|
+
id: json["id"],
|
|
1094
|
+
kind: json["kind"],
|
|
1095
|
+
label: json["label"] == null ? void 0 : json["label"],
|
|
1096
|
+
limit: json["limit"],
|
|
1097
|
+
resetsAt: json["resets_at"] == null ? void 0 : new Date(json["resets_at"]),
|
|
1098
|
+
scope: CreditSpendPolicyScopeFromJSON(json["scope"]),
|
|
1099
|
+
window: json["window"] == null ? void 0 : CreditSpendWindowFromJSON(json["window"])
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1064
1102
|
function CheckFlagsResponseDataFromJSON(json) {
|
|
1065
1103
|
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
1066
1104
|
}
|
|
@@ -1070,6 +1108,9 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
1070
1108
|
}
|
|
1071
1109
|
return {
|
|
1072
1110
|
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
1111
|
+
creditSpendPolicies: json["credit_spend_policies"].map(
|
|
1112
|
+
CreditSpendPolicyFromJSON
|
|
1113
|
+
),
|
|
1073
1114
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
1074
1115
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
1075
1116
|
};
|
|
@@ -1198,7 +1239,55 @@ var CreditBalancesFromJSON = (json) => {
|
|
|
1198
1239
|
}
|
|
1199
1240
|
return balances;
|
|
1200
1241
|
};
|
|
1201
|
-
var
|
|
1242
|
+
var CreditSpendPoliciesFromJSON = (json) => {
|
|
1243
|
+
if (!Array.isArray(json)) {
|
|
1244
|
+
return [];
|
|
1245
|
+
}
|
|
1246
|
+
const policies = [];
|
|
1247
|
+
for (const raw of json) {
|
|
1248
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1249
|
+
const id = raw.id;
|
|
1250
|
+
const creditId = raw.credit_id ?? raw.creditId;
|
|
1251
|
+
const kind = raw.kind;
|
|
1252
|
+
const scope = raw.scope;
|
|
1253
|
+
const limit = raw.limit;
|
|
1254
|
+
if (typeof id !== "string" || typeof creditId !== "string" || typeof kind !== "string" || typeof scope !== "string" || typeof limit !== "number") {
|
|
1255
|
+
continue;
|
|
1256
|
+
}
|
|
1257
|
+
const policy = {
|
|
1258
|
+
id,
|
|
1259
|
+
creditId,
|
|
1260
|
+
kind,
|
|
1261
|
+
scope,
|
|
1262
|
+
limit,
|
|
1263
|
+
consumed: typeof raw.consumed === "number" ? raw.consumed : 0
|
|
1264
|
+
};
|
|
1265
|
+
if (typeof raw.label === "string") {
|
|
1266
|
+
policy.label = raw.label;
|
|
1267
|
+
}
|
|
1268
|
+
const window2 = raw.window;
|
|
1269
|
+
if (window2 != null && typeof window2 === "object" && typeof window2.unit === "string" && typeof window2.count === "number") {
|
|
1270
|
+
policy.window = { unit: window2.unit, count: window2.count };
|
|
1271
|
+
}
|
|
1272
|
+
const resetsAt = raw.resets_at ?? raw.resetsAt;
|
|
1273
|
+
if (typeof resetsAt === "string" || resetsAt instanceof Date) {
|
|
1274
|
+
const parsed = new Date(resetsAt);
|
|
1275
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
1276
|
+
policy.resetsAt = parsed;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
policies.push(policy);
|
|
1280
|
+
}
|
|
1281
|
+
return policies;
|
|
1282
|
+
};
|
|
1283
|
+
var creditSpendPoliciesEqual = (a, b) => {
|
|
1284
|
+
if (a.length !== b.length) return false;
|
|
1285
|
+
return a.every((x, i) => {
|
|
1286
|
+
const y = b[i];
|
|
1287
|
+
return x.id === y.id && x.creditId === y.creditId && x.kind === y.kind && x.scope === y.scope && x.label === y.label && x.limit === y.limit && x.consumed === y.consumed && x.resetsAt?.getTime() === y.resetsAt?.getTime() && x.window?.unit === y.window?.unit && x.window?.count === y.window?.count;
|
|
1288
|
+
});
|
|
1289
|
+
};
|
|
1290
|
+
var cacheVersion = "35d92bc6";
|
|
1202
1291
|
function contextString(context) {
|
|
1203
1292
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
1204
1293
|
const sortedKeys = Object.keys(
|
|
@@ -1213,7 +1302,7 @@ function contextString(context) {
|
|
|
1213
1302
|
}, {});
|
|
1214
1303
|
return JSON.stringify(sortedContext);
|
|
1215
1304
|
}
|
|
1216
|
-
var version = "1.
|
|
1305
|
+
var version = "1.10.0";
|
|
1217
1306
|
var SINGLETON = {};
|
|
1218
1307
|
var models_exports = {};
|
|
1219
1308
|
__export2(models_exports, {
|
|
@@ -2380,6 +2469,7 @@ var flagStateCachePrefix = "schematicCache";
|
|
|
2380
2469
|
var flagStateCacheMaxContexts = 10;
|
|
2381
2470
|
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
2382
2471
|
var emptyCreditBalances = Object.freeze({});
|
|
2472
|
+
var emptyCreditSpendPolicies = [];
|
|
2383
2473
|
var Schematic = class {
|
|
2384
2474
|
_additionalHeaders = {};
|
|
2385
2475
|
apiKey;
|
|
@@ -2397,6 +2487,7 @@ var Schematic = class {
|
|
|
2397
2487
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
2398
2488
|
planListeners = /* @__PURE__ */ new Set();
|
|
2399
2489
|
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
2490
|
+
creditSpendPolicyListeners = /* @__PURE__ */ new Set();
|
|
2400
2491
|
storage;
|
|
2401
2492
|
persistFlagState = true;
|
|
2402
2493
|
flagStateCacheKey;
|
|
@@ -2407,6 +2498,7 @@ var Schematic = class {
|
|
|
2407
2498
|
featureUsageEventMap = {};
|
|
2408
2499
|
planChecks = {};
|
|
2409
2500
|
creditBalances = {};
|
|
2501
|
+
creditSpendPolicies = {};
|
|
2410
2502
|
webSocketUrl = "wss://api.schematichq.com";
|
|
2411
2503
|
webSocketConnectionTimeout = 1e4;
|
|
2412
2504
|
webSocketReconnect = true;
|
|
@@ -2799,6 +2891,19 @@ var Schematic = class {
|
|
|
2799
2891
|
this.notifyCreditBalanceListeners(merged);
|
|
2800
2892
|
}
|
|
2801
2893
|
}
|
|
2894
|
+
if (message.credit_spend_policies !== void 0 && message.credit_spend_policies !== null) {
|
|
2895
|
+
const contextStr = contextString(context);
|
|
2896
|
+
const next = CreditSpendPoliciesFromJSON(message.credit_spend_policies);
|
|
2897
|
+
const previous = this.creditSpendPolicies[contextStr] ?? [];
|
|
2898
|
+
if (!creditSpendPoliciesEqual(previous, next)) {
|
|
2899
|
+
this.creditSpendPolicies[contextStr] = next;
|
|
2900
|
+
this.debug(
|
|
2901
|
+
`WebSocket credit spend policy update received. Notifying listeners`,
|
|
2902
|
+
{ creditSpendPolicies: next }
|
|
2903
|
+
);
|
|
2904
|
+
this.notifyCreditSpendPolicyListeners(next);
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2802
2907
|
this.persistContextToCache(contextString(context));
|
|
2803
2908
|
this.flushContextDependentEventQueue();
|
|
2804
2909
|
this.setIsPending(false);
|
|
@@ -3300,10 +3405,19 @@ var Schematic = class {
|
|
|
3300
3405
|
this.creditBalances[contextStr] = balances;
|
|
3301
3406
|
}
|
|
3302
3407
|
}
|
|
3408
|
+
let revivedCreditSpendPolicies;
|
|
3409
|
+
if (entry.creditSpendPolicies !== void 0 && entry.creditSpendPolicies !== null) {
|
|
3410
|
+
const policies = CreditSpendPoliciesFromJSON(entry.creditSpendPolicies);
|
|
3411
|
+
if (policies.length > 0) {
|
|
3412
|
+
revivedCreditSpendPolicies = policies;
|
|
3413
|
+
this.creditSpendPolicies[contextStr] = policies;
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3303
3416
|
fresh[contextStr] = {
|
|
3304
3417
|
checks: revivedChecks,
|
|
3305
3418
|
plan: revivedPlan,
|
|
3306
3419
|
creditBalances: revivedCreditBalances,
|
|
3420
|
+
creditSpendPolicies: revivedCreditSpendPolicies,
|
|
3307
3421
|
updatedAt: entry.updatedAt
|
|
3308
3422
|
};
|
|
3309
3423
|
contextsLoaded += 1;
|
|
@@ -3317,7 +3431,8 @@ var Schematic = class {
|
|
|
3317
3431
|
const checksForContext = this.checks[contextStr];
|
|
3318
3432
|
const planForContext = this.planChecks[contextStr];
|
|
3319
3433
|
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
3320
|
-
|
|
3434
|
+
const creditSpendPoliciesForContext = this.creditSpendPolicies[contextStr];
|
|
3435
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0 && creditSpendPoliciesForContext === void 0) {
|
|
3321
3436
|
return;
|
|
3322
3437
|
}
|
|
3323
3438
|
if (this.cachedFlagState === null) {
|
|
@@ -3336,6 +3451,7 @@ var Schematic = class {
|
|
|
3336
3451
|
checks: cleanChecks,
|
|
3337
3452
|
plan: planForContext,
|
|
3338
3453
|
creditBalances: creditBalancesForContext,
|
|
3454
|
+
creditSpendPolicies: creditSpendPoliciesForContext,
|
|
3339
3455
|
updatedAt: Date.now()
|
|
3340
3456
|
};
|
|
3341
3457
|
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
@@ -3352,6 +3468,9 @@ var Schematic = class {
|
|
|
3352
3468
|
for (const key of Object.keys(this.creditBalances)) {
|
|
3353
3469
|
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
3354
3470
|
}
|
|
3471
|
+
for (const key of Object.keys(this.creditSpendPolicies)) {
|
|
3472
|
+
if (!survivorKeys.has(key)) delete this.creditSpendPolicies[key];
|
|
3473
|
+
}
|
|
3355
3474
|
this.cachedFlagState = {
|
|
3356
3475
|
version: cacheVersion,
|
|
3357
3476
|
contexts: Object.fromEntries(survivors)
|
|
@@ -3946,6 +4065,18 @@ var Schematic = class {
|
|
|
3946
4065
|
const contextStr = contextString(this.context);
|
|
3947
4066
|
return this.creditBalances[contextStr]?.[creditId];
|
|
3948
4067
|
};
|
|
4068
|
+
/** Get every credit spend policy binding the current context, company-scope first */
|
|
4069
|
+
getCreditSpendPolicies = () => {
|
|
4070
|
+
const contextStr = contextString(this.context);
|
|
4071
|
+
return this.creditSpendPolicies[contextStr] ?? emptyCreditSpendPolicies;
|
|
4072
|
+
};
|
|
4073
|
+
/** Get the spend policies binding a single credit type in the current context */
|
|
4074
|
+
getCreditSpendPoliciesForCredit = (creditId) => {
|
|
4075
|
+
const policies = this.getCreditSpendPolicies().filter(
|
|
4076
|
+
(policy) => policy.creditId === creditId
|
|
4077
|
+
);
|
|
4078
|
+
return policies.length > 0 ? policies : emptyCreditSpendPolicies;
|
|
4079
|
+
};
|
|
3949
4080
|
// flag checks state
|
|
3950
4081
|
getFlagCheck = (flagKey) => {
|
|
3951
4082
|
const contextStr = contextString(this.context);
|
|
@@ -4012,6 +4143,13 @@ var Schematic = class {
|
|
|
4012
4143
|
this.creditBalanceListeners.delete(listener);
|
|
4013
4144
|
};
|
|
4014
4145
|
};
|
|
4146
|
+
/** Register an event listener that will be notified with the context's credit spend policies whenever the set changes */
|
|
4147
|
+
addCreditSpendPolicyListener = (listener) => {
|
|
4148
|
+
this.creditSpendPolicyListeners.add(listener);
|
|
4149
|
+
return () => {
|
|
4150
|
+
this.creditSpendPolicyListeners.delete(listener);
|
|
4151
|
+
};
|
|
4152
|
+
};
|
|
4015
4153
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
4016
4154
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
4017
4155
|
if (listeners.size > 0) {
|
|
@@ -4075,6 +4213,16 @@ var Schematic = class {
|
|
|
4075
4213
|
});
|
|
4076
4214
|
});
|
|
4077
4215
|
};
|
|
4216
|
+
notifyCreditSpendPolicyListeners = (value) => {
|
|
4217
|
+
const listeners = this.creditSpendPolicyListeners ?? [];
|
|
4218
|
+
listeners.forEach((listener) => {
|
|
4219
|
+
if (listener.length > 0) {
|
|
4220
|
+
listener(value);
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
listener();
|
|
4224
|
+
});
|
|
4225
|
+
};
|
|
4078
4226
|
notifyCreditBalanceListeners = (value) => {
|
|
4079
4227
|
const listeners = this.creditBalanceListeners ?? [];
|
|
4080
4228
|
if (listeners.size > 0) {
|
|
@@ -5091,7 +5239,7 @@ function staticSource(data) {
|
|
|
5091
5239
|
}
|
|
5092
5240
|
|
|
5093
5241
|
// src/version.ts
|
|
5094
|
-
var version2 = "1.
|
|
5242
|
+
var version2 = "1.10.0";
|
|
5095
5243
|
|
|
5096
5244
|
// src/context/schematic.tsx
|
|
5097
5245
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -5184,6 +5332,7 @@ var useSchematic = () => {
|
|
|
5184
5332
|
|
|
5185
5333
|
// src/hooks/schematic.ts
|
|
5186
5334
|
var import_react6 = require("react");
|
|
5335
|
+
var emptyPolicies = [];
|
|
5187
5336
|
var useSchematicClient = (opts) => {
|
|
5188
5337
|
const schematic = useSchematic();
|
|
5189
5338
|
const { client } = opts ?? {};
|
|
@@ -5299,6 +5448,34 @@ var useSchematicCreditBalance = (creditId, opts) => {
|
|
|
5299
5448
|
[balance, isPending]
|
|
5300
5449
|
);
|
|
5301
5450
|
};
|
|
5451
|
+
var useSchematicCreditSpendPolicies = (opts) => {
|
|
5452
|
+
const client = useSchematicClient(opts);
|
|
5453
|
+
const subscribe = (0, import_react6.useCallback)(
|
|
5454
|
+
(callback) => client.addCreditSpendPolicyListener(callback),
|
|
5455
|
+
[client]
|
|
5456
|
+
);
|
|
5457
|
+
const policies = (0, import_react6.useSyncExternalStore)(
|
|
5458
|
+
subscribe,
|
|
5459
|
+
() => client.getCreditSpendPolicies(),
|
|
5460
|
+
() => emptyPolicies
|
|
5461
|
+
);
|
|
5462
|
+
const isPendingSubscribe = (0, import_react6.useCallback)(
|
|
5463
|
+
(callback) => client.addIsPendingListener(callback),
|
|
5464
|
+
[client]
|
|
5465
|
+
);
|
|
5466
|
+
const isPending = (0, import_react6.useSyncExternalStore)(
|
|
5467
|
+
isPendingSubscribe,
|
|
5468
|
+
() => client.getIsPending(),
|
|
5469
|
+
() => true
|
|
5470
|
+
);
|
|
5471
|
+
return (0, import_react6.useMemo)(
|
|
5472
|
+
() => ({
|
|
5473
|
+
policies,
|
|
5474
|
+
isLoading: policies.length === 0 && isPending
|
|
5475
|
+
}),
|
|
5476
|
+
[policies, isPending]
|
|
5477
|
+
);
|
|
5478
|
+
};
|
|
5302
5479
|
var useSchematicIsPending = (opts) => {
|
|
5303
5480
|
const client = useSchematicClient(opts);
|
|
5304
5481
|
const subscribe = (0, import_react6.useCallback)(
|
|
@@ -593,6 +593,12 @@ declare interface CheckFlagsResponseData {
|
|
|
593
593
|
creditBalances?: {
|
|
594
594
|
[key: string]: CompanyCreditBalance;
|
|
595
595
|
};
|
|
596
|
+
/**
|
|
597
|
+
* Credit spend policies binding the evaluated company and user; empty when none bind. Each response carries the whole set, so replace any previously received set with it. Advisory: the flag values do not reflect them, since a check names no draw amount
|
|
598
|
+
* @type {Array<CreditSpendPolicy>}
|
|
599
|
+
* @memberof CheckFlagsResponseData
|
|
600
|
+
*/
|
|
601
|
+
creditSpendPolicies: Array<CreditSpendPolicy_2>;
|
|
596
602
|
/**
|
|
597
603
|
*
|
|
598
604
|
* @type {Array<CheckFlagResponseData>}
|
|
@@ -946,6 +952,153 @@ declare const CreditBalancesFromJSON: (json: any) => CreditBalances;
|
|
|
946
952
|
|
|
947
953
|
declare type CreditBalancesListenerFn = (value: CreditBalances) => void;
|
|
948
954
|
|
|
955
|
+
/** Every spend policy binding the current context, company-scope first */
|
|
956
|
+
export declare type CreditSpendPolicies = CreditSpendPolicy[];
|
|
957
|
+
|
|
958
|
+
/** Compare two policy sets by value, so an unchanged restream skips the notify. */
|
|
959
|
+
declare const creditSpendPoliciesEqual: (a: CreditSpendPolicies, b: CreditSpendPolicies) => boolean;
|
|
960
|
+
|
|
961
|
+
declare const CreditSpendPoliciesFromJSON: (json: any) => CreditSpendPolicies;
|
|
962
|
+
|
|
963
|
+
declare type CreditSpendPoliciesListenerFn = (value: CreditSpendPolicies) => void;
|
|
964
|
+
|
|
965
|
+
/** One limit on spending a credit */
|
|
966
|
+
export declare type CreditSpendPolicy = {
|
|
967
|
+
id: string;
|
|
968
|
+
creditId: string;
|
|
969
|
+
kind: CreditSpendPolicyKind;
|
|
970
|
+
scope: CreditSpendPolicyScope;
|
|
971
|
+
label?: string;
|
|
972
|
+
/** The ceiling, in credits */
|
|
973
|
+
limit: number;
|
|
974
|
+
/** How much of the limit is already spent in the current period; 0 for per_draw */
|
|
975
|
+
consumed: number;
|
|
976
|
+
/** For windowed kinds, when the current period ends and consumed no longer applies */
|
|
977
|
+
resetsAt?: Date;
|
|
978
|
+
/** Set for windowed kinds only */
|
|
979
|
+
window?: CreditSpendWindow;
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
*
|
|
984
|
+
* @export
|
|
985
|
+
* @interface CreditSpendPolicy
|
|
986
|
+
*/
|
|
987
|
+
declare interface CreditSpendPolicy_2 {
|
|
988
|
+
/**
|
|
989
|
+
* How much of the limit is already spent in the current period
|
|
990
|
+
* @type {number}
|
|
991
|
+
* @memberof CreditSpendPolicy
|
|
992
|
+
*/
|
|
993
|
+
consumed?: number;
|
|
994
|
+
/**
|
|
995
|
+
* The credit the policy limits
|
|
996
|
+
* @type {string}
|
|
997
|
+
* @memberof CreditSpendPolicy
|
|
998
|
+
*/
|
|
999
|
+
creditId: string;
|
|
1000
|
+
/**
|
|
1001
|
+
* The ID of the policy
|
|
1002
|
+
* @type {string}
|
|
1003
|
+
* @memberof CreditSpendPolicy
|
|
1004
|
+
*/
|
|
1005
|
+
id: string;
|
|
1006
|
+
/**
|
|
1007
|
+
* How the limit is applied
|
|
1008
|
+
* @type {string}
|
|
1009
|
+
* @memberof CreditSpendPolicy
|
|
1010
|
+
*/
|
|
1011
|
+
kind: string;
|
|
1012
|
+
/**
|
|
1013
|
+
* The name the account gave the policy
|
|
1014
|
+
* @type {string}
|
|
1015
|
+
* @memberof CreditSpendPolicy
|
|
1016
|
+
*/
|
|
1017
|
+
label?: string | null;
|
|
1018
|
+
/**
|
|
1019
|
+
* The ceiling, in credits
|
|
1020
|
+
* @type {number}
|
|
1021
|
+
* @memberof CreditSpendPolicy
|
|
1022
|
+
*/
|
|
1023
|
+
limit: number;
|
|
1024
|
+
/**
|
|
1025
|
+
* For a windowed limit, when the current period ends and consumed no longer applies
|
|
1026
|
+
* @type {Date}
|
|
1027
|
+
* @memberof CreditSpendPolicy
|
|
1028
|
+
*/
|
|
1029
|
+
resetsAt?: Date | null;
|
|
1030
|
+
/**
|
|
1031
|
+
* Whether the policy limits the company or one user
|
|
1032
|
+
* @type {CreditSpendPolicyScope}
|
|
1033
|
+
* @memberof CreditSpendPolicy
|
|
1034
|
+
*/
|
|
1035
|
+
scope: CreditSpendPolicyScope_2;
|
|
1036
|
+
/**
|
|
1037
|
+
* For a windowed limit, the period it accumulates over
|
|
1038
|
+
* @type {CreditSpendWindow}
|
|
1039
|
+
* @memberof CreditSpendPolicy
|
|
1040
|
+
*/
|
|
1041
|
+
window?: CreditSpendWindow_2;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/** How a spend policy applies its limit. Unknown kinds are carried, not dropped:
|
|
1045
|
+
* the server may ship a kind this SDK version predates. */
|
|
1046
|
+
export declare type CreditSpendPolicyKind = "per_draw" | "window" | (string & {});
|
|
1047
|
+
|
|
1048
|
+
declare type CreditSpendPolicyListenerFn = CreditSpendPoliciesListenerFn | EmptyListenerFn;
|
|
1049
|
+
|
|
1050
|
+
/** Whether a spend policy limits the company or one user */
|
|
1051
|
+
export declare type CreditSpendPolicyScope = "company" | "user" | (string & {});
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
*
|
|
1055
|
+
* @export
|
|
1056
|
+
*/
|
|
1057
|
+
declare const CreditSpendPolicyScope_2: {
|
|
1058
|
+
readonly Company: "company";
|
|
1059
|
+
readonly User: "user";
|
|
1060
|
+
readonly Group: "group";
|
|
1061
|
+
};
|
|
1062
|
+
|
|
1063
|
+
declare type CreditSpendPolicyScope_2 = (typeof CreditSpendPolicyScope_2)[keyof typeof CreditSpendPolicyScope_2];
|
|
1064
|
+
|
|
1065
|
+
/** The period a windowed spend policy accumulates over */
|
|
1066
|
+
export declare type CreditSpendWindow = {
|
|
1067
|
+
unit: string;
|
|
1068
|
+
count: number;
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Schematic API
|
|
1073
|
+
* Schematic API
|
|
1074
|
+
*
|
|
1075
|
+
* The version of the OpenAPI document: 0.1
|
|
1076
|
+
*
|
|
1077
|
+
*
|
|
1078
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
1079
|
+
* https://openapi-generator.tech
|
|
1080
|
+
* Do not edit the class manually.
|
|
1081
|
+
*/
|
|
1082
|
+
/**
|
|
1083
|
+
*
|
|
1084
|
+
* @export
|
|
1085
|
+
* @interface CreditSpendWindow
|
|
1086
|
+
*/
|
|
1087
|
+
declare interface CreditSpendWindow_2 {
|
|
1088
|
+
/**
|
|
1089
|
+
* How many units make up one period
|
|
1090
|
+
* @type {number}
|
|
1091
|
+
* @memberof CreditSpendWindow
|
|
1092
|
+
*/
|
|
1093
|
+
count: number;
|
|
1094
|
+
/**
|
|
1095
|
+
* The period the limit accumulates over
|
|
1096
|
+
* @type {string}
|
|
1097
|
+
* @memberof CreditSpendWindow
|
|
1098
|
+
*/
|
|
1099
|
+
unit: string;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
949
1102
|
/**
|
|
950
1103
|
*
|
|
951
1104
|
* @export
|
|
@@ -1463,6 +1616,7 @@ export declare class Schematic {
|
|
|
1463
1616
|
private isPendingListeners;
|
|
1464
1617
|
private planListeners;
|
|
1465
1618
|
private creditBalanceListeners;
|
|
1619
|
+
private creditSpendPolicyListeners;
|
|
1466
1620
|
private storage;
|
|
1467
1621
|
private persistFlagState;
|
|
1468
1622
|
private flagStateCacheKey;
|
|
@@ -1473,6 +1627,7 @@ export declare class Schematic {
|
|
|
1473
1627
|
private featureUsageEventMap;
|
|
1474
1628
|
private planChecks;
|
|
1475
1629
|
private creditBalances;
|
|
1630
|
+
private creditSpendPolicies;
|
|
1476
1631
|
private webSocketUrl;
|
|
1477
1632
|
private webSocketConnectionTimeout;
|
|
1478
1633
|
private webSocketReconnect;
|
|
@@ -1691,6 +1846,10 @@ export declare class Schematic {
|
|
|
1691
1846
|
getCreditBalances: () => CreditBalances;
|
|
1692
1847
|
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
1693
1848
|
getCreditBalance: (creditId: string) => CreditBalance | undefined;
|
|
1849
|
+
/** Get every credit spend policy binding the current context, company-scope first */
|
|
1850
|
+
getCreditSpendPolicies: () => CreditSpendPolicies;
|
|
1851
|
+
/** Get the spend policies binding a single credit type in the current context */
|
|
1852
|
+
getCreditSpendPoliciesForCredit: (creditId: string) => CreditSpendPolicies;
|
|
1694
1853
|
getFlagCheck: (flagKey: string) => CheckFlagReturn | undefined;
|
|
1695
1854
|
getFlagValue: (flagKey: string) => boolean | undefined;
|
|
1696
1855
|
/** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
|
|
@@ -1700,11 +1859,14 @@ export declare class Schematic {
|
|
|
1700
1859
|
addPlanListener: (listener: PlanListenerFn) => () => void;
|
|
1701
1860
|
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
1702
1861
|
addCreditBalanceListener: (listener: CreditBalanceListenerFn) => () => void;
|
|
1862
|
+
/** Register an event listener that will be notified with the context's credit spend policies whenever the set changes */
|
|
1863
|
+
addCreditSpendPolicyListener: (listener: CreditSpendPolicyListenerFn) => () => void;
|
|
1703
1864
|
private notifyFlagCheckListeners;
|
|
1704
1865
|
/** Add or update a CheckFlagReturn in the featureUsageEventMap */
|
|
1705
1866
|
private updateFeatureUsageEventMap;
|
|
1706
1867
|
private notifyFlagValueListeners;
|
|
1707
1868
|
private notifyPlanListeners;
|
|
1869
|
+
private notifyCreditSpendPolicyListeners;
|
|
1708
1870
|
private notifyCreditBalanceListeners;
|
|
1709
1871
|
}
|
|
1710
1872
|
|
|
@@ -1752,6 +1914,14 @@ export declare type SchematicCreditBalance = {
|
|
|
1752
1914
|
isLoading: boolean;
|
|
1753
1915
|
};
|
|
1754
1916
|
|
|
1917
|
+
/** The credit spend policies binding the current context, plus a loading flag */
|
|
1918
|
+
export declare type SchematicCreditSpendPolicies = {
|
|
1919
|
+
/** Company-scope policies first, then the actor's own; empty when none bind */
|
|
1920
|
+
policies: SchematicJS.CreditSpendPolicies;
|
|
1921
|
+
/** True while the policies are still loading and nothing has arrived yet */
|
|
1922
|
+
isLoading: boolean;
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1755
1925
|
export declare interface SchematicHookOpts {
|
|
1756
1926
|
client?: SchematicJS.Schematic;
|
|
1757
1927
|
}
|
|
@@ -1822,6 +1992,15 @@ declare namespace SchematicJS {
|
|
|
1822
1992
|
CreditBalances,
|
|
1823
1993
|
CreditBalancesFromJSON,
|
|
1824
1994
|
CreditBalancesListenerFn,
|
|
1995
|
+
CreditSpendPolicies,
|
|
1996
|
+
creditSpendPoliciesEqual,
|
|
1997
|
+
CreditSpendPoliciesFromJSON,
|
|
1998
|
+
CreditSpendPoliciesListenerFn,
|
|
1999
|
+
CreditSpendPolicy,
|
|
2000
|
+
CreditSpendPolicyKind,
|
|
2001
|
+
CreditSpendPolicyListenerFn,
|
|
2002
|
+
CreditSpendPolicyScope,
|
|
2003
|
+
CreditSpendWindow,
|
|
1825
2004
|
DEFAULT_INVOICE_QUERY,
|
|
1826
2005
|
Discount,
|
|
1827
2006
|
EmptyListenerFn,
|
|
@@ -2206,6 +2385,11 @@ export declare const useSchematicContext: (opts?: SchematicHookOpts) => {
|
|
|
2206
2385
|
*/
|
|
2207
2386
|
export declare const useSchematicCreditBalance: (creditId: string | undefined, opts?: SchematicHookOpts) => SchematicCreditBalance;
|
|
2208
2387
|
|
|
2388
|
+
/** Every credit spend policy binding the current context, company-scope first.
|
|
2389
|
+
* Streams over the websocket, so an edit in the dashboard lands here without a
|
|
2390
|
+
* refetch. */
|
|
2391
|
+
export declare const useSchematicCreditSpendPolicies: (opts?: SchematicHookOpts) => SchematicCreditSpendPolicies;
|
|
2392
|
+
|
|
2209
2393
|
export declare const useSchematicEntitlement: (key: string, opts?: UseSchematicFlagOpts) => SchematicJS.CheckFlagReturn;
|
|
2210
2394
|
|
|
2211
2395
|
export declare const useSchematicEvents: (opts?: SchematicHookOpts) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// node_modules/.pnpm/@schematichq+schematic-js@1.
|
|
1
|
+
// node_modules/.pnpm/@schematichq+schematic-js@1.10.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -994,6 +994,43 @@ function DatastreamCompanyPlanFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
994
994
|
trialStatus: json["trial_status"] == null ? void 0 : TrialStatusFromJSON(json["trial_status"])
|
|
995
995
|
};
|
|
996
996
|
}
|
|
997
|
+
function CreditSpendPolicyScopeFromJSON(json) {
|
|
998
|
+
return CreditSpendPolicyScopeFromJSONTyped(json, false);
|
|
999
|
+
}
|
|
1000
|
+
function CreditSpendPolicyScopeFromJSONTyped(json, ignoreDiscriminator) {
|
|
1001
|
+
return json;
|
|
1002
|
+
}
|
|
1003
|
+
function CreditSpendWindowFromJSON(json) {
|
|
1004
|
+
return CreditSpendWindowFromJSONTyped(json, false);
|
|
1005
|
+
}
|
|
1006
|
+
function CreditSpendWindowFromJSONTyped(json, ignoreDiscriminator) {
|
|
1007
|
+
if (json == null) {
|
|
1008
|
+
return json;
|
|
1009
|
+
}
|
|
1010
|
+
return {
|
|
1011
|
+
count: json["count"],
|
|
1012
|
+
unit: json["unit"]
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
function CreditSpendPolicyFromJSON(json) {
|
|
1016
|
+
return CreditSpendPolicyFromJSONTyped(json, false);
|
|
1017
|
+
}
|
|
1018
|
+
function CreditSpendPolicyFromJSONTyped(json, ignoreDiscriminator) {
|
|
1019
|
+
if (json == null) {
|
|
1020
|
+
return json;
|
|
1021
|
+
}
|
|
1022
|
+
return {
|
|
1023
|
+
consumed: json["consumed"] == null ? void 0 : json["consumed"],
|
|
1024
|
+
creditId: json["credit_id"],
|
|
1025
|
+
id: json["id"],
|
|
1026
|
+
kind: json["kind"],
|
|
1027
|
+
label: json["label"] == null ? void 0 : json["label"],
|
|
1028
|
+
limit: json["limit"],
|
|
1029
|
+
resetsAt: json["resets_at"] == null ? void 0 : new Date(json["resets_at"]),
|
|
1030
|
+
scope: CreditSpendPolicyScopeFromJSON(json["scope"]),
|
|
1031
|
+
window: json["window"] == null ? void 0 : CreditSpendWindowFromJSON(json["window"])
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
997
1034
|
function CheckFlagsResponseDataFromJSON(json) {
|
|
998
1035
|
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
999
1036
|
}
|
|
@@ -1003,6 +1040,9 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
1003
1040
|
}
|
|
1004
1041
|
return {
|
|
1005
1042
|
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
1043
|
+
creditSpendPolicies: json["credit_spend_policies"].map(
|
|
1044
|
+
CreditSpendPolicyFromJSON
|
|
1045
|
+
),
|
|
1006
1046
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
1007
1047
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
1008
1048
|
};
|
|
@@ -1131,7 +1171,55 @@ var CreditBalancesFromJSON = (json) => {
|
|
|
1131
1171
|
}
|
|
1132
1172
|
return balances;
|
|
1133
1173
|
};
|
|
1134
|
-
var
|
|
1174
|
+
var CreditSpendPoliciesFromJSON = (json) => {
|
|
1175
|
+
if (!Array.isArray(json)) {
|
|
1176
|
+
return [];
|
|
1177
|
+
}
|
|
1178
|
+
const policies = [];
|
|
1179
|
+
for (const raw of json) {
|
|
1180
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1181
|
+
const id = raw.id;
|
|
1182
|
+
const creditId = raw.credit_id ?? raw.creditId;
|
|
1183
|
+
const kind = raw.kind;
|
|
1184
|
+
const scope = raw.scope;
|
|
1185
|
+
const limit = raw.limit;
|
|
1186
|
+
if (typeof id !== "string" || typeof creditId !== "string" || typeof kind !== "string" || typeof scope !== "string" || typeof limit !== "number") {
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
const policy = {
|
|
1190
|
+
id,
|
|
1191
|
+
creditId,
|
|
1192
|
+
kind,
|
|
1193
|
+
scope,
|
|
1194
|
+
limit,
|
|
1195
|
+
consumed: typeof raw.consumed === "number" ? raw.consumed : 0
|
|
1196
|
+
};
|
|
1197
|
+
if (typeof raw.label === "string") {
|
|
1198
|
+
policy.label = raw.label;
|
|
1199
|
+
}
|
|
1200
|
+
const window2 = raw.window;
|
|
1201
|
+
if (window2 != null && typeof window2 === "object" && typeof window2.unit === "string" && typeof window2.count === "number") {
|
|
1202
|
+
policy.window = { unit: window2.unit, count: window2.count };
|
|
1203
|
+
}
|
|
1204
|
+
const resetsAt = raw.resets_at ?? raw.resetsAt;
|
|
1205
|
+
if (typeof resetsAt === "string" || resetsAt instanceof Date) {
|
|
1206
|
+
const parsed = new Date(resetsAt);
|
|
1207
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
1208
|
+
policy.resetsAt = parsed;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
policies.push(policy);
|
|
1212
|
+
}
|
|
1213
|
+
return policies;
|
|
1214
|
+
};
|
|
1215
|
+
var creditSpendPoliciesEqual = (a, b) => {
|
|
1216
|
+
if (a.length !== b.length) return false;
|
|
1217
|
+
return a.every((x, i) => {
|
|
1218
|
+
const y = b[i];
|
|
1219
|
+
return x.id === y.id && x.creditId === y.creditId && x.kind === y.kind && x.scope === y.scope && x.label === y.label && x.limit === y.limit && x.consumed === y.consumed && x.resetsAt?.getTime() === y.resetsAt?.getTime() && x.window?.unit === y.window?.unit && x.window?.count === y.window?.count;
|
|
1220
|
+
});
|
|
1221
|
+
};
|
|
1222
|
+
var cacheVersion = "35d92bc6";
|
|
1135
1223
|
function contextString(context) {
|
|
1136
1224
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
1137
1225
|
const sortedKeys = Object.keys(
|
|
@@ -1146,7 +1234,7 @@ function contextString(context) {
|
|
|
1146
1234
|
}, {});
|
|
1147
1235
|
return JSON.stringify(sortedContext);
|
|
1148
1236
|
}
|
|
1149
|
-
var version = "1.
|
|
1237
|
+
var version = "1.10.0";
|
|
1150
1238
|
var SINGLETON = {};
|
|
1151
1239
|
var models_exports = {};
|
|
1152
1240
|
__export(models_exports, {
|
|
@@ -2313,6 +2401,7 @@ var flagStateCachePrefix = "schematicCache";
|
|
|
2313
2401
|
var flagStateCacheMaxContexts = 10;
|
|
2314
2402
|
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
2315
2403
|
var emptyCreditBalances = Object.freeze({});
|
|
2404
|
+
var emptyCreditSpendPolicies = [];
|
|
2316
2405
|
var Schematic = class {
|
|
2317
2406
|
_additionalHeaders = {};
|
|
2318
2407
|
apiKey;
|
|
@@ -2330,6 +2419,7 @@ var Schematic = class {
|
|
|
2330
2419
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
2331
2420
|
planListeners = /* @__PURE__ */ new Set();
|
|
2332
2421
|
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
2422
|
+
creditSpendPolicyListeners = /* @__PURE__ */ new Set();
|
|
2333
2423
|
storage;
|
|
2334
2424
|
persistFlagState = true;
|
|
2335
2425
|
flagStateCacheKey;
|
|
@@ -2340,6 +2430,7 @@ var Schematic = class {
|
|
|
2340
2430
|
featureUsageEventMap = {};
|
|
2341
2431
|
planChecks = {};
|
|
2342
2432
|
creditBalances = {};
|
|
2433
|
+
creditSpendPolicies = {};
|
|
2343
2434
|
webSocketUrl = "wss://api.schematichq.com";
|
|
2344
2435
|
webSocketConnectionTimeout = 1e4;
|
|
2345
2436
|
webSocketReconnect = true;
|
|
@@ -2732,6 +2823,19 @@ var Schematic = class {
|
|
|
2732
2823
|
this.notifyCreditBalanceListeners(merged);
|
|
2733
2824
|
}
|
|
2734
2825
|
}
|
|
2826
|
+
if (message.credit_spend_policies !== void 0 && message.credit_spend_policies !== null) {
|
|
2827
|
+
const contextStr = contextString(context);
|
|
2828
|
+
const next = CreditSpendPoliciesFromJSON(message.credit_spend_policies);
|
|
2829
|
+
const previous = this.creditSpendPolicies[contextStr] ?? [];
|
|
2830
|
+
if (!creditSpendPoliciesEqual(previous, next)) {
|
|
2831
|
+
this.creditSpendPolicies[contextStr] = next;
|
|
2832
|
+
this.debug(
|
|
2833
|
+
`WebSocket credit spend policy update received. Notifying listeners`,
|
|
2834
|
+
{ creditSpendPolicies: next }
|
|
2835
|
+
);
|
|
2836
|
+
this.notifyCreditSpendPolicyListeners(next);
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2735
2839
|
this.persistContextToCache(contextString(context));
|
|
2736
2840
|
this.flushContextDependentEventQueue();
|
|
2737
2841
|
this.setIsPending(false);
|
|
@@ -3233,10 +3337,19 @@ var Schematic = class {
|
|
|
3233
3337
|
this.creditBalances[contextStr] = balances;
|
|
3234
3338
|
}
|
|
3235
3339
|
}
|
|
3340
|
+
let revivedCreditSpendPolicies;
|
|
3341
|
+
if (entry.creditSpendPolicies !== void 0 && entry.creditSpendPolicies !== null) {
|
|
3342
|
+
const policies = CreditSpendPoliciesFromJSON(entry.creditSpendPolicies);
|
|
3343
|
+
if (policies.length > 0) {
|
|
3344
|
+
revivedCreditSpendPolicies = policies;
|
|
3345
|
+
this.creditSpendPolicies[contextStr] = policies;
|
|
3346
|
+
}
|
|
3347
|
+
}
|
|
3236
3348
|
fresh[contextStr] = {
|
|
3237
3349
|
checks: revivedChecks,
|
|
3238
3350
|
plan: revivedPlan,
|
|
3239
3351
|
creditBalances: revivedCreditBalances,
|
|
3352
|
+
creditSpendPolicies: revivedCreditSpendPolicies,
|
|
3240
3353
|
updatedAt: entry.updatedAt
|
|
3241
3354
|
};
|
|
3242
3355
|
contextsLoaded += 1;
|
|
@@ -3250,7 +3363,8 @@ var Schematic = class {
|
|
|
3250
3363
|
const checksForContext = this.checks[contextStr];
|
|
3251
3364
|
const planForContext = this.planChecks[contextStr];
|
|
3252
3365
|
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
3253
|
-
|
|
3366
|
+
const creditSpendPoliciesForContext = this.creditSpendPolicies[contextStr];
|
|
3367
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0 && creditSpendPoliciesForContext === void 0) {
|
|
3254
3368
|
return;
|
|
3255
3369
|
}
|
|
3256
3370
|
if (this.cachedFlagState === null) {
|
|
@@ -3269,6 +3383,7 @@ var Schematic = class {
|
|
|
3269
3383
|
checks: cleanChecks,
|
|
3270
3384
|
plan: planForContext,
|
|
3271
3385
|
creditBalances: creditBalancesForContext,
|
|
3386
|
+
creditSpendPolicies: creditSpendPoliciesForContext,
|
|
3272
3387
|
updatedAt: Date.now()
|
|
3273
3388
|
};
|
|
3274
3389
|
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
@@ -3285,6 +3400,9 @@ var Schematic = class {
|
|
|
3285
3400
|
for (const key of Object.keys(this.creditBalances)) {
|
|
3286
3401
|
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
3287
3402
|
}
|
|
3403
|
+
for (const key of Object.keys(this.creditSpendPolicies)) {
|
|
3404
|
+
if (!survivorKeys.has(key)) delete this.creditSpendPolicies[key];
|
|
3405
|
+
}
|
|
3288
3406
|
this.cachedFlagState = {
|
|
3289
3407
|
version: cacheVersion,
|
|
3290
3408
|
contexts: Object.fromEntries(survivors)
|
|
@@ -3879,6 +3997,18 @@ var Schematic = class {
|
|
|
3879
3997
|
const contextStr = contextString(this.context);
|
|
3880
3998
|
return this.creditBalances[contextStr]?.[creditId];
|
|
3881
3999
|
};
|
|
4000
|
+
/** Get every credit spend policy binding the current context, company-scope first */
|
|
4001
|
+
getCreditSpendPolicies = () => {
|
|
4002
|
+
const contextStr = contextString(this.context);
|
|
4003
|
+
return this.creditSpendPolicies[contextStr] ?? emptyCreditSpendPolicies;
|
|
4004
|
+
};
|
|
4005
|
+
/** Get the spend policies binding a single credit type in the current context */
|
|
4006
|
+
getCreditSpendPoliciesForCredit = (creditId) => {
|
|
4007
|
+
const policies = this.getCreditSpendPolicies().filter(
|
|
4008
|
+
(policy) => policy.creditId === creditId
|
|
4009
|
+
);
|
|
4010
|
+
return policies.length > 0 ? policies : emptyCreditSpendPolicies;
|
|
4011
|
+
};
|
|
3882
4012
|
// flag checks state
|
|
3883
4013
|
getFlagCheck = (flagKey) => {
|
|
3884
4014
|
const contextStr = contextString(this.context);
|
|
@@ -3945,6 +4075,13 @@ var Schematic = class {
|
|
|
3945
4075
|
this.creditBalanceListeners.delete(listener);
|
|
3946
4076
|
};
|
|
3947
4077
|
};
|
|
4078
|
+
/** Register an event listener that will be notified with the context's credit spend policies whenever the set changes */
|
|
4079
|
+
addCreditSpendPolicyListener = (listener) => {
|
|
4080
|
+
this.creditSpendPolicyListeners.add(listener);
|
|
4081
|
+
return () => {
|
|
4082
|
+
this.creditSpendPolicyListeners.delete(listener);
|
|
4083
|
+
};
|
|
4084
|
+
};
|
|
3948
4085
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
3949
4086
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
3950
4087
|
if (listeners.size > 0) {
|
|
@@ -4008,6 +4145,16 @@ var Schematic = class {
|
|
|
4008
4145
|
});
|
|
4009
4146
|
});
|
|
4010
4147
|
};
|
|
4148
|
+
notifyCreditSpendPolicyListeners = (value) => {
|
|
4149
|
+
const listeners = this.creditSpendPolicyListeners ?? [];
|
|
4150
|
+
listeners.forEach((listener) => {
|
|
4151
|
+
if (listener.length > 0) {
|
|
4152
|
+
listener(value);
|
|
4153
|
+
return;
|
|
4154
|
+
}
|
|
4155
|
+
listener();
|
|
4156
|
+
});
|
|
4157
|
+
};
|
|
4011
4158
|
notifyCreditBalanceListeners = (value) => {
|
|
4012
4159
|
const listeners = this.creditBalanceListeners ?? [];
|
|
4013
4160
|
if (listeners.size > 0) {
|
|
@@ -5030,7 +5177,7 @@ function staticSource(data) {
|
|
|
5030
5177
|
}
|
|
5031
5178
|
|
|
5032
5179
|
// src/version.ts
|
|
5033
|
-
var version2 = "1.
|
|
5180
|
+
var version2 = "1.10.0";
|
|
5034
5181
|
|
|
5035
5182
|
// src/context/schematic.tsx
|
|
5036
5183
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
@@ -5123,6 +5270,7 @@ var useSchematic = () => {
|
|
|
5123
5270
|
|
|
5124
5271
|
// src/hooks/schematic.ts
|
|
5125
5272
|
import { useMemo as useMemo6, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback2 } from "react";
|
|
5273
|
+
var emptyPolicies = [];
|
|
5126
5274
|
var useSchematicClient = (opts) => {
|
|
5127
5275
|
const schematic = useSchematic();
|
|
5128
5276
|
const { client } = opts ?? {};
|
|
@@ -5238,6 +5386,34 @@ var useSchematicCreditBalance = (creditId, opts) => {
|
|
|
5238
5386
|
[balance, isPending]
|
|
5239
5387
|
);
|
|
5240
5388
|
};
|
|
5389
|
+
var useSchematicCreditSpendPolicies = (opts) => {
|
|
5390
|
+
const client = useSchematicClient(opts);
|
|
5391
|
+
const subscribe = useCallback2(
|
|
5392
|
+
(callback) => client.addCreditSpendPolicyListener(callback),
|
|
5393
|
+
[client]
|
|
5394
|
+
);
|
|
5395
|
+
const policies = useSyncExternalStore2(
|
|
5396
|
+
subscribe,
|
|
5397
|
+
() => client.getCreditSpendPolicies(),
|
|
5398
|
+
() => emptyPolicies
|
|
5399
|
+
);
|
|
5400
|
+
const isPendingSubscribe = useCallback2(
|
|
5401
|
+
(callback) => client.addIsPendingListener(callback),
|
|
5402
|
+
[client]
|
|
5403
|
+
);
|
|
5404
|
+
const isPending = useSyncExternalStore2(
|
|
5405
|
+
isPendingSubscribe,
|
|
5406
|
+
() => client.getIsPending(),
|
|
5407
|
+
() => true
|
|
5408
|
+
);
|
|
5409
|
+
return useMemo6(
|
|
5410
|
+
() => ({
|
|
5411
|
+
policies,
|
|
5412
|
+
isLoading: policies.length === 0 && isPending
|
|
5413
|
+
}),
|
|
5414
|
+
[policies, isPending]
|
|
5415
|
+
);
|
|
5416
|
+
};
|
|
5241
5417
|
var useSchematicIsPending = (opts) => {
|
|
5242
5418
|
const client = useSchematicClient(opts);
|
|
5243
5419
|
const subscribe = useCallback2(
|
|
@@ -5269,6 +5445,7 @@ export {
|
|
|
5269
5445
|
useSchematic,
|
|
5270
5446
|
useSchematicContext,
|
|
5271
5447
|
useSchematicCreditBalance,
|
|
5448
|
+
useSchematicCreditSpendPolicies,
|
|
5272
5449
|
useSchematicEntitlement,
|
|
5273
5450
|
useSchematicEvents,
|
|
5274
5451
|
useSchematicFlag,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schematichq/schematic-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"main": "dist/schematic-react.cjs.js",
|
|
5
5
|
"module": "dist/schematic-react.esm.js",
|
|
6
6
|
"types": "dist/schematic-react.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@eslint/js": "^10.0.1",
|
|
36
36
|
"@microsoft/api-extractor": "^7.59.2",
|
|
37
|
-
"@schematichq/schematic-js": "^1.
|
|
37
|
+
"@schematichq/schematic-js": "^1.10.0",
|
|
38
38
|
"@testing-library/dom": "^10.4.2",
|
|
39
39
|
"@testing-library/jest-dom": "^7.0.1",
|
|
40
40
|
"@testing-library/react": "^16.3.3",
|