@andco/sdk 0.0.2 → 0.0.4
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/LICENSE +1 -1
- package/README.md +96 -54
- package/dist/auth.d.ts +8 -3
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +32 -23
- package/dist/browser/controller.d.ts +55 -1
- package/dist/browser/controller.d.ts.map +1 -1
- package/dist/browser/controller.js +166 -9
- package/dist/browser/frame.d.ts +4 -3
- package/dist/browser/frame.d.ts.map +1 -1
- package/dist/browser/frame.js +12 -20
- package/dist/browser/index.d.ts +18 -6
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +64 -29
- package/dist/browser/popup.d.ts +6 -1
- package/dist/browser/popup.d.ts.map +1 -1
- package/dist/browser/popup.js +37 -8
- package/dist/cli/index.d.ts +4 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -3
- package/dist/cli/server.d.ts +5 -0
- package/dist/cli/server.d.ts.map +1 -1
- package/dist/cli/server.js +5 -0
- package/dist/client.d.ts +66 -19
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +125 -74
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/credentials.d.ts +58 -4
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +0 -0
- package/dist/errors.d.ts +23 -21
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -20
- package/dist/globals.d.ts +25 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +15 -0
- package/dist/grants-api.d.ts +34 -0
- package/dist/grants-api.d.ts.map +1 -0
- package/dist/grants-api.js +48 -0
- package/dist/grants.d.ts +16 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +13 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/inflight.d.ts +31 -0
- package/dist/inflight.d.ts.map +1 -0
- package/dist/inflight.js +26 -0
- package/dist/intents.d.ts +386 -40
- package/dist/intents.d.ts.map +1 -1
- package/dist/intents.js +712 -53
- package/dist/oauth.d.ts +55 -6
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +86 -57
- package/dist/presenter.d.ts +59 -11
- package/dist/presenter.d.ts.map +1 -1
- package/dist/presenter.js +40 -1
- package/dist/resource.d.ts +109 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +151 -0
- package/dist/rest.d.ts +23 -4
- package/dist/rest.d.ts.map +1 -1
- package/dist/rest.js +46 -5
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server-metadata.generated.d.ts.map +1 -1
- package/dist/server-metadata.generated.js +8 -4
- package/dist/service.d.ts +109 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +241 -0
- package/dist/session-store.d.ts +12 -4
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +64 -14
- package/dist/storage.d.ts +16 -23
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +27 -25
- package/dist/tokens.d.ts +46 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +148 -0
- package/package.json +13 -3
package/dist/browser/popup.js
CHANGED
|
@@ -28,7 +28,8 @@ export function andcoPopupPresentationId() {
|
|
|
28
28
|
return PRESENTATION_ID_PATTERN.test(presentationId) ? presentationId : null;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Hands this document's callback to the window that
|
|
31
|
+
* Hands this document's callback — an authorization or an Intent outcome — to the window that
|
|
32
|
+
* opened it, then closes.
|
|
32
33
|
*
|
|
33
34
|
* The popup cannot complete the exchange itself: the PKCE verifier was generated by the opener and
|
|
34
35
|
* never left it. So this is a courier, not a consumer — it carries the callback URL back and dies.
|
|
@@ -41,7 +42,11 @@ export function relayAndcoPopupCallback(allowedOrigins, options = {}) {
|
|
|
41
42
|
if (typeof window === "undefined")
|
|
42
43
|
return { status: "not_callback" };
|
|
43
44
|
const url = options.callbackUrl ? new URL(options.callbackUrl, window.location.href) : new URL(window.location.href);
|
|
44
|
-
const isCallback = Boolean(options.callbackUrl) ||
|
|
45
|
+
const isCallback = Boolean(options.callbackUrl) ||
|
|
46
|
+
url.searchParams.has("code") ||
|
|
47
|
+
url.searchParams.has("error") ||
|
|
48
|
+
// An Intent callback carries no authorization code; its outcome is the whole payload.
|
|
49
|
+
url.searchParams.has("andco_intent_result");
|
|
45
50
|
if (!isCallback)
|
|
46
51
|
return { status: "not_callback" };
|
|
47
52
|
const presentationId = andcoPopupPresentationId();
|
|
@@ -62,8 +67,9 @@ export function relayAndcoPopupCallback(allowedOrigins, options = {}) {
|
|
|
62
67
|
const message = openerOrigin === window.location.origin ? sdkMessage(presentationId, url) : protocolResult(presentationId, url);
|
|
63
68
|
// Strip before leaving. If closing is refused, the code must not remain visible in the address
|
|
64
69
|
// bar or in the window name.
|
|
65
|
-
for (const parameter of ["code", "state", "error", "error_description"])
|
|
70
|
+
for (const parameter of ["code", "state", "error", "error_description", "andco_intent_result", "intent_id"]) {
|
|
66
71
|
url.searchParams.delete(parameter);
|
|
72
|
+
}
|
|
67
73
|
window.history.replaceState(window.history.state, "", url);
|
|
68
74
|
window.name = "";
|
|
69
75
|
window.opener?.postMessage(message, openerOrigin);
|
|
@@ -75,14 +81,25 @@ function sdkMessage(presentationId, url) {
|
|
|
75
81
|
}
|
|
76
82
|
function protocolResult(presentationId, url) {
|
|
77
83
|
const envelope = { protocol: ANDCO_SDK_PROTOCOL, version: ANDCO_PROTOCOL_VERSION, presentationId };
|
|
84
|
+
// An Intent reports a lifecycle outcome and nothing else. Whether money moved is read from the
|
|
85
|
+
// Resource Server afterwards, never carried in a window message.
|
|
86
|
+
const intent = url.searchParams.get("andco_intent_result");
|
|
87
|
+
if (intent === "complete") {
|
|
88
|
+
return { ...envelope, type: "intent.complete" };
|
|
89
|
+
}
|
|
90
|
+
else if (intent) {
|
|
91
|
+
return { ...envelope, type: "intent.dismiss" };
|
|
92
|
+
}
|
|
78
93
|
const code = url.searchParams.get("code");
|
|
79
|
-
if (code)
|
|
94
|
+
if (code) {
|
|
80
95
|
return { ...envelope, type: "oauth.authorization_code", authorizationCode: code };
|
|
96
|
+
}
|
|
81
97
|
const error = url.searchParams.get("error") ?? "invalid_request";
|
|
82
98
|
// `access_denied` is the only OAuth error that carries a decision, and it is the one the
|
|
83
99
|
// Authorization Server returns when the user declines.
|
|
84
|
-
if (error === "access_denied")
|
|
100
|
+
if (error === "access_denied") {
|
|
85
101
|
return { ...envelope, type: "oauth.dismiss" };
|
|
102
|
+
}
|
|
86
103
|
const description = url.searchParams.get("error_description");
|
|
87
104
|
return {
|
|
88
105
|
...envelope,
|
|
@@ -105,12 +122,19 @@ function protocolResult(presentationId, url) {
|
|
|
105
122
|
* ```
|
|
106
123
|
*/
|
|
107
124
|
export function openAndcoPopupWindow(options) {
|
|
108
|
-
const
|
|
125
|
+
const name = `${ANDCO_POPUP_NAME_PREFIX}${options.presentationId}`;
|
|
126
|
+
const href = options.url?.href ?? "about:blank";
|
|
127
|
+
console.debug("[openAndcoPopupWindow] opening %s %s", options.target ?? "popup", name);
|
|
128
|
+
// Without window features a browser opens a tab; with them, a popup window.
|
|
129
|
+
const popup = options.target === "newtab"
|
|
130
|
+
? window.open(href, name)
|
|
131
|
+
: window.open(href, name, windowFeatures({ width: 620, height: 720 }));
|
|
109
132
|
if (!popup) {
|
|
110
133
|
return {
|
|
111
134
|
blocked: true,
|
|
112
135
|
navigate: () => { },
|
|
113
136
|
result: Promise.resolve(Result.fail(ANDCO_ERROR_CODES.POPUP_BLOCKED)),
|
|
137
|
+
focus: () => { },
|
|
114
138
|
close: () => { },
|
|
115
139
|
};
|
|
116
140
|
}
|
|
@@ -154,15 +178,20 @@ export function openAndcoPopupWindow(options) {
|
|
|
154
178
|
popup.close();
|
|
155
179
|
settle(Result.fail(ANDCO_ERROR_CODES.POPUP_TIMEOUT));
|
|
156
180
|
}, POPUP_TIMEOUT_MS);
|
|
157
|
-
|
|
181
|
+
const abort = () => {
|
|
158
182
|
popup.close();
|
|
159
183
|
settle(Result.ok(null));
|
|
160
|
-
}
|
|
184
|
+
};
|
|
185
|
+
if (options.signal?.aborted)
|
|
186
|
+
abort();
|
|
187
|
+
else
|
|
188
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
161
189
|
});
|
|
162
190
|
return {
|
|
163
191
|
blocked: false,
|
|
164
192
|
navigate: (url) => popup.location.assign(url.href),
|
|
165
193
|
result,
|
|
194
|
+
focus: () => popup.focus(),
|
|
166
195
|
close: () => popup.close(),
|
|
167
196
|
};
|
|
168
197
|
}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AndcoClient, type AndcoClientOptions } from "../client.js";
|
|
2
2
|
import { Result } from "../errors.js";
|
|
3
|
-
import
|
|
3
|
+
import { AndcoPresenter, type AndcoPresentOptions } from "../presenter.js";
|
|
4
|
+
/** Browser launch, terminal output, and callback timeout overrides for CLI authorization. */
|
|
4
5
|
export type AndcoCliPresenterOptions = {
|
|
5
6
|
/** Opens the authorization URL. Defaults to printing it, so nothing is assumed about the host. */
|
|
6
7
|
open?: (url: URL) => void | Promise<void>;
|
|
@@ -28,11 +29,12 @@ export type AndcoCliPresenterOptions = {
|
|
|
28
29
|
* const { data: session } = await andco.auth.signIn();
|
|
29
30
|
* ```
|
|
30
31
|
*/
|
|
31
|
-
export declare class
|
|
32
|
+
export declare class AndcoPresenterCli extends AndcoPresenter {
|
|
32
33
|
private readonly options;
|
|
33
34
|
constructor(options?: AndcoCliPresenterOptions);
|
|
34
35
|
present(presentation: AndcoPresentOptions): Promise<Result<URL | null>>;
|
|
35
36
|
}
|
|
37
|
+
/** Instance configuration with an optional CLI authorization presenter. */
|
|
36
38
|
export type AndcoCliOptions = Omit<AndcoClientOptions, "presenter"> & {
|
|
37
39
|
presenter?: AndcoPresenter;
|
|
38
40
|
};
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAqB,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAqB,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG3E,6FAA6F;AAC7F,MAAM,MAAM,wBAAwB,GAAG;IACrC,kGAAkG;IAClG,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAkB,SAAQ,cAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,wBAA6B;IAI7D,OAAO,CAAC,YAAY,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CAqC9E;AAED,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,GAAG;IACpE,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAE/E"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AndcoClient } from "../client.js";
|
|
2
2
|
import { isLoopback } from "../config.js";
|
|
3
3
|
import { ANDCO_ERROR_CODES, Result } from "../errors.js";
|
|
4
|
+
import { AndcoPresenter } from "../presenter.js";
|
|
4
5
|
import { LoopbackServer } from "./server.js";
|
|
5
6
|
/**
|
|
6
7
|
* Presents an authorization from a terminal, using a one-shot loopback receiver.
|
|
@@ -21,9 +22,10 @@ import { LoopbackServer } from "./server.js";
|
|
|
21
22
|
* const { data: session } = await andco.auth.signIn();
|
|
22
23
|
* ```
|
|
23
24
|
*/
|
|
24
|
-
export class
|
|
25
|
+
export class AndcoPresenterCli extends AndcoPresenter {
|
|
25
26
|
options;
|
|
26
27
|
constructor(options = {}) {
|
|
28
|
+
super();
|
|
27
29
|
this.options = options;
|
|
28
30
|
}
|
|
29
31
|
async present(presentation) {
|
|
@@ -44,9 +46,14 @@ export class AndcoCliPresenter {
|
|
|
44
46
|
});
|
|
45
47
|
}
|
|
46
48
|
try {
|
|
49
|
+
// Resolved after the receiver is bound: a pushed request is created on demand, and there is
|
|
50
|
+
// nothing to push before the callback it must name exists.
|
|
51
|
+
const resolved = await AndcoPresenter.present(presentation.url);
|
|
52
|
+
if (resolved.error)
|
|
53
|
+
return Result.fail(resolved.error);
|
|
47
54
|
// The bound port may differ from the configured one when it asked for any free port, and the
|
|
48
55
|
// authorization request must carry the exact URI the server will redirect to.
|
|
49
|
-
const url = new URL(
|
|
56
|
+
const url = new URL(resolved.data.href);
|
|
50
57
|
url.searchParams.set("redirect_uri", receiver.redirectUri.href);
|
|
51
58
|
if (this.options.open)
|
|
52
59
|
await this.options.open(url);
|
|
@@ -68,5 +75,5 @@ export class AndcoCliPresenter {
|
|
|
68
75
|
* credential is `andco.session.set(...)`, not a write into a private storage key.
|
|
69
76
|
*/
|
|
70
77
|
export function createAndcoInstanceForCLI(options) {
|
|
71
|
-
return new AndcoClient({ ...options, presenter: options.presenter ?? new
|
|
78
|
+
return new AndcoClient({ ...options, presenter: options.presenter ?? new AndcoPresenterCli() });
|
|
72
79
|
}
|
package/dist/cli/server.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/** Local OAuth callback receiver. The caller owns state/PKCE validation and server cleanup. */
|
|
1
2
|
export declare class LoopbackServer {
|
|
2
3
|
#private;
|
|
3
4
|
private constructor();
|
|
5
|
+
/** Starts listening; a missing port selects an available port reflected in `redirectUri`. */
|
|
4
6
|
static start(configured: URL): Promise<LoopbackServer>;
|
|
7
|
+
/** Exact callback URL including the port allocated by the operating system. */
|
|
5
8
|
get redirectUri(): URL;
|
|
9
|
+
/** Waits for a callback or returns `null` on timeout. Call `close()` after either outcome. */
|
|
6
10
|
wait(timeoutMs: number): Promise<URL | null>;
|
|
11
|
+
/** Closes the listener and any remaining connections. */
|
|
7
12
|
close(): Promise<void>;
|
|
8
13
|
private listen;
|
|
9
14
|
private static hostFor;
|
package/dist/cli/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/cli/server.ts"],"names":[],"mappings":"AAEA,qBAAa,cAAc;;IAKzB,OAAO;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/cli/server.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,qBAAa,cAAc;;IAKzB,OAAO;IAKP,6FAA6F;WAChF,KAAK,CAAC,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC;IAc5D,+EAA+E;IAC/E,IAAI,WAAW,IAAI,GAAG,CAErB;IAED,8FAA8F;IAC9F,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAS5C,yDAAyD;IACzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiDtB,OAAO,CAAC,MAAM;IAcd,OAAO,CAAC,MAAM,CAAC,OAAO;CAGvB"}
|
package/dist/cli/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
|
+
/** Local OAuth callback receiver. The caller owns state/PKCE validation and server cleanup. */
|
|
2
3
|
export class LoopbackServer {
|
|
3
4
|
#server;
|
|
4
5
|
#resolveCallback;
|
|
@@ -7,6 +8,7 @@ export class LoopbackServer {
|
|
|
7
8
|
this.#redirectUri = configured;
|
|
8
9
|
this.#server = this.#buildServer();
|
|
9
10
|
}
|
|
11
|
+
/** Starts listening; a missing port selects an available port reflected in `redirectUri`. */
|
|
10
12
|
static async start(configured) {
|
|
11
13
|
const receiver = new LoopbackServer(configured);
|
|
12
14
|
await receiver.listen();
|
|
@@ -19,9 +21,11 @@ export class LoopbackServer {
|
|
|
19
21
|
receiver.#redirectUri.port = String(address.port);
|
|
20
22
|
return receiver;
|
|
21
23
|
}
|
|
24
|
+
/** Exact callback URL including the port allocated by the operating system. */
|
|
22
25
|
get redirectUri() {
|
|
23
26
|
return this.#redirectUri;
|
|
24
27
|
}
|
|
28
|
+
/** Waits for a callback or returns `null` on timeout. Call `close()` after either outcome. */
|
|
25
29
|
wait(timeoutMs) {
|
|
26
30
|
return new Promise((resolve) => {
|
|
27
31
|
this.#resolveCallback = resolve;
|
|
@@ -30,6 +34,7 @@ export class LoopbackServer {
|
|
|
30
34
|
timer.unref?.();
|
|
31
35
|
});
|
|
32
36
|
}
|
|
37
|
+
/** Closes the listener and any remaining connections. */
|
|
33
38
|
close() {
|
|
34
39
|
return new Promise((resolve) => {
|
|
35
40
|
this.#server.closeAllConnections?.();
|
package/dist/client.d.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
|
-
import type { AndCoRandomSource } from "@andco/protocol";
|
|
2
1
|
import { AndcoAuth } from "./auth.js";
|
|
3
2
|
import { type AndcoConfig, type AndcoConfigInput } from "./config.js";
|
|
4
3
|
import { type AndcoCredentials, type AndcoSession } from "./credentials.js";
|
|
4
|
+
import { type AndcoGlobals } from "./globals.js";
|
|
5
|
+
import { AndcoGrants } from "./grants-api.js";
|
|
6
|
+
import type { AndcoInflight } from "./inflight.js";
|
|
5
7
|
import { AndcoIntents } from "./intents.js";
|
|
6
8
|
import { type AndcoAuthorizationRequest, AndcoOAuth, type AndcoTransportMode } from "./oauth.js";
|
|
7
|
-
import
|
|
9
|
+
import { AndcoPresenter } from "./presenter.js";
|
|
10
|
+
import { AndcoResource } from "./resource.js";
|
|
8
11
|
import { AndcoRest } from "./rest.js";
|
|
9
12
|
import { type AndcoSessionSource, AndcoSessionStore } from "./session-store.js";
|
|
10
|
-
import type {
|
|
13
|
+
import type { AndcoStorage } from "./storage.js";
|
|
14
|
+
import { AndcoTokens } from "./tokens.js";
|
|
11
15
|
/** A Resource Server Definition: immutable, and able to bind itself to a client. */
|
|
12
16
|
export interface AndcoResourceServer<Client> {
|
|
17
|
+
/** Registered Resource Server ID used in authorization contributions. */
|
|
13
18
|
readonly id: string;
|
|
19
|
+
/** OAuth Resource Indicator used to select the matching bearer credential. */
|
|
14
20
|
readonly resource: string;
|
|
15
21
|
/**
|
|
16
22
|
* Produces an operational client for this Resource Server from resolved credentials.
|
|
@@ -21,15 +27,11 @@ export interface AndcoResourceServer<Client> {
|
|
|
21
27
|
*/
|
|
22
28
|
use(credentials: AndcoCredentials): Client;
|
|
23
29
|
}
|
|
24
|
-
/**
|
|
25
|
-
export type AndcoGlobals = {
|
|
26
|
-
fetch: typeof globalThis.fetch;
|
|
27
|
-
/** Threaded into the Protocol Contract's `RANDOM_UUID`, so a runtime without Web Crypto can supply its own. */
|
|
28
|
-
crypto: AndCoRandomSource;
|
|
29
|
-
};
|
|
30
|
+
/** Configuration and runtime capabilities shared by browser, server, and CLI instances. */
|
|
30
31
|
export type AndcoClientOptions = AndcoConfigInput & {
|
|
31
32
|
/** Confidential credential. Its presence is what makes this a confidential OAuth client. */
|
|
32
33
|
clientSecret?: string | null;
|
|
34
|
+
/** Overrides runtime fetch and randomness; omitted capabilities use platform defaults. */
|
|
33
35
|
globals?: Partial<AndcoGlobals>;
|
|
34
36
|
/** Authorization Transport Policy. Defaults to `auto`. */
|
|
35
37
|
transport?: AndcoTransportMode;
|
|
@@ -37,14 +39,66 @@ export type AndcoClientOptions = AndcoConfigInput & {
|
|
|
37
39
|
presenter?: AndcoPresenter;
|
|
38
40
|
/** Persists a transaction so it survives a full-page redirect. */
|
|
39
41
|
persistTransaction?: (request: AndcoAuthorizationRequest) => void | Promise<void>;
|
|
42
|
+
/** Session persistence adapter. Defaults to memory unless a runtime factory supplies one. */
|
|
40
43
|
storage?: AndcoStorage;
|
|
41
44
|
/** A session the caller already resolved, so the first snapshot is real rather than unresolved. */
|
|
42
45
|
initialSession?: AndcoSession | null;
|
|
43
|
-
|
|
46
|
+
/** Shares one refresh among concurrent callers. Defaults to sharing within this runtime. */
|
|
47
|
+
inflight?: AndcoInflight;
|
|
44
48
|
/** Consulted once during the load, before storage. This is where a URL callback enters. */
|
|
45
49
|
source?: AndcoSessionSource;
|
|
50
|
+
/** Writes session changes to storage unless `false`; defaults to `true`. */
|
|
46
51
|
persist?: boolean;
|
|
47
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* The eight collaborator fields shared, verbatim, by {@link AndcoClient} and both of the authorized
|
|
55
|
+
* views behind `with(...)` and `authorized()`. Declaring them once here is what keeps adding a field
|
|
56
|
+
* to the instance from requiring three synchronized edits.
|
|
57
|
+
*
|
|
58
|
+
* This is a construction seam, not a claim that the three are interchangeable: each subclass still
|
|
59
|
+
* decides for itself — per the ADR-0023 invariants documented at `AndcoAuthedClientImpl` and
|
|
60
|
+
* `AndcoAuthorizedViewImpl` — whether a given field's value is freshly built or borrowed by reference
|
|
61
|
+
* from an owner. The base constructor only stores whatever it is handed.
|
|
62
|
+
*/
|
|
63
|
+
declare class AndcoClientFields {
|
|
64
|
+
readonly config: AndcoConfig;
|
|
65
|
+
readonly clientSecret: string | null;
|
|
66
|
+
readonly globals: AndcoGlobals;
|
|
67
|
+
readonly oauth: AndcoOAuth;
|
|
68
|
+
readonly rest: AndcoRest;
|
|
69
|
+
readonly intents: AndcoIntents;
|
|
70
|
+
readonly auth: AndcoAuth;
|
|
71
|
+
readonly session: AndcoSessionStore;
|
|
72
|
+
/** Offline verification of access tokens with the Authorization Server JWKS. */
|
|
73
|
+
readonly tokens: AndcoTokens;
|
|
74
|
+
/** Live Grant lookup for a token. */
|
|
75
|
+
readonly grants: AndcoGrants;
|
|
76
|
+
protected constructor(fields: {
|
|
77
|
+
config: AndcoConfig;
|
|
78
|
+
clientSecret: string | null;
|
|
79
|
+
globals: AndcoGlobals;
|
|
80
|
+
oauth: AndcoOAuth;
|
|
81
|
+
rest: AndcoRest;
|
|
82
|
+
intents: AndcoIntents;
|
|
83
|
+
auth: AndcoAuth;
|
|
84
|
+
session: AndcoSessionStore;
|
|
85
|
+
tokens: AndcoTokens;
|
|
86
|
+
grants: AndcoGrants;
|
|
87
|
+
});
|
|
88
|
+
/**
|
|
89
|
+
* Acts as the Resource Server identified by `resource`: verifies tokens and protects routes.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const orders = andco.resource({ resource: "https://casa-norte.example/api" });
|
|
94
|
+
* app.use("/api/orders/*", orders.protect({ scopes: ["orders:read"] }).hono());
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
resource(options: {
|
|
98
|
+
resource: string;
|
|
99
|
+
resourceMetadata?: string;
|
|
100
|
+
}): AndcoResource;
|
|
101
|
+
}
|
|
48
102
|
/**
|
|
49
103
|
* An Andco Instance without resolved credentials.
|
|
50
104
|
*
|
|
@@ -65,15 +119,7 @@ export type AndcoClientOptions = AndcoConfigInput & {
|
|
|
65
119
|
* const bound = andco.with(await sessionFromCookie());
|
|
66
120
|
* ```
|
|
67
121
|
*/
|
|
68
|
-
export declare class AndcoClient {
|
|
69
|
-
readonly config: AndcoConfig;
|
|
70
|
-
readonly clientSecret: string | null;
|
|
71
|
-
readonly globals: AndcoGlobals;
|
|
72
|
-
readonly oauth: AndcoOAuth;
|
|
73
|
-
readonly rest: AndcoRest;
|
|
74
|
-
readonly intents: AndcoIntents;
|
|
75
|
-
readonly auth: AndcoAuth;
|
|
76
|
-
readonly session: AndcoSessionStore;
|
|
122
|
+
export declare class AndcoClient extends AndcoClientFields {
|
|
77
123
|
/** Runtime discriminant: `false` here, `true` on the value `with(...)` returns. */
|
|
78
124
|
readonly isAuthed: false;
|
|
79
125
|
constructor(options: AndcoClientOptions);
|
|
@@ -132,4 +178,5 @@ export declare class AndcoClient {
|
|
|
132
178
|
export type AndcoClientAuthed = Omit<AndcoClient, "isAuthed" | "with" | "authorized"> & AndcoCredentials & {
|
|
133
179
|
readonly isAuthed: true;
|
|
134
180
|
};
|
|
181
|
+
export {};
|
|
135
182
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -2,10 +2,63 @@ import { AndcoAuth } from "./auth.js";
|
|
|
2
2
|
import { AndcoConfig as Config } from "./config.js";
|
|
3
3
|
import { credentialsFromSession, isCredentials } from "./credentials.js";
|
|
4
4
|
import { Result } from "./errors.js";
|
|
5
|
+
import { resolveGlobals } from "./globals.js";
|
|
6
|
+
import { AndcoGrants } from "./grants-api.js";
|
|
5
7
|
import { AndcoIntents } from "./intents.js";
|
|
6
8
|
import { AndcoOAuth } from "./oauth.js";
|
|
9
|
+
import { AndcoPresenter } from "./presenter.js";
|
|
10
|
+
import { AndcoResource } from "./resource.js";
|
|
7
11
|
import { AndcoRest } from "./rest.js";
|
|
8
12
|
import { AndcoSessionStore, browserRequired } from "./session-store.js";
|
|
13
|
+
import { AndcoTokens } from "./tokens.js";
|
|
14
|
+
/**
|
|
15
|
+
* The eight collaborator fields shared, verbatim, by {@link AndcoClient} and both of the authorized
|
|
16
|
+
* views behind `with(...)` and `authorized()`. Declaring them once here is what keeps adding a field
|
|
17
|
+
* to the instance from requiring three synchronized edits.
|
|
18
|
+
*
|
|
19
|
+
* This is a construction seam, not a claim that the three are interchangeable: each subclass still
|
|
20
|
+
* decides for itself — per the ADR-0023 invariants documented at `AndcoAuthedClientImpl` and
|
|
21
|
+
* `AndcoAuthorizedViewImpl` — whether a given field's value is freshly built or borrowed by reference
|
|
22
|
+
* from an owner. The base constructor only stores whatever it is handed.
|
|
23
|
+
*/
|
|
24
|
+
class AndcoClientFields {
|
|
25
|
+
config;
|
|
26
|
+
clientSecret;
|
|
27
|
+
globals;
|
|
28
|
+
oauth;
|
|
29
|
+
rest;
|
|
30
|
+
intents;
|
|
31
|
+
auth;
|
|
32
|
+
session;
|
|
33
|
+
/** Offline verification of access tokens with the Authorization Server JWKS. */
|
|
34
|
+
tokens;
|
|
35
|
+
/** Live Grant lookup for a token. */
|
|
36
|
+
grants;
|
|
37
|
+
constructor(fields) {
|
|
38
|
+
this.config = fields.config;
|
|
39
|
+
this.clientSecret = fields.clientSecret;
|
|
40
|
+
this.globals = fields.globals;
|
|
41
|
+
this.oauth = fields.oauth;
|
|
42
|
+
this.rest = fields.rest;
|
|
43
|
+
this.intents = fields.intents;
|
|
44
|
+
this.auth = fields.auth;
|
|
45
|
+
this.session = fields.session;
|
|
46
|
+
this.tokens = fields.tokens;
|
|
47
|
+
this.grants = fields.grants;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Acts as the Resource Server identified by `resource`: verifies tokens and protects routes.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const orders = andco.resource({ resource: "https://casa-norte.example/api" });
|
|
55
|
+
* app.use("/api/orders/*", orders.protect({ scopes: ["orders:read"] }).hono());
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
resource(options) {
|
|
59
|
+
return new AndcoResource({ ...options, tokens: this.tokens, grants: this.grants });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
9
62
|
/**
|
|
10
63
|
* An Andco Instance without resolved credentials.
|
|
11
64
|
*
|
|
@@ -26,50 +79,52 @@ import { AndcoSessionStore, browserRequired } from "./session-store.js";
|
|
|
26
79
|
* const bound = andco.with(await sessionFromCookie());
|
|
27
80
|
* ```
|
|
28
81
|
*/
|
|
29
|
-
export class AndcoClient {
|
|
30
|
-
config;
|
|
31
|
-
clientSecret;
|
|
32
|
-
globals;
|
|
33
|
-
oauth;
|
|
34
|
-
rest;
|
|
35
|
-
intents;
|
|
36
|
-
auth;
|
|
37
|
-
session;
|
|
82
|
+
export class AndcoClient extends AndcoClientFields {
|
|
38
83
|
/** Runtime discriminant: `false` here, `true` on the value `with(...)` returns. */
|
|
39
84
|
isAuthed = false;
|
|
40
85
|
constructor(options) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
config: this.config,
|
|
49
|
-
fetch: this.globals.fetch,
|
|
50
|
-
clientSecret: this.clientSecret,
|
|
86
|
+
const config = Config.from(options);
|
|
87
|
+
const clientSecret = options.clientSecret ?? null;
|
|
88
|
+
const globals = resolveGlobals(options.globals);
|
|
89
|
+
const oauth = new AndcoOAuth({
|
|
90
|
+
config,
|
|
91
|
+
globals,
|
|
92
|
+
clientSecret,
|
|
51
93
|
transport: options.transport,
|
|
52
94
|
});
|
|
53
95
|
// The store is real even without a presenter: it is what lets `rest` stay one object across a
|
|
54
96
|
// sign-in, and what gives `auth` something to operate on regardless of runtime.
|
|
55
|
-
|
|
56
|
-
config
|
|
57
|
-
oauth
|
|
97
|
+
const session = new AndcoSessionStore({
|
|
98
|
+
config,
|
|
99
|
+
oauth,
|
|
58
100
|
storage: options.storage,
|
|
59
101
|
initialSession: options.initialSession,
|
|
60
|
-
|
|
102
|
+
inflight: options.inflight,
|
|
61
103
|
source: options.source,
|
|
62
104
|
persist: options.persist,
|
|
63
105
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
106
|
+
// One presenter for the whole instance: authorization and Intent are the same seam, so a
|
|
107
|
+
// runtime that can present one can present the other. Not public — nothing outside the
|
|
108
|
+
// instance chooses how it presents, and every mirror of this type would have to carry it.
|
|
109
|
+
const presenter = options.presenter ?? new AndcoPresenterStateless();
|
|
110
|
+
const auth = new AndcoAuth({
|
|
111
|
+
config,
|
|
112
|
+
oauth,
|
|
113
|
+
store: session,
|
|
114
|
+
presenter,
|
|
68
115
|
persistTransaction: options.persistTransaction,
|
|
69
|
-
|
|
116
|
+
globals,
|
|
70
117
|
});
|
|
71
|
-
|
|
72
|
-
|
|
118
|
+
const rest = new AndcoRest({ config, globals, credentials: session });
|
|
119
|
+
const intents = new AndcoIntents({
|
|
120
|
+
rest,
|
|
121
|
+
config,
|
|
122
|
+
presenter,
|
|
123
|
+
globals,
|
|
124
|
+
});
|
|
125
|
+
const tokens = new AndcoTokens({ config, globals });
|
|
126
|
+
const grants = new AndcoGrants({ config, globals });
|
|
127
|
+
super({ config, clientSecret, globals, oauth, rest, intents, auth, session, tokens, grants });
|
|
73
128
|
}
|
|
74
129
|
/**
|
|
75
130
|
* Binds *explicit* credentials for one unit of work, owning its own REST surface.
|
|
@@ -131,45 +186,45 @@ export class AndcoClient {
|
|
|
131
186
|
}
|
|
132
187
|
}
|
|
133
188
|
/** Presents nothing; every authorization attempt fails clearly instead of doing nothing silently. */
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
},
|
|
139
|
-
};
|
|
189
|
+
class AndcoPresenterStateless extends AndcoPresenter {
|
|
190
|
+
async present() {
|
|
191
|
+
return Result.fail(browserRequired());
|
|
192
|
+
}
|
|
140
193
|
}
|
|
141
194
|
/**
|
|
142
195
|
* The implementation behind `with(...)`. Not exported: `AndcoClientAuthed` is the entire public
|
|
143
196
|
* contract, so a caller never has a reason to name this type.
|
|
144
197
|
*/
|
|
145
|
-
class AndcoAuthedClientImpl {
|
|
198
|
+
class AndcoAuthedClientImpl extends AndcoClientFields {
|
|
146
199
|
credentials;
|
|
147
200
|
isAuthed = true;
|
|
148
|
-
config;
|
|
149
|
-
clientSecret;
|
|
150
|
-
globals;
|
|
151
|
-
oauth;
|
|
152
|
-
rest;
|
|
153
|
-
intents;
|
|
154
|
-
auth;
|
|
155
|
-
session;
|
|
156
201
|
constructor(owner, credentials) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
this.globals = owner.globals;
|
|
161
|
-
this.oauth = owner.oauth;
|
|
162
|
-
this.rest = new AndcoRest({ config: owner.config, fetch: owner.globals.fetch, credentials });
|
|
163
|
-
this.intents = new AndcoIntents(this.rest, owner.globals.crypto);
|
|
202
|
+
const rest = new AndcoRest({ config: owner.config, globals: owner.globals, credentials });
|
|
203
|
+
// No presenter: `with(...)` is the per-request server shape, and a request presents nothing.
|
|
204
|
+
const intents = new AndcoIntents({ rest, config: owner.config, globals: owner.globals });
|
|
164
205
|
// In-memory and unlinked from `credentials`: it exists only so `auth` has something to operate
|
|
165
206
|
// on, since a bare token or a caller-supplied resolver carries no persistable session shape.
|
|
166
|
-
|
|
167
|
-
|
|
207
|
+
const session = new AndcoSessionStore({ config: owner.config, oauth: owner.oauth, persist: false });
|
|
208
|
+
const auth = new AndcoAuth({
|
|
209
|
+
config: owner.config,
|
|
168
210
|
oauth: owner.oauth,
|
|
169
|
-
store:
|
|
170
|
-
presenter:
|
|
171
|
-
|
|
211
|
+
store: session,
|
|
212
|
+
presenter: new AndcoPresenterStateless(),
|
|
213
|
+
globals: owner.globals,
|
|
172
214
|
});
|
|
215
|
+
super({
|
|
216
|
+
config: owner.config,
|
|
217
|
+
clientSecret: owner.clientSecret,
|
|
218
|
+
globals: owner.globals,
|
|
219
|
+
oauth: owner.oauth,
|
|
220
|
+
rest,
|
|
221
|
+
intents,
|
|
222
|
+
auth,
|
|
223
|
+
session,
|
|
224
|
+
tokens: owner.tokens,
|
|
225
|
+
grants: owner.grants,
|
|
226
|
+
});
|
|
227
|
+
this.credentials = credentials;
|
|
173
228
|
}
|
|
174
229
|
accessTokenFor(resource) {
|
|
175
230
|
return this.credentials.accessTokenFor(resource);
|
|
@@ -181,27 +236,23 @@ class AndcoAuthedClientImpl {
|
|
|
181
236
|
* unchanged across a sign-in, satisfying "one REST surface per instance" even where a framework
|
|
182
237
|
* adapter hands out a fresh `AndcoClientAuthed` reference on every Authorized Identity change.
|
|
183
238
|
*/
|
|
184
|
-
class AndcoAuthorizedViewImpl {
|
|
239
|
+
class AndcoAuthorizedViewImpl extends AndcoClientFields {
|
|
185
240
|
owner;
|
|
186
241
|
isAuthed = true;
|
|
187
|
-
config;
|
|
188
|
-
clientSecret;
|
|
189
|
-
globals;
|
|
190
|
-
oauth;
|
|
191
|
-
rest;
|
|
192
|
-
intents;
|
|
193
|
-
auth;
|
|
194
|
-
session;
|
|
195
242
|
constructor(owner) {
|
|
243
|
+
super({
|
|
244
|
+
config: owner.config,
|
|
245
|
+
clientSecret: owner.clientSecret,
|
|
246
|
+
globals: owner.globals,
|
|
247
|
+
oauth: owner.oauth,
|
|
248
|
+
rest: owner.rest,
|
|
249
|
+
intents: owner.intents,
|
|
250
|
+
auth: owner.auth,
|
|
251
|
+
session: owner.session,
|
|
252
|
+
tokens: owner.tokens,
|
|
253
|
+
grants: owner.grants,
|
|
254
|
+
});
|
|
196
255
|
this.owner = owner;
|
|
197
|
-
this.config = owner.config;
|
|
198
|
-
this.clientSecret = owner.clientSecret;
|
|
199
|
-
this.globals = owner.globals;
|
|
200
|
-
this.oauth = owner.oauth;
|
|
201
|
-
this.rest = owner.rest;
|
|
202
|
-
this.intents = owner.intents;
|
|
203
|
-
this.auth = owner.auth;
|
|
204
|
-
this.session = owner.session;
|
|
205
256
|
}
|
|
206
257
|
/** Delegates to the instance's own session store on every call, so a rotated token is still picked up. */
|
|
207
258
|
accessTokenFor(resource) {
|
package/dist/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type AndcoTheme = "base";
|
|
|
5
5
|
* An OAuth scope. Known Andco scopes are suggested; a Resource Server may define its own.
|
|
6
6
|
*
|
|
7
7
|
* The Protocol Contract already knows the scope vocabulary, so this is that type rather than a bare
|
|
8
|
-
* `string`: an editor completes `
|
|
8
|
+
* `string`: an editor completes `offline_access` without closing the door on a scope Andco has
|
|
9
9
|
* not shipped yet.
|
|
10
10
|
*/
|
|
11
11
|
export type AndcoScope = AndCoScope;
|
|
@@ -75,6 +75,7 @@ export declare class AndcoConfig {
|
|
|
75
75
|
widgetURL(release: number, surface?: "button"): URL;
|
|
76
76
|
/** Whether an origin may participate in popup messaging for this instance. */
|
|
77
77
|
allowsPopupOrigin(origin: string): boolean;
|
|
78
|
+
/** Serializes configuration to constructor input without credentials or runtime collaborators. */
|
|
78
79
|
toJSON(): AndcoConfigInput;
|
|
79
80
|
}
|
|
80
81
|
/** Loopback over plain HTTP is accepted so local development and CLI callbacks work unmodified. */
|