@fonderie/client 1.3.0 → 1.5.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/brain/signatures.md +26 -0
- package/dist/index.cjs +94 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/brain/signatures.md
CHANGED
|
@@ -49,6 +49,7 @@ new FonderieClient(opts: IFonderieClientOptions): FonderieClient
|
|
|
49
49
|
.webhooks: WebhooksClient
|
|
50
50
|
.customers: CustomersClient
|
|
51
51
|
.media: MediaClient
|
|
52
|
+
.config: ConfigClient
|
|
52
53
|
.setAccessToken(token: string | undefined): void
|
|
53
54
|
.clearCache(): void
|
|
54
55
|
.setWorkspaceId(workspaceId: string | undefined): void
|
|
@@ -239,6 +240,7 @@ interface ISetConfigInput {
|
|
|
239
240
|
description?: string;
|
|
240
241
|
active?: boolean;
|
|
241
242
|
ifVersion?: number;
|
|
243
|
+
allowTypeChange?: boolean;
|
|
242
244
|
}
|
|
243
245
|
|
|
244
246
|
interface ISetSecretInput {
|
|
@@ -1601,10 +1603,14 @@ function castConfigValue(type: ConfigValueType, raw: string): CastResult
|
|
|
1601
1603
|
|
|
1602
1604
|
function configKeyProblem(key: string): string | null
|
|
1603
1605
|
|
|
1606
|
+
function configValueLabel(value: unknown): string
|
|
1607
|
+
|
|
1604
1608
|
function configValueType(value: unknown): ConfigValueType
|
|
1605
1609
|
|
|
1606
1610
|
function formatConfigValue(value: unknown, type?: ConfigValueType): string
|
|
1607
1611
|
|
|
1612
|
+
function inferConfigValue(raw: string): IInferredConfigValue
|
|
1613
|
+
|
|
1608
1614
|
type CastResult = {
|
|
1609
1615
|
ok: true;
|
|
1610
1616
|
value: unknown;
|
|
@@ -1614,4 +1620,24 @@ type CastResult = {
|
|
|
1614
1620
|
};
|
|
1615
1621
|
|
|
1616
1622
|
type ConfigValueType = 'string' | 'number' | 'boolean' | 'json';
|
|
1623
|
+
|
|
1624
|
+
interface IInferredConfigValue {
|
|
1625
|
+
type: ConfigValueType;
|
|
1626
|
+
value: unknown;
|
|
1627
|
+
label: string;
|
|
1628
|
+
ambiguous: boolean;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
new ConfigClient(http: HttpClient, tokens: TokenStore): ConfigClient
|
|
1632
|
+
.load(): Promise<IRemoteConfigState>
|
|
1633
|
+
.get<T>(key: string, fallback: T): T
|
|
1634
|
+
.snapshot(): IRemoteConfigState
|
|
1635
|
+
.subscribe(listener: Listener): () => void
|
|
1636
|
+
|
|
1637
|
+
interface IRemoteConfigState {
|
|
1638
|
+
values: Readonly<Record<string, unknown>>;
|
|
1639
|
+
loadedAt: Date | null;
|
|
1640
|
+
isLoading: boolean;
|
|
1641
|
+
error: unknown;
|
|
1642
|
+
}
|
|
1617
1643
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
CONFIG_KEY_PATTERN: () => CONFIG_KEY_PATTERN,
|
|
31
31
|
CONFIG_VALUE_TYPES: () => CONFIG_VALUE_TYPES,
|
|
32
32
|
ConfigAdminClient: () => ConfigAdminClient,
|
|
33
|
+
ConfigClient: () => ConfigClient,
|
|
33
34
|
CourierAdminClient: () => CourierAdminClient,
|
|
34
35
|
CustomersClient: () => CustomersClient,
|
|
35
36
|
FonderieApiError: () => FonderieApiError,
|
|
@@ -39,10 +40,12 @@ __export(index_exports, {
|
|
|
39
40
|
WorkspacesClient: () => WorkspacesClient,
|
|
40
41
|
castConfigValue: () => castConfigValue,
|
|
41
42
|
configKeyProblem: () => configKeyProblem,
|
|
43
|
+
configValueLabel: () => configValueLabel,
|
|
42
44
|
configValueType: () => configValueType,
|
|
43
45
|
createMemoryCache: () => createMemoryCache,
|
|
44
46
|
describeLocation: () => describeLocation,
|
|
45
47
|
formatConfigValue: () => formatConfigValue,
|
|
48
|
+
inferConfigValue: () => inferConfigValue,
|
|
46
49
|
isMfaRequired: () => isMfaRequired
|
|
47
50
|
});
|
|
48
51
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -1145,6 +1148,62 @@ var MediaClient = class {
|
|
|
1145
1148
|
}
|
|
1146
1149
|
};
|
|
1147
1150
|
|
|
1151
|
+
// src/modules/config.ts
|
|
1152
|
+
var ConfigClient = class {
|
|
1153
|
+
constructor(http, tokens) {
|
|
1154
|
+
this.http = http;
|
|
1155
|
+
this.tokens = tokens;
|
|
1156
|
+
}
|
|
1157
|
+
http;
|
|
1158
|
+
tokens;
|
|
1159
|
+
state = { values: {}, loadedAt: null, isLoading: false, error: null };
|
|
1160
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1161
|
+
inFlight = null;
|
|
1162
|
+
// GET /config/public — fetch the public values into the shared snapshot.
|
|
1163
|
+
// Concurrent calls share one request. A failure keeps the previous values
|
|
1164
|
+
// (a flag that was on does not flicker off because one refresh failed) and
|
|
1165
|
+
// is reported in `error`; before any success, reads fall back to defaults.
|
|
1166
|
+
load() {
|
|
1167
|
+
if (this.inFlight) return this.inFlight;
|
|
1168
|
+
this.set({ isLoading: true });
|
|
1169
|
+
this.inFlight = this.http.request({
|
|
1170
|
+
method: "GET",
|
|
1171
|
+
path: "/config/public",
|
|
1172
|
+
// Sent when signed in, so per-user values can be served later
|
|
1173
|
+
// without a client change; the route itself is public.
|
|
1174
|
+
token: this.tokens.get()
|
|
1175
|
+
}).then(
|
|
1176
|
+
(res) => this.set({ values: res.result?.values ?? {}, loadedAt: /* @__PURE__ */ new Date(), isLoading: false, error: null }),
|
|
1177
|
+
(error) => this.set({ isLoading: false, error })
|
|
1178
|
+
).finally(() => {
|
|
1179
|
+
this.inFlight = null;
|
|
1180
|
+
});
|
|
1181
|
+
return this.inFlight;
|
|
1182
|
+
}
|
|
1183
|
+
// One value, with the fallback used when the key is absent — before the
|
|
1184
|
+
// first load, when it failed, or when the server does not expose the key.
|
|
1185
|
+
// Pick the SAFE fallback (feature off), not the optimistic one.
|
|
1186
|
+
get(key, fallback) {
|
|
1187
|
+
return Object.hasOwn(this.state.values, key) ? this.state.values[key] : fallback;
|
|
1188
|
+
}
|
|
1189
|
+
// The whole current state (values, loadedAt, isLoading, error).
|
|
1190
|
+
snapshot() {
|
|
1191
|
+
return this.state;
|
|
1192
|
+
}
|
|
1193
|
+
// Called with the new state after every change; returns an unsubscribe.
|
|
1194
|
+
subscribe(listener) {
|
|
1195
|
+
this.listeners.add(listener);
|
|
1196
|
+
return () => {
|
|
1197
|
+
this.listeners.delete(listener);
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
set(patch) {
|
|
1201
|
+
this.state = { ...this.state, ...patch };
|
|
1202
|
+
for (const listener of this.listeners) listener(this.state);
|
|
1203
|
+
return this.state;
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1148
1207
|
// src/modules/webhooks.ts
|
|
1149
1208
|
var WebhooksClient = class {
|
|
1150
1209
|
constructor(http, tokens) {
|
|
@@ -1481,6 +1540,8 @@ var FonderieClient = class {
|
|
|
1481
1540
|
webhooks;
|
|
1482
1541
|
customers;
|
|
1483
1542
|
media;
|
|
1543
|
+
/** Public remote config: flags and settings the server exposes to frontends. */
|
|
1544
|
+
config;
|
|
1484
1545
|
http;
|
|
1485
1546
|
tokens;
|
|
1486
1547
|
workspaceId;
|
|
@@ -1504,6 +1565,7 @@ var FonderieClient = class {
|
|
|
1504
1565
|
this.webhooks = new WebhooksClient(this.http, this.tokens);
|
|
1505
1566
|
this.customers = new CustomersClient(this.http, this.tokens);
|
|
1506
1567
|
this.media = new MediaClient(this.http, this.tokens);
|
|
1568
|
+
this.config = new ConfigClient(this.http, this.tokens);
|
|
1507
1569
|
if (opts.workspaceId !== void 0) this.setWorkspaceId(opts.workspaceId);
|
|
1508
1570
|
}
|
|
1509
1571
|
// Single-flight refresh: POST /auth/refresh with the app-supplied refresh
|
|
@@ -2170,6 +2232,35 @@ function configKeyProblem(key) {
|
|
|
2170
2232
|
if (!key) return "Enter a key.";
|
|
2171
2233
|
return CONFIG_KEY_PATTERN.test(key) ? null : 'Start with a letter; use letters, digits, ".", "_" or "-" (max 128).';
|
|
2172
2234
|
}
|
|
2235
|
+
var PLAIN_NUMBER = /^-?(0|[1-9]\d*)(\.\d+)?$/;
|
|
2236
|
+
function configValueLabel(value) {
|
|
2237
|
+
if (typeof value === "string") return "Text";
|
|
2238
|
+
if (typeof value === "number") return "Number";
|
|
2239
|
+
if (typeof value === "boolean") return "On/off";
|
|
2240
|
+
if (Array.isArray(value)) return "List";
|
|
2241
|
+
if (value === null) return "Empty";
|
|
2242
|
+
return "Object";
|
|
2243
|
+
}
|
|
2244
|
+
function inferConfigValue(raw) {
|
|
2245
|
+
const t = raw.trim();
|
|
2246
|
+
if (t === "true" || t === "false") {
|
|
2247
|
+
return { type: "boolean", value: t === "true", label: "On/off", ambiguous: true };
|
|
2248
|
+
}
|
|
2249
|
+
if (PLAIN_NUMBER.test(t)) {
|
|
2250
|
+
const n = Number(t);
|
|
2251
|
+
if (Number.isFinite(n) && String(n) === t) return { type: "number", value: n, label: "Number", ambiguous: true };
|
|
2252
|
+
}
|
|
2253
|
+
if (t.startsWith("{") || t.startsWith("[")) {
|
|
2254
|
+
try {
|
|
2255
|
+
const parsed = JSON.parse(t);
|
|
2256
|
+
if (parsed !== null && typeof parsed === "object") {
|
|
2257
|
+
return { type: "json", value: parsed, label: Array.isArray(parsed) ? "List" : "Object", ambiguous: false };
|
|
2258
|
+
}
|
|
2259
|
+
} catch {
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
return { type: "string", value: raw, label: "Text", ambiguous: false };
|
|
2263
|
+
}
|
|
2173
2264
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2174
2265
|
0 && (module.exports = {
|
|
2175
2266
|
AdminClient,
|
|
@@ -2182,6 +2273,7 @@ function configKeyProblem(key) {
|
|
|
2182
2273
|
CONFIG_KEY_PATTERN,
|
|
2183
2274
|
CONFIG_VALUE_TYPES,
|
|
2184
2275
|
ConfigAdminClient,
|
|
2276
|
+
ConfigClient,
|
|
2185
2277
|
CourierAdminClient,
|
|
2186
2278
|
CustomersClient,
|
|
2187
2279
|
FonderieApiError,
|
|
@@ -2191,10 +2283,12 @@ function configKeyProblem(key) {
|
|
|
2191
2283
|
WorkspacesClient,
|
|
2192
2284
|
castConfigValue,
|
|
2193
2285
|
configKeyProblem,
|
|
2286
|
+
configValueLabel,
|
|
2194
2287
|
configValueType,
|
|
2195
2288
|
createMemoryCache,
|
|
2196
2289
|
describeLocation,
|
|
2197
2290
|
formatConfigValue,
|
|
2291
|
+
inferConfigValue,
|
|
2198
2292
|
isMfaRequired
|
|
2199
2293
|
});
|
|
2200
2294
|
//# sourceMappingURL=index.cjs.map
|