@schematichq/schematic-angular 1.6.0 → 1.7.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
CHANGED
|
@@ -376,6 +376,54 @@ export class CreditMeterComponent {
|
|
|
376
376
|
|
|
377
377
|
It switches to the new credit as the source emits. While the ID is `undefined`, it emits the client's loading state and a balance of `0`.
|
|
378
378
|
|
|
379
|
+
### Credit spend policies
|
|
380
|
+
|
|
381
|
+
Use `creditSpendPolicies$` to observe the spend limits that bind the current company and user. It emits over the DataStream, so a policy edited or deleted in the dashboard arrives without a refetch:
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { Component, inject } from "@angular/core";
|
|
385
|
+
import { AsyncPipe } from "@angular/common";
|
|
386
|
+
import { SchematicService } from "@schematichq/schematic-angular";
|
|
387
|
+
|
|
388
|
+
@Component({
|
|
389
|
+
selector: "app-spend-limits",
|
|
390
|
+
standalone: true,
|
|
391
|
+
imports: [AsyncPipe],
|
|
392
|
+
template: `
|
|
393
|
+
@if (spendPolicies$ | async; as spend) {
|
|
394
|
+
@if (spend.isLoading) {
|
|
395
|
+
<div>Loading…</div>
|
|
396
|
+
} @else {
|
|
397
|
+
<ul>
|
|
398
|
+
@for (policy of spend.policies; track policy.id) {
|
|
399
|
+
<li>
|
|
400
|
+
@if (policy.kind === "window" && policy.window) {
|
|
401
|
+
{{ policy.scope }} limit: {{ policy.consumed }} of {{ policy.limit }} credits used this {{ policy.window.unit }}
|
|
402
|
+
} @else {
|
|
403
|
+
{{ policy.scope }} limit: {{ policy.limit }} credits per request
|
|
404
|
+
}
|
|
405
|
+
</li>
|
|
406
|
+
}
|
|
407
|
+
</ul>
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
`,
|
|
411
|
+
})
|
|
412
|
+
export class SpendLimitsComponent {
|
|
413
|
+
private schematic = inject(SchematicService);
|
|
414
|
+
spendPolicies$ = this.schematic.creditSpendPolicies$();
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
`creditSpendPolicies$` emits an object with the following properties:
|
|
419
|
+
|
|
420
|
+
| Property | Type | Description |
|
|
421
|
+
| --- | --- | --- |
|
|
422
|
+
| `policies` | `CreditSpendPolicies` | Company-scope policies first, then the user's own; empty when none bind |
|
|
423
|
+
| `isLoading` | `boolean` | `true` while the policies are still loading and nothing has arrived yet |
|
|
424
|
+
|
|
425
|
+
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.
|
|
426
|
+
|
|
379
427
|
## API Reference
|
|
380
428
|
|
|
381
429
|
### `provideSchematic(config)`
|
|
@@ -396,6 +444,7 @@ Injectable service providing all Schematic functionality:
|
|
|
396
444
|
| `entitlement$(key, fallback?)` | `Observable<CheckFlagReturn>` | Observe detailed entitlement data |
|
|
397
445
|
| `plan$()` | `Observable<CheckPlanReturn \| undefined>` | Observe plan information |
|
|
398
446
|
| `creditBalance$(creditId)` | `Observable<SchematicCreditBalance>` | Observe a company's lease-aware credit balance. Takes a credit ID or an Observable of credit IDs |
|
|
447
|
+
| `creditSpendPolicies$()` | `Observable<SchematicCreditSpendPolicies>` | Observe the credit spend policies binding the current context |
|
|
399
448
|
| `isPending$()` | `Observable<boolean>` | Observe loading state |
|
|
400
449
|
|
|
401
450
|
### `SCHEMATIC_CLIENT`
|
|
@@ -1,212 +1,227 @@
|
|
|
1
|
-
import * as i0 from
|
|
2
|
-
import {
|
|
3
|
-
import * as SchematicJS from
|
|
4
|
-
|
|
5
|
-
import { Observable, distinctUntilChanged,
|
|
6
|
-
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { DestroyRef, Injectable, InjectionToken, inject, makeEnvironmentProviders } from "@angular/core";
|
|
3
|
+
import * as SchematicJS from "@schematichq/schematic-js";
|
|
4
|
+
import { RuleType, Schematic, TrialStatus, UsagePeriod } from "@schematichq/schematic-js";
|
|
5
|
+
import { Observable, distinctUntilChanged, finalize, isObservable, map, shareReplay, switchMap } from "rxjs";
|
|
7
6
|
const SCHEMATIC_CLIENT = new InjectionToken("SchematicClient");
|
|
8
|
-
|
|
9
7
|
function shallowEqual(a, b) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (valA instanceof Date && valB instanceof Date) {
|
|
22
|
-
return valA.getTime() === valB.getTime();
|
|
23
|
-
}
|
|
24
|
-
return valA === valB;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
class SchematicService {
|
|
28
|
-
client = inject(SCHEMATIC_CLIENT);
|
|
29
|
-
flagValueCache = new Map();
|
|
30
|
-
entitlementCache = new Map();
|
|
31
|
-
creditBalanceCache = new Map();
|
|
32
|
-
planCache;
|
|
33
|
-
isPendingCache;
|
|
34
|
-
getClient() {
|
|
35
|
-
return this.client;
|
|
36
|
-
}
|
|
37
|
-
setContext(context) {
|
|
38
|
-
this.client.setContext(context);
|
|
39
|
-
}
|
|
40
|
-
identify(body) {
|
|
41
|
-
this.client.identify(body);
|
|
42
|
-
}
|
|
43
|
-
track(body) {
|
|
44
|
-
this.client.track(body);
|
|
45
|
-
}
|
|
46
|
-
flagValue$(key, fallback = false) {
|
|
47
|
-
const cacheKey = `${key}:${fallback}`;
|
|
48
|
-
let cached = this.flagValueCache.get(cacheKey);
|
|
49
|
-
if (cached)
|
|
50
|
-
return cached;
|
|
51
|
-
cached = new Observable((subscriber) => {
|
|
52
|
-
const current = this.client.getFlagValue(key);
|
|
53
|
-
subscriber.next(current ?? fallback);
|
|
54
|
-
const unsubscribe = this.client.addFlagValueListener(key, () => {
|
|
55
|
-
const value = this.client.getFlagValue(key);
|
|
56
|
-
subscriber.next(value ?? fallback);
|
|
57
|
-
});
|
|
58
|
-
return () => unsubscribe();
|
|
59
|
-
}).pipe(distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }), finalize(() => this.flagValueCache.delete(cacheKey)));
|
|
60
|
-
this.flagValueCache.set(cacheKey, cached);
|
|
61
|
-
return cached;
|
|
62
|
-
}
|
|
63
|
-
entitlement$(key, fallback = false) {
|
|
64
|
-
const cacheKey = `${key}:${fallback}`;
|
|
65
|
-
let cached = this.entitlementCache.get(cacheKey);
|
|
66
|
-
if (cached)
|
|
67
|
-
return cached;
|
|
68
|
-
const fallbackCheck = {
|
|
69
|
-
flag: key,
|
|
70
|
-
reason: "Fallback",
|
|
71
|
-
value: fallback,
|
|
72
|
-
};
|
|
73
|
-
cached = new Observable((subscriber) => {
|
|
74
|
-
const current = this.client.getFlagCheck(key);
|
|
75
|
-
subscriber.next(current ?? fallbackCheck);
|
|
76
|
-
const unsubscribe = this.client.addFlagCheckListener(key, () => {
|
|
77
|
-
const check = this.client.getFlagCheck(key);
|
|
78
|
-
subscriber.next(check ?? fallbackCheck);
|
|
79
|
-
});
|
|
80
|
-
return () => unsubscribe();
|
|
81
|
-
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({ bufferSize: 1, refCount: true }), finalize(() => this.entitlementCache.delete(cacheKey)));
|
|
82
|
-
this.entitlementCache.set(cacheKey, cached);
|
|
83
|
-
return cached;
|
|
84
|
-
}
|
|
85
|
-
plan$() {
|
|
86
|
-
if (this.planCache)
|
|
87
|
-
return this.planCache;
|
|
88
|
-
this.planCache = new Observable((subscriber) => {
|
|
89
|
-
subscriber.next(this.client.getPlan());
|
|
90
|
-
const unsubscribe = this.client.addPlanListener(() => {
|
|
91
|
-
subscriber.next(this.client.getPlan());
|
|
92
|
-
});
|
|
93
|
-
return () => unsubscribe();
|
|
94
|
-
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({ bufferSize: 1, refCount: true }), finalize(() => {
|
|
95
|
-
this.planCache = undefined;
|
|
96
|
-
}));
|
|
97
|
-
return this.planCache;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Observe a company's live, lease-aware credit balance for a single credit type.
|
|
101
|
-
*
|
|
102
|
-
* Surfaces the spendable `settled` balance, sourced from the streamed credit
|
|
103
|
-
* balances map (keyed by credit ID). It emits as partials arrive over the
|
|
104
|
-
* DataStream, so it stays accurate during an open lease — when the raw
|
|
105
|
-
* `remaining` would otherwise read stale / falsely "exhausted".
|
|
106
|
-
*
|
|
107
|
-
* The credit ID is available on a feature's entitlement: `entitlement$(key)`
|
|
108
|
-
* emits `creditId` for credit-based features. Pass that stream straight in:
|
|
109
|
-
* this accepts an Observable of credit IDs as well as a plain one, switching
|
|
110
|
-
* to the new credit as the source emits. While the ID is undefined it emits
|
|
111
|
-
* the client's loading state and a balance of 0.
|
|
112
|
-
*/
|
|
113
|
-
creditBalance$(creditId) {
|
|
114
|
-
if (isObservable(creditId)) {
|
|
115
|
-
return creditId.pipe(distinctUntilChanged(), switchMap((id) => this.creditBalanceFor(id)), distinctUntilChanged(shallowEqual), shareReplay({ bufferSize: 1, refCount: true }));
|
|
116
|
-
}
|
|
117
|
-
return this.creditBalanceFor(creditId);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Emits a zeroed balance that still tracks the client's loading state, for
|
|
121
|
-
* when there is no credit ID to read (a check that has not arrived yet, or a
|
|
122
|
-
* feature that is not credit-based).
|
|
123
|
-
*/
|
|
124
|
-
noCreditBalance$() {
|
|
125
|
-
return this.isPending$().pipe(map((isLoading) => ({ balance: 0, isLoading })));
|
|
126
|
-
}
|
|
127
|
-
creditBalanceFor(creditId) {
|
|
128
|
-
if (creditId === undefined)
|
|
129
|
-
return this.noCreditBalance$();
|
|
130
|
-
let cached = this.creditBalanceCache.get(creditId);
|
|
131
|
-
if (cached)
|
|
132
|
-
return cached;
|
|
133
|
-
cached = new Observable((subscriber) => {
|
|
134
|
-
const emit = () => {
|
|
135
|
-
const balance = this.client.getCreditBalance(creditId);
|
|
136
|
-
subscriber.next({
|
|
137
|
-
balance: balance?.settled ?? 0,
|
|
138
|
-
isLoading: balance === undefined && this.client.getIsPending(),
|
|
139
|
-
});
|
|
140
|
-
};
|
|
141
|
-
emit();
|
|
142
|
-
const unsubscribeBalance = this.client.addCreditBalanceListener(() => emit());
|
|
143
|
-
const unsubscribePending = this.client.addIsPendingListener(() => emit());
|
|
144
|
-
return () => {
|
|
145
|
-
unsubscribeBalance();
|
|
146
|
-
unsubscribePending();
|
|
147
|
-
};
|
|
148
|
-
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({ bufferSize: 1, refCount: true }), finalize(() => this.creditBalanceCache.delete(creditId)));
|
|
149
|
-
this.creditBalanceCache.set(creditId, cached);
|
|
150
|
-
return cached;
|
|
151
|
-
}
|
|
152
|
-
isPending$() {
|
|
153
|
-
if (this.isPendingCache)
|
|
154
|
-
return this.isPendingCache;
|
|
155
|
-
this.isPendingCache = new Observable((subscriber) => {
|
|
156
|
-
subscriber.next(this.client.getIsPending());
|
|
157
|
-
const unsubscribe = this.client.addIsPendingListener(() => {
|
|
158
|
-
subscriber.next(this.client.getIsPending());
|
|
159
|
-
});
|
|
160
|
-
return () => unsubscribe();
|
|
161
|
-
}).pipe(distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }), finalize(() => {
|
|
162
|
-
this.isPendingCache = undefined;
|
|
163
|
-
}));
|
|
164
|
-
return this.isPendingCache;
|
|
165
|
-
}
|
|
166
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SchematicService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
167
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: SchematicService });
|
|
8
|
+
if (a === b) return true;
|
|
9
|
+
if (!a || !b) return false;
|
|
10
|
+
const keysA = Object.keys(a);
|
|
11
|
+
const keysB = Object.keys(b);
|
|
12
|
+
if (keysA.length !== keysB.length) return false;
|
|
13
|
+
return keysA.every((key) => {
|
|
14
|
+
const valA = a[key];
|
|
15
|
+
const valB = b[key];
|
|
16
|
+
if (valA instanceof Date && valB instanceof Date) return valA.getTime() === valB.getTime();
|
|
17
|
+
return valA === valB;
|
|
18
|
+
});
|
|
168
19
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
20
|
+
var SchematicService = class SchematicService {
|
|
21
|
+
client = inject(SCHEMATIC_CLIENT);
|
|
22
|
+
flagValueCache = /* @__PURE__ */ new Map();
|
|
23
|
+
entitlementCache = /* @__PURE__ */ new Map();
|
|
24
|
+
creditBalanceCache = /* @__PURE__ */ new Map();
|
|
25
|
+
creditSpendPoliciesCache;
|
|
26
|
+
planCache;
|
|
27
|
+
isPendingCache;
|
|
28
|
+
getClient() {
|
|
29
|
+
return this.client;
|
|
30
|
+
}
|
|
31
|
+
setContext(context) {
|
|
32
|
+
this.client.setContext(context);
|
|
33
|
+
}
|
|
34
|
+
identify(body) {
|
|
35
|
+
this.client.identify(body);
|
|
36
|
+
}
|
|
37
|
+
track(body) {
|
|
38
|
+
this.client.track(body);
|
|
39
|
+
}
|
|
40
|
+
flagValue$(key, fallback = false) {
|
|
41
|
+
const cacheKey = `${key}:${fallback}`;
|
|
42
|
+
let cached = this.flagValueCache.get(cacheKey);
|
|
43
|
+
if (cached) return cached;
|
|
44
|
+
cached = new Observable((subscriber) => {
|
|
45
|
+
const current = this.client.getFlagValue(key);
|
|
46
|
+
subscriber.next(current ?? fallback);
|
|
47
|
+
const unsubscribe = this.client.addFlagValueListener(key, () => {
|
|
48
|
+
const value = this.client.getFlagValue(key);
|
|
49
|
+
subscriber.next(value ?? fallback);
|
|
50
|
+
});
|
|
51
|
+
return () => unsubscribe();
|
|
52
|
+
}).pipe(distinctUntilChanged(), shareReplay({
|
|
53
|
+
bufferSize: 1,
|
|
54
|
+
refCount: true
|
|
55
|
+
}), finalize(() => this.flagValueCache.delete(cacheKey)));
|
|
56
|
+
this.flagValueCache.set(cacheKey, cached);
|
|
57
|
+
return cached;
|
|
58
|
+
}
|
|
59
|
+
entitlement$(key, fallback = false) {
|
|
60
|
+
const cacheKey = `${key}:${fallback}`;
|
|
61
|
+
let cached = this.entitlementCache.get(cacheKey);
|
|
62
|
+
if (cached) return cached;
|
|
63
|
+
const fallbackCheck = {
|
|
64
|
+
flag: key,
|
|
65
|
+
reason: "Fallback",
|
|
66
|
+
value: fallback
|
|
67
|
+
};
|
|
68
|
+
cached = new Observable((subscriber) => {
|
|
69
|
+
const current = this.client.getFlagCheck(key);
|
|
70
|
+
subscriber.next(current ?? fallbackCheck);
|
|
71
|
+
const unsubscribe = this.client.addFlagCheckListener(key, () => {
|
|
72
|
+
const check = this.client.getFlagCheck(key);
|
|
73
|
+
subscriber.next(check ?? fallbackCheck);
|
|
74
|
+
});
|
|
75
|
+
return () => unsubscribe();
|
|
76
|
+
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({
|
|
77
|
+
bufferSize: 1,
|
|
78
|
+
refCount: true
|
|
79
|
+
}), finalize(() => this.entitlementCache.delete(cacheKey)));
|
|
80
|
+
this.entitlementCache.set(cacheKey, cached);
|
|
81
|
+
return cached;
|
|
82
|
+
}
|
|
83
|
+
plan$() {
|
|
84
|
+
if (this.planCache) return this.planCache;
|
|
85
|
+
this.planCache = new Observable((subscriber) => {
|
|
86
|
+
subscriber.next(this.client.getPlan());
|
|
87
|
+
const unsubscribe = this.client.addPlanListener(() => {
|
|
88
|
+
subscriber.next(this.client.getPlan());
|
|
89
|
+
});
|
|
90
|
+
return () => unsubscribe();
|
|
91
|
+
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({
|
|
92
|
+
bufferSize: 1,
|
|
93
|
+
refCount: true
|
|
94
|
+
}), finalize(() => {
|
|
95
|
+
this.planCache = void 0;
|
|
96
|
+
}));
|
|
97
|
+
return this.planCache;
|
|
98
|
+
}
|
|
99
|
+
creditBalance$(creditId) {
|
|
100
|
+
if (isObservable(creditId)) return creditId.pipe(distinctUntilChanged(), switchMap((id) => this.creditBalanceFor(id)), distinctUntilChanged(shallowEqual), shareReplay({
|
|
101
|
+
bufferSize: 1,
|
|
102
|
+
refCount: true
|
|
103
|
+
}));
|
|
104
|
+
return this.creditBalanceFor(creditId);
|
|
105
|
+
}
|
|
106
|
+
noCreditBalance$() {
|
|
107
|
+
return this.isPending$().pipe(map((isLoading) => ({
|
|
108
|
+
balance: 0,
|
|
109
|
+
isLoading
|
|
110
|
+
})));
|
|
111
|
+
}
|
|
112
|
+
creditBalanceFor(creditId) {
|
|
113
|
+
if (creditId === void 0) return this.noCreditBalance$();
|
|
114
|
+
let cached = this.creditBalanceCache.get(creditId);
|
|
115
|
+
if (cached) return cached;
|
|
116
|
+
cached = new Observable((subscriber) => {
|
|
117
|
+
const emit = () => {
|
|
118
|
+
const balance = this.client.getCreditBalance(creditId);
|
|
119
|
+
subscriber.next({
|
|
120
|
+
balance: balance?.settled ?? 0,
|
|
121
|
+
isLoading: balance === void 0 && this.client.getIsPending()
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
emit();
|
|
125
|
+
const unsubscribeBalance = this.client.addCreditBalanceListener(() => emit());
|
|
126
|
+
const unsubscribePending = this.client.addIsPendingListener(() => emit());
|
|
127
|
+
return () => {
|
|
128
|
+
unsubscribeBalance();
|
|
129
|
+
unsubscribePending();
|
|
130
|
+
};
|
|
131
|
+
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({
|
|
132
|
+
bufferSize: 1,
|
|
133
|
+
refCount: true
|
|
134
|
+
}), finalize(() => this.creditBalanceCache.delete(creditId)));
|
|
135
|
+
this.creditBalanceCache.set(creditId, cached);
|
|
136
|
+
return cached;
|
|
137
|
+
}
|
|
138
|
+
creditSpendPolicies$() {
|
|
139
|
+
if (this.creditSpendPoliciesCache) return this.creditSpendPoliciesCache;
|
|
140
|
+
this.creditSpendPoliciesCache = new Observable((subscriber) => {
|
|
141
|
+
const emit = () => {
|
|
142
|
+
const policies = this.client.getCreditSpendPolicies();
|
|
143
|
+
subscriber.next({
|
|
144
|
+
policies,
|
|
145
|
+
isLoading: policies.length === 0 && this.client.getIsPending()
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
emit();
|
|
149
|
+
const unsubscribePolicies = this.client.addCreditSpendPolicyListener(() => emit());
|
|
150
|
+
const unsubscribePending = this.client.addIsPendingListener(() => emit());
|
|
151
|
+
return () => {
|
|
152
|
+
unsubscribePolicies();
|
|
153
|
+
unsubscribePending();
|
|
154
|
+
};
|
|
155
|
+
}).pipe(distinctUntilChanged(shallowEqual), shareReplay({
|
|
156
|
+
bufferSize: 1,
|
|
157
|
+
refCount: true
|
|
158
|
+
}), finalize(() => {
|
|
159
|
+
this.creditSpendPoliciesCache = void 0;
|
|
160
|
+
}));
|
|
161
|
+
return this.creditSpendPoliciesCache;
|
|
162
|
+
}
|
|
163
|
+
isPending$() {
|
|
164
|
+
if (this.isPendingCache) return this.isPendingCache;
|
|
165
|
+
this.isPendingCache = new Observable((subscriber) => {
|
|
166
|
+
subscriber.next(this.client.getIsPending());
|
|
167
|
+
const unsubscribe = this.client.addIsPendingListener(() => {
|
|
168
|
+
subscriber.next(this.client.getIsPending());
|
|
169
|
+
});
|
|
170
|
+
return () => unsubscribe();
|
|
171
|
+
}).pipe(distinctUntilChanged(), shareReplay({
|
|
172
|
+
bufferSize: 1,
|
|
173
|
+
refCount: true
|
|
174
|
+
}), finalize(() => {
|
|
175
|
+
this.isPendingCache = void 0;
|
|
176
|
+
}));
|
|
177
|
+
return this.isPendingCache;
|
|
178
|
+
}
|
|
179
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
180
|
+
minVersion: "12.0.0",
|
|
181
|
+
version: "22.2.0",
|
|
182
|
+
ngImport: i0,
|
|
183
|
+
type: SchematicService,
|
|
184
|
+
deps: [],
|
|
185
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
186
|
+
});
|
|
187
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
188
|
+
minVersion: "12.0.0",
|
|
189
|
+
version: "22.2.0",
|
|
190
|
+
ngImport: i0,
|
|
191
|
+
type: SchematicService
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
195
|
+
minVersion: "12.0.0",
|
|
196
|
+
version: "22.2.0",
|
|
197
|
+
ngImport: i0,
|
|
198
|
+
type: SchematicService,
|
|
199
|
+
decorators: [{ type: Injectable }]
|
|
200
|
+
});
|
|
201
|
+
const version = "1.7.0";
|
|
175
202
|
function provideSchematic(config) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
return client;
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
SchematicService,
|
|
204
|
-
]);
|
|
203
|
+
const { client: providedClient, publishableKey, additionalHeaders, ...restOpts } = config;
|
|
204
|
+
return makeEnvironmentProviders([{
|
|
205
|
+
provide: SCHEMATIC_CLIENT,
|
|
206
|
+
useFactory: () => {
|
|
207
|
+
const isProvidedClient = !!providedClient;
|
|
208
|
+
const client = isProvidedClient ? providedClient : new SchematicJS.Schematic(publishableKey, {
|
|
209
|
+
...restOpts,
|
|
210
|
+
useWebSocket: true,
|
|
211
|
+
additionalHeaders: {
|
|
212
|
+
"X-Schematic-Client-Version": `schematic-angular@${version}`,
|
|
213
|
+
...additionalHeaders
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
inject(DestroyRef).onDestroy(() => {
|
|
217
|
+
if (!isProvidedClient) client.cleanup().catch((error) => {
|
|
218
|
+
console.error("Error during Schematic cleanup:", error);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
return client;
|
|
222
|
+
}
|
|
223
|
+
}, SchematicService]);
|
|
205
224
|
}
|
|
225
|
+
export { RuleType, SCHEMATIC_CLIENT, Schematic, SchematicService, TrialStatus, UsagePeriod, provideSchematic };
|
|
206
226
|
|
|
207
|
-
|
|
208
|
-
* Generated bundle index. Do not edit.
|
|
209
|
-
*/
|
|
210
|
-
|
|
211
|
-
export { SCHEMATIC_CLIENT, SchematicService, provideSchematic };
|
|
212
|
-
//# sourceMappingURL=schematichq-schematic-angular.mjs.map
|
|
227
|
+
//# sourceMappingURL=schematichq-schematic-angular.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schematichq-schematic-angular.mjs","sources":["../../src/token.ts","../../src/schematic.service.ts","../../src/version.ts","../../src/provide.ts","../../src/schematichq-schematic-angular.ts"],"sourcesContent":["import { InjectionToken } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\n\nexport const SCHEMATIC_CLIENT = new InjectionToken<SchematicJS.Schematic>(\n \"SchematicClient\",\n);\n","import { Injectable, inject } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\nimport {\n Observable,\n distinctUntilChanged,\n finalize,\n isObservable,\n map,\n shareReplay,\n switchMap,\n} from \"rxjs\";\nimport { SCHEMATIC_CLIENT } from \"./token\";\n\n/** A company's credit balance for a single credit type, plus a loading flag */\nexport type SchematicCreditBalance = {\n /** The spendable balance; 0 while loading or when the company holds no balance in this credit */\n balance: number;\n /** True while the balance is still loading and no value has arrived yet */\n isLoading: boolean;\n};\n\nfunction shallowEqual<T extends Record<string, unknown>>(\n a: T | undefined,\n b: T | undefined,\n): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n return keysA.every((key) => {\n const valA = a[key];\n const valB = b[key];\n if (valA instanceof Date && valB instanceof Date) {\n return valA.getTime() === valB.getTime();\n }\n return valA === valB;\n });\n}\n\n@Injectable()\nexport class SchematicService {\n private client = inject(SCHEMATIC_CLIENT);\n\n private flagValueCache = new Map<string, Observable<boolean>>();\n private entitlementCache = new Map<\n string,\n Observable<SchematicJS.CheckFlagReturn>\n >();\n private creditBalanceCache = new Map<\n string,\n Observable<SchematicCreditBalance>\n >();\n private planCache?: Observable<SchematicJS.CheckPlanReturn | undefined>;\n private isPendingCache?: Observable<boolean>;\n\n getClient(): SchematicJS.Schematic {\n return this.client;\n }\n\n setContext(context: SchematicJS.SchematicContext): void {\n this.client.setContext(context);\n }\n\n identify(body: SchematicJS.EventBodyIdentify): void {\n this.client.identify(body);\n }\n\n track(body: SchematicJS.EventBodyTrack): void {\n this.client.track(body);\n }\n\n flagValue$(key: string, fallback: boolean = false): Observable<boolean> {\n const cacheKey = `${key}:${fallback}`;\n let cached = this.flagValueCache.get(cacheKey);\n if (cached) return cached;\n\n cached = new Observable<boolean>((subscriber) => {\n const current = this.client.getFlagValue(key);\n subscriber.next(current ?? fallback);\n\n const unsubscribe = this.client.addFlagValueListener(key, () => {\n const value = this.client.getFlagValue(key);\n subscriber.next(value ?? fallback);\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.flagValueCache.delete(cacheKey)),\n );\n\n this.flagValueCache.set(cacheKey, cached);\n return cached;\n }\n\n entitlement$(\n key: string,\n fallback: boolean = false,\n ): Observable<SchematicJS.CheckFlagReturn> {\n const cacheKey = `${key}:${fallback}`;\n let cached = this.entitlementCache.get(cacheKey);\n if (cached) return cached;\n\n const fallbackCheck: SchematicJS.CheckFlagReturn = {\n flag: key,\n reason: \"Fallback\",\n value: fallback,\n };\n\n cached = new Observable<SchematicJS.CheckFlagReturn>((subscriber) => {\n const current = this.client.getFlagCheck(key);\n subscriber.next(current ?? fallbackCheck);\n\n const unsubscribe = this.client.addFlagCheckListener(key, () => {\n const check = this.client.getFlagCheck(key);\n subscriber.next(check ?? fallbackCheck);\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.entitlementCache.delete(cacheKey)),\n );\n\n this.entitlementCache.set(cacheKey, cached);\n return cached;\n }\n\n plan$(): Observable<SchematicJS.CheckPlanReturn | undefined> {\n if (this.planCache) return this.planCache;\n\n this.planCache = new Observable<SchematicJS.CheckPlanReturn | undefined>(\n (subscriber) => {\n subscriber.next(this.client.getPlan());\n\n const unsubscribe = this.client.addPlanListener(() => {\n subscriber.next(this.client.getPlan());\n });\n\n return () => unsubscribe();\n },\n ).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => {\n this.planCache = undefined;\n }),\n );\n\n return this.planCache;\n }\n\n /**\n * Observe a company's live, lease-aware credit balance for a single credit type.\n *\n * Surfaces the spendable `settled` balance, sourced from the streamed credit\n * balances map (keyed by credit ID). It emits as partials arrive over the\n * DataStream, so it stays accurate during an open lease — when the raw\n * `remaining` would otherwise read stale / falsely \"exhausted\".\n *\n * The credit ID is available on a feature's entitlement: `entitlement$(key)`\n * emits `creditId` for credit-based features. Pass that stream straight in:\n * this accepts an Observable of credit IDs as well as a plain one, switching\n * to the new credit as the source emits. While the ID is undefined it emits\n * the client's loading state and a balance of 0.\n */\n creditBalance$(\n creditId: string | undefined | Observable<string | undefined>,\n ): Observable<SchematicCreditBalance> {\n if (isObservable(creditId)) {\n return creditId.pipe(\n distinctUntilChanged(),\n switchMap((id) => this.creditBalanceFor(id)),\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n }\n\n return this.creditBalanceFor(creditId);\n }\n\n /**\n * Emits a zeroed balance that still tracks the client's loading state, for\n * when there is no credit ID to read (a check that has not arrived yet, or a\n * feature that is not credit-based).\n */\n private noCreditBalance$(): Observable<SchematicCreditBalance> {\n return this.isPending$().pipe(\n map((isLoading) => ({ balance: 0, isLoading })),\n );\n }\n\n private creditBalanceFor(\n creditId: string | undefined,\n ): Observable<SchematicCreditBalance> {\n if (creditId === undefined) return this.noCreditBalance$();\n\n let cached = this.creditBalanceCache.get(creditId);\n if (cached) return cached;\n\n cached = new Observable<SchematicCreditBalance>((subscriber) => {\n const emit = () => {\n const balance = this.client.getCreditBalance(creditId);\n subscriber.next({\n balance: balance?.settled ?? 0,\n isLoading: balance === undefined && this.client.getIsPending(),\n });\n };\n\n emit();\n\n const unsubscribeBalance = this.client.addCreditBalanceListener(() =>\n emit(),\n );\n const unsubscribePending = this.client.addIsPendingListener(() => emit());\n\n return () => {\n unsubscribeBalance();\n unsubscribePending();\n };\n }).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.creditBalanceCache.delete(creditId)),\n );\n\n this.creditBalanceCache.set(creditId, cached);\n return cached;\n }\n\n isPending$(): Observable<boolean> {\n if (this.isPendingCache) return this.isPendingCache;\n\n this.isPendingCache = new Observable<boolean>((subscriber) => {\n subscriber.next(this.client.getIsPending());\n\n const unsubscribe = this.client.addIsPendingListener(() => {\n subscriber.next(this.client.getIsPending());\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => {\n this.isPendingCache = undefined;\n }),\n );\n\n return this.isPendingCache;\n }\n}\n","export const version = \"1.6.0\";\n","import { DestroyRef, inject, makeEnvironmentProviders } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\n\nimport { SchematicService } from \"./schematic.service\";\nimport { SCHEMATIC_CLIENT } from \"./token\";\nimport { version } from \"./version\";\n\ntype BaseSchematicConfig = Omit<SchematicJS.SchematicOptions, \"useWebSocket\">;\n\ntype SchematicConfigWithClient = BaseSchematicConfig & {\n client: SchematicJS.Schematic;\n publishableKey?: never;\n};\n\ntype SchematicConfigWithKey = BaseSchematicConfig & {\n client?: never;\n publishableKey: string;\n};\n\nexport type SchematicConfig =\n SchematicConfigWithClient | SchematicConfigWithKey;\n\nexport function provideSchematic(config: SchematicConfig) {\n const {\n client: providedClient,\n publishableKey,\n additionalHeaders,\n ...restOpts\n } = config;\n\n return makeEnvironmentProviders([\n {\n provide: SCHEMATIC_CLIENT,\n useFactory: () => {\n const isProvidedClient = !!providedClient;\n\n const client = isProvidedClient\n ? providedClient\n : new SchematicJS.Schematic(publishableKey!, {\n ...restOpts,\n useWebSocket: true,\n additionalHeaders: {\n \"X-Schematic-Client-Version\": `schematic-angular@${version}`,\n ...additionalHeaders,\n },\n });\n\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(() => {\n if (!isProvidedClient) {\n client.cleanup().catch((error: unknown) => {\n console.error(\"Error during Schematic cleanup:\", error);\n });\n }\n });\n\n return client;\n },\n },\n SchematicService,\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schematichq-schematic-angular.mjs","names":[],"sources":["../../src/token.ts","../../src/schematic.service.ts","../../src/version.ts","../../src/provide.ts"],"sourcesContent":["import { InjectionToken } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\n\nexport const SCHEMATIC_CLIENT = new InjectionToken<SchematicJS.Schematic>(\n \"SchematicClient\",\n);\n","import { Injectable, inject } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\nimport {\n Observable,\n distinctUntilChanged,\n finalize,\n isObservable,\n map,\n shareReplay,\n switchMap,\n} from \"rxjs\";\nimport { SCHEMATIC_CLIENT } from \"./token\";\n\n/** A company's credit balance for a single credit type, plus a loading flag */\nexport type SchematicCreditBalance = {\n /** The spendable balance; 0 while loading or when the company holds no balance in this credit */\n balance: number;\n /** True while the balance is still loading and no value has arrived yet */\n isLoading: boolean;\n};\n\n/** The credit spend policies binding the current context, plus a loading flag */\nexport type SchematicCreditSpendPolicies = {\n /** Company-scope policies first, then the user's own; empty when none bind */\n policies: SchematicJS.CreditSpendPolicies;\n /** True while the policies are still loading and nothing has arrived yet */\n isLoading: boolean;\n};\n\nfunction shallowEqual<T extends Record<string, unknown>>(\n a: T | undefined,\n b: T | undefined,\n): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n return keysA.every((key) => {\n const valA = a[key];\n const valB = b[key];\n if (valA instanceof Date && valB instanceof Date) {\n return valA.getTime() === valB.getTime();\n }\n return valA === valB;\n });\n}\n\n@Injectable()\nexport class SchematicService {\n private client = inject(SCHEMATIC_CLIENT);\n\n private flagValueCache = new Map<string, Observable<boolean>>();\n private entitlementCache = new Map<\n string,\n Observable<SchematicJS.CheckFlagReturn>\n >();\n private creditBalanceCache = new Map<\n string,\n Observable<SchematicCreditBalance>\n >();\n private creditSpendPoliciesCache?: Observable<SchematicCreditSpendPolicies>;\n private planCache?: Observable<SchematicJS.CheckPlanReturn | undefined>;\n private isPendingCache?: Observable<boolean>;\n\n getClient(): SchematicJS.Schematic {\n return this.client;\n }\n\n setContext(context: SchematicJS.SchematicContext): void {\n this.client.setContext(context);\n }\n\n identify(body: SchematicJS.EventBodyIdentify): void {\n this.client.identify(body);\n }\n\n track(body: SchematicJS.EventBodyTrack): void {\n this.client.track(body);\n }\n\n flagValue$(key: string, fallback: boolean = false): Observable<boolean> {\n const cacheKey = `${key}:${fallback}`;\n let cached = this.flagValueCache.get(cacheKey);\n if (cached) return cached;\n\n cached = new Observable<boolean>((subscriber) => {\n const current = this.client.getFlagValue(key);\n subscriber.next(current ?? fallback);\n\n const unsubscribe = this.client.addFlagValueListener(key, () => {\n const value = this.client.getFlagValue(key);\n subscriber.next(value ?? fallback);\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.flagValueCache.delete(cacheKey)),\n );\n\n this.flagValueCache.set(cacheKey, cached);\n return cached;\n }\n\n entitlement$(\n key: string,\n fallback: boolean = false,\n ): Observable<SchematicJS.CheckFlagReturn> {\n const cacheKey = `${key}:${fallback}`;\n let cached = this.entitlementCache.get(cacheKey);\n if (cached) return cached;\n\n const fallbackCheck: SchematicJS.CheckFlagReturn = {\n flag: key,\n reason: \"Fallback\",\n value: fallback,\n };\n\n cached = new Observable<SchematicJS.CheckFlagReturn>((subscriber) => {\n const current = this.client.getFlagCheck(key);\n subscriber.next(current ?? fallbackCheck);\n\n const unsubscribe = this.client.addFlagCheckListener(key, () => {\n const check = this.client.getFlagCheck(key);\n subscriber.next(check ?? fallbackCheck);\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.entitlementCache.delete(cacheKey)),\n );\n\n this.entitlementCache.set(cacheKey, cached);\n return cached;\n }\n\n plan$(): Observable<SchematicJS.CheckPlanReturn | undefined> {\n if (this.planCache) return this.planCache;\n\n this.planCache = new Observable<SchematicJS.CheckPlanReturn | undefined>(\n (subscriber) => {\n subscriber.next(this.client.getPlan());\n\n const unsubscribe = this.client.addPlanListener(() => {\n subscriber.next(this.client.getPlan());\n });\n\n return () => unsubscribe();\n },\n ).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => {\n this.planCache = undefined;\n }),\n );\n\n return this.planCache;\n }\n\n /**\n * Observe a company's live, lease-aware credit balance for a single credit type.\n *\n * Surfaces the spendable `settled` balance, sourced from the streamed credit\n * balances map (keyed by credit ID). It emits as partials arrive over the\n * DataStream, so it stays accurate during an open lease — when the raw\n * `remaining` would otherwise read stale / falsely \"exhausted\".\n *\n * The credit ID is available on a feature's entitlement: `entitlement$(key)`\n * emits `creditId` for credit-based features. Pass that stream straight in:\n * this accepts an Observable of credit IDs as well as a plain one, switching\n * to the new credit as the source emits. While the ID is undefined it emits\n * the client's loading state and a balance of 0.\n */\n creditBalance$(\n creditId: string | undefined | Observable<string | undefined>,\n ): Observable<SchematicCreditBalance> {\n if (isObservable(creditId)) {\n return creditId.pipe(\n distinctUntilChanged(),\n switchMap((id) => this.creditBalanceFor(id)),\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n );\n }\n\n return this.creditBalanceFor(creditId);\n }\n\n /**\n * Emits a zeroed balance that still tracks the client's loading state, for\n * when there is no credit ID to read (a check that has not arrived yet, or a\n * feature that is not credit-based).\n */\n private noCreditBalance$(): Observable<SchematicCreditBalance> {\n return this.isPending$().pipe(\n map((isLoading) => ({ balance: 0, isLoading })),\n );\n }\n\n private creditBalanceFor(\n creditId: string | undefined,\n ): Observable<SchematicCreditBalance> {\n if (creditId === undefined) return this.noCreditBalance$();\n\n let cached = this.creditBalanceCache.get(creditId);\n if (cached) return cached;\n\n cached = new Observable<SchematicCreditBalance>((subscriber) => {\n const emit = () => {\n const balance = this.client.getCreditBalance(creditId);\n subscriber.next({\n balance: balance?.settled ?? 0,\n isLoading: balance === undefined && this.client.getIsPending(),\n });\n };\n\n emit();\n\n const unsubscribeBalance = this.client.addCreditBalanceListener(() =>\n emit(),\n );\n const unsubscribePending = this.client.addIsPendingListener(() => emit());\n\n return () => {\n unsubscribeBalance();\n unsubscribePending();\n };\n }).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => this.creditBalanceCache.delete(creditId)),\n );\n\n this.creditBalanceCache.set(creditId, cached);\n return cached;\n }\n\n /**\n * Observe every credit spend policy binding the current context, company-scope\n * first. It emits as partials arrive over the DataStream, so a policy edited\n * or deleted in the dashboard arrives without a refetch. A window policy also\n * carries `consumed` and `resetsAt`, which move as credits are spent.\n */\n creditSpendPolicies$(): Observable<SchematicCreditSpendPolicies> {\n if (this.creditSpendPoliciesCache) return this.creditSpendPoliciesCache;\n\n this.creditSpendPoliciesCache =\n new Observable<SchematicCreditSpendPolicies>((subscriber) => {\n const emit = () => {\n const policies = this.client.getCreditSpendPolicies();\n subscriber.next({\n policies,\n isLoading: policies.length === 0 && this.client.getIsPending(),\n });\n };\n\n emit();\n\n const unsubscribePolicies = this.client.addCreditSpendPolicyListener(\n () => emit(),\n );\n const unsubscribePending = this.client.addIsPendingListener(() =>\n emit(),\n );\n\n return () => {\n unsubscribePolicies();\n unsubscribePending();\n };\n }).pipe(\n distinctUntilChanged(shallowEqual),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => {\n this.creditSpendPoliciesCache = undefined;\n }),\n );\n\n return this.creditSpendPoliciesCache;\n }\n\n isPending$(): Observable<boolean> {\n if (this.isPendingCache) return this.isPendingCache;\n\n this.isPendingCache = new Observable<boolean>((subscriber) => {\n subscriber.next(this.client.getIsPending());\n\n const unsubscribe = this.client.addIsPendingListener(() => {\n subscriber.next(this.client.getIsPending());\n });\n\n return () => unsubscribe();\n }).pipe(\n distinctUntilChanged(),\n shareReplay({ bufferSize: 1, refCount: true }),\n finalize(() => {\n this.isPendingCache = undefined;\n }),\n );\n\n return this.isPendingCache;\n }\n}\n","export const version = \"1.7.0\";\n","import { DestroyRef, inject, makeEnvironmentProviders } from \"@angular/core\";\nimport * as SchematicJS from \"@schematichq/schematic-js\";\n\nimport { SchematicService } from \"./schematic.service\";\nimport { SCHEMATIC_CLIENT } from \"./token\";\nimport { version } from \"./version\";\n\ntype BaseSchematicConfig = Omit<SchematicJS.SchematicOptions, \"useWebSocket\">;\n\ntype SchematicConfigWithClient = BaseSchematicConfig & {\n client: SchematicJS.Schematic;\n publishableKey?: never;\n};\n\ntype SchematicConfigWithKey = BaseSchematicConfig & {\n client?: never;\n publishableKey: string;\n};\n\nexport type SchematicConfig =\n SchematicConfigWithClient | SchematicConfigWithKey;\n\nexport function provideSchematic(config: SchematicConfig) {\n const {\n client: providedClient,\n publishableKey,\n additionalHeaders,\n ...restOpts\n } = config;\n\n return makeEnvironmentProviders([\n {\n provide: SCHEMATIC_CLIENT,\n useFactory: () => {\n const isProvidedClient = !!providedClient;\n\n const client = isProvidedClient\n ? providedClient\n : new SchematicJS.Schematic(publishableKey!, {\n ...restOpts,\n useWebSocket: true,\n additionalHeaders: {\n \"X-Schematic-Client-Version\": `schematic-angular@${version}`,\n ...additionalHeaders,\n },\n });\n\n const destroyRef = inject(DestroyRef);\n destroyRef.onDestroy(() => {\n if (!isProvidedClient) {\n client.cleanup().catch((error: unknown) => {\n console.error(\"Error during Schematic cleanup:\", error);\n });\n }\n });\n\n return client;\n },\n },\n SchematicService,\n ]);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schematichq/schematic-angular",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"author": "Schematic <engineering@schematichq.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"url": "git+ssh://git@github.com/SchematicHQ/schematic-js.git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@schematichq/schematic-js": "^1.
|
|
11
|
+
"@schematichq/schematic-js": "^1.10.0",
|
|
12
12
|
"tslib": "^2.3.0"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
@@ -1,70 +1,80 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
3
|
-
import * as
|
|
4
|
-
|
|
5
|
-
import { Observable } from
|
|
6
|
-
|
|
1
|
+
import * as SchematicJS from "@schematichq/schematic-js";
|
|
2
|
+
import { CheckFlagReturn, CheckPlanReturn, CompanyCreditBalance, CreditBalance, CreditBalances, CreditSpendPolicies, CreditSpendPolicy, CreditSpendPolicyKind, CreditSpendPolicyScope, CreditSpendWindow, Event, EventBody, EventBodyIdentify, EventBodyTrack, EventType, Keys, RuleType, Schematic, SchematicContext, SchematicOptions, StoragePersister, Traits, TrialStatus, UsagePeriod, WarningTier } from "@schematichq/schematic-js";
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import { InjectionToken } from "@angular/core";
|
|
5
|
+
import { Observable } from "rxjs";
|
|
7
6
|
type BaseSchematicConfig = Omit<SchematicJS.SchematicOptions, "useWebSocket">;
|
|
8
7
|
type SchematicConfigWithClient = BaseSchematicConfig & {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
client: SchematicJS.Schematic;
|
|
9
|
+
publishableKey?: never;
|
|
11
10
|
};
|
|
12
11
|
type SchematicConfigWithKey = BaseSchematicConfig & {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
client?: never;
|
|
13
|
+
publishableKey: string;
|
|
15
14
|
};
|
|
16
15
|
type SchematicConfig = SchematicConfigWithClient | SchematicConfigWithKey;
|
|
17
|
-
declare function provideSchematic(config: SchematicConfig):
|
|
18
|
-
|
|
19
|
-
declare const SCHEMATIC_CLIENT: InjectionToken<SchematicJS.Schematic>;
|
|
20
|
-
|
|
16
|
+
export declare function provideSchematic(config: SchematicConfig): import("@angular/core").EnvironmentProviders;
|
|
17
|
+
export declare const SCHEMATIC_CLIENT: InjectionToken<SchematicJS.Schematic>;
|
|
21
18
|
/** A company's credit balance for a single credit type, plus a loading flag */
|
|
22
19
|
type SchematicCreditBalance = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
/** The spendable balance; 0 while loading or when the company holds no balance in this credit */
|
|
21
|
+
balance: number;
|
|
22
|
+
/** True while the balance is still loading and no value has arrived yet */
|
|
23
|
+
isLoading: boolean;
|
|
27
24
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
25
|
+
/** The credit spend policies binding the current context, plus a loading flag */
|
|
26
|
+
type SchematicCreditSpendPolicies = {
|
|
27
|
+
/** Company-scope policies first, then the user's own; empty when none bind */
|
|
28
|
+
policies: SchematicJS.CreditSpendPolicies;
|
|
29
|
+
/** True while the policies are still loading and nothing has arrived yet */
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
};
|
|
32
|
+
export declare class SchematicService {
|
|
33
|
+
private client;
|
|
34
|
+
private flagValueCache;
|
|
35
|
+
private entitlementCache;
|
|
36
|
+
private creditBalanceCache;
|
|
37
|
+
private creditSpendPoliciesCache?;
|
|
38
|
+
private planCache?;
|
|
39
|
+
private isPendingCache?;
|
|
40
|
+
getClient(): SchematicJS.Schematic;
|
|
41
|
+
setContext(context: SchematicJS.SchematicContext): void;
|
|
42
|
+
identify(body: SchematicJS.EventBodyIdentify): void;
|
|
43
|
+
track(body: SchematicJS.EventBodyTrack): void;
|
|
44
|
+
flagValue$(key: string, fallback?: boolean): Observable<boolean>;
|
|
45
|
+
entitlement$(key: string, fallback?: boolean): Observable<SchematicJS.CheckFlagReturn>;
|
|
46
|
+
plan$(): Observable<SchematicJS.CheckPlanReturn | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* Observe a company's live, lease-aware credit balance for a single credit type.
|
|
49
|
+
*
|
|
50
|
+
* Surfaces the spendable `settled` balance, sourced from the streamed credit
|
|
51
|
+
* balances map (keyed by credit ID). It emits as partials arrive over the
|
|
52
|
+
* DataStream, so it stays accurate during an open lease — when the raw
|
|
53
|
+
* `remaining` would otherwise read stale / falsely "exhausted".
|
|
54
|
+
*
|
|
55
|
+
* The credit ID is available on a feature's entitlement: `entitlement$(key)`
|
|
56
|
+
* emits `creditId` for credit-based features. Pass that stream straight in:
|
|
57
|
+
* this accepts an Observable of credit IDs as well as a plain one, switching
|
|
58
|
+
* to the new credit as the source emits. While the ID is undefined it emits
|
|
59
|
+
* the client's loading state and a balance of 0.
|
|
60
|
+
*/
|
|
61
|
+
creditBalance$(creditId: string | undefined | Observable<string | undefined>): Observable<SchematicCreditBalance>;
|
|
62
|
+
/**
|
|
63
|
+
* Emits a zeroed balance that still tracks the client's loading state, for
|
|
64
|
+
* when there is no credit ID to read (a check that has not arrived yet, or a
|
|
65
|
+
* feature that is not credit-based).
|
|
66
|
+
*/
|
|
67
|
+
private noCreditBalance$;
|
|
68
|
+
private creditBalanceFor;
|
|
69
|
+
/**
|
|
70
|
+
* Observe every credit spend policy binding the current context, company-scope
|
|
71
|
+
* first. It emits as partials arrive over the DataStream, so a policy edited
|
|
72
|
+
* or deleted in the dashboard arrives without a refetch. A window policy also
|
|
73
|
+
* carries `consumed` and `resetsAt`, which move as credits are spent.
|
|
74
|
+
*/
|
|
75
|
+
creditSpendPolicies$(): Observable<SchematicCreditSpendPolicies>;
|
|
76
|
+
isPending$(): Observable<boolean>;
|
|
77
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SchematicService, never>;
|
|
78
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
67
79
|
}
|
|
68
|
-
|
|
69
|
-
export { SCHEMATIC_CLIENT, SchematicService, provideSchematic };
|
|
70
|
-
export type { SchematicConfig, SchematicCreditBalance };
|
|
80
|
+
export { type CheckFlagReturn, type CheckPlanReturn, type CompanyCreditBalance, type CreditBalance, type CreditBalances, type CreditSpendPolicies, type CreditSpendPolicy, type CreditSpendPolicyKind, type CreditSpendPolicyScope, type CreditSpendWindow, type Event, type EventBody, type EventBodyIdentify, type EventBodyTrack, type EventType, type Keys, RuleType, Schematic, type SchematicConfig, type SchematicContext, type SchematicCreditBalance, type SchematicCreditSpendPolicies, type SchematicOptions, type StoragePersister, type Traits, TrialStatus, UsagePeriod, type WarningTier };
|