@mitralab.io/sdk-core 0.1.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/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/contracts/README.md +31 -0
- package/contracts/manifest.json +11 -0
- package/contracts/v0.1.0/sdk-parity.json +787 -0
- package/dist/index.cjs +443 -0
- package/dist/index.d.cts +171 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.js +404 -0
- package/package.json +82 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
interface SdkCoreErrorFactory {
|
|
2
|
+
configuration(message: string): Error;
|
|
3
|
+
invalidResponse(message: string): Error;
|
|
4
|
+
}
|
|
5
|
+
declare class SdkCoreConfigurationError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
declare class SdkCoreResponseError extends Error {
|
|
9
|
+
readonly code = "INVALID_RESPONSE";
|
|
10
|
+
readonly retryable = false;
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
declare const defaultSdkCoreErrorFactory: SdkCoreErrorFactory;
|
|
14
|
+
|
|
15
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
16
|
+
type QueryParamValue = string | number | boolean | undefined;
|
|
17
|
+
interface TransportRequestOptions {
|
|
18
|
+
method?: HttpMethod;
|
|
19
|
+
body?: unknown;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
params?: Record<string, QueryParamValue>;
|
|
22
|
+
}
|
|
23
|
+
interface Transport {
|
|
24
|
+
request<T>(path: string, options?: TransportRequestOptions): Promise<T>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface Plan {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
interface Tenant {
|
|
33
|
+
id: string;
|
|
34
|
+
shortId: string;
|
|
35
|
+
legacyId: number | null;
|
|
36
|
+
slug: string;
|
|
37
|
+
plan: Plan;
|
|
38
|
+
name: string;
|
|
39
|
+
description: string | null;
|
|
40
|
+
hexColor: string | null;
|
|
41
|
+
icon: string | null;
|
|
42
|
+
infraStatus: string;
|
|
43
|
+
active: boolean;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
interface User {
|
|
47
|
+
id: string;
|
|
48
|
+
tenant: Tenant;
|
|
49
|
+
name: string;
|
|
50
|
+
email: string;
|
|
51
|
+
imageUrl: string | null;
|
|
52
|
+
onboardingCompleted: boolean;
|
|
53
|
+
}
|
|
54
|
+
interface EntityListOptions {
|
|
55
|
+
sort?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
skip?: number;
|
|
58
|
+
fields?: string[];
|
|
59
|
+
}
|
|
60
|
+
interface EntityTable<T = Record<string, unknown>> {
|
|
61
|
+
list(sortOrOptions?: string | EntityListOptions, limit?: number, skip?: number, fields?: string[]): Promise<T[]>;
|
|
62
|
+
filter(query: Record<string, unknown>, sort?: string, limit?: number, skip?: number, fields?: string[]): Promise<T[]>;
|
|
63
|
+
get(id: string | number): Promise<T>;
|
|
64
|
+
create(data: Partial<T>): Promise<T>;
|
|
65
|
+
bulkCreate(data: Partial<T>[]): Promise<T[]>;
|
|
66
|
+
update(id: string | number, data: Partial<T>): Promise<T>;
|
|
67
|
+
delete(id: string | number): Promise<void>;
|
|
68
|
+
deleteMany(query: Record<string, unknown>): Promise<{
|
|
69
|
+
deleted: number;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
|
72
|
+
interface QueryResult {
|
|
73
|
+
rows: Record<string, unknown>[];
|
|
74
|
+
affectedRows?: number | null;
|
|
75
|
+
durationMs: number;
|
|
76
|
+
}
|
|
77
|
+
interface FunctionExecution {
|
|
78
|
+
id: string;
|
|
79
|
+
functionId: string;
|
|
80
|
+
functionVersionId: string;
|
|
81
|
+
status: string;
|
|
82
|
+
input: Record<string, unknown> | null;
|
|
83
|
+
output: Record<string, unknown> | null;
|
|
84
|
+
errorMessage: string | null;
|
|
85
|
+
logs: string | null;
|
|
86
|
+
durationMs: number | null;
|
|
87
|
+
startedAt: string | null;
|
|
88
|
+
finishedAt: string | null;
|
|
89
|
+
createdAt: string;
|
|
90
|
+
}
|
|
91
|
+
interface ProxyInput {
|
|
92
|
+
method: string;
|
|
93
|
+
endpoint: string;
|
|
94
|
+
headers?: Record<string, string>;
|
|
95
|
+
body?: unknown;
|
|
96
|
+
queryParams?: Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
interface ProxyResult {
|
|
99
|
+
status: number;
|
|
100
|
+
headers: Record<string, string>;
|
|
101
|
+
body: unknown;
|
|
102
|
+
durationMs: number;
|
|
103
|
+
executionId: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface AuthModule {
|
|
107
|
+
me(): Promise<User>;
|
|
108
|
+
}
|
|
109
|
+
declare function createAuthModule(transport: Transport, errors?: SdkCoreErrorFactory): AuthModule;
|
|
110
|
+
|
|
111
|
+
interface EntitiesModule {
|
|
112
|
+
getTable<T = Record<string, unknown>>(tableName: string): EntityTable<T>;
|
|
113
|
+
}
|
|
114
|
+
type EntitiesProxy = EntitiesModule & {
|
|
115
|
+
[tableName: string]: EntityTable;
|
|
116
|
+
};
|
|
117
|
+
declare function createEntitiesModule(transport: Transport, errors?: SdkCoreErrorFactory): EntitiesProxy;
|
|
118
|
+
|
|
119
|
+
type InvocationType = "sync" | "async";
|
|
120
|
+
type EmptyFunctionInput = "empty-object" | "omit-body";
|
|
121
|
+
interface FunctionsModuleOptions {
|
|
122
|
+
executeInvocationType?: InvocationType;
|
|
123
|
+
emptyInput?: EmptyFunctionInput;
|
|
124
|
+
}
|
|
125
|
+
interface FunctionsModule {
|
|
126
|
+
execute(id: string, input?: Record<string, unknown>): Promise<FunctionExecution>;
|
|
127
|
+
executeAsync(id: string, input?: Record<string, unknown>): Promise<FunctionExecution>;
|
|
128
|
+
getExecution(id: string): Promise<FunctionExecution>;
|
|
129
|
+
cancelExecution(id: string): Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
declare function createFunctionsModule(transport: Transport, options?: FunctionsModuleOptions, errors?: SdkCoreErrorFactory): FunctionsModule;
|
|
132
|
+
|
|
133
|
+
interface IntegrationModule {
|
|
134
|
+
executeResource(resourceId: string, params?: Record<string, unknown>): Promise<ProxyResult>;
|
|
135
|
+
execute(configId: string, request: ProxyInput): Promise<ProxyResult>;
|
|
136
|
+
}
|
|
137
|
+
declare function createIntegrationModule(transport: Transport, errors?: SdkCoreErrorFactory): IntegrationModule;
|
|
138
|
+
|
|
139
|
+
interface QueriesModule {
|
|
140
|
+
execute(id: string, parameters?: Record<string, unknown>): Promise<QueryResult>;
|
|
141
|
+
}
|
|
142
|
+
declare function createQueriesModule(transport: Transport, getDataSourceId: () => string | undefined, errors?: SdkCoreErrorFactory): QueriesModule;
|
|
143
|
+
|
|
144
|
+
interface SdkCoreTransports {
|
|
145
|
+
auth: Transport;
|
|
146
|
+
dataManager: Transport;
|
|
147
|
+
functions: Transport;
|
|
148
|
+
integration: Transport;
|
|
149
|
+
}
|
|
150
|
+
interface SdkCoreOptions {
|
|
151
|
+
transports: SdkCoreTransports;
|
|
152
|
+
getDataSourceId: () => string | undefined;
|
|
153
|
+
functions?: FunctionsModuleOptions;
|
|
154
|
+
errors?: SdkCoreErrorFactory;
|
|
155
|
+
}
|
|
156
|
+
interface SdkCore {
|
|
157
|
+
readonly auth: AuthModule;
|
|
158
|
+
readonly entities: EntitiesProxy;
|
|
159
|
+
readonly functions: FunctionsModule;
|
|
160
|
+
readonly integration: IntegrationModule;
|
|
161
|
+
readonly queries: QueriesModule;
|
|
162
|
+
}
|
|
163
|
+
declare function createSdkCore(options: SdkCoreOptions): SdkCore;
|
|
164
|
+
|
|
165
|
+
declare function encodePathSegment(value: string | number, name: string, errors?: SdkCoreErrorFactory): string;
|
|
166
|
+
|
|
167
|
+
declare function expectObject<T extends object>(value: unknown, context: string, errors?: SdkCoreErrorFactory): T;
|
|
168
|
+
declare function expectObjectArray<T extends object>(value: unknown, context: string, errors?: SdkCoreErrorFactory): T[];
|
|
169
|
+
declare function expectEmpty(value: unknown, context: string, errors?: SdkCoreErrorFactory): void;
|
|
170
|
+
|
|
171
|
+
export { type AuthModule, type EmptyFunctionInput, type EntitiesModule, type EntitiesProxy, type EntityListOptions, type EntityTable, type FunctionExecution, type FunctionsModule, type FunctionsModuleOptions, type HttpMethod, type IntegrationModule, type InvocationType, type Plan, type ProxyInput, type ProxyResult, type QueriesModule, type QueryParamValue, type QueryResult, type SdkCore, SdkCoreConfigurationError, type SdkCoreErrorFactory, type SdkCoreOptions, SdkCoreResponseError, type SdkCoreTransports, type Tenant, type Transport, type TransportRequestOptions, type User, createAuthModule, createEntitiesModule, createFunctionsModule, createIntegrationModule, createQueriesModule, createSdkCore, defaultSdkCoreErrorFactory, encodePathSegment, expectEmpty, expectObject, expectObjectArray };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var SdkCoreConfigurationError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "SdkCoreConfigurationError";
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var SdkCoreResponseError = class extends Error {
|
|
9
|
+
code = "INVALID_RESPONSE";
|
|
10
|
+
retryable = false;
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "SdkCoreResponseError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var defaultSdkCoreErrorFactory = {
|
|
17
|
+
configuration: (message) => new SdkCoreConfigurationError(message),
|
|
18
|
+
invalidResponse: (message) => new SdkCoreResponseError(message)
|
|
19
|
+
};
|
|
20
|
+
function configurationError(message, errors = defaultSdkCoreErrorFactory) {
|
|
21
|
+
throw errors.configuration(message);
|
|
22
|
+
}
|
|
23
|
+
function invalidResponse(message, errors = defaultSdkCoreErrorFactory) {
|
|
24
|
+
throw errors.invalidResponse(message);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/response.ts
|
|
28
|
+
function isObject(value) {
|
|
29
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30
|
+
}
|
|
31
|
+
function isNullableString(value) {
|
|
32
|
+
return value === null || typeof value === "string";
|
|
33
|
+
}
|
|
34
|
+
function isInteger(value) {
|
|
35
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
36
|
+
}
|
|
37
|
+
function isNullableInteger(value) {
|
|
38
|
+
return value === null || isInteger(value);
|
|
39
|
+
}
|
|
40
|
+
function isStringRecord(value) {
|
|
41
|
+
return isObject(value) && Object.values(value).every((item) => typeof item === "string");
|
|
42
|
+
}
|
|
43
|
+
function hasOwn(value, property) {
|
|
44
|
+
return Object.prototype.hasOwnProperty.call(value, property);
|
|
45
|
+
}
|
|
46
|
+
function invalidField(context, field, errors) {
|
|
47
|
+
return invalidResponse(`${context} has an invalid ${field} field`, errors);
|
|
48
|
+
}
|
|
49
|
+
function expectObject(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
50
|
+
if (!isObject(value)) {
|
|
51
|
+
return invalidResponse(`${context} must be a JSON object`, errors);
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
function expectObjectArray(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
56
|
+
if (!Array.isArray(value) || value.some((item) => !isObject(item))) {
|
|
57
|
+
return invalidResponse(`${context} must be a JSON array of objects`, errors);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function expectTenant(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
62
|
+
const tenant = expectObject(value, context, errors);
|
|
63
|
+
if (typeof tenant.id !== "string") invalidField(context, "id", errors);
|
|
64
|
+
if (typeof tenant.shortId !== "string") invalidField(context, "shortId", errors);
|
|
65
|
+
if (!isNullableInteger(tenant.legacyId)) invalidField(context, "legacyId", errors);
|
|
66
|
+
if (typeof tenant.slug !== "string") invalidField(context, "slug", errors);
|
|
67
|
+
if (!isObject(tenant.plan)) invalidField(context, "plan", errors);
|
|
68
|
+
if (typeof tenant.plan.id !== "string") invalidField(`${context} plan`, "id", errors);
|
|
69
|
+
if (typeof tenant.plan.name !== "string") invalidField(`${context} plan`, "name", errors);
|
|
70
|
+
if (typeof tenant.name !== "string") invalidField(context, "name", errors);
|
|
71
|
+
if (!isNullableString(tenant.description)) invalidField(context, "description", errors);
|
|
72
|
+
if (!isNullableString(tenant.hexColor)) invalidField(context, "hexColor", errors);
|
|
73
|
+
if (!isNullableString(tenant.icon)) invalidField(context, "icon", errors);
|
|
74
|
+
if (typeof tenant.infraStatus !== "string") invalidField(context, "infraStatus", errors);
|
|
75
|
+
if (typeof tenant.active !== "boolean") invalidField(context, "active", errors);
|
|
76
|
+
return tenant;
|
|
77
|
+
}
|
|
78
|
+
function expectUser(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
79
|
+
const user = expectObject(value, context, errors);
|
|
80
|
+
if (typeof user.id !== "string") invalidField(context, "id", errors);
|
|
81
|
+
expectTenant(user.tenant, `${context} tenant`, errors);
|
|
82
|
+
if (typeof user.name !== "string") invalidField(context, "name", errors);
|
|
83
|
+
if (typeof user.email !== "string") invalidField(context, "email", errors);
|
|
84
|
+
if (!isNullableString(user.imageUrl)) invalidField(context, "imageUrl", errors);
|
|
85
|
+
if (typeof user.onboardingCompleted !== "boolean") {
|
|
86
|
+
invalidField(context, "onboardingCompleted", errors);
|
|
87
|
+
}
|
|
88
|
+
return user;
|
|
89
|
+
}
|
|
90
|
+
function expectQueryResult(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
91
|
+
const result = expectObject(value, context, errors);
|
|
92
|
+
if (!Array.isArray(result.rows) || result.rows.some((row) => !isObject(row))) {
|
|
93
|
+
invalidField(context, "rows", errors);
|
|
94
|
+
}
|
|
95
|
+
if (hasOwn(result, "affectedRows") && !isNullableInteger(result.affectedRows)) {
|
|
96
|
+
invalidField(context, "affectedRows", errors);
|
|
97
|
+
}
|
|
98
|
+
if (!isInteger(result.durationMs)) {
|
|
99
|
+
invalidField(context, "durationMs", errors);
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
function expectFunctionExecution(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
104
|
+
const execution = expectObject(value, context, errors);
|
|
105
|
+
if (typeof execution.id !== "string") invalidField(context, "id", errors);
|
|
106
|
+
if (typeof execution.functionId !== "string") invalidField(context, "functionId", errors);
|
|
107
|
+
if (typeof execution.functionVersionId !== "string") {
|
|
108
|
+
invalidField(context, "functionVersionId", errors);
|
|
109
|
+
}
|
|
110
|
+
if (typeof execution.status !== "string") invalidField(context, "status", errors);
|
|
111
|
+
if (execution.input !== null && !isObject(execution.input)) {
|
|
112
|
+
invalidField(context, "input", errors);
|
|
113
|
+
}
|
|
114
|
+
if (execution.output !== null && !isObject(execution.output)) {
|
|
115
|
+
invalidField(context, "output", errors);
|
|
116
|
+
}
|
|
117
|
+
if (!isNullableString(execution.errorMessage)) {
|
|
118
|
+
invalidField(context, "errorMessage", errors);
|
|
119
|
+
}
|
|
120
|
+
if (!isNullableString(execution.logs)) invalidField(context, "logs", errors);
|
|
121
|
+
if (!isNullableInteger(execution.durationMs)) invalidField(context, "durationMs", errors);
|
|
122
|
+
if (!isNullableString(execution.startedAt)) invalidField(context, "startedAt", errors);
|
|
123
|
+
if (!isNullableString(execution.finishedAt)) invalidField(context, "finishedAt", errors);
|
|
124
|
+
if (typeof execution.createdAt !== "string") invalidField(context, "createdAt", errors);
|
|
125
|
+
return execution;
|
|
126
|
+
}
|
|
127
|
+
function expectProxyResult(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
128
|
+
const result = expectObject(value, context, errors);
|
|
129
|
+
if (!isInteger(result.status)) {
|
|
130
|
+
invalidField(context, "status", errors);
|
|
131
|
+
}
|
|
132
|
+
if (!isStringRecord(result.headers)) invalidField(context, "headers", errors);
|
|
133
|
+
if (!hasOwn(result, "body")) invalidField(context, "body", errors);
|
|
134
|
+
if (!isInteger(result.durationMs)) {
|
|
135
|
+
invalidField(context, "durationMs", errors);
|
|
136
|
+
}
|
|
137
|
+
if (typeof result.executionId !== "string") invalidField(context, "executionId", errors);
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
function expectEmpty(value, context, errors = defaultSdkCoreErrorFactory) {
|
|
141
|
+
if (value !== void 0) invalidResponse(`${context} must be empty`, errors);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/modules/auth.ts
|
|
145
|
+
function createAuthModule(transport, errors = defaultSdkCoreErrorFactory) {
|
|
146
|
+
return {
|
|
147
|
+
async me() {
|
|
148
|
+
return expectUser(
|
|
149
|
+
await transport.request("/api/v1/auth/me", { method: "GET" }),
|
|
150
|
+
"Current user response",
|
|
151
|
+
errors
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/path.ts
|
|
158
|
+
function encodePathSegment(value, name, errors = defaultSdkCoreErrorFactory) {
|
|
159
|
+
const segment = String(value);
|
|
160
|
+
if (!segment.trim()) configurationError(`${name} must not be empty`, errors);
|
|
161
|
+
if (segment === "." || segment === "..") {
|
|
162
|
+
configurationError(`${name} must not be a dot segment`, errors);
|
|
163
|
+
}
|
|
164
|
+
return encodeURIComponent(segment);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/modules/entities.ts
|
|
168
|
+
var DefaultEntitiesModule = class {
|
|
169
|
+
constructor(transport, errors) {
|
|
170
|
+
this.transport = transport;
|
|
171
|
+
this.errors = errors;
|
|
172
|
+
}
|
|
173
|
+
tables = /* @__PURE__ */ new Map();
|
|
174
|
+
getTable(tableName) {
|
|
175
|
+
if (!this.tables.has(tableName)) {
|
|
176
|
+
this.tables.set(tableName, this.createTable(tableName));
|
|
177
|
+
}
|
|
178
|
+
return this.tables.get(tableName);
|
|
179
|
+
}
|
|
180
|
+
createTable(tableName) {
|
|
181
|
+
const basePath = `/api/v1/tables/${encodePathSegment(tableName, "tableName", this.errors)}/records`;
|
|
182
|
+
return {
|
|
183
|
+
list: async (sortOrOptions, limit, skip, fields) => {
|
|
184
|
+
const options = typeof sortOrOptions === "object" ? sortOrOptions : void 0;
|
|
185
|
+
const params = {
|
|
186
|
+
sort: options?.sort ?? (typeof sortOrOptions === "string" ? sortOrOptions : void 0),
|
|
187
|
+
limit: options?.limit ?? limit,
|
|
188
|
+
skip: options?.skip ?? skip,
|
|
189
|
+
fields: (options?.fields ?? fields)?.join(",")
|
|
190
|
+
};
|
|
191
|
+
const response = expectObject(
|
|
192
|
+
await this.transport.request(basePath, { method: "GET", params }),
|
|
193
|
+
"Entity list response",
|
|
194
|
+
this.errors
|
|
195
|
+
);
|
|
196
|
+
return expectObjectArray(response.data, "Entity list data", this.errors);
|
|
197
|
+
},
|
|
198
|
+
filter: async (query, sort, limit, skip, fields) => {
|
|
199
|
+
const response = expectObject(
|
|
200
|
+
await this.transport.request(basePath, {
|
|
201
|
+
method: "GET",
|
|
202
|
+
params: {
|
|
203
|
+
q: JSON.stringify(query),
|
|
204
|
+
sort,
|
|
205
|
+
limit,
|
|
206
|
+
skip,
|
|
207
|
+
fields: fields?.join(",")
|
|
208
|
+
}
|
|
209
|
+
}),
|
|
210
|
+
"Entity list response",
|
|
211
|
+
this.errors
|
|
212
|
+
);
|
|
213
|
+
return expectObjectArray(response.data, "Entity list data", this.errors);
|
|
214
|
+
},
|
|
215
|
+
get: async (id) => expectObject(
|
|
216
|
+
await this.transport.request(
|
|
217
|
+
`${basePath}/${encodePathSegment(id, "id", this.errors)}`,
|
|
218
|
+
{ method: "GET" }
|
|
219
|
+
),
|
|
220
|
+
"Entity response",
|
|
221
|
+
this.errors
|
|
222
|
+
),
|
|
223
|
+
create: async (data) => expectObject(
|
|
224
|
+
await this.transport.request(basePath, { method: "POST", body: data }),
|
|
225
|
+
"Created entity response",
|
|
226
|
+
this.errors
|
|
227
|
+
),
|
|
228
|
+
bulkCreate: async (data) => expectObjectArray(
|
|
229
|
+
await this.transport.request(`${basePath}/bulk`, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
body: data
|
|
232
|
+
}),
|
|
233
|
+
"Bulk create response",
|
|
234
|
+
this.errors
|
|
235
|
+
),
|
|
236
|
+
update: async (id, data) => expectObject(
|
|
237
|
+
await this.transport.request(
|
|
238
|
+
`${basePath}/${encodePathSegment(id, "id", this.errors)}`,
|
|
239
|
+
{ method: "PUT", body: data }
|
|
240
|
+
),
|
|
241
|
+
"Updated entity response",
|
|
242
|
+
this.errors
|
|
243
|
+
),
|
|
244
|
+
delete: (id) => this.transport.request(`${basePath}/${encodePathSegment(id, "id", this.errors)}`, {
|
|
245
|
+
method: "DELETE"
|
|
246
|
+
}).then((response) => expectEmpty(response, "Delete entity response", this.errors)),
|
|
247
|
+
deleteMany: async (query) => {
|
|
248
|
+
if (Object.keys(query).length === 0) {
|
|
249
|
+
configurationError("query must not be empty for deleteMany", this.errors);
|
|
250
|
+
}
|
|
251
|
+
const response = expectObject(
|
|
252
|
+
await this.transport.request(basePath, {
|
|
253
|
+
method: "DELETE",
|
|
254
|
+
params: { q: JSON.stringify(query) }
|
|
255
|
+
}),
|
|
256
|
+
"Delete many response",
|
|
257
|
+
this.errors
|
|
258
|
+
);
|
|
259
|
+
if (!Number.isInteger(response.deleted)) {
|
|
260
|
+
return invalidResponse(
|
|
261
|
+
"Delete many response must include an integer deleted count",
|
|
262
|
+
this.errors
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return { deleted: response.deleted };
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
function createEntitiesModule(transport, errors = defaultSdkCoreErrorFactory) {
|
|
271
|
+
const instance = new DefaultEntitiesModule(transport, errors);
|
|
272
|
+
return new Proxy(instance, {
|
|
273
|
+
get(target, property, receiver) {
|
|
274
|
+
if (typeof property !== "string" || property in target) {
|
|
275
|
+
return Reflect.get(target, property, receiver);
|
|
276
|
+
}
|
|
277
|
+
return target.getTable(property);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/modules/functions.ts
|
|
283
|
+
var DefaultFunctionsModule = class {
|
|
284
|
+
constructor(transport, errors, options) {
|
|
285
|
+
this.transport = transport;
|
|
286
|
+
this.errors = errors;
|
|
287
|
+
this.options = options;
|
|
288
|
+
}
|
|
289
|
+
execute(id, input) {
|
|
290
|
+
return this.executeWithType(id, this.options.executeInvocationType, input);
|
|
291
|
+
}
|
|
292
|
+
executeAsync(id, input) {
|
|
293
|
+
return this.executeWithType(id, "async", input);
|
|
294
|
+
}
|
|
295
|
+
getExecution(id) {
|
|
296
|
+
return this.transport.request(
|
|
297
|
+
`/api/v1/executions/${encodePathSegment(id, "execution id", this.errors)}`,
|
|
298
|
+
{ method: "GET" }
|
|
299
|
+
).then(
|
|
300
|
+
(response) => expectFunctionExecution(response, "Function execution response", this.errors)
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
cancelExecution(id) {
|
|
304
|
+
return this.transport.request(
|
|
305
|
+
`/api/v1/executions/${encodePathSegment(id, "execution id", this.errors)}/cancel`,
|
|
306
|
+
{ method: "POST" }
|
|
307
|
+
).then((response) => expectEmpty(response, "Cancel execution response", this.errors));
|
|
308
|
+
}
|
|
309
|
+
executeWithType(id, invocationType, input) {
|
|
310
|
+
const request = {
|
|
311
|
+
method: "POST",
|
|
312
|
+
...input !== void 0 || this.options.emptyInput !== "omit-body" ? { body: { input: input ?? {} } } : {},
|
|
313
|
+
...invocationType === void 0 ? {} : { headers: { "X-Invocation-Type": invocationType } }
|
|
314
|
+
};
|
|
315
|
+
return this.transport.request(
|
|
316
|
+
`/api/v1/functions/${encodePathSegment(id, "function id", this.errors)}/execute`,
|
|
317
|
+
request
|
|
318
|
+
).then(
|
|
319
|
+
(response) => expectFunctionExecution(response, "Function execution response", this.errors)
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
function createFunctionsModule(transport, options = {}, errors = defaultSdkCoreErrorFactory) {
|
|
324
|
+
return new DefaultFunctionsModule(transport, errors, options);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/modules/integration.ts
|
|
328
|
+
function createIntegrationModule(transport, errors = defaultSdkCoreErrorFactory) {
|
|
329
|
+
return {
|
|
330
|
+
async executeResource(resourceId, params = {}) {
|
|
331
|
+
return expectProxyResult(
|
|
332
|
+
await transport.request(
|
|
333
|
+
`/api/v1/proxy/resources/${encodePathSegment(resourceId, "resource id", errors)}/execute`,
|
|
334
|
+
{ method: "POST", body: { params } }
|
|
335
|
+
),
|
|
336
|
+
"Integration resource response",
|
|
337
|
+
errors
|
|
338
|
+
);
|
|
339
|
+
},
|
|
340
|
+
async execute(configId, request) {
|
|
341
|
+
return expectProxyResult(
|
|
342
|
+
await transport.request(
|
|
343
|
+
`/api/v1/proxy/template-configs/${encodePathSegment(configId, "config id", errors)}/execute`,
|
|
344
|
+
{ method: "POST", body: { ...request, source: "SDK" } }
|
|
345
|
+
),
|
|
346
|
+
"Integration proxy response",
|
|
347
|
+
errors
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/modules/queries.ts
|
|
354
|
+
function createQueriesModule(transport, getDataSourceId, errors = defaultSdkCoreErrorFactory) {
|
|
355
|
+
return {
|
|
356
|
+
async execute(id, parameters = {}) {
|
|
357
|
+
const dataSourceId = getDataSourceId();
|
|
358
|
+
if (!dataSourceId) {
|
|
359
|
+
configurationError(
|
|
360
|
+
"A dataSourceId is required for queries. Call client.init() first or configure dataSourceId.",
|
|
361
|
+
errors
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
return expectQueryResult(
|
|
365
|
+
await transport.request(
|
|
366
|
+
`/api/v1/custom-queries/${encodePathSegment(id, "query id", errors)}/execute`,
|
|
367
|
+
{
|
|
368
|
+
method: "POST",
|
|
369
|
+
body: { dataSourceId, parameters }
|
|
370
|
+
}
|
|
371
|
+
),
|
|
372
|
+
"Query execution response",
|
|
373
|
+
errors
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/core.ts
|
|
380
|
+
function createSdkCore(options) {
|
|
381
|
+
const errors = options.errors ?? defaultSdkCoreErrorFactory;
|
|
382
|
+
return {
|
|
383
|
+
auth: createAuthModule(options.transports.auth, errors),
|
|
384
|
+
entities: createEntitiesModule(options.transports.dataManager, errors),
|
|
385
|
+
functions: createFunctionsModule(options.transports.functions, options.functions, errors),
|
|
386
|
+
integration: createIntegrationModule(options.transports.integration, errors),
|
|
387
|
+
queries: createQueriesModule(options.transports.dataManager, options.getDataSourceId, errors)
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
export {
|
|
391
|
+
SdkCoreConfigurationError,
|
|
392
|
+
SdkCoreResponseError,
|
|
393
|
+
createAuthModule,
|
|
394
|
+
createEntitiesModule,
|
|
395
|
+
createFunctionsModule,
|
|
396
|
+
createIntegrationModule,
|
|
397
|
+
createQueriesModule,
|
|
398
|
+
createSdkCore,
|
|
399
|
+
defaultSdkCoreErrorFactory,
|
|
400
|
+
encodePathSegment,
|
|
401
|
+
expectEmpty,
|
|
402
|
+
expectObject,
|
|
403
|
+
expectObjectArray
|
|
404
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mitralab.io/sdk-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Environment-neutral contracts and modules shared by Mitra JavaScript SDKs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"contracts",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE",
|
|
27
|
+
"CHANGELOG.md"
|
|
28
|
+
],
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
35
|
+
"format": "prettier --write .",
|
|
36
|
+
"format:check": "prettier --check .",
|
|
37
|
+
"lint": "eslint .",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"test": "vitest run --coverage",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"check:exports": "node scripts/check-exports.mjs",
|
|
42
|
+
"check:contracts": "node scripts/check-contracts.mjs",
|
|
43
|
+
"pack:check": "npm pack --dry-run",
|
|
44
|
+
"smoke:package": "node scripts/smoke-package.mjs",
|
|
45
|
+
"check": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run build && npm run check:exports && npm run check:contracts && npm run pack:check && npm run smoke:package",
|
|
46
|
+
"prepublishOnly": "npm run check"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"mitra",
|
|
50
|
+
"sdk",
|
|
51
|
+
"core",
|
|
52
|
+
"typescript"
|
|
53
|
+
],
|
|
54
|
+
"author": "Mitra Platform",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "https://github.com/mitralab-dev/mitra-core-sdk"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/mitralab-dev/mitra-core-sdk#readme",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/mitralab-dev/mitra-core-sdk/issues"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18.0.0"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@eslint/js": "^9.39.1",
|
|
69
|
+
"@types/node": "^22.15.0",
|
|
70
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
71
|
+
"eslint": "^9.39.1",
|
|
72
|
+
"globals": "^16.5.0",
|
|
73
|
+
"prettier": "^3.8.1",
|
|
74
|
+
"tsup": "^8.5.1",
|
|
75
|
+
"typescript": "~5.9.3",
|
|
76
|
+
"typescript-eslint": "^8.57.1",
|
|
77
|
+
"vitest": "^3.2.4"
|
|
78
|
+
},
|
|
79
|
+
"overrides": {
|
|
80
|
+
"esbuild": "^0.25.0"
|
|
81
|
+
}
|
|
82
|
+
}
|