@astralbeam/sdk 0.6.0 → 0.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 +2 -3
- package/dist/client.d.ts +7 -2
- package/dist/client.js +1 -1
- package/dist/{core-DYXxodYg.js → core-BF1G1dLe.js} +79 -27
- package/dist/core.d.ts +2 -2
- package/dist/core.js +2 -2
- package/dist/{index-TbZxlv54.d.ts → index-CudekMKM.d.ts} +146 -23
- package/dist/react.d.ts +10 -49
- package/dist/react.js +5 -12
- package/dist/server.d.ts +20 -16
- package/dist/server.js +42 -39
- package/dist/widget-PZ-6BF36.js +79 -0
- package/package.json +4 -18
- package/dist/vue.d.ts +0 -4
- package/dist/vue.js +0 -4
- package/dist/widget-CfLWAtV7.js +0 -79
package/dist/server.d.ts
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
|
|
3
1
|
//#region src/server/index.d.ts
|
|
4
2
|
declare const CHAT_AUTH_TOKEN_AUDIENCE = "astralbeam";
|
|
5
3
|
declare const CHAT_AUTH_TOKEN_TYPE = "astralbeam+jwt";
|
|
6
4
|
declare const CHAT_AUTH_TOKEN_VERSION = 4;
|
|
7
5
|
declare const CHAT_AUTH_TOKEN_LIFETIME_SECONDS = 300;
|
|
8
6
|
declare const CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS = 600;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readonly
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
readonly
|
|
16
|
-
|
|
17
|
-
readonly admin: Schema.optional<Schema.Boolean>;
|
|
18
|
-
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
|
|
19
|
-
}>;
|
|
7
|
+
/** A JSON value, which is all a `metadata` object may hold: the token carries it verbatim. */
|
|
8
|
+
type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
|
|
9
|
+
readonly [key: string]: JsonValue;
|
|
10
|
+
};
|
|
11
|
+
/** A `metadata` object: caller-owned keys, preserved verbatim in the token's claims. */
|
|
12
|
+
type JsonMetadata = {
|
|
13
|
+
readonly [key: string]: JsonValue;
|
|
14
|
+
};
|
|
20
15
|
/** Tenant identity from the Organization's application, including JSON metadata. */
|
|
21
|
-
|
|
16
|
+
interface Tenant {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly name?: string | undefined;
|
|
19
|
+
readonly metadata?: JsonMetadata | undefined;
|
|
20
|
+
}
|
|
22
21
|
/** User of an Organization's Tenant who interacts with AstralBeam. */
|
|
23
|
-
|
|
22
|
+
interface TenantUser {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly name?: string | undefined;
|
|
25
|
+
readonly admin?: boolean | undefined;
|
|
26
|
+
readonly metadata?: JsonMetadata | undefined;
|
|
27
|
+
}
|
|
24
28
|
interface CreateChatAuthTokenOptions<TTenantUser extends TenantUser = TenantUser, TTenant extends Tenant = Tenant> {
|
|
25
29
|
readonly apiKey: string;
|
|
26
30
|
readonly user: TTenantUser;
|
|
@@ -35,4 +39,4 @@ declare function createChatAuthToken<TTenantUser extends TenantUser = TenantUser
|
|
|
35
39
|
expiresInSeconds
|
|
36
40
|
}: CreateChatAuthTokenOptions<TTenantUser, TTenant>): Promise<string>;
|
|
37
41
|
//#endregion
|
|
38
|
-
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION, CreateChatAuthTokenOptions,
|
|
42
|
+
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION, CreateChatAuthTokenOptions, JsonMetadata, JsonValue, Tenant, TenantUser, createChatAuthToken };
|
package/dist/server.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
1
|
//#region node_modules/.deno/jose@6.2.9/node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
3
2
|
const encoder = new TextEncoder();
|
|
4
3
|
const decoder = new TextDecoder();
|
|
@@ -645,43 +644,22 @@ const CHAT_AUTH_TOKEN_LIFETIME_SECONDS = 300;
|
|
|
645
644
|
const CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS = 600;
|
|
646
645
|
const CHAT_AUTH_TOKEN_MAX_BYTES = 16384;
|
|
647
646
|
const IDENTITY_MAX_BYTES = 8192;
|
|
647
|
+
const EXTERNAL_ID_MAX_LENGTH = 255;
|
|
648
|
+
const API_KEY_PATTERN = /^key_[0-9a-z-]{1,63}_[0-9a-z-]{1,63}_abo_[A-Za-z]{64}$/;
|
|
649
|
+
const TENANT_FIELDS = [
|
|
650
|
+
"id",
|
|
651
|
+
"name",
|
|
652
|
+
"metadata"
|
|
653
|
+
];
|
|
654
|
+
const TENANT_USER_FIELDS = [
|
|
655
|
+
"id",
|
|
656
|
+
"name",
|
|
657
|
+
"admin",
|
|
658
|
+
"metadata"
|
|
659
|
+
];
|
|
648
660
|
const textEncoder = new TextEncoder();
|
|
649
|
-
const SlugSchema = Schema.String.pipe(Schema.check(Schema.isPattern(/^[0-9a-z-]{1,63}$/)));
|
|
650
|
-
const ApiKeySecretSchema = Schema.String.pipe(Schema.check(Schema.isPattern(/^abo_[A-Za-z]{64}$/)));
|
|
651
|
-
const ApiKeySchema = Schema.TemplateLiteral([
|
|
652
|
-
"key_",
|
|
653
|
-
SlugSchema,
|
|
654
|
-
"_",
|
|
655
|
-
SlugSchema,
|
|
656
|
-
"_",
|
|
657
|
-
ApiKeySecretSchema
|
|
658
|
-
]);
|
|
659
|
-
const isApiKey = Schema.is(ApiKeySchema);
|
|
660
|
-
const MetadataSchema = Schema.JsonObject.annotate({ message: "metadata must be a JSON object" });
|
|
661
|
-
const TenantExternalIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => value.length >= 1 && value.length <= 255, { message: "tenant.id must be a 1-255 character string" })));
|
|
662
|
-
const TenantUserExternalIdSchema = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => value.length >= 1 && value.length <= 255, { message: "user.id must be a 1-255 character string" })));
|
|
663
|
-
const TenantSchema = Schema.Struct({
|
|
664
|
-
id: TenantExternalIdSchema,
|
|
665
|
-
name: Schema.optional(Schema.String),
|
|
666
|
-
metadata: Schema.optional(MetadataSchema)
|
|
667
|
-
});
|
|
668
|
-
const TenantUserSchema = Schema.Struct({
|
|
669
|
-
id: TenantUserExternalIdSchema,
|
|
670
|
-
name: Schema.optional(Schema.String),
|
|
671
|
-
admin: Schema.optional(Schema.Boolean),
|
|
672
|
-
metadata: Schema.optional(MetadataSchema)
|
|
673
|
-
});
|
|
674
|
-
const IdentitySchema = Schema.Struct({
|
|
675
|
-
user: TenantUserSchema,
|
|
676
|
-
tenant: TenantSchema
|
|
677
|
-
}).pipe(Schema.check(Schema.makeFilter((value) => textEncoder.encode(JSON.stringify(value)).byteLength <= IDENTITY_MAX_BYTES, { message: `user and tenant must not exceed ${IDENTITY_MAX_BYTES} bytes` })));
|
|
678
|
-
const decodeIdentity = Schema.decodeUnknownSync(IdentitySchema, {
|
|
679
|
-
errors: "all",
|
|
680
|
-
onExcessProperty: "error",
|
|
681
|
-
reportInput: false
|
|
682
|
-
});
|
|
683
661
|
function parseApiKey(apiKey) {
|
|
684
|
-
if (!
|
|
662
|
+
if (!API_KEY_PATTERN.test(apiKey)) throw new Error("apiKey must match key_<organization>_<key>_abo_<secret>");
|
|
685
663
|
const separator = apiKey.lastIndexOf("_abo_");
|
|
686
664
|
const keyId = apiKey.slice(0, separator);
|
|
687
665
|
const keySecret = apiKey.slice(separator + 1);
|
|
@@ -691,11 +669,36 @@ function parseApiKey(apiKey) {
|
|
|
691
669
|
keySecret
|
|
692
670
|
};
|
|
693
671
|
}
|
|
672
|
+
function isPlainObject(value) {
|
|
673
|
+
if (typeof value !== "object" || value === null) return false;
|
|
674
|
+
const prototype = Object.getPrototypeOf(value);
|
|
675
|
+
return prototype === Object.prototype || prototype === null;
|
|
676
|
+
}
|
|
677
|
+
function isJsonValue(value) {
|
|
678
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
679
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
680
|
+
if (Array.isArray(value)) return value.every(isJsonValue);
|
|
681
|
+
return isPlainObject(value) && Object.values(value).every(isJsonValue);
|
|
682
|
+
}
|
|
683
|
+
function validateIdentity(label, value, isUser) {
|
|
684
|
+
if (!isPlainObject(value)) throw new Error(`${label} must be an object`);
|
|
685
|
+
const fields = isUser ? TENANT_USER_FIELDS : TENANT_FIELDS;
|
|
686
|
+
for (const key of Object.keys(value)) if (!fields.includes(key)) throw new Error(`${label} has an unknown field "${key}"`);
|
|
687
|
+
const { id, name, admin, metadata } = value;
|
|
688
|
+
if (typeof id !== "string" || id.length < 1 || id.length > EXTERNAL_ID_MAX_LENGTH) throw new Error(`${label}.id must be a 1-${EXTERNAL_ID_MAX_LENGTH} character string`);
|
|
689
|
+
if (name !== void 0 && typeof name !== "string") throw new Error(`${label}.name must be a string`);
|
|
690
|
+
if (isUser && admin !== void 0 && typeof admin !== "boolean") throw new Error(`${label}.admin must be a boolean`);
|
|
691
|
+
if (metadata !== void 0 && !(isPlainObject(metadata) && isJsonValue(metadata))) throw new Error(`${label}.metadata must be a JSON object`);
|
|
692
|
+
}
|
|
694
693
|
function validatedIdentity(user, tenant) {
|
|
695
|
-
|
|
694
|
+
validateIdentity("user", user, true);
|
|
695
|
+
validateIdentity("tenant", tenant, false);
|
|
696
|
+
const json = JSON.stringify({
|
|
696
697
|
user,
|
|
697
698
|
tenant
|
|
698
|
-
})
|
|
699
|
+
});
|
|
700
|
+
if (textEncoder.encode(json).byteLength > IDENTITY_MAX_BYTES) throw new Error(`user and tenant must not exceed ${IDENTITY_MAX_BYTES} bytes`);
|
|
701
|
+
return JSON.parse(json);
|
|
699
702
|
}
|
|
700
703
|
async function signingKey(secret) {
|
|
701
704
|
const digest = await crypto.subtle.digest("SHA-256", textEncoder.encode(secret));
|
|
@@ -720,4 +723,4 @@ async function createChatAuthToken({ apiKey, user, tenant, expiresInSeconds = 30
|
|
|
720
723
|
return token;
|
|
721
724
|
}
|
|
722
725
|
//#endregion
|
|
723
|
-
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION,
|
|
726
|
+
export { CHAT_AUTH_TOKEN_AUDIENCE, CHAT_AUTH_TOKEN_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_MAX_LIFETIME_SECONDS, CHAT_AUTH_TOKEN_TYPE, CHAT_AUTH_TOKEN_VERSION, createChatAuthToken };
|