@seamapi/http 0.0.2
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.txt +20 -0
- package/README.md +155 -0
- package/connect.d.ts +1 -0
- package/connect.js +2 -0
- package/connect.js.map +1 -0
- package/dist/connect.cjs +219 -0
- package/dist/connect.cjs.map +1 -0
- package/dist/connect.d.cts +35 -0
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/index.js.map +1 -0
- package/lib/seam/connect/auth.d.ts +7 -0
- package/lib/seam/connect/auth.js +47 -0
- package/lib/seam/connect/auth.js.map +1 -0
- package/lib/seam/connect/axios.d.ts +3 -0
- package/lib/seam/connect/axios.js +17 -0
- package/lib/seam/connect/axios.js.map +1 -0
- package/lib/seam/connect/client-options.d.ts +19 -0
- package/lib/seam/connect/client-options.js +29 -0
- package/lib/seam/connect/client-options.js.map +1 -0
- package/lib/seam/connect/client.d.ts +11 -0
- package/lib/seam/connect/client.js +51 -0
- package/lib/seam/connect/client.js.map +1 -0
- package/lib/seam/connect/index.d.ts +1 -0
- package/lib/seam/connect/index.js +2 -0
- package/lib/seam/connect/index.js.map +1 -0
- package/lib/seam/connect/legacy/workspaces.d.ts +8 -0
- package/lib/seam/connect/legacy/workspaces.js +10 -0
- package/lib/seam/connect/legacy/workspaces.js.map +1 -0
- package/lib/seam/connect/parse-options.d.ts +2 -0
- package/lib/seam/connect/parse-options.js +20 -0
- package/lib/seam/connect/parse-options.js.map +1 -0
- package/lib/seam/connect/routes/workspaces.d.ts +11 -0
- package/lib/seam/connect/routes/workspaces.js +20 -0
- package/lib/seam/connect/routes/workspaces.js.map +1 -0
- package/package.json +109 -0
- package/src/connect.ts +1 -0
- package/src/index.ts +1 -0
- package/src/lib/seam/connect/auth.ts +86 -0
- package/src/lib/seam/connect/axios.ts +23 -0
- package/src/lib/seam/connect/client-options.ts +62 -0
- package/src/lib/seam/connect/client.ts +63 -0
- package/src/lib/seam/connect/index.ts +1 -0
- package/src/lib/seam/connect/legacy/workspaces.ts +26 -0
- package/src/lib/seam/connect/parse-options.ts +28 -0
- package/src/lib/seam/connect/routes/workspaces.ts +41 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _SeamHttp_legacy;
|
|
13
|
+
import { createAxiosClient } from './axios.js';
|
|
14
|
+
import { InvalidSeamHttpOptionsError, isSeamHttpOptionsWithApiKey, isSeamHttpOptionsWithClientSessionToken, } from './client-options.js';
|
|
15
|
+
import { LegacyWorkspacesHttp } from './legacy/workspaces.js';
|
|
16
|
+
import { parseOptions } from './parse-options.js';
|
|
17
|
+
import { WorkspacesHttp } from './routes/workspaces.js';
|
|
18
|
+
export class SeamHttp {
|
|
19
|
+
constructor(apiKeyOrOptions) {
|
|
20
|
+
_SeamHttp_legacy.set(this, void 0);
|
|
21
|
+
const options = parseOptions(apiKeyOrOptions);
|
|
22
|
+
__classPrivateFieldSet(this, _SeamHttp_legacy, options.enableLegacyMethodBehaivor, "f");
|
|
23
|
+
this.client = createAxiosClient(options);
|
|
24
|
+
}
|
|
25
|
+
static fromApiKey(apiKey, options = {}) {
|
|
26
|
+
const opts = { ...options, apiKey };
|
|
27
|
+
if (!isSeamHttpOptionsWithApiKey(opts)) {
|
|
28
|
+
throw new InvalidSeamHttpOptionsError('Missing apiKey');
|
|
29
|
+
}
|
|
30
|
+
return new SeamHttp(opts);
|
|
31
|
+
}
|
|
32
|
+
static fromClientSessionToken(clientSessionToken, options = {}) {
|
|
33
|
+
const opts = { ...options, clientSessionToken };
|
|
34
|
+
if (!isSeamHttpOptionsWithClientSessionToken(opts)) {
|
|
35
|
+
throw new InvalidSeamHttpOptionsError('Missing clientSessionToken');
|
|
36
|
+
}
|
|
37
|
+
return new SeamHttp(opts);
|
|
38
|
+
}
|
|
39
|
+
// TODO
|
|
40
|
+
// static fromPublishableKey and deprecate getClientSessionToken
|
|
41
|
+
// TODO: Should we keep makeRequest?
|
|
42
|
+
// Better to implement error handling and wrapping in an error handler.
|
|
43
|
+
// makeRequest
|
|
44
|
+
get workspaces() {
|
|
45
|
+
if (__classPrivateFieldGet(this, _SeamHttp_legacy, "f"))
|
|
46
|
+
return new LegacyWorkspacesHttp(this.client);
|
|
47
|
+
return new WorkspacesHttp(this.client);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
_SeamHttp_legacy = new WeakMap();
|
|
51
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/lib/seam/connect/client.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,uCAAuC,GAIxC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEvD,MAAM,OAAO,QAAQ;IAKnB,YAAY,eAAyC;QAFrD,mCAAgB;QAGd,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;QAC7C,uBAAA,IAAI,oBAAW,OAAO,CAAC,0BAA0B,MAAA,CAAA;QACjD,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1C,CAAC;IAED,MAAM,CAAC,UAAU,CACf,MAA2C,EAC3C,UAAqD,EAAE;QAEvD,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAA;QACnC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,EAAE;YACtC,MAAM,IAAI,2BAA2B,CAAC,gBAAgB,CAAC,CAAA;SACxD;QACD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAED,MAAM,CAAC,sBAAsB,CAC3B,kBAA+E,EAC/E,UAGI,EAAE;QAEN,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,kBAAkB,EAAE,CAAA;QAC/C,IAAI,CAAC,uCAAuC,CAAC,IAAI,CAAC,EAAE;YAClD,MAAM,IAAI,2BAA2B,CAAC,4BAA4B,CAAC,CAAA;SACpE;QACD,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAED,OAAO;IACP,gEAAgE;IAEhE,oCAAoC;IACpC,uEAAuE;IACvE,cAAc;IAEd,IAAI,UAAU;QACZ,IAAI,uBAAA,IAAI,wBAAQ;YAAE,OAAO,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC9D,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './client.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/seam/connect/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteRequestParams, RouteResponse } from '@seamapi/types/connect';
|
|
2
|
+
import type { SetNonNullable } from 'type-fest';
|
|
3
|
+
import { WorkspacesHttp } from '../../../../lib/seam/connect/routes/workspaces.js';
|
|
4
|
+
export declare class LegacyWorkspacesHttp extends WorkspacesHttp {
|
|
5
|
+
get(params?: WorkspacesGetParams): Promise<WorkspacesGetResponse['workspace']>;
|
|
6
|
+
}
|
|
7
|
+
export type WorkspacesGetParams = SetNonNullable<Required<RouteRequestParams<'/workspaces/get'>>>;
|
|
8
|
+
export type WorkspacesGetResponse = SetNonNullable<Required<RouteResponse<'/workspaces/get'>>>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WorkspacesHttp } from '../../../../lib/seam/connect/routes/workspaces.js';
|
|
2
|
+
export class LegacyWorkspacesHttp extends WorkspacesHttp {
|
|
3
|
+
async get(params = {}) {
|
|
4
|
+
const { data } = await this.client.get('/workspaces/get', {
|
|
5
|
+
params,
|
|
6
|
+
});
|
|
7
|
+
return data.workspace;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../../src/lib/seam/connect/legacy/workspaces.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AAEtE,MAAM,OAAO,oBAAqB,SAAQ,cAAc;IAC7C,KAAK,CAAC,GAAG,CAChB,SAA8B,EAAE;QAEhC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACpC,iBAAiB,EACjB;YACE,MAAM;SACP,CACF,CAAA;QACD,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const parseOptions = (apiKeyOrOptions) => {
|
|
2
|
+
const options = typeof apiKeyOrOptions === 'string'
|
|
3
|
+
? { apiKey: apiKeyOrOptions }
|
|
4
|
+
: apiKeyOrOptions;
|
|
5
|
+
const endpoint = options.endpoint ??
|
|
6
|
+
globalThis.process?.env?.['SEAM_ENDPOINT'] ??
|
|
7
|
+
globalThis.process?.env?.['SEAM_API_URL'] ??
|
|
8
|
+
'https://connect.getseam.com';
|
|
9
|
+
const apiKey = 'apiKey' in options
|
|
10
|
+
? options.apiKey
|
|
11
|
+
: globalThis.process?.env?.['SEAM_API_KEY'];
|
|
12
|
+
return {
|
|
13
|
+
...options,
|
|
14
|
+
...(apiKey != null ? { apiKey } : {}),
|
|
15
|
+
endpoint,
|
|
16
|
+
axiosOptions: options.axiosOptions ?? {},
|
|
17
|
+
enableLegacyMethodBehaivor: false,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=parse-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-options.js","sourceRoot":"","sources":["../../../src/lib/seam/connect/parse-options.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,eAAyC,EACd,EAAE;IAC7B,MAAM,OAAO,GACX,OAAO,eAAe,KAAK,QAAQ;QACjC,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE;QAC7B,CAAC,CAAC,eAAe,CAAA;IAErB,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ;QAChB,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC;QAC1C,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC;QACzC,6BAA6B,CAAA;IAE/B,MAAM,MAAM,GACV,QAAQ,IAAI,OAAO;QACjB,CAAC,CAAC,OAAO,CAAC,MAAM;QAChB,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,CAAA;IAE/C,OAAO;QACL,GAAG,OAAO;QACV,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,QAAQ;QACR,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,0BAA0B,EAAE,KAAK;KAClC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RouteRequestParams, RouteResponse } from '@seamapi/types/connect';
|
|
2
|
+
import { Axios } from 'axios';
|
|
3
|
+
import type { SetNonNullable } from 'type-fest';
|
|
4
|
+
import type { SeamHttpOptions } from '../../../../lib/seam/connect/client-options.js';
|
|
5
|
+
export declare class WorkspacesHttp {
|
|
6
|
+
client: Axios;
|
|
7
|
+
constructor(apiKeyOrOptionsOrClient: Axios | string | SeamHttpOptions);
|
|
8
|
+
get(params?: WorkspacesGetParams): Promise<WorkspacesGetResponse['workspace']>;
|
|
9
|
+
}
|
|
10
|
+
export type WorkspacesGetParams = SetNonNullable<Required<RouteRequestParams<'/workspaces/get'>>>;
|
|
11
|
+
export type WorkspacesGetResponse = SetNonNullable<Required<RouteResponse<'/workspaces/get'>>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Axios } from 'axios';
|
|
2
|
+
import { createAxiosClient } from '../../../../lib/seam/connect/axios.js';
|
|
3
|
+
import { parseOptions } from '../../../../lib/seam/connect/parse-options.js';
|
|
4
|
+
export class WorkspacesHttp {
|
|
5
|
+
constructor(apiKeyOrOptionsOrClient) {
|
|
6
|
+
if (apiKeyOrOptionsOrClient instanceof Axios) {
|
|
7
|
+
this.client = apiKeyOrOptionsOrClient;
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const options = parseOptions(apiKeyOrOptionsOrClient);
|
|
11
|
+
this.client = createAxiosClient(options);
|
|
12
|
+
}
|
|
13
|
+
async get(params = {}) {
|
|
14
|
+
const { data } = await this.client.get('/workspaces/get', {
|
|
15
|
+
params,
|
|
16
|
+
});
|
|
17
|
+
return data.workspace;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../../src/lib/seam/connect/routes/workspaces.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAG7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAEhE,MAAM,OAAO,cAAc;IAGzB,YAAY,uBAAyD;QACnE,IAAI,uBAAuB,YAAY,KAAK,EAAE;YAC5C,IAAI,CAAC,MAAM,GAAG,uBAAuB,CAAA;YACrC,OAAM;SACP;QAED,MAAM,OAAO,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAA;QACrD,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,GAAG,CACP,SAA8B,EAAE;QAEhC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACpC,iBAAiB,EACjB;YACE,MAAM;SACP,CACF,CAAA;QACD,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;CACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seamapi/http",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "JavaScript HTTP client for the Seam API written in TypeScript.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./index.js",
|
|
11
|
+
"require": "./dist/index.cjs",
|
|
12
|
+
"types": "./index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./connect": {
|
|
15
|
+
"import": "./connect.js",
|
|
16
|
+
"require": "./dist/connect.cjs",
|
|
17
|
+
"types": "./connect.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"module": "index.js",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"keywords": [
|
|
23
|
+
"node"
|
|
24
|
+
],
|
|
25
|
+
"homepage": "https://github.com/seamapi/javascript-http",
|
|
26
|
+
"bugs": "https://github.com/seamapi/javascript-http/issues",
|
|
27
|
+
"repository": "seamapi/javascript-http",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"author": {
|
|
30
|
+
"name": "Seam Labs, Inc.",
|
|
31
|
+
"email": "devops@getseam.com"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"index.js",
|
|
35
|
+
"index.js.map",
|
|
36
|
+
"index.d.ts",
|
|
37
|
+
"connect.js",
|
|
38
|
+
"connect.js.map",
|
|
39
|
+
"connect.d.ts",
|
|
40
|
+
"dist",
|
|
41
|
+
"lib",
|
|
42
|
+
"src",
|
|
43
|
+
"!**/*.test.ts"
|
|
44
|
+
],
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "npm run build:entrypoints",
|
|
47
|
+
"prebuild": "concurrently --raw --group 'tsx src/index.ts' 'tsx src/connect.ts'",
|
|
48
|
+
"postbuild": "concurrently --raw --group 'node ./index.js' 'node ./connect.js'",
|
|
49
|
+
"build:entrypoints": "npm run build:ts",
|
|
50
|
+
"postbuild:entrypoints": "tsup",
|
|
51
|
+
"build:ts": "tsc --project tsconfig.build.json",
|
|
52
|
+
"prebuild:ts": "del 'index.*' 'connect.*' 'lib'",
|
|
53
|
+
"postbuild:ts": "tsc-alias --project tsconfig.build.json",
|
|
54
|
+
"typecheck": "tsc",
|
|
55
|
+
"test": "c8 ava",
|
|
56
|
+
"pretest": "tsx src/index.ts",
|
|
57
|
+
"test:update": "ava --update-snapshots",
|
|
58
|
+
"test:watch": "ava --watch",
|
|
59
|
+
"test:debug": "ava debug --break",
|
|
60
|
+
"lint": "eslint --ignore-path .gitignore .",
|
|
61
|
+
"prelint": "prettier --check --ignore-path .gitignore .",
|
|
62
|
+
"postversion": "git push --follow-tags",
|
|
63
|
+
"example": "tsx examples",
|
|
64
|
+
"example:inspect": "tsx --inspect examples",
|
|
65
|
+
"format": "eslint --ignore-path .gitignore --fix .",
|
|
66
|
+
"preformat": "prettier --write --ignore-path .gitignore .",
|
|
67
|
+
"report": "c8 report"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=16.13.0",
|
|
71
|
+
"npm": ">= 8.1.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@seamapi/types": "^1.0.0",
|
|
75
|
+
"type-fest": "^4.0.0"
|
|
76
|
+
},
|
|
77
|
+
"peerDependenciesMeta": {
|
|
78
|
+
"@seamapi/types": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"type-fest": {
|
|
82
|
+
"optional": true
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"dependencies": {
|
|
86
|
+
"axios": "^1.5.0"
|
|
87
|
+
},
|
|
88
|
+
"devDependencies": {
|
|
89
|
+
"@seamapi/types": "^1.14.0",
|
|
90
|
+
"@types/node": "^18.11.18",
|
|
91
|
+
"ava": "^5.0.1",
|
|
92
|
+
"c8": "^8.0.0",
|
|
93
|
+
"concurrently": "^8.2.1",
|
|
94
|
+
"del-cli": "^5.0.0",
|
|
95
|
+
"eslint": "^8.9.0",
|
|
96
|
+
"eslint-config-prettier": "^9.0.0",
|
|
97
|
+
"eslint-config-standard": "^17.1.0",
|
|
98
|
+
"eslint-config-standard-with-typescript": "^39.0.0",
|
|
99
|
+
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
100
|
+
"eslint-plugin-unused-imports": "^3.0.0",
|
|
101
|
+
"landlubber": "^1.0.0",
|
|
102
|
+
"prettier": "^3.0.0",
|
|
103
|
+
"tsc-alias": "^1.8.2",
|
|
104
|
+
"tsup": "^7.2.0",
|
|
105
|
+
"tsx": "^3.12.1",
|
|
106
|
+
"type-fest": "^4.3.1",
|
|
107
|
+
"typescript": "^5.1.0"
|
|
108
|
+
}
|
|
109
|
+
}
|
package/src/connect.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/seam/connect/index.js'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default null
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvalidSeamHttpOptionsError,
|
|
3
|
+
isSeamHttpOptionsWithApiKey,
|
|
4
|
+
isSeamHttpOptionsWithClientSessionToken,
|
|
5
|
+
type SeamHttpOptions,
|
|
6
|
+
type SeamHttpOptionsWithApiKey,
|
|
7
|
+
type SeamHttpOptionsWithClientSessionToken,
|
|
8
|
+
} from './client-options.js'
|
|
9
|
+
|
|
10
|
+
type Headers = Record<string, string>
|
|
11
|
+
|
|
12
|
+
export const getAuthHeaders = (options: SeamHttpOptions): Headers => {
|
|
13
|
+
if (isSeamHttpOptionsWithApiKey(options)) {
|
|
14
|
+
return getAuthHeadersForApiKey(options)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (isSeamHttpOptionsWithClientSessionToken(options)) {
|
|
18
|
+
return getAuthHeadersForClientSessionToken(options)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
throw new InvalidSeamHttpOptionsError(
|
|
22
|
+
'Must specify an apiKey or clientSessionToken',
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getAuthHeadersForApiKey = ({
|
|
27
|
+
apiKey,
|
|
28
|
+
}: SeamHttpOptionsWithApiKey): Headers => {
|
|
29
|
+
if (isClientSessionToken(apiKey)) {
|
|
30
|
+
throw new InvalidSeamTokenError(
|
|
31
|
+
'A Client Session Token cannot be used as an apiKey',
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (isAccessToken(apiKey)) {
|
|
36
|
+
throw new InvalidSeamTokenError(
|
|
37
|
+
'An access token cannot be used as an apiKey',
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isJwt(apiKey) || !isSeamToken(apiKey)) {
|
|
42
|
+
throw new InvalidSeamTokenError(
|
|
43
|
+
`Unknown or invalid apiKey format, expected token to start with ${tokenPrefix}`,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
authorization: `Bearer ${apiKey}`,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const getAuthHeadersForClientSessionToken = ({
|
|
53
|
+
clientSessionToken,
|
|
54
|
+
}: SeamHttpOptionsWithClientSessionToken): Headers => {
|
|
55
|
+
if (!isClientSessionToken(clientSessionToken)) {
|
|
56
|
+
throw new InvalidSeamTokenError(
|
|
57
|
+
`Unknown or invalid clientSessionToken format, expected token to start with ${clientSessionTokenPrefix}`,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
authorization: `Bearer ${clientSessionToken}`,
|
|
63
|
+
'client-session-token': clientSessionToken,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class InvalidSeamTokenError extends Error {
|
|
68
|
+
constructor(message: string) {
|
|
69
|
+
super(`SeamHttp received an invalid token: ${message}`)
|
|
70
|
+
this.name = this.constructor.name
|
|
71
|
+
Error.captureStackTrace(this, this.constructor)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const tokenPrefix = 'seam_'
|
|
76
|
+
|
|
77
|
+
const clientSessionTokenPrefix = 'seam_cst'
|
|
78
|
+
|
|
79
|
+
const isClientSessionToken = (token: string): boolean =>
|
|
80
|
+
token.startsWith(clientSessionTokenPrefix)
|
|
81
|
+
|
|
82
|
+
const isAccessToken = (token: string): boolean => token.startsWith('seam_at')
|
|
83
|
+
|
|
84
|
+
const isJwt = (token: string): boolean => token.startsWith('ey')
|
|
85
|
+
|
|
86
|
+
const isSeamToken = (token: string): boolean => token.startsWith(tokenPrefix)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import axios, { type Axios } from 'axios'
|
|
2
|
+
|
|
3
|
+
import { getAuthHeaders } from './auth.js'
|
|
4
|
+
import {
|
|
5
|
+
isSeamHttpOptionsWithClientSessionToken,
|
|
6
|
+
type SeamHttpOptions,
|
|
7
|
+
} from './client-options.js'
|
|
8
|
+
|
|
9
|
+
export const createAxiosClient = (
|
|
10
|
+
options: Required<SeamHttpOptions>,
|
|
11
|
+
): Axios => {
|
|
12
|
+
// TODO: axiosRetry? Allow options to configure this if so
|
|
13
|
+
return axios.create({
|
|
14
|
+
baseURL: options.endpoint,
|
|
15
|
+
withCredentials: isSeamHttpOptionsWithClientSessionToken(options),
|
|
16
|
+
...options.axiosOptions,
|
|
17
|
+
headers: {
|
|
18
|
+
...getAuthHeaders(options),
|
|
19
|
+
...options.axiosOptions.headers,
|
|
20
|
+
// TODO: User-Agent
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from 'axios'
|
|
2
|
+
|
|
3
|
+
export type SeamHttpOptions =
|
|
4
|
+
| SeamHttpOptionsWithApiKey
|
|
5
|
+
| SeamHttpOptionsWithClientSessionToken
|
|
6
|
+
|
|
7
|
+
interface SeamHttpCommonOptions {
|
|
8
|
+
endpoint?: string
|
|
9
|
+
axiosOptions?: AxiosRequestConfig
|
|
10
|
+
enableLegacyMethodBehaivor?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface SeamHttpOptionsWithApiKey extends SeamHttpCommonOptions {
|
|
14
|
+
apiKey: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const isSeamHttpOptionsWithApiKey = (
|
|
18
|
+
options: SeamHttpOptions,
|
|
19
|
+
): options is SeamHttpOptionsWithApiKey => {
|
|
20
|
+
if (!('apiKey' in options)) return false
|
|
21
|
+
|
|
22
|
+
if ('clientSessionToken' in options && options.clientSessionToken != null) {
|
|
23
|
+
throw new InvalidSeamHttpOptionsError(
|
|
24
|
+
'The clientSessionToken option cannot be used with the apiKey option.',
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SeamHttpOptionsWithClientSessionToken
|
|
32
|
+
extends SeamHttpCommonOptions {
|
|
33
|
+
clientSessionToken: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const isSeamHttpOptionsWithClientSessionToken = (
|
|
37
|
+
options: SeamHttpOptions,
|
|
38
|
+
): options is SeamHttpOptionsWithClientSessionToken => {
|
|
39
|
+
if (!('clientSessionToken' in options)) return false
|
|
40
|
+
|
|
41
|
+
if ('apiKey' in options && options.apiKey != null) {
|
|
42
|
+
throw new InvalidSeamHttpOptionsError(
|
|
43
|
+
'The clientSessionToken option cannot be used with the apiKey option.',
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class InvalidSeamHttpOptionsError extends Error {
|
|
51
|
+
constructor(message: string) {
|
|
52
|
+
super(`SeamHttp received invalid options: ${message}`)
|
|
53
|
+
this.name = this.constructor.name
|
|
54
|
+
Error.captureStackTrace(this, this.constructor)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// TODO: withSessionToken { sessionToken } or withMultiWorkspaceApiKey { apiKey }?
|
|
59
|
+
// export interface SeamHttpOptionsWithSessionToken extends SeamHttpCommonOptions {
|
|
60
|
+
// workspaceId: string
|
|
61
|
+
// apiKey: string
|
|
62
|
+
// }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Axios } from 'axios'
|
|
2
|
+
|
|
3
|
+
import { createAxiosClient } from './axios.js'
|
|
4
|
+
import {
|
|
5
|
+
InvalidSeamHttpOptionsError,
|
|
6
|
+
isSeamHttpOptionsWithApiKey,
|
|
7
|
+
isSeamHttpOptionsWithClientSessionToken,
|
|
8
|
+
type SeamHttpOptions,
|
|
9
|
+
type SeamHttpOptionsWithApiKey,
|
|
10
|
+
type SeamHttpOptionsWithClientSessionToken,
|
|
11
|
+
} from './client-options.js'
|
|
12
|
+
import { LegacyWorkspacesHttp } from './legacy/workspaces.js'
|
|
13
|
+
import { parseOptions } from './parse-options.js'
|
|
14
|
+
import { WorkspacesHttp } from './routes/workspaces.js'
|
|
15
|
+
|
|
16
|
+
export class SeamHttp {
|
|
17
|
+
client: Axios
|
|
18
|
+
|
|
19
|
+
#legacy: boolean
|
|
20
|
+
|
|
21
|
+
constructor(apiKeyOrOptions: string | SeamHttpOptions) {
|
|
22
|
+
const options = parseOptions(apiKeyOrOptions)
|
|
23
|
+
this.#legacy = options.enableLegacyMethodBehaivor
|
|
24
|
+
this.client = createAxiosClient(options)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static fromApiKey(
|
|
28
|
+
apiKey: SeamHttpOptionsWithApiKey['apiKey'],
|
|
29
|
+
options: Omit<SeamHttpOptionsWithApiKey, 'apiKey'> = {},
|
|
30
|
+
): SeamHttp {
|
|
31
|
+
const opts = { ...options, apiKey }
|
|
32
|
+
if (!isSeamHttpOptionsWithApiKey(opts)) {
|
|
33
|
+
throw new InvalidSeamHttpOptionsError('Missing apiKey')
|
|
34
|
+
}
|
|
35
|
+
return new SeamHttp(opts)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static fromClientSessionToken(
|
|
39
|
+
clientSessionToken: SeamHttpOptionsWithClientSessionToken['clientSessionToken'],
|
|
40
|
+
options: Omit<
|
|
41
|
+
SeamHttpOptionsWithClientSessionToken,
|
|
42
|
+
'clientSessionToken'
|
|
43
|
+
> = {},
|
|
44
|
+
): SeamHttp {
|
|
45
|
+
const opts = { ...options, clientSessionToken }
|
|
46
|
+
if (!isSeamHttpOptionsWithClientSessionToken(opts)) {
|
|
47
|
+
throw new InvalidSeamHttpOptionsError('Missing clientSessionToken')
|
|
48
|
+
}
|
|
49
|
+
return new SeamHttp(opts)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// TODO
|
|
53
|
+
// static fromPublishableKey and deprecate getClientSessionToken
|
|
54
|
+
|
|
55
|
+
// TODO: Should we keep makeRequest?
|
|
56
|
+
// Better to implement error handling and wrapping in an error handler.
|
|
57
|
+
// makeRequest
|
|
58
|
+
|
|
59
|
+
get workspaces(): WorkspacesHttp {
|
|
60
|
+
if (this.#legacy) return new LegacyWorkspacesHttp(this.client)
|
|
61
|
+
return new WorkspacesHttp(this.client)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './client.js'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RouteRequestParams, RouteResponse } from '@seamapi/types/connect'
|
|
2
|
+
import type { SetNonNullable } from 'type-fest'
|
|
3
|
+
|
|
4
|
+
import { WorkspacesHttp } from 'lib/seam/connect/routes/workspaces.js'
|
|
5
|
+
|
|
6
|
+
export class LegacyWorkspacesHttp extends WorkspacesHttp {
|
|
7
|
+
override async get(
|
|
8
|
+
params: WorkspacesGetParams = {},
|
|
9
|
+
): Promise<WorkspacesGetResponse['workspace']> {
|
|
10
|
+
const { data } = await this.client.get<WorkspacesGetResponse>(
|
|
11
|
+
'/workspaces/get',
|
|
12
|
+
{
|
|
13
|
+
params,
|
|
14
|
+
},
|
|
15
|
+
)
|
|
16
|
+
return data.workspace
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type WorkspacesGetParams = SetNonNullable<
|
|
21
|
+
Required<RouteRequestParams<'/workspaces/get'>>
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
export type WorkspacesGetResponse = SetNonNullable<
|
|
25
|
+
Required<RouteResponse<'/workspaces/get'>>
|
|
26
|
+
>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SeamHttpOptions } from './client-options.js'
|
|
2
|
+
export const parseOptions = (
|
|
3
|
+
apiKeyOrOptions: string | SeamHttpOptions,
|
|
4
|
+
): Required<SeamHttpOptions> => {
|
|
5
|
+
const options =
|
|
6
|
+
typeof apiKeyOrOptions === 'string'
|
|
7
|
+
? { apiKey: apiKeyOrOptions }
|
|
8
|
+
: apiKeyOrOptions
|
|
9
|
+
|
|
10
|
+
const endpoint =
|
|
11
|
+
options.endpoint ??
|
|
12
|
+
globalThis.process?.env?.['SEAM_ENDPOINT'] ??
|
|
13
|
+
globalThis.process?.env?.['SEAM_API_URL'] ??
|
|
14
|
+
'https://connect.getseam.com'
|
|
15
|
+
|
|
16
|
+
const apiKey =
|
|
17
|
+
'apiKey' in options
|
|
18
|
+
? options.apiKey
|
|
19
|
+
: globalThis.process?.env?.['SEAM_API_KEY']
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
...options,
|
|
23
|
+
...(apiKey != null ? { apiKey } : {}),
|
|
24
|
+
endpoint,
|
|
25
|
+
axiosOptions: options.axiosOptions ?? {},
|
|
26
|
+
enableLegacyMethodBehaivor: false,
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { RouteRequestParams, RouteResponse } from '@seamapi/types/connect'
|
|
2
|
+
import { Axios } from 'axios'
|
|
3
|
+
import type { SetNonNullable } from 'type-fest'
|
|
4
|
+
|
|
5
|
+
import { createAxiosClient } from 'lib/seam/connect/axios.js'
|
|
6
|
+
import type { SeamHttpOptions } from 'lib/seam/connect/client-options.js'
|
|
7
|
+
import { parseOptions } from 'lib/seam/connect/parse-options.js'
|
|
8
|
+
|
|
9
|
+
export class WorkspacesHttp {
|
|
10
|
+
client: Axios
|
|
11
|
+
|
|
12
|
+
constructor(apiKeyOrOptionsOrClient: Axios | string | SeamHttpOptions) {
|
|
13
|
+
if (apiKeyOrOptionsOrClient instanceof Axios) {
|
|
14
|
+
this.client = apiKeyOrOptionsOrClient
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const options = parseOptions(apiKeyOrOptionsOrClient)
|
|
19
|
+
this.client = createAxiosClient(options)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async get(
|
|
23
|
+
params: WorkspacesGetParams = {},
|
|
24
|
+
): Promise<WorkspacesGetResponse['workspace']> {
|
|
25
|
+
const { data } = await this.client.get<WorkspacesGetResponse>(
|
|
26
|
+
'/workspaces/get',
|
|
27
|
+
{
|
|
28
|
+
params,
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
return data.workspace
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type WorkspacesGetParams = SetNonNullable<
|
|
36
|
+
Required<RouteRequestParams<'/workspaces/get'>>
|
|
37
|
+
>
|
|
38
|
+
|
|
39
|
+
export type WorkspacesGetResponse = SetNonNullable<
|
|
40
|
+
Required<RouteResponse<'/workspaces/get'>>
|
|
41
|
+
>
|