@farthershore/farthershore-js 0.0.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 +137 -0
- package/dist/bootstrap.d.ts +6 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +147 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/catalog.d.ts +81 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +281 -0
- package/dist/catalog.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +56 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +48 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +22 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +104 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/react/hooks.d.ts +47 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +87 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +10 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/provider.d.ts +15 -0
- package/dist/react/provider.d.ts.map +1 -0
- package/dist/react/provider.js +25 -0
- package/dist/react/provider.js.map +1 -0
- package/dist/react/use-async.d.ts +14 -0
- package/dist/react/use-async.d.ts.map +1 -0
- package/dist/react/use-async.js +39 -0
- package/dist/react/use-async.js.map +1 -0
- package/dist/resources/_shared.d.ts +6 -0
- package/dist/resources/_shared.d.ts.map +1 -0
- package/dist/resources/_shared.js +13 -0
- package/dist/resources/_shared.js.map +1 -0
- package/dist/resources/analytics.d.ts +8 -0
- package/dist/resources/analytics.d.ts.map +1 -0
- package/dist/resources/analytics.js +9 -0
- package/dist/resources/analytics.js.map +1 -0
- package/dist/resources/auth.d.ts +18 -0
- package/dist/resources/auth.d.ts.map +1 -0
- package/dist/resources/auth.js +61 -0
- package/dist/resources/auth.js.map +1 -0
- package/dist/resources/billing.d.ts +33 -0
- package/dist/resources/billing.d.ts.map +1 -0
- package/dist/resources/billing.js +61 -0
- package/dist/resources/billing.js.map +1 -0
- package/dist/resources/feature.d.ts +17 -0
- package/dist/resources/feature.d.ts.map +1 -0
- package/dist/resources/feature.js +14 -0
- package/dist/resources/feature.js.map +1 -0
- package/dist/resources/keys.d.ts +15 -0
- package/dist/resources/keys.d.ts.map +1 -0
- package/dist/resources/keys.js +55 -0
- package/dist/resources/keys.js.map +1 -0
- package/dist/resources/plans.d.ts +42 -0
- package/dist/resources/plans.d.ts.map +1 -0
- package/dist/resources/plans.js +43 -0
- package/dist/resources/plans.js.map +1 -0
- package/dist/resources/product.d.ts +7 -0
- package/dist/resources/product.d.ts.map +1 -0
- package/dist/resources/product.js +8 -0
- package/dist/resources/product.js.map +1 -0
- package/dist/resources/usage.d.ts +17 -0
- package/dist/resources/usage.d.ts.map +1 -0
- package/dist/resources/usage.js +35 -0
- package/dist/resources/usage.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Thin hooks over the client — each is a data-fetch (useAsync) plus, where it
|
|
2
|
+
// makes sense, the matching mutations (so a component never reaches for the raw
|
|
3
|
+
// client). All routing/auth still lives in the SDK.
|
|
4
|
+
import { useMemo } from "react";
|
|
5
|
+
import { useFartherShore } from "./provider.js";
|
|
6
|
+
import { useAsync } from "./use-async.js";
|
|
7
|
+
export function useBootstrap() {
|
|
8
|
+
const fs = useFartherShore();
|
|
9
|
+
return useAsync(() => fs.bootstrap(), [fs]);
|
|
10
|
+
}
|
|
11
|
+
export function useProduct() {
|
|
12
|
+
const fs = useFartherShore();
|
|
13
|
+
return useAsync(() => fs.product.get(), [fs]);
|
|
14
|
+
}
|
|
15
|
+
export function useSession() {
|
|
16
|
+
const fs = useFartherShore();
|
|
17
|
+
const state = useAsync(() => fs.auth.getSession(), [fs]);
|
|
18
|
+
return {
|
|
19
|
+
...state,
|
|
20
|
+
async signIn(input) {
|
|
21
|
+
await fs.auth.signIn(input);
|
|
22
|
+
state.refresh();
|
|
23
|
+
},
|
|
24
|
+
async signOut() {
|
|
25
|
+
await fs.auth.signOut();
|
|
26
|
+
state.refresh();
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function useApiKeys() {
|
|
31
|
+
const fs = useFartherShore();
|
|
32
|
+
const state = useAsync(() => fs.keys.list(), [fs]);
|
|
33
|
+
return {
|
|
34
|
+
...state,
|
|
35
|
+
async create(input) {
|
|
36
|
+
const key = await fs.keys.create(input);
|
|
37
|
+
state.refresh();
|
|
38
|
+
return key;
|
|
39
|
+
},
|
|
40
|
+
async revoke(keyId) {
|
|
41
|
+
await fs.keys.revoke(keyId);
|
|
42
|
+
state.refresh();
|
|
43
|
+
},
|
|
44
|
+
async rotate(keyId) {
|
|
45
|
+
const key = await fs.keys.rotate(keyId);
|
|
46
|
+
state.refresh();
|
|
47
|
+
return key;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function useUsage(range) {
|
|
52
|
+
const fs = useFartherShore();
|
|
53
|
+
return useAsync(async () => {
|
|
54
|
+
const [summary, events] = await Promise.all([
|
|
55
|
+
fs.usage.summary(range),
|
|
56
|
+
fs.usage.events(range),
|
|
57
|
+
]);
|
|
58
|
+
return { summary, events };
|
|
59
|
+
}, [fs, range?.from, range?.to]);
|
|
60
|
+
}
|
|
61
|
+
export function useBilling() {
|
|
62
|
+
const fs = useFartherShore();
|
|
63
|
+
const state = useAsync(() => fs.billing.subscription(), [fs]);
|
|
64
|
+
return {
|
|
65
|
+
...state,
|
|
66
|
+
openBillingPortal: (input) => fs.billing.openBillingPortal(input),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function usePlans() {
|
|
70
|
+
const fs = useFartherShore();
|
|
71
|
+
const state = useAsync(() => fs.plans.list(), [fs]);
|
|
72
|
+
return {
|
|
73
|
+
...state,
|
|
74
|
+
subscribe: (input) => fs.plans.subscribe(input),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Live prepaid/credit balance for the current subscription, or null. */
|
|
78
|
+
export function useCreditBalance() {
|
|
79
|
+
const fs = useFartherShore();
|
|
80
|
+
return useAsync(() => fs.billing.creditBalance(), [fs]);
|
|
81
|
+
}
|
|
82
|
+
/** A stable handle to a builder feature (routed through the Gateway). */
|
|
83
|
+
export function useFeature(name) {
|
|
84
|
+
const fs = useFartherShore();
|
|
85
|
+
return useMemo(() => fs.feature(name), [fs, name]);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FartherShoreProvider, useFartherShore } from "./provider.js";
|
|
2
|
+
export type { FartherShoreProviderProps } from "./provider.js";
|
|
3
|
+
export { useAsync } from "./use-async.js";
|
|
4
|
+
export type { AsyncState, AsyncResult } from "./use-async.js";
|
|
5
|
+
export { useBootstrap, useProduct, useSession, useApiKeys, useUsage, useBilling, usePlans, useCreditBalance, useFeature, } from "./hooks.js";
|
|
6
|
+
export type { SessionResult, ApiKeysResult, UsageData, BillingResult, PlansResult, } from "./hooks.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EACL,YAAY,EACZ,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,aAAa,EACb,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @farthershore/farthershore-js/react — React bindings for the Frontend SDK.
|
|
2
|
+
//
|
|
3
|
+
// import { FartherShoreProvider, useApiKeys } from "@farthershore/farthershore-js/react";
|
|
4
|
+
//
|
|
5
|
+
// `react` is an OPTIONAL peer dependency — only consumers of this subpath pull it
|
|
6
|
+
// in; the core SDK ('@farthershore/farthershore-js') stays framework-agnostic.
|
|
7
|
+
export { FartherShoreProvider, useFartherShore } from "./provider.js";
|
|
8
|
+
export { useAsync } from "./use-async.js";
|
|
9
|
+
export { useBootstrap, useProduct, useSession, useApiKeys, useUsage, useBilling, usePlans, useCreditBalance, useFeature, } from "./hooks.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,4FAA4F;AAC5F,EAAE;AACF,kFAAkF;AAClF,+EAA+E;AAE/E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGtE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EACL,YAAY,EACZ,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,UAAU,GACX,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type FartherShoreClient, type FartherShoreConfig } from "../index.js";
|
|
3
|
+
export interface FartherShoreProviderProps {
|
|
4
|
+
/** A pre-built client (preferred — you own its config + lifetime). */
|
|
5
|
+
client?: FartherShoreClient;
|
|
6
|
+
/** Or a config to build one internally. Pass a STABLE object (module-level /
|
|
7
|
+
* memoized) so the client isn't recreated every render. */
|
|
8
|
+
config?: FartherShoreConfig;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/** Provides one Farther Shore client to the tree. Mount once at the app root. */
|
|
12
|
+
export declare function FartherShoreProvider({ client, config, children, }: FartherShoreProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
/** The client from context. Throws if used outside a provider. */
|
|
14
|
+
export declare function useFartherShore(): FartherShoreClient;
|
|
15
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;gEAC4D;IAC5D,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,MAAM,EACN,QAAQ,GACT,EAAE,yBAAyB,2CAc3B;AAED,kEAAkE;AAClE,wBAAgB,eAAe,IAAI,kBAAkB,CAQpD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo } from "react";
|
|
3
|
+
import { createFartherShoreClient, } from "../index.js";
|
|
4
|
+
const FartherShoreContext = createContext(null);
|
|
5
|
+
/** Provides one Farther Shore client to the tree. Mount once at the app root. */
|
|
6
|
+
export function FartherShoreProvider({ client, config, children, }) {
|
|
7
|
+
const value = useMemo(() => {
|
|
8
|
+
if (client)
|
|
9
|
+
return client;
|
|
10
|
+
if (!config) {
|
|
11
|
+
throw new Error("FartherShoreProvider requires a `client` or `config`.");
|
|
12
|
+
}
|
|
13
|
+
return createFartherShoreClient(config);
|
|
14
|
+
}, [client, config]);
|
|
15
|
+
return (_jsx(FartherShoreContext.Provider, { value: value, children: children }));
|
|
16
|
+
}
|
|
17
|
+
/** The client from context. Throws if used outside a provider. */
|
|
18
|
+
export function useFartherShore() {
|
|
19
|
+
const client = useContext(FartherShoreContext);
|
|
20
|
+
if (!client) {
|
|
21
|
+
throw new Error("useFartherShore must be used within <FartherShoreProvider>.");
|
|
22
|
+
}
|
|
23
|
+
return client;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAC3E,OAAO,EACL,wBAAwB,GAGzB,MAAM,aAAa,CAAC;AAErB,MAAM,mBAAmB,GAAG,aAAa,CAA4B,IAAI,CAAC,CAAC;AAW3E,iFAAiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,EACnC,MAAM,EACN,MAAM,EACN,QAAQ,GACkB;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAqB,GAAG,EAAE;QAC7C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAErB,OAAO,CACL,KAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACvC,QAAQ,GACoB,CAChC,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface AsyncState<T> {
|
|
2
|
+
data: T | null;
|
|
3
|
+
loading: boolean;
|
|
4
|
+
error: Error | null;
|
|
5
|
+
}
|
|
6
|
+
export interface AsyncResult<T> extends AsyncState<T> {
|
|
7
|
+
/** Re-run the async function. */
|
|
8
|
+
refresh: () => void;
|
|
9
|
+
}
|
|
10
|
+
/** A small data-fetching primitive the hooks share: tracks {data, loading,
|
|
11
|
+
* error}, re-runs when `deps` change or `refresh()` is called, and ignores a
|
|
12
|
+
* resolution after unmount/dep-change (no setState-after-unmount). */
|
|
13
|
+
export declare function useAsync<T>(fn: () => Promise<T>, deps: readonly unknown[]): AsyncResult<T>;
|
|
14
|
+
//# sourceMappingURL=use-async.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-async.d.ts","sourceRoot":"","sources":["../../src/react/use-async.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;IACnD,iCAAiC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;uEAEuE;AACvE,wBAAgB,QAAQ,CAAC,CAAC,EACxB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE,SAAS,OAAO,EAAE,GACvB,WAAW,CAAC,CAAC,CAAC,CAkChB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
/** A small data-fetching primitive the hooks share: tracks {data, loading,
|
|
3
|
+
* error}, re-runs when `deps` change or `refresh()` is called, and ignores a
|
|
4
|
+
* resolution after unmount/dep-change (no setState-after-unmount). */
|
|
5
|
+
export function useAsync(fn, deps) {
|
|
6
|
+
const [state, setState] = useState({
|
|
7
|
+
data: null,
|
|
8
|
+
loading: true,
|
|
9
|
+
error: null,
|
|
10
|
+
});
|
|
11
|
+
const [nonce, setNonce] = useState(0);
|
|
12
|
+
const fnRef = useRef(fn);
|
|
13
|
+
fnRef.current = fn;
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
let active = true;
|
|
16
|
+
setState((s) => ({ data: s.data, loading: true, error: null }));
|
|
17
|
+
fnRef
|
|
18
|
+
.current()
|
|
19
|
+
.then((data) => {
|
|
20
|
+
if (active)
|
|
21
|
+
setState({ data, loading: false, error: null });
|
|
22
|
+
})
|
|
23
|
+
.catch((e) => {
|
|
24
|
+
if (active) {
|
|
25
|
+
setState({
|
|
26
|
+
data: null,
|
|
27
|
+
loading: false,
|
|
28
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return () => {
|
|
33
|
+
active = false;
|
|
34
|
+
};
|
|
35
|
+
}, [...deps, nonce]);
|
|
36
|
+
const refresh = useCallback(() => setNonce((n) => n + 1), []);
|
|
37
|
+
return { ...state, refresh };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=use-async.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-async.js","sourceRoot":"","sources":["../../src/react/use-async.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAajE;;uEAEuE;AACvE,MAAM,UAAU,QAAQ,CACtB,EAAoB,EACpB,IAAwB;IAExB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB;QAChD,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACzB,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;IAEnB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAChE,KAAK;aACF,OAAO,EAAE;aACT,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,MAAM;gBAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;YACpB,IAAI,MAAM,EAAE,CAAC;gBACX,QAAQ,CAAC;oBACP,IAAI,EAAE,IAAI;oBACV,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;iBACrD,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAErB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ClientContext } from "../config.js";
|
|
2
|
+
/** The product id, or a clear error telling the caller to bootstrap first. */
|
|
3
|
+
export declare function requireProductId(ctx: ClientContext): string;
|
|
4
|
+
/** Build a `/portal/products/:id/me…` path. */
|
|
5
|
+
export declare function mePath(productId: string, suffix?: string): string;
|
|
6
|
+
//# sourceMappingURL=_shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/resources/_shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAO3D;AAED,+CAA+C;AAC/C,wBAAgB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FartherShoreNotReadyError } from "../errors.js";
|
|
2
|
+
/** The product id, or a clear error telling the caller to bootstrap first. */
|
|
3
|
+
export function requireProductId(ctx) {
|
|
4
|
+
if (!ctx.productId) {
|
|
5
|
+
throw new FartherShoreNotReadyError("product unknown — call fs.bootstrap() first, or pass productId to createFartherShoreClient().");
|
|
6
|
+
}
|
|
7
|
+
return ctx.productId;
|
|
8
|
+
}
|
|
9
|
+
/** Build a `/portal/products/:id/me…` path. */
|
|
10
|
+
export function mePath(productId, suffix = "") {
|
|
11
|
+
return `/portal/products/${encodeURIComponent(productId)}/me${suffix}`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=_shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/resources/_shared.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEzD,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,GAAkB;IACjD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,IAAI,yBAAyB,CACjC,+FAA+F,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC,SAAS,CAAC;AACvB,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,MAAM,CAAC,SAAiB,EAAE,MAAM,GAAG,EAAE;IACnD,OAAO,oBAAoB,kBAAkB,CAAC,SAAS,CAAC,MAAM,MAAM,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AnalyticsResource {
|
|
2
|
+
/** Request analytics — no consumer-facing platform endpoint yet. The closest
|
|
3
|
+
* data today is `usage.events()` (recent events) + audit logs. Throws to stay
|
|
4
|
+
* honest rather than silently returning empty. */
|
|
5
|
+
requests(): never;
|
|
6
|
+
}
|
|
7
|
+
export declare function createAnalyticsResource(): AnalyticsResource;
|
|
8
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/resources/analytics.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC;;uDAEmD;IACnD,QAAQ,IAAI,KAAK,CAAC;CACnB;AAED,wBAAgB,uBAAuB,IAAI,iBAAiB,CAQ3D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FartherShoreNotImplementedError } from "../errors.js";
|
|
2
|
+
export function createAnalyticsResource() {
|
|
3
|
+
return {
|
|
4
|
+
requests() {
|
|
5
|
+
throw new FartherShoreNotImplementedError("analytics.requests() has no consumer endpoint yet — closest data is usage.events(). (Deferred.)");
|
|
6
|
+
},
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/resources/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAS/D,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,QAAQ;YACN,MAAM,IAAI,+BAA+B,CACvC,iGAAiG,CAClG,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ClientContext } from "../config.js";
|
|
2
|
+
import type { Session, SignInResult } from "../types.js";
|
|
3
|
+
export interface AuthResource {
|
|
4
|
+
/** The current session (authenticated + a light subscriber slice). Resolves to
|
|
5
|
+
* `{ authenticated: false }` on a 401/403 rather than throwing. */
|
|
6
|
+
getSession(): Promise<Session>;
|
|
7
|
+
/** Test/preview-env sign-in: exchange an `fsk_test_…` access key for a session
|
|
8
|
+
* (persona strategy). Clerk-strategy envs sign in via the Clerk browser SDK —
|
|
9
|
+
* pass `getToken` to the client config and call `setToken` instead. */
|
|
10
|
+
signIn(input: {
|
|
11
|
+
apiKey: string;
|
|
12
|
+
}): Promise<SignInResult>;
|
|
13
|
+
signOut(): Promise<void>;
|
|
14
|
+
/** Set the session bearer directly (e.g. from Clerk's `session.getToken()`). */
|
|
15
|
+
setToken(token: string | null): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function createAuthResource(ctx: ClientContext): AuthResource;
|
|
18
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/resources/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAgBrE,MAAM,WAAW,YAAY;IAC3B;wEACoE;IACpE,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B;;4EAEwE;IACxE,MAAM,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACtC;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,CA2DnE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { coreFetch } from "../http.js";
|
|
2
|
+
import { FartherShoreApiError } from "../errors.js";
|
|
3
|
+
import { mePath, requireProductId } from "./_shared.js";
|
|
4
|
+
export function createAuthResource(ctx) {
|
|
5
|
+
return {
|
|
6
|
+
async getSession() {
|
|
7
|
+
const productId = requireProductId(ctx);
|
|
8
|
+
try {
|
|
9
|
+
const raw = await coreFetch(ctx, {
|
|
10
|
+
method: "GET",
|
|
11
|
+
path: mePath(productId),
|
|
12
|
+
});
|
|
13
|
+
const s = raw.subscriber;
|
|
14
|
+
const subscriber = s
|
|
15
|
+
? {
|
|
16
|
+
status: s.status ?? null,
|
|
17
|
+
planKey: s.planKey ?? null,
|
|
18
|
+
compiledPlanId: s.compiledPlanId ?? null,
|
|
19
|
+
}
|
|
20
|
+
: null;
|
|
21
|
+
return { authenticated: true, subscriber };
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (err instanceof FartherShoreApiError &&
|
|
25
|
+
(err.status === 401 || err.status === 403)) {
|
|
26
|
+
return { authenticated: false, subscriber: null };
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
async signIn(input) {
|
|
32
|
+
const raw = await coreFetch(ctx, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
path: "/portal/auth/persona-session",
|
|
35
|
+
body: { apiKey: input.apiKey },
|
|
36
|
+
auth: "none",
|
|
37
|
+
});
|
|
38
|
+
ctx.sessionToken = raw.sessionToken;
|
|
39
|
+
return {
|
|
40
|
+
token: raw.sessionToken,
|
|
41
|
+
expiresAt: raw.expiresAt,
|
|
42
|
+
user: raw.user,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
async signOut() {
|
|
46
|
+
try {
|
|
47
|
+
await coreFetch(ctx, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
path: "/portal/auth/persona-logout",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
ctx.sessionToken = null;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
setToken(token) {
|
|
57
|
+
ctx.sessionToken = token;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/resources/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AA4BxD,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,OAAO;QACL,KAAK,CAAC,UAAU;YACd,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAuB,GAAG,EAAE;oBACrD,MAAM,EAAE,KAAK;oBACb,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC;iBACxB,CAAC,CAAC;gBACH,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC;gBACzB,MAAM,UAAU,GAAsB,CAAC;oBACrC,CAAC,CAAC;wBACE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;wBACxB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,IAAI;wBAC1B,cAAc,EAAE,CAAC,CAAC,cAAc,IAAI,IAAI;qBACzC;oBACH,CAAC,CAAC,IAAI,CAAC;gBACT,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;YAC7C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IACE,GAAG,YAAY,oBAAoB;oBACnC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,EAC1C,CAAC;oBACD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;gBACpD,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK;YAChB,MAAM,GAAG,GAAG,MAAM,SAAS,CAAoB,GAAG,EAAE;gBAClD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,8BAA8B;gBACpC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;gBAC9B,IAAI,EAAE,MAAM;aACb,CAAC,CAAC;YACH,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;YACpC,OAAO;gBACL,KAAK,EAAE,GAAG,CAAC,YAAY;gBACvB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,OAAO;YACX,IAAI,CAAC;gBACH,MAAM,SAAS,CAAO,GAAG,EAAE;oBACzB,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,6BAA6B;iBACpC,CAAC,CAAC;YACL,CAAC;oBAAS,CAAC;gBACT,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,KAAK;YACZ,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ClientContext } from "../config.js";
|
|
2
|
+
import type { Subscription } from "../types.js";
|
|
3
|
+
/** Live Stripe-backed credit balance for the current subscription. `null` when
|
|
4
|
+
* the subscription has no credit grants / no Stripe binding, or the upstream
|
|
5
|
+
* fetch is unavailable. */
|
|
6
|
+
export interface CreditBalance {
|
|
7
|
+
/** Spendable balance remaining, in cents. */
|
|
8
|
+
availableCents: number;
|
|
9
|
+
/** Total ledger balance, in cents. */
|
|
10
|
+
ledgerCents: number;
|
|
11
|
+
/** Currency code (USD-only today). */
|
|
12
|
+
currency: string;
|
|
13
|
+
}
|
|
14
|
+
export interface BillingResource {
|
|
15
|
+
/** The consumer's current subscription for this product, or null. */
|
|
16
|
+
subscription(): Promise<Subscription | null>;
|
|
17
|
+
/** Open the Stripe-hosted billing portal (payment method + invoices). Returns
|
|
18
|
+
* the URL to navigate to. This is also how invoices are viewed in V0. */
|
|
19
|
+
openBillingPortal(input?: {
|
|
20
|
+
returnUrl?: string;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
url: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** Live prepaid/credit balance for the current subscription, or null when
|
|
25
|
+
* there is no credit surface. Degrades to null rather than throwing on a
|
|
26
|
+
* 404 (no subscription/grant). */
|
|
27
|
+
creditBalance(): Promise<CreditBalance | null>;
|
|
28
|
+
/** Structured invoice list — no platform endpoint; use openBillingPortal().
|
|
29
|
+
* Throws to stay honest. */
|
|
30
|
+
invoices(): never;
|
|
31
|
+
}
|
|
32
|
+
export declare function createBillingResource(ctx: ClientContext): BillingResource;
|
|
33
|
+
//# sourceMappingURL=billing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../../src/resources/billing.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAKlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA+BhD;;4BAE4B;AAC5B,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,YAAY,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC7C;8EAC0E;IAC1E,iBAAiB,CAAC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E;;uCAEmC;IACnC,aAAa,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC/C;iCAC6B;IAC7B,QAAQ,IAAI,KAAK,CAAC;CACnB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,eAAe,CA6DzE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { coreFetch } from "../http.js";
|
|
2
|
+
import { FartherShoreApiError, FartherShoreNotImplementedError, } from "../errors.js";
|
|
3
|
+
import { mePath, requireProductId } from "./_shared.js";
|
|
4
|
+
export function createBillingResource(ctx) {
|
|
5
|
+
return {
|
|
6
|
+
async subscription() {
|
|
7
|
+
const productId = requireProductId(ctx);
|
|
8
|
+
const raw = await coreFetch(ctx, {
|
|
9
|
+
method: "GET",
|
|
10
|
+
path: mePath(productId, "/subscription"),
|
|
11
|
+
});
|
|
12
|
+
if (!raw)
|
|
13
|
+
return null;
|
|
14
|
+
return {
|
|
15
|
+
id: raw.subscriptionId ?? raw.id ?? "",
|
|
16
|
+
status: raw.status ?? raw.subscriptionLifecycle ?? raw.lifecycle ?? "",
|
|
17
|
+
planKey: raw.planKey ?? raw.plan?.planKey ?? null,
|
|
18
|
+
planName: raw.planName ?? raw.plan?.displayName ?? raw.plan?.planName ?? null,
|
|
19
|
+
raw,
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
async openBillingPortal(input = {}) {
|
|
23
|
+
const productId = requireProductId(ctx);
|
|
24
|
+
const raw = await coreFetch(ctx, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
path: mePath(productId, "/billing-portal-session"),
|
|
27
|
+
body: { returnUrl: input.returnUrl },
|
|
28
|
+
});
|
|
29
|
+
return { url: raw.url };
|
|
30
|
+
},
|
|
31
|
+
async creditBalance() {
|
|
32
|
+
const productId = requireProductId(ctx);
|
|
33
|
+
try {
|
|
34
|
+
const raw = await coreFetch(ctx, {
|
|
35
|
+
method: "GET",
|
|
36
|
+
path: mePath(productId, "/credit-balance"),
|
|
37
|
+
});
|
|
38
|
+
if (!raw.balance)
|
|
39
|
+
return null;
|
|
40
|
+
return {
|
|
41
|
+
availableCents: raw.balance.availableCents,
|
|
42
|
+
ledgerCents: raw.balance.ledgerCents,
|
|
43
|
+
currency: raw.balance.currency,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
// No subscription / no credit grant on file → degrade to null so the
|
|
48
|
+
// portal still renders the rest of the billing surface.
|
|
49
|
+
if (err instanceof FartherShoreApiError &&
|
|
50
|
+
(err.status === 404 || err.status === 401 || err.status === 403)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
invoices() {
|
|
57
|
+
throw new FartherShoreNotImplementedError("billing.invoices() has no JSON endpoint — use billing.openBillingPortal() for Stripe-hosted invoices. (Deferred.)");
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=billing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../src/resources/billing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAyDxD,MAAM,UAAU,qBAAqB,CAAC,GAAkB;IACtD,OAAO;QACL,KAAK,CAAC,YAAY;YAChB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAyB,GAAG,EAAE;gBACvD,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC;aACzC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtB,OAAO;gBACL,EAAE,EAAE,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE;gBACtC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE;gBACtE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,IAAI;gBACjD,QAAQ,EACN,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI;gBACrE,GAAG;aACJ,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,iBAAiB,CAAC,KAAK,GAAG,EAAE;YAChC,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAmB,GAAG,EAAE;gBACjD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,yBAAyB,CAAC;gBAClD,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE;aACrC,CAAC,CAAC;YACH,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,aAAa;YACjB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAmB,GAAG,EAAE;oBACjD,MAAM,EAAE,KAAK;oBACb,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC;iBAC3C,CAAC,CAAC;gBACH,IAAI,CAAC,GAAG,CAAC,OAAO;oBAAE,OAAO,IAAI,CAAC;gBAC9B,OAAO;oBACL,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc;oBAC1C,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW;oBACpC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ;iBAC/B,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,qEAAqE;gBACrE,wDAAwD;gBACxD,IACE,GAAG,YAAY,oBAAoB;oBACnC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,EAChE,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,QAAQ;YACN,MAAM,IAAI,+BAA+B,CACvC,mHAAmH,CACpH,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ClientContext } from "../config.js";
|
|
2
|
+
export interface GatewayRequestInit extends RequestInit {
|
|
3
|
+
/** Override the consumer API key for this call (else the client's apiKey). */
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
}
|
|
6
|
+
/** A handle to one builder-defined feature. The Gateway routes by HTTP
|
|
7
|
+
* method+path (it proxies the product's own routes); the feature name is a
|
|
8
|
+
* label/metadata. Frontend code never sees the gateway URL. */
|
|
9
|
+
export interface FeatureHandle {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
/** Call a route on the product's Gateway. Returns the raw Response. */
|
|
12
|
+
fetch(path: string, init?: GatewayRequestInit): Promise<Response>;
|
|
13
|
+
/** Convenience: fetch + parse JSON. */
|
|
14
|
+
json<T = unknown>(path: string, init?: GatewayRequestInit): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createFeature(ctx: ClientContext, name: string): FeatureHandle;
|
|
17
|
+
//# sourceMappingURL=feature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../../src/resources/feature.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;gEAEgE;AAChE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,uCAAuC;IACvC,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACxE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAW7E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { gatewayFetch } from "../http.js";
|
|
2
|
+
export function createFeature(ctx, name) {
|
|
3
|
+
return {
|
|
4
|
+
name,
|
|
5
|
+
fetch(path, init) {
|
|
6
|
+
return gatewayFetch(ctx, path, init);
|
|
7
|
+
},
|
|
8
|
+
async json(path, init) {
|
|
9
|
+
const res = await gatewayFetch(ctx, path, init);
|
|
10
|
+
return (await res.json());
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.js","sourceRoot":"","sources":["../../src/resources/feature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAmB1C,MAAM,UAAU,aAAa,CAAC,GAAkB,EAAE,IAAY;IAC5D,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,IAAI,EAAE,IAAI;YACd,OAAO,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,IAAI,CAAI,IAAY,EAAE,IAAyB;YACnD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAChD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ClientContext } from "../config.js";
|
|
2
|
+
import type { ApiKey, CreatedApiKey } from "../types.js";
|
|
3
|
+
export interface KeysResource {
|
|
4
|
+
list(): Promise<ApiKey[]>;
|
|
5
|
+
/** Create a key. The returned `secret` is shown ONCE. */
|
|
6
|
+
create(input?: {
|
|
7
|
+
label?: string;
|
|
8
|
+
scopes?: string[];
|
|
9
|
+
}): Promise<CreatedApiKey>;
|
|
10
|
+
revoke(keyId: string): Promise<void>;
|
|
11
|
+
/** Rotate a key — revokes the old and returns a new `secret` (shown once). */
|
|
12
|
+
rotate(keyId: string): Promise<CreatedApiKey>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createKeysResource(ctx: ClientContext): KeysResource;
|
|
15
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/resources/keys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmCzD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1B,yDAAyD;IACzD,MAAM,CAAC,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,8EAA8E;IAC9E,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC/C;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,CAyCnE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { coreFetch } from "../http.js";
|
|
2
|
+
import { mePath, requireProductId } from "./_shared.js";
|
|
3
|
+
function mapKey(k) {
|
|
4
|
+
return {
|
|
5
|
+
id: k.id,
|
|
6
|
+
keyPrefix: k.keyPrefix,
|
|
7
|
+
label: k.label ?? null,
|
|
8
|
+
// Normalize the platform enum casing (ACTIVE/REVOKED) to a stable lowercase
|
|
9
|
+
// SDK contract so consumers can compare against "active"/"revoked".
|
|
10
|
+
status: (k.status ?? "").toLowerCase(),
|
|
11
|
+
createdAt: k.createdAt,
|
|
12
|
+
lastUsedAt: k.lastUsedAt ?? null,
|
|
13
|
+
revokedAt: k.revokedAt ?? null,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function withSecret(k) {
|
|
17
|
+
return { ...mapKey(k), secret: k.plaintext ?? k.rawKey ?? "" };
|
|
18
|
+
}
|
|
19
|
+
export function createKeysResource(ctx) {
|
|
20
|
+
return {
|
|
21
|
+
async list() {
|
|
22
|
+
const productId = requireProductId(ctx);
|
|
23
|
+
const raw = await coreFetch(ctx, {
|
|
24
|
+
method: "GET",
|
|
25
|
+
path: mePath(productId, "/api-keys"),
|
|
26
|
+
});
|
|
27
|
+
return raw.map(mapKey);
|
|
28
|
+
},
|
|
29
|
+
async create(input = {}) {
|
|
30
|
+
const productId = requireProductId(ctx);
|
|
31
|
+
const raw = await coreFetch(ctx, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
path: mePath(productId, "/api-keys"),
|
|
34
|
+
body: { label: input.label, scopes: input.scopes },
|
|
35
|
+
});
|
|
36
|
+
return withSecret(raw);
|
|
37
|
+
},
|
|
38
|
+
async revoke(keyId) {
|
|
39
|
+
const productId = requireProductId(ctx);
|
|
40
|
+
await coreFetch(ctx, {
|
|
41
|
+
method: "DELETE",
|
|
42
|
+
path: mePath(productId, `/api-keys/${encodeURIComponent(keyId)}`),
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
async rotate(keyId) {
|
|
46
|
+
const productId = requireProductId(ctx);
|
|
47
|
+
const raw = await coreFetch(ctx, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
path: mePath(productId, `/api-keys/${encodeURIComponent(keyId)}/rotate`),
|
|
50
|
+
});
|
|
51
|
+
return withSecret(raw);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/resources/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAgBxD,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QACtB,4EAA4E;QAC5E,oEAAoE;QACpE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE;QACtC,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI;QAChC,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,IAAI;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,CAAgB;IAClC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;AACjE,CAAC;AAWD,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,OAAO;QACL,KAAK,CAAC,IAAI;YACR,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAW,GAAG,EAAE;gBACzC,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC;aACrC,CAAC,CAAC;YACH,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE;YACrB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAgB,GAAG,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC;gBACpC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;aACnD,CAAC,CAAC;YACH,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK;YAChB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,SAAS,CAAO,GAAG,EAAE;gBACzB,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,aAAa,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;aAClE,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK;YAChB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAgB,GAAG,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,MAAM,CACV,SAAS,EACT,aAAa,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAChD;aACF,CAAC,CAAC;YACH,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
|