@makemind/sdk 0.1.0 → 0.2.1
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 +74 -0
- package/README.md +11 -7
- package/dist/index.d.mts +143 -98
- package/dist/index.d.ts +143 -98
- package/dist/index.js +116 -77
- package/dist/index.mjs +116 -77
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -101,6 +101,8 @@ var ErrorCodes = {
|
|
|
101
101
|
NOT_FOUND: "NOT_FOUND",
|
|
102
102
|
ALREADY_EXISTS: "ALREADY_EXISTS",
|
|
103
103
|
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
104
|
+
/** No refresh credential on this client; the session is intact but cannot be refreshed here. */
|
|
105
|
+
AUTH_REFRESH_UNAVAILABLE: "AUTH_REFRESH_UNAVAILABLE",
|
|
104
106
|
// Tenant errors
|
|
105
107
|
TENANT_NOT_FOUND: "TENANT_NOT_FOUND",
|
|
106
108
|
TENANT_SUSPENDED: "TENANT_SUSPENDED",
|
|
@@ -265,30 +267,17 @@ var MAKEMINDAuth = class {
|
|
|
265
267
|
async signInWithEmailAndPassword(email, password) {
|
|
266
268
|
return this.signInWithEmail(email, password);
|
|
267
269
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this._memberships = response.memberships || [];
|
|
280
|
-
this.setAuthToken(response.token);
|
|
281
|
-
this.persistSession(response.user, response.token, response.refreshToken, response.memberships);
|
|
282
|
-
this.onAuthStateChange(response.user);
|
|
283
|
-
this.notifyAuthStateCallbacks(response.user);
|
|
284
|
-
return response.user;
|
|
285
|
-
} catch (error) {
|
|
286
|
-
if (error instanceof MAKEMINDError) {
|
|
287
|
-
throw error;
|
|
288
|
-
}
|
|
289
|
-
throw new MAKEMINDError("AUTH_ERROR", "Failed to sign up");
|
|
290
|
-
}
|
|
291
|
-
}
|
|
270
|
+
/*
|
|
271
|
+
* `signUp` stood here. The platform registers nobody from this surface
|
|
272
|
+
* (2026-09-17): `/auth/signup` was removed and answers 404, so the method
|
|
273
|
+
* could only ever fail. A published client that offers an operation the
|
|
274
|
+
* server does not have is a lie the caller finds at runtime; it is removed
|
|
275
|
+
* rather than left to throw.
|
|
276
|
+
*
|
|
277
|
+
* Where accounts come from now: a platform account exists once its person
|
|
278
|
+
* signs in at the tenant portal; a tenant's own end users register in that
|
|
279
|
+
* tenant's pool (`endusers-selfRegisterEndUser`).
|
|
280
|
+
*/
|
|
292
281
|
async signOut() {
|
|
293
282
|
try {
|
|
294
283
|
await this.apiClient.post("/auth/signout", {});
|
|
@@ -303,12 +292,12 @@ var MAKEMINDAuth = class {
|
|
|
303
292
|
this.notifyAuthStateCallbacks(null);
|
|
304
293
|
}
|
|
305
294
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
295
|
+
/*
|
|
296
|
+
* `sendPasswordResetEmail` stood here, with `confirmPasswordReset` and
|
|
297
|
+
* `verifyEmail` below. All three routes were removed with the sign-up they
|
|
298
|
+
* belonged to: the reset ended at an email this platform could not send,
|
|
299
|
+
* while the API answered that a link had been sent.
|
|
300
|
+
*/
|
|
312
301
|
onAuthStateChanged(callback) {
|
|
313
302
|
this.authStateCallbacks.add(callback);
|
|
314
303
|
callback(this._currentUser);
|
|
@@ -344,7 +333,13 @@ var MAKEMINDAuth = class {
|
|
|
344
333
|
} else if (this._currentUser) {
|
|
345
334
|
this.persistSession(this._currentUser, response.token, response.refreshToken, response.memberships);
|
|
346
335
|
}
|
|
347
|
-
} catch {
|
|
336
|
+
} catch (error) {
|
|
337
|
+
if (error instanceof MAKEMINDError && error.code === ErrorCodes.VALIDATION_ERROR) {
|
|
338
|
+
throw new MAKEMINDError(
|
|
339
|
+
ErrorCodes.AUTH_REFRESH_UNAVAILABLE,
|
|
340
|
+
"This client holds no refresh credential; sign in again to pick up new claims"
|
|
341
|
+
);
|
|
342
|
+
}
|
|
348
343
|
await this.signOut();
|
|
349
344
|
throw new MAKEMINDError("UNAUTHENTICATED", "Session expired");
|
|
350
345
|
}
|
|
@@ -426,25 +421,6 @@ var MAKEMINDAuth = class {
|
|
|
426
421
|
}
|
|
427
422
|
await this.apiClient.dispatch("resendVerificationEmail");
|
|
428
423
|
}
|
|
429
|
-
/**
|
|
430
|
-
* Verify email with code
|
|
431
|
-
*/
|
|
432
|
-
async verifyEmail(code) {
|
|
433
|
-
await this.apiClient.post("/auth/verify-email", {
|
|
434
|
-
code,
|
|
435
|
-
applicationId: this.applicationId
|
|
436
|
-
}, { skipAuth: true });
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Confirm password reset with code
|
|
440
|
-
*/
|
|
441
|
-
async confirmPasswordReset(code, newPassword) {
|
|
442
|
-
await this.apiClient.post("/auth/confirm-reset", {
|
|
443
|
-
code,
|
|
444
|
-
newPassword,
|
|
445
|
-
applicationId: this.applicationId
|
|
446
|
-
}, { skipAuth: true });
|
|
447
|
-
}
|
|
448
424
|
/**
|
|
449
425
|
* OAuth redirect-based sign-in is NOT supported by this backend.
|
|
450
426
|
* The backend has no /oauth/initiate or /oauth/callback routes.
|
|
@@ -601,31 +577,49 @@ var MAKEMINDData = class {
|
|
|
601
577
|
metadata: { hasMore: res.hasMore ?? false, lastDocId: res.nextCursor }
|
|
602
578
|
};
|
|
603
579
|
}
|
|
580
|
+
/*
|
|
581
|
+
* Every method on this service addresses the document platform — the store
|
|
582
|
+
* `query`, the batch methods, `aggregate` and `search` already read. The
|
|
583
|
+
* single-document methods used to go through the REST data door, which
|
|
584
|
+
* keeps a separate tree with a fixed set of collection names: a document
|
|
585
|
+
* created there was invisible to `query` and refused by `batchDelete`, and
|
|
586
|
+
* a collection of the tenant's own naming was refused at the door. One
|
|
587
|
+
* object, one store.
|
|
588
|
+
*/
|
|
604
589
|
async get(options) {
|
|
605
590
|
try {
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
);
|
|
609
|
-
return
|
|
591
|
+
const doc = await this.apiClient.dispatch("dataGetDocument", {
|
|
592
|
+
id: options.documentId
|
|
593
|
+
});
|
|
594
|
+
return { id: doc.id ?? options.documentId, data: doc.data };
|
|
610
595
|
} catch (error) {
|
|
611
|
-
if (error instanceof MAKEMINDError && error.code === "NOT_FOUND") {
|
|
596
|
+
if (error instanceof MAKEMINDError && (error.code === "NOT_FOUND" || error.code === "DATA_NOT_FOUND")) {
|
|
612
597
|
return null;
|
|
613
598
|
}
|
|
614
599
|
throw error;
|
|
615
600
|
}
|
|
616
601
|
}
|
|
617
602
|
async create(options) {
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
603
|
+
const created = await this.apiClient.dispatch(
|
|
604
|
+
"dataCreateDocument",
|
|
605
|
+
{
|
|
606
|
+
collection: options.collection,
|
|
607
|
+
data: options.data,
|
|
608
|
+
id: options.documentId
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
return { id: created.id, data: options.data };
|
|
623
612
|
}
|
|
624
613
|
async update(options) {
|
|
625
|
-
await this.apiClient.
|
|
614
|
+
await this.apiClient.dispatch("dataUpdateDocument", {
|
|
615
|
+
id: options.documentId,
|
|
616
|
+
data: options.data
|
|
617
|
+
});
|
|
626
618
|
}
|
|
627
619
|
async delete(options) {
|
|
628
|
-
await this.apiClient.
|
|
620
|
+
await this.apiClient.dispatch("dataDeleteDocument", {
|
|
621
|
+
id: options.documentId
|
|
622
|
+
});
|
|
629
623
|
}
|
|
630
624
|
onSnapshot(options, callback) {
|
|
631
625
|
const subscriptionId = `doc:${options.collection}:${options.documentId}`;
|
|
@@ -743,11 +737,33 @@ var MAKEMINDData = class {
|
|
|
743
737
|
...documentId ? { id: documentId } : {},
|
|
744
738
|
data
|
|
745
739
|
}));
|
|
740
|
+
const results = await this.batchWrite(operations);
|
|
741
|
+
return results.map((r) => ({ id: r.id, data: {} }));
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Send a batch and refuse to report a partial one as whole.
|
|
745
|
+
*
|
|
746
|
+
* The backend answers per item: an item it would not perform comes back
|
|
747
|
+
* `status: 'denied'` with the reason (`DATA_ALREADY_EXISTS` for a create over
|
|
748
|
+
* an id that exists, `DATA_WRITE_ONCE_VIOLATION`, `AUTH_ACCESS_DENIED`) while
|
|
749
|
+
* the others commit. Reading only the ids told the caller every item was
|
|
750
|
+
* written. A denied item now raises `BATCH_PARTIALLY_DENIED`, and the error
|
|
751
|
+
* carries every item's result so the caller can see which ones did commit.
|
|
752
|
+
*/
|
|
753
|
+
async batchWrite(operations) {
|
|
746
754
|
const response = await this.apiClient.dispatch(
|
|
747
755
|
"dataBatchWrite",
|
|
748
756
|
{ operations }
|
|
749
757
|
);
|
|
750
|
-
|
|
758
|
+
const denied = response.results.filter((r) => r.status === "denied");
|
|
759
|
+
if (denied.length > 0) {
|
|
760
|
+
throw new MAKEMINDError(
|
|
761
|
+
"BATCH_PARTIALLY_DENIED",
|
|
762
|
+
`${denied.length} of ${response.results.length} batch operations were refused: ` + denied.map((r) => `${r.id} (${r.error ?? "denied"})`).join(", "),
|
|
763
|
+
{ results: response.results, denied }
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
return response.results;
|
|
751
767
|
}
|
|
752
768
|
async batchUpdate(collection, updates) {
|
|
753
769
|
const operations = updates.map(({ documentId, data }) => ({
|
|
@@ -755,14 +771,14 @@ var MAKEMINDData = class {
|
|
|
755
771
|
id: documentId,
|
|
756
772
|
data
|
|
757
773
|
}));
|
|
758
|
-
await this.
|
|
774
|
+
await this.batchWrite(operations);
|
|
759
775
|
}
|
|
760
776
|
async batchDelete(collection, documentIds) {
|
|
761
777
|
const operations = documentIds.map((id) => ({
|
|
762
778
|
type: "delete",
|
|
763
779
|
id
|
|
764
780
|
}));
|
|
765
|
-
await this.
|
|
781
|
+
await this.batchWrite(operations);
|
|
766
782
|
}
|
|
767
783
|
// Export/Import operations
|
|
768
784
|
//
|
|
@@ -2835,12 +2851,12 @@ var MAKEMINDAI = class {
|
|
|
2835
2851
|
}
|
|
2836
2852
|
/**
|
|
2837
2853
|
* Document analysis (summary, field extraction, or QA).
|
|
2838
|
-
*
|
|
2839
|
-
*
|
|
2840
|
-
*
|
|
2841
|
-
*
|
|
2854
|
+
* The document itself is sent — a PDF as a `document` part, which the
|
|
2855
|
+
* platform hands only to a model that reads PDFs (core-ai 18 §5.2). `document`
|
|
2856
|
+
* is an https address the platform reads, or a `data:application/pdf;base64,…`
|
|
2857
|
+
* URI.
|
|
2842
2858
|
*/
|
|
2843
|
-
async analyzeDocument(
|
|
2859
|
+
async analyzeDocument(document2, analysisType, options) {
|
|
2844
2860
|
const systemPromptMap = {
|
|
2845
2861
|
summary: "You are a document summarization assistant. Summarize the provided document concisely.",
|
|
2846
2862
|
extract: `You are a document extraction assistant. Extract the following fields from the document as JSON: ${(options?.extractFields ?? []).join(", ")}.`,
|
|
@@ -2848,9 +2864,10 @@ var MAKEMINDAI = class {
|
|
|
2848
2864
|
};
|
|
2849
2865
|
const response = await this.apiClient.dispatch("ai-aiChat", {
|
|
2850
2866
|
tenantId: this.getTenantId(),
|
|
2867
|
+
...options?.model ? { model: options.model } : {},
|
|
2851
2868
|
messages: [
|
|
2852
2869
|
{ role: "system", content: systemPromptMap[analysisType] },
|
|
2853
|
-
{ role: "user", content:
|
|
2870
|
+
{ role: "user", content: [{ type: "document", document: { url: document2 } }] }
|
|
2854
2871
|
]
|
|
2855
2872
|
});
|
|
2856
2873
|
let result = response.content;
|
|
@@ -2866,6 +2883,20 @@ var MAKEMINDAI = class {
|
|
|
2866
2883
|
usage: { totalTokens: response.usage.totalTokens }
|
|
2867
2884
|
};
|
|
2868
2885
|
}
|
|
2886
|
+
/**
|
|
2887
|
+
* A document's text as written, page by page and line by line, from an OCR
|
|
2888
|
+
* engine — each line with its confidence and its box on the page (core-ai 18
|
|
2889
|
+
* §5.3). One call reads at most 30 pages; read the next window while `more`.
|
|
2890
|
+
* `document` is an https address or a data URI (PDF, PNG, JPEG, TIFF).
|
|
2891
|
+
*/
|
|
2892
|
+
async ocr(document2, options) {
|
|
2893
|
+
return this.apiClient.dispatch("ai-aiOcr", {
|
|
2894
|
+
tenantId: this.getTenantId(),
|
|
2895
|
+
document: { url: document2, ...options?.mediaType ? { mediaType: options.mediaType } : {} },
|
|
2896
|
+
...options?.pages ? { pages: options.pages } : {},
|
|
2897
|
+
...options?.model ? { model: options.model } : {}
|
|
2898
|
+
});
|
|
2899
|
+
}
|
|
2869
2900
|
// Text generation
|
|
2870
2901
|
async generate(prompt, options) {
|
|
2871
2902
|
const response = await this.chat(
|
|
@@ -3081,8 +3112,12 @@ var MAKEMINDApps = class {
|
|
|
3081
3112
|
// ============================================
|
|
3082
3113
|
// Publishing & Versioning
|
|
3083
3114
|
// ============================================
|
|
3084
|
-
|
|
3085
|
-
|
|
3115
|
+
/**
|
|
3116
|
+
* Cut a version and publish it — to everyone, or with `rolloutPercent`
|
|
3117
|
+
* (1–99) to that share of visitors beside the published version.
|
|
3118
|
+
*/
|
|
3119
|
+
async publish(appId, changelog, options = {}) {
|
|
3120
|
+
const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog, ...options });
|
|
3086
3121
|
return response;
|
|
3087
3122
|
}
|
|
3088
3123
|
async unpublish(appId) {
|
|
@@ -3281,16 +3316,20 @@ var MAKEMINDApps = class {
|
|
|
3281
3316
|
// ============================================
|
|
3282
3317
|
// AI Features
|
|
3283
3318
|
// ============================================
|
|
3319
|
+
/** A widget subtree in DSL from a description (app builder DDD 08 §9). */
|
|
3284
3320
|
async generateUI(prompt, context, appId) {
|
|
3285
3321
|
const response = await this.apiClient.post(
|
|
3286
3322
|
"/apps/ai/generate-ui",
|
|
3287
3323
|
{ prompt, context, appId }
|
|
3288
3324
|
);
|
|
3289
|
-
return {
|
|
3325
|
+
return { content: response.content };
|
|
3290
3326
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
return
|
|
3327
|
+
/** DSL actions a widget could run, from the tools the app's origin offers. */
|
|
3328
|
+
async suggestActions(appId, widgetType) {
|
|
3329
|
+
return this.apiClient.post(
|
|
3330
|
+
`/apps/${appId}/ai/suggest-actions`,
|
|
3331
|
+
{ widgetType }
|
|
3332
|
+
);
|
|
3294
3333
|
}
|
|
3295
3334
|
// ============================================
|
|
3296
3335
|
// Collaboration
|
package/dist/index.mjs
CHANGED
|
@@ -45,6 +45,8 @@ var ErrorCodes = {
|
|
|
45
45
|
NOT_FOUND: "NOT_FOUND",
|
|
46
46
|
ALREADY_EXISTS: "ALREADY_EXISTS",
|
|
47
47
|
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
48
|
+
/** No refresh credential on this client; the session is intact but cannot be refreshed here. */
|
|
49
|
+
AUTH_REFRESH_UNAVAILABLE: "AUTH_REFRESH_UNAVAILABLE",
|
|
48
50
|
// Tenant errors
|
|
49
51
|
TENANT_NOT_FOUND: "TENANT_NOT_FOUND",
|
|
50
52
|
TENANT_SUSPENDED: "TENANT_SUSPENDED",
|
|
@@ -209,30 +211,17 @@ var MAKEMINDAuth = class {
|
|
|
209
211
|
async signInWithEmailAndPassword(email, password) {
|
|
210
212
|
return this.signInWithEmail(email, password);
|
|
211
213
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
this._memberships = response.memberships || [];
|
|
224
|
-
this.setAuthToken(response.token);
|
|
225
|
-
this.persistSession(response.user, response.token, response.refreshToken, response.memberships);
|
|
226
|
-
this.onAuthStateChange(response.user);
|
|
227
|
-
this.notifyAuthStateCallbacks(response.user);
|
|
228
|
-
return response.user;
|
|
229
|
-
} catch (error) {
|
|
230
|
-
if (error instanceof MAKEMINDError) {
|
|
231
|
-
throw error;
|
|
232
|
-
}
|
|
233
|
-
throw new MAKEMINDError("AUTH_ERROR", "Failed to sign up");
|
|
234
|
-
}
|
|
235
|
-
}
|
|
214
|
+
/*
|
|
215
|
+
* `signUp` stood here. The platform registers nobody from this surface
|
|
216
|
+
* (2026-09-17): `/auth/signup` was removed and answers 404, so the method
|
|
217
|
+
* could only ever fail. A published client that offers an operation the
|
|
218
|
+
* server does not have is a lie the caller finds at runtime; it is removed
|
|
219
|
+
* rather than left to throw.
|
|
220
|
+
*
|
|
221
|
+
* Where accounts come from now: a platform account exists once its person
|
|
222
|
+
* signs in at the tenant portal; a tenant's own end users register in that
|
|
223
|
+
* tenant's pool (`endusers-selfRegisterEndUser`).
|
|
224
|
+
*/
|
|
236
225
|
async signOut() {
|
|
237
226
|
try {
|
|
238
227
|
await this.apiClient.post("/auth/signout", {});
|
|
@@ -247,12 +236,12 @@ var MAKEMINDAuth = class {
|
|
|
247
236
|
this.notifyAuthStateCallbacks(null);
|
|
248
237
|
}
|
|
249
238
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
239
|
+
/*
|
|
240
|
+
* `sendPasswordResetEmail` stood here, with `confirmPasswordReset` and
|
|
241
|
+
* `verifyEmail` below. All three routes were removed with the sign-up they
|
|
242
|
+
* belonged to: the reset ended at an email this platform could not send,
|
|
243
|
+
* while the API answered that a link had been sent.
|
|
244
|
+
*/
|
|
256
245
|
onAuthStateChanged(callback) {
|
|
257
246
|
this.authStateCallbacks.add(callback);
|
|
258
247
|
callback(this._currentUser);
|
|
@@ -288,7 +277,13 @@ var MAKEMINDAuth = class {
|
|
|
288
277
|
} else if (this._currentUser) {
|
|
289
278
|
this.persistSession(this._currentUser, response.token, response.refreshToken, response.memberships);
|
|
290
279
|
}
|
|
291
|
-
} catch {
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (error instanceof MAKEMINDError && error.code === ErrorCodes.VALIDATION_ERROR) {
|
|
282
|
+
throw new MAKEMINDError(
|
|
283
|
+
ErrorCodes.AUTH_REFRESH_UNAVAILABLE,
|
|
284
|
+
"This client holds no refresh credential; sign in again to pick up new claims"
|
|
285
|
+
);
|
|
286
|
+
}
|
|
292
287
|
await this.signOut();
|
|
293
288
|
throw new MAKEMINDError("UNAUTHENTICATED", "Session expired");
|
|
294
289
|
}
|
|
@@ -370,25 +365,6 @@ var MAKEMINDAuth = class {
|
|
|
370
365
|
}
|
|
371
366
|
await this.apiClient.dispatch("resendVerificationEmail");
|
|
372
367
|
}
|
|
373
|
-
/**
|
|
374
|
-
* Verify email with code
|
|
375
|
-
*/
|
|
376
|
-
async verifyEmail(code) {
|
|
377
|
-
await this.apiClient.post("/auth/verify-email", {
|
|
378
|
-
code,
|
|
379
|
-
applicationId: this.applicationId
|
|
380
|
-
}, { skipAuth: true });
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Confirm password reset with code
|
|
384
|
-
*/
|
|
385
|
-
async confirmPasswordReset(code, newPassword) {
|
|
386
|
-
await this.apiClient.post("/auth/confirm-reset", {
|
|
387
|
-
code,
|
|
388
|
-
newPassword,
|
|
389
|
-
applicationId: this.applicationId
|
|
390
|
-
}, { skipAuth: true });
|
|
391
|
-
}
|
|
392
368
|
/**
|
|
393
369
|
* OAuth redirect-based sign-in is NOT supported by this backend.
|
|
394
370
|
* The backend has no /oauth/initiate or /oauth/callback routes.
|
|
@@ -545,31 +521,49 @@ var MAKEMINDData = class {
|
|
|
545
521
|
metadata: { hasMore: res.hasMore ?? false, lastDocId: res.nextCursor }
|
|
546
522
|
};
|
|
547
523
|
}
|
|
524
|
+
/*
|
|
525
|
+
* Every method on this service addresses the document platform — the store
|
|
526
|
+
* `query`, the batch methods, `aggregate` and `search` already read. The
|
|
527
|
+
* single-document methods used to go through the REST data door, which
|
|
528
|
+
* keeps a separate tree with a fixed set of collection names: a document
|
|
529
|
+
* created there was invisible to `query` and refused by `batchDelete`, and
|
|
530
|
+
* a collection of the tenant's own naming was refused at the door. One
|
|
531
|
+
* object, one store.
|
|
532
|
+
*/
|
|
548
533
|
async get(options) {
|
|
549
534
|
try {
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
);
|
|
553
|
-
return
|
|
535
|
+
const doc = await this.apiClient.dispatch("dataGetDocument", {
|
|
536
|
+
id: options.documentId
|
|
537
|
+
});
|
|
538
|
+
return { id: doc.id ?? options.documentId, data: doc.data };
|
|
554
539
|
} catch (error) {
|
|
555
|
-
if (error instanceof MAKEMINDError && error.code === "NOT_FOUND") {
|
|
540
|
+
if (error instanceof MAKEMINDError && (error.code === "NOT_FOUND" || error.code === "DATA_NOT_FOUND")) {
|
|
556
541
|
return null;
|
|
557
542
|
}
|
|
558
543
|
throw error;
|
|
559
544
|
}
|
|
560
545
|
}
|
|
561
546
|
async create(options) {
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
547
|
+
const created = await this.apiClient.dispatch(
|
|
548
|
+
"dataCreateDocument",
|
|
549
|
+
{
|
|
550
|
+
collection: options.collection,
|
|
551
|
+
data: options.data,
|
|
552
|
+
id: options.documentId
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
return { id: created.id, data: options.data };
|
|
567
556
|
}
|
|
568
557
|
async update(options) {
|
|
569
|
-
await this.apiClient.
|
|
558
|
+
await this.apiClient.dispatch("dataUpdateDocument", {
|
|
559
|
+
id: options.documentId,
|
|
560
|
+
data: options.data
|
|
561
|
+
});
|
|
570
562
|
}
|
|
571
563
|
async delete(options) {
|
|
572
|
-
await this.apiClient.
|
|
564
|
+
await this.apiClient.dispatch("dataDeleteDocument", {
|
|
565
|
+
id: options.documentId
|
|
566
|
+
});
|
|
573
567
|
}
|
|
574
568
|
onSnapshot(options, callback) {
|
|
575
569
|
const subscriptionId = `doc:${options.collection}:${options.documentId}`;
|
|
@@ -687,11 +681,33 @@ var MAKEMINDData = class {
|
|
|
687
681
|
...documentId ? { id: documentId } : {},
|
|
688
682
|
data
|
|
689
683
|
}));
|
|
684
|
+
const results = await this.batchWrite(operations);
|
|
685
|
+
return results.map((r) => ({ id: r.id, data: {} }));
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Send a batch and refuse to report a partial one as whole.
|
|
689
|
+
*
|
|
690
|
+
* The backend answers per item: an item it would not perform comes back
|
|
691
|
+
* `status: 'denied'` with the reason (`DATA_ALREADY_EXISTS` for a create over
|
|
692
|
+
* an id that exists, `DATA_WRITE_ONCE_VIOLATION`, `AUTH_ACCESS_DENIED`) while
|
|
693
|
+
* the others commit. Reading only the ids told the caller every item was
|
|
694
|
+
* written. A denied item now raises `BATCH_PARTIALLY_DENIED`, and the error
|
|
695
|
+
* carries every item's result so the caller can see which ones did commit.
|
|
696
|
+
*/
|
|
697
|
+
async batchWrite(operations) {
|
|
690
698
|
const response = await this.apiClient.dispatch(
|
|
691
699
|
"dataBatchWrite",
|
|
692
700
|
{ operations }
|
|
693
701
|
);
|
|
694
|
-
|
|
702
|
+
const denied = response.results.filter((r) => r.status === "denied");
|
|
703
|
+
if (denied.length > 0) {
|
|
704
|
+
throw new MAKEMINDError(
|
|
705
|
+
"BATCH_PARTIALLY_DENIED",
|
|
706
|
+
`${denied.length} of ${response.results.length} batch operations were refused: ` + denied.map((r) => `${r.id} (${r.error ?? "denied"})`).join(", "),
|
|
707
|
+
{ results: response.results, denied }
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
return response.results;
|
|
695
711
|
}
|
|
696
712
|
async batchUpdate(collection, updates) {
|
|
697
713
|
const operations = updates.map(({ documentId, data }) => ({
|
|
@@ -699,14 +715,14 @@ var MAKEMINDData = class {
|
|
|
699
715
|
id: documentId,
|
|
700
716
|
data
|
|
701
717
|
}));
|
|
702
|
-
await this.
|
|
718
|
+
await this.batchWrite(operations);
|
|
703
719
|
}
|
|
704
720
|
async batchDelete(collection, documentIds) {
|
|
705
721
|
const operations = documentIds.map((id) => ({
|
|
706
722
|
type: "delete",
|
|
707
723
|
id
|
|
708
724
|
}));
|
|
709
|
-
await this.
|
|
725
|
+
await this.batchWrite(operations);
|
|
710
726
|
}
|
|
711
727
|
// Export/Import operations
|
|
712
728
|
//
|
|
@@ -2779,12 +2795,12 @@ var MAKEMINDAI = class {
|
|
|
2779
2795
|
}
|
|
2780
2796
|
/**
|
|
2781
2797
|
* Document analysis (summary, field extraction, or QA).
|
|
2782
|
-
*
|
|
2783
|
-
*
|
|
2784
|
-
*
|
|
2785
|
-
*
|
|
2798
|
+
* The document itself is sent — a PDF as a `document` part, which the
|
|
2799
|
+
* platform hands only to a model that reads PDFs (core-ai 18 §5.2). `document`
|
|
2800
|
+
* is an https address the platform reads, or a `data:application/pdf;base64,…`
|
|
2801
|
+
* URI.
|
|
2786
2802
|
*/
|
|
2787
|
-
async analyzeDocument(
|
|
2803
|
+
async analyzeDocument(document2, analysisType, options) {
|
|
2788
2804
|
const systemPromptMap = {
|
|
2789
2805
|
summary: "You are a document summarization assistant. Summarize the provided document concisely.",
|
|
2790
2806
|
extract: `You are a document extraction assistant. Extract the following fields from the document as JSON: ${(options?.extractFields ?? []).join(", ")}.`,
|
|
@@ -2792,9 +2808,10 @@ var MAKEMINDAI = class {
|
|
|
2792
2808
|
};
|
|
2793
2809
|
const response = await this.apiClient.dispatch("ai-aiChat", {
|
|
2794
2810
|
tenantId: this.getTenantId(),
|
|
2811
|
+
...options?.model ? { model: options.model } : {},
|
|
2795
2812
|
messages: [
|
|
2796
2813
|
{ role: "system", content: systemPromptMap[analysisType] },
|
|
2797
|
-
{ role: "user", content:
|
|
2814
|
+
{ role: "user", content: [{ type: "document", document: { url: document2 } }] }
|
|
2798
2815
|
]
|
|
2799
2816
|
});
|
|
2800
2817
|
let result = response.content;
|
|
@@ -2810,6 +2827,20 @@ var MAKEMINDAI = class {
|
|
|
2810
2827
|
usage: { totalTokens: response.usage.totalTokens }
|
|
2811
2828
|
};
|
|
2812
2829
|
}
|
|
2830
|
+
/**
|
|
2831
|
+
* A document's text as written, page by page and line by line, from an OCR
|
|
2832
|
+
* engine — each line with its confidence and its box on the page (core-ai 18
|
|
2833
|
+
* §5.3). One call reads at most 30 pages; read the next window while `more`.
|
|
2834
|
+
* `document` is an https address or a data URI (PDF, PNG, JPEG, TIFF).
|
|
2835
|
+
*/
|
|
2836
|
+
async ocr(document2, options) {
|
|
2837
|
+
return this.apiClient.dispatch("ai-aiOcr", {
|
|
2838
|
+
tenantId: this.getTenantId(),
|
|
2839
|
+
document: { url: document2, ...options?.mediaType ? { mediaType: options.mediaType } : {} },
|
|
2840
|
+
...options?.pages ? { pages: options.pages } : {},
|
|
2841
|
+
...options?.model ? { model: options.model } : {}
|
|
2842
|
+
});
|
|
2843
|
+
}
|
|
2813
2844
|
// Text generation
|
|
2814
2845
|
async generate(prompt, options) {
|
|
2815
2846
|
const response = await this.chat(
|
|
@@ -3025,8 +3056,12 @@ var MAKEMINDApps = class {
|
|
|
3025
3056
|
// ============================================
|
|
3026
3057
|
// Publishing & Versioning
|
|
3027
3058
|
// ============================================
|
|
3028
|
-
|
|
3029
|
-
|
|
3059
|
+
/**
|
|
3060
|
+
* Cut a version and publish it — to everyone, or with `rolloutPercent`
|
|
3061
|
+
* (1–99) to that share of visitors beside the published version.
|
|
3062
|
+
*/
|
|
3063
|
+
async publish(appId, changelog, options = {}) {
|
|
3064
|
+
const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog, ...options });
|
|
3030
3065
|
return response;
|
|
3031
3066
|
}
|
|
3032
3067
|
async unpublish(appId) {
|
|
@@ -3225,16 +3260,20 @@ var MAKEMINDApps = class {
|
|
|
3225
3260
|
// ============================================
|
|
3226
3261
|
// AI Features
|
|
3227
3262
|
// ============================================
|
|
3263
|
+
/** A widget subtree in DSL from a description (app builder DDD 08 §9). */
|
|
3228
3264
|
async generateUI(prompt, context, appId) {
|
|
3229
3265
|
const response = await this.apiClient.post(
|
|
3230
3266
|
"/apps/ai/generate-ui",
|
|
3231
3267
|
{ prompt, context, appId }
|
|
3232
3268
|
);
|
|
3233
|
-
return {
|
|
3269
|
+
return { content: response.content };
|
|
3234
3270
|
}
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
return
|
|
3271
|
+
/** DSL actions a widget could run, from the tools the app's origin offers. */
|
|
3272
|
+
async suggestActions(appId, widgetType) {
|
|
3273
|
+
return this.apiClient.post(
|
|
3274
|
+
`/apps/${appId}/ai/suggest-actions`,
|
|
3275
|
+
{ widgetType }
|
|
3276
|
+
);
|
|
3238
3277
|
}
|
|
3239
3278
|
// ============================================
|
|
3240
3279
|
// Collaboration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makemind/sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "MAKEMIND Platform SDK for Web Applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -34,15 +34,17 @@
|
|
|
34
34
|
"firebase": "^10.14.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
+
"@makemind/app-builder-ui": "file:../app-builder-ui",
|
|
37
38
|
"@types/jsdom": "^30.0.0",
|
|
38
39
|
"@types/node": "^20.10.0",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
41
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
39
42
|
"eslint": "^8.55.0",
|
|
40
43
|
"firebase": "^10.7.0",
|
|
41
44
|
"jsdom": "^30.0.1",
|
|
42
45
|
"tsup": "^8.0.1",
|
|
43
46
|
"typescript": "^5.3.0",
|
|
44
|
-
"vitest": "^1.0.0"
|
|
45
|
-
"@makemind/app-builder-ui": "file:../app-builder-ui"
|
|
47
|
+
"vitest": "^1.0.0"
|
|
46
48
|
},
|
|
47
49
|
"keywords": [
|
|
48
50
|
"makemind",
|