@casual-simulation/aux-runtime 3.7.0 → 3.7.1-alpha.17809973136

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.
@@ -1,6 +1,6 @@
1
1
  import { DEBUG_STRING, debugStringifyFunction } from './AuxGlobalContext';
2
2
  import { hasValue, trimTag, isBot, BOT_SPACE_TAG, toast as toastMessage, getScriptIssues as scriptIssues, tip as tipMessage, hideTips as hideTipMessages, showJoinCode as calcShowJoinCode, requestFullscreen, exitFullscreen, html as htmlMessage, hideHtml as hideHtmlMessage, setClipboard as calcSetClipboard, tweenTo as calcTweenTo, showChat as calcShowChat, hideChat as calcHideChat, runScript, getMediaPermission as calcGetMediaPermission, getAverageFrameRate as calcGetAverageFrameRate, enableAR as calcEnableAR, disableAR as calcDisableAR, enableVR as calcEnableVR, disableVR as calcDisableVR, arSupported as calcARSupported, vrSupported as calcVRSupported, showUploadAuxFile as calcShowUploadAuxFile, openQRCodeScanner as calcOpenQRCodeScanner, showQRCode as calcShowQRCode, openBarcodeScanner as calcOpenBarcodeScanner, showBarcode as calcShowBarcode, importAUX as calcImportAUX, showInputForTag as calcShowInputForTag, showInput as calcShowInput, showConfirm as calcShowConfirm, replaceDragBot as calcReplaceDragBot, goToDimension as calcGoToDimension, goToURL as calcGoToURL, openURL as calcOpenURL, playSound as calcPlaySound, bufferSound as calcBufferSound, cancelSound as calcCancelSound, shell as calcShell, reject as calcReject, localFormAnimation as calcLocalFormAnimation, webhook as calcWebhook, superShout as calcSuperShout, share as calcShare, registerPrefix as calcRegisterPrefix, localPositionTween as calcLocalPositionTween, localRotationTween as calcLocalRotationTween, showUploadFiles as calcShowUploadFiles, download, loadSimulation, unloadSimulation, getUploadState, addState, getPortalTag, KNOWN_PORTALS, openConsole, tagsOnBot, getOriginalObject, getBotSpace, trimEvent, CREATE_ACTION_NAME, CREATE_ANY_ACTION_NAME, DESTROY_ACTION_NAME, ORIGINAL_OBJECT, getRemoteCount, getRemotes, listInstUpdates as calcListInstUpdates, getInstStateFromUpdates as calcGetInstStateFromUpdates, action, calculateAnchorPoint, calculateAnchorPointOffset, getBotPosition as calcGetBotPosition, getBotRotation as calcGetBotRotation, isRuntimeBot, SET_TAG_MASK_SYMBOL, CLEAR_TAG_MASKS_SYMBOL, getBotScale, EDIT_TAG_SYMBOL, EDIT_TAG_MASK_SYMBOL, circleWipe, addDropSnap as calcAddDropSnap, addDropGrid as calcAddDropGrid, animateToPosition, beginAudioRecording as calcBeginAudioRecording, endAudioRecording as calcEndAudioRecording, beginRecording as calcBeginRecording, endRecording as calcEndRecording, speakText as calcSpeakText, getVoices as calcGetVoices, getGeolocation as calcGetGeolocation, cancelAnimation, disablePOV, enablePOV, enableCustomDragging as calcEnableCustomDragging, MINI_PORTAL, registerCustomApp, setAppOutput, unregisterCustomApp, requestAuthData as calcRequestAuthData, createBot, defineGlobalBot as calcDefineGlobalBot, TEMPORARY_BOT_PARTITION_ID, convertToString, GET_TAG_MASKS_SYMBOL, isBotLink, parseBotLink, createBotLink, convertGeolocationToWhat3Words as calcConvertGeolocationToWhat3Words, meetCommand as calcMeetCommand, meetFunction as calcMeetFunction, openImageClassifier as calcOpenImageClassifier, classifyImages as calcOpenClassifyImages, isBotDate, DATE_TAG_PREFIX, parseBotDate, realNumberOrDefault, raycastFromCamera as calcRaycastFromCamera, raycastInPortal as calcRaycastInPortal, calculateRayFromCamera as calcCalculateRayFromCamera, bufferFormAddressGltf, startFormAnimation as calcStartFormAnimation, stopFormAnimation as calcStopFormAnimation, listFormAnimations as calcListFormAnimations, calculateStringTagValue, createInitializationUpdate as calcCreateInitalizationUpdate, applyUpdatesToInst as calcApplyUpdatesToInst, configureWakeLock, getWakeLockConfiguration as calcGetWakeLockConfiguration, analyticsRecordEvent as calcAnalyticsRecordEvent, KNOWN_TAGS, isStoredVersion2, getCurrentInstUpdate as calcGetCurrentInstUpdate, openPhotoCamera as calcOpenPhotoCamera, getEasing, enableCollaboration as calcEnableCollaboration, showAccountInfo as calcShowAccountInfo, reportInst as calcReportInst, getRecordsEndpoint as calcGetRecordsEndpoint, ldrawCountAddressBuildSteps as calcLdrawCountAddressBuildSteps, ldrawCountTextBuildSteps as calcLdrawCountTextBuildSteps, calculateViewportCoordinatesFromPosition as calcCalculateViewportCoordinatesFromPosition, calculateScreenCoordinatesFromViewportCoordinates as calcCalculateScreenCoordinatesFromViewportCoordinates, calculateViewportCoordinatesFromScreenCoordinates as calcCalculateViewportCoordinatesFromScreenCoordinates, capturePortalScreenshot as calcCapturePortalScreenshot, createStaticHtml as calcCreateStaticHtmlFromBots, recordLoom, watchLoom, getLoomMetadata, loadSharedDocument, installAuxFile as calcInstallAuxFile, calculateStringListTagValue, calculateScreenCoordinatesFromPosition as calcCalculateScreenCoordinatesFromPosition, addMapLayer as calcAddMapLayer, removeMapLayer as calcRemoveMapLayer, GET_DYNAMIC_LISTENERS_SYMBOL, ADD_BOT_LISTENER_SYMBOL, REMOVE_BOT_LISTENER_SYMBOL, } from '@casual-simulation/aux-common/bots';
3
- import { aiChat, aiChatStream, aiGenerateSkybox, aiGenerateImage, grantRecordPermission as calcGrantRecordPermission, revokeRecordPermission as calcRevokeRecordPermission, grantInstAdminPermission as calcGrantInstAdminPermission, grantUserRole as calcGrantUserRole, revokeUserRole as calcRevokeUserRole, grantInstRole as calcGrantInstRole, revokeInstRole as calcRevokeInstRole, listUserStudios as calcListUserStudios, joinRoom as calcJoinRoom, leaveRoom as calcLeaveRoom, setRoomOptions as calcSetRoomOptions, getRoomOptions as calcGetRoomOptions, getRoomTrackOptions as calcGetRoomTrackOptions, setRoomTrackOptions as calcSetRoomTrackOptions, getRoomRemoteOptions as calcGetRoomRemoteOptions, listDataRecord, recordEvent as calcRecordEvent, getEventCount as calcGetEventCount, getFile as calcGetFile, eraseFile as calcEraseFile, getPublicRecordKey as calcGetPublicRecordKey, recordData as calcRecordData, getRecordData, eraseRecordData, recordFile as calcRecordFile, listDataRecordByMarker, aiHumeGetAccessToken, aiSloydGenerateModel, recordWebhook as calcRecordWebhook, getWebhook as calcGetWebhook, listWebhooks as calcListWebhooks, listWebhooksByMarker as calcListWebhooksByMarker, eraseWebhook as calcEraseWebhook, runWebhook as calcRunWebhook, recordNotification as calcRecordNotification, getNotification as calcGetNotification, listNotifications as calcListNotifications, listNotificationsByMarker as calcListNotificationsByMarker, eraseNotification as calcEraseNotification, subscribeToNotification as calcSubscribeToNotification, unsubscribeFromNotification as calcUnsubscribeFromNotification, sendNotification as calcSendNotification, listNotificationSubscriptions as calcListNotificationSubscriptions, listUserNotificationSubscriptions as calcListUserNotificationSubscriptions, aiOpenAICreateRealtimeSession, grantEntitlements as calcGrantEntitlements, recordPackageVersion as calcRecordPackageVersion, erasePackageVersion as calcErasePackageVersion, listPackageVersions as calcListPackageVersions, getPackageVersion as calcGetPackageVersion, recordPackageContainer as calcRecordPackageContainer, erasePackageContaienr as calcErasePackageContainer, listPackageContainers as calcListPackageContainers, listPackageContainersByMarker as calcListPackageContainersByMarker, getPackageContainer as calcGetPackageContainer, installPackage as calcInstallPackage, listInstalledPackages as calcListInstalledPackages, recordsCallProcedure, } from './RecordsEvents';
3
+ import { aiChat, aiChatStream, aiGenerateSkybox, aiGenerateImage, grantRecordPermission as calcGrantRecordPermission, revokeRecordPermission as calcRevokeRecordPermission, listPermissions as calcListPermissions, grantInstAdminPermission as calcGrantInstAdminPermission, grantUserRole as calcGrantUserRole, revokeUserRole as calcRevokeUserRole, grantInstRole as calcGrantInstRole, revokeInstRole as calcRevokeInstRole, listUserStudios as calcListUserStudios, listStudioRecords as calcListStudioRecords, joinRoom as calcJoinRoom, leaveRoom as calcLeaveRoom, setRoomOptions as calcSetRoomOptions, getRoomOptions as calcGetRoomOptions, getRoomTrackOptions as calcGetRoomTrackOptions, setRoomTrackOptions as calcSetRoomTrackOptions, getRoomRemoteOptions as calcGetRoomRemoteOptions, listDataRecord, recordEvent as calcRecordEvent, getEventCount as calcGetEventCount, getFile as calcGetFile, eraseFile as calcEraseFile, getPublicRecordKey as calcGetPublicRecordKey, recordData as calcRecordData, getRecordData, eraseRecordData, recordFile as calcRecordFile, listDataRecordByMarker, aiHumeGetAccessToken, aiSloydGenerateModel, recordWebhook as calcRecordWebhook, getWebhook as calcGetWebhook, listWebhooks as calcListWebhooks, listWebhooksByMarker as calcListWebhooksByMarker, eraseWebhook as calcEraseWebhook, runWebhook as calcRunWebhook, recordNotification as calcRecordNotification, getNotification as calcGetNotification, listNotifications as calcListNotifications, listNotificationsByMarker as calcListNotificationsByMarker, eraseNotification as calcEraseNotification, subscribeToNotification as calcSubscribeToNotification, unsubscribeFromNotification as calcUnsubscribeFromNotification, sendNotification as calcSendNotification, listNotificationSubscriptions as calcListNotificationSubscriptions, listUserNotificationSubscriptions as calcListUserNotificationSubscriptions, aiOpenAICreateRealtimeSession, grantEntitlements as calcGrantEntitlements, recordPackageVersion as calcRecordPackageVersion, erasePackageVersion as calcErasePackageVersion, listPackageVersions as calcListPackageVersions, getPackageVersion as calcGetPackageVersion, recordPackageContainer as calcRecordPackageContainer, erasePackageContaienr as calcErasePackageContainer, listPackageContainers as calcListPackageContainers, listPackageContainersByMarker as calcListPackageContainersByMarker, getPackageContainer as calcGetPackageContainer, installPackage as calcInstallPackage, listInstalledPackages as calcListInstalledPackages, listInsts as calcListInsts, listInstsByMarker as calcListInstsByMarker, recordsCallProcedure, } from './RecordsEvents';
4
4
  import { sortBy, cloneDeep, union, isEqual } from 'es-toolkit/compat';
5
5
  import { remote as calcRemote, DEFAULT_BRANCH_NAME, formatVersionNumber, parseVersionNumber, PRIVATE_MARKER, } from '@casual-simulation/aux-common';
6
6
  import { RanOutOfEnergyError } from './AuxResults';
@@ -33,6 +33,7 @@ import { INTERPRETABLE_FUNCTION } from './AuxCompiler';
33
33
  import { constructInitializationUpdate, mergeInstUpdates as calcMergeInstUpdates, } from '@casual-simulation/aux-common/partitions/PartitionUtils';
34
34
  import { CasualOSError } from './CasualOSError';
35
35
  import { attachRuntime, detachRuntime } from './RuntimeEvents';
36
+ import { query as q } from './database/DatabaseUtils';
36
37
  const _html = htm.bind(h);
37
38
  const html = ((...args) => {
38
39
  return _html(...args);
@@ -142,6 +143,201 @@ function getBotSnapshot(bot) {
142
143
  const DEAD_RECKONING_OFFSET = 50;
143
144
  const DEG_TO_RAD = Math.PI / 180;
144
145
  const RAD_TO_DEG = 180 / Math.PI;
146
+ /**
147
+ * Represents a connection to a database record.
148
+ *
149
+ * @dochash types/records/database
150
+ * @docname Database
151
+ *
152
+ * @example Get a database connection.
153
+ * const database = os.getDatabase('myRecord', 'myDatabase');
154
+ */
155
+ export class ApiDatabase {
156
+ constructor(recordName, address, options, context) {
157
+ this._recordName = recordName;
158
+ this._address = address;
159
+ this._options = options;
160
+ this._context = context;
161
+ }
162
+ /**
163
+ * Constructs a database statement from the given [template string literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).
164
+ *
165
+ * Once constructed, the returned statement can be used with `run()` or `batch()`.
166
+ *
167
+ * @param templates The string templates.
168
+ * @param params The parameters to interpolate into the templates.
169
+ * @returns A database statement.
170
+ *
171
+ * @example Create a database statement from a SQL query
172
+ * const statement = database.sql`SELECT * FROM items`;
173
+ *
174
+ * @example Use a parameter in a database statement
175
+ * const itemId = 'abc';
176
+ * const statement = database.sql`SELECT * FROM items WHERE id = ${itemId}`;
177
+ */
178
+ sql(templates, ...params) {
179
+ return q(templates, ...params);
180
+ }
181
+ /**
182
+ * Creates a new database statement from the given SQL and parameters.
183
+ * @param sql The SQL query string.
184
+ * @param params The parameters to include in the query.
185
+ * @returns A new database statement.
186
+ */
187
+ statement(sql, ...params) {
188
+ return {
189
+ query: sql,
190
+ params,
191
+ };
192
+ }
193
+ /**
194
+ * Runs the given readonly query against the database.
195
+ * This method requires queries to be read-only. This means that queries can only select data, they cannot insert, update, or delete data.
196
+ *
197
+ * Supports [template string literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) for parameterized queries.
198
+ *
199
+ * **Warning:** To avoid [SQL Injection attacks](https://en.wikipedia.org/wiki/SQL_injection), always use template literals with expressions. Never use the `+` operator to concatenate strings containing SQL code.
200
+ *
201
+ * @param templates The string templates.
202
+ * @param params The parameters that should be used.
203
+ * @returns A promise that resolves when the query has completed.
204
+ *
205
+ * @example Select all items from a table
206
+ * const result = await database.query`SELECT * FROM items`;
207
+ *
208
+ * @example Use a parameter in a query
209
+ * const itemId = 'abc';
210
+ * const result = await database.query`SELECT * FROM items WHERE id = ${itemId}`;
211
+ */
212
+ async query(templates, ...params) {
213
+ return this.run(q(templates, ...params), true);
214
+ }
215
+ /**
216
+ * Runs the given SQL on the database and returns the result.
217
+ * This method supports read-write queries. This means that queries can be used to select, insert, update, and delete data.
218
+ *
219
+ * Supports [template string literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) for parameterized queries.
220
+ *
221
+ * **Warning:** To avoid [SQL Injection attacks](https://en.wikipedia.org/wiki/SQL_injection), always use template literals with expressions. Never use the `+` operator to concatenate strings containing SQL code.
222
+ *
223
+ * @param templates The string templates.
224
+ * @param params The parameters that should be used.
225
+ * @returns A promise that resolves when the SQL has completed.
226
+ *
227
+ * @example Insert a new item into a table
228
+ * const name = "New Item";
229
+ * const value = 100;
230
+ * const result = await database.execute`INSERT INTO items (name, value) VALUES (${name}, ${value})`;
231
+ *
232
+ */
233
+ async execute(templates, ...params) {
234
+ return this.run(q(templates, ...params), false);
235
+ }
236
+ /**
237
+ * Runs the given statements in a single transaction. Transactions can be used to group multiple statements together.
238
+ * If one statement fails, then none of the statements will have any effect.
239
+ *
240
+ * @param func The function that should be used to build the statements.
241
+ * @param readonly Whether the statements are read-only. If true, then the statements cannot modify data.
242
+ *
243
+ * @example Run multiple select queries at once
244
+ * const results = await database.batch([
245
+ * database.sql`SELECT * FROM items WHERE id = 'abc'`,
246
+ * database.sql`SELECT * FROM items WHERE id = 'def'`,
247
+ * database.sql`SELECT * FROM items WHERE id = 'ghi'`,
248
+ * ]);
249
+ *
250
+ * @example Insert multiple items at once
251
+ * const results = await database.batch([
252
+ * database.sql`INSERT INTO items (name, value) VALUES ('Item 1', 100)`,
253
+ * database.sql`INSERT INTO items (name, value) VALUES ('Item 2', 200)`,
254
+ * database.sql`INSERT INTO items (name, value) VALUES ('Item 3', 300)`,
255
+ * ], false);
256
+ */
257
+ async batch(statements, readonly = true) {
258
+ const result = await this._run(statements, readonly);
259
+ if (result.success === false) {
260
+ return result;
261
+ }
262
+ else {
263
+ return {
264
+ success: true,
265
+ results: result.items.map((r) => this._mapResult(r)),
266
+ };
267
+ }
268
+ }
269
+ /**
270
+ * Runs the given database statement.
271
+ *
272
+ * @param statement The statement to run.
273
+ * @param readonly Whether the statement is read-only. If true, then the statement cannot modify data.
274
+ */
275
+ async run(statement, readonly = true) {
276
+ const batch = await this.batch([statement], readonly);
277
+ if (batch.success === false) {
278
+ return batch;
279
+ }
280
+ else {
281
+ const firstResult = batch.results[0];
282
+ return {
283
+ success: true,
284
+ ...firstResult,
285
+ };
286
+ }
287
+ }
288
+ /**
289
+ * Gets an interface to the database that returns unmodified query results.
290
+ */
291
+ get raw() {
292
+ return {
293
+ sql: this.sql.bind(this),
294
+ query: (templates, ...params) => {
295
+ return this._run([q(templates, ...params)], true);
296
+ },
297
+ execute: (templates, ...params) => {
298
+ return this._run([q(templates, ...params)], false);
299
+ },
300
+ batch: (statements, readonly = true) => {
301
+ return this._run(statements, readonly);
302
+ },
303
+ run: (statement, readonly = true) => {
304
+ return this._run([statement], readonly);
305
+ },
306
+ };
307
+ }
308
+ _mapResult(result) {
309
+ const rows = [];
310
+ for (let row of result.rows) {
311
+ const value = {};
312
+ for (let i = 0; i < result.columns.length; i++) {
313
+ value[result.columns[i]] = row[i];
314
+ }
315
+ rows.push(value);
316
+ }
317
+ return {
318
+ rows,
319
+ lastInsertId: result.lastInsertId,
320
+ affectedRowCount: result.affectedRowCount,
321
+ };
322
+ }
323
+ _run(statements, readonly) {
324
+ const task = this._context.createTask();
325
+ const action = recordsCallProcedure({
326
+ queryDatabase: {
327
+ input: {
328
+ recordName: this._recordName,
329
+ address: this._address,
330
+ statements,
331
+ readonly,
332
+ },
333
+ },
334
+ }, this._options, task.taskId);
335
+ this._context.enqueueAction(action);
336
+ let promise = task.promise;
337
+ promise[ORIGINAL_OBJECT] = action;
338
+ return promise;
339
+ }
340
+ }
145
341
  /**
146
342
  * Creates a library that includes the default functions and APIs.
147
343
  * @param context The global context that should be used.
@@ -539,10 +735,12 @@ export function createDefaultLibrary(context) {
539
735
  reportInst,
540
736
  requestAuthBot,
541
737
  requestAuthBotInBackground,
738
+ createRecord,
542
739
  getPublicRecordKey,
543
740
  getSubjectlessPublicRecordKey,
544
741
  grantPermission,
545
742
  revokePermission,
743
+ listPermissions,
546
744
  grantInstAdminPermission,
547
745
  grantUserRole,
548
746
  revokeUserRole,
@@ -557,6 +755,8 @@ export function createDefaultLibrary(context) {
557
755
  listDataByMarker,
558
756
  eraseData,
559
757
  eraseManualApprovalData,
758
+ listInsts,
759
+ listInstsByMarker,
560
760
  recordWebhook,
561
761
  runWebhook,
562
762
  getWebhook,
@@ -601,7 +801,13 @@ export function createDefaultLibrary(context) {
601
801
  listSearchCollectionsByMarker,
602
802
  recordSearchDocument,
603
803
  eraseSearchDocument,
804
+ recordDatabase,
805
+ getDatabase,
806
+ eraseDatabase,
807
+ listDatabases,
808
+ listDatabasesByMarker,
604
809
  listUserStudios,
810
+ listStudioRecords,
605
811
  getRecordsEndpoint,
606
812
  convertGeolocationToWhat3Words,
607
813
  raycastFromCamera,
@@ -621,6 +827,8 @@ export function createDefaultLibrary(context) {
621
827
  detachDebugger,
622
828
  addMapLayer,
623
829
  removeMapLayer,
830
+ addBotMapLayer,
831
+ removeBotMapLayer,
624
832
  remotes,
625
833
  listInstUpdates,
626
834
  getInstStateFromUpdates,
@@ -5018,6 +5226,61 @@ export function createDefaultLibrary(context) {
5018
5226
  const event = calcDefineGlobalBot(name, botId, task.taskId);
5019
5227
  return addAsyncAction(task, event);
5020
5228
  }
5229
+ /**
5230
+ * Creates a record with the given name. If a studio is specified, then the record will be created in the given studio.
5231
+ * If not specified, then the record will be owned by the current user.
5232
+ *
5233
+ * Returns a promise that resolves with an object that indicates if the request was successful.
5234
+ *
5235
+ * Permissions: User must be logged in. If a studio is specified, then the user must be a member of the studio.
5236
+ *
5237
+ * @param recordName the name of the record to create.
5238
+ * @param studioId the ID of the studio that should own the record. If not specified, the record will be owned by the current user.
5239
+ *
5240
+ * @example Create a record owned by the current user.
5241
+ * const result = await os.createRecord('myRecord');
5242
+ *
5243
+ * if (result.success) {
5244
+ * os.toast('Record created successfully!');
5245
+ * } else {
5246
+ * os.toast('Failed to create record: ' + result.errorMessage);
5247
+ * }
5248
+ *
5249
+ * @example Create a record in a studio.
5250
+ * const result = await os.createRecord('myStudioRecord', 'myStudioId');
5251
+ *
5252
+ * if (result.success) {
5253
+ * os.toast('Studio record created successfully!');
5254
+ * } else {
5255
+ * os.toast('Failed to create studio record: ' + result.errorMessage);
5256
+ * }
5257
+ *
5258
+ * @dochash actions/os/records
5259
+ * @docid os.createRecord
5260
+ * @docname os.createRecord
5261
+ * @docgroup 01-records
5262
+ */
5263
+ function createRecord(recordName, studioId) {
5264
+ if (!hasValue(recordName)) {
5265
+ throw new Error('recordName must be provided.');
5266
+ }
5267
+ else if (typeof recordName !== 'string') {
5268
+ throw new Error('recordName must be a string.');
5269
+ }
5270
+ if (hasValue(studioId) && typeof studioId !== 'string') {
5271
+ throw new Error('studioId must be a string.');
5272
+ }
5273
+ const task = context.createTask();
5274
+ const event = recordsCallProcedure({
5275
+ createRecord: {
5276
+ input: {
5277
+ recordName,
5278
+ studioId,
5279
+ },
5280
+ },
5281
+ }, {}, task.taskId);
5282
+ return addAsyncAction(task, event);
5283
+ }
5021
5284
  /**
5022
5285
  * Requests an [access key](glossary:record-key) for the [public record](glossary:record) with the given name.
5023
5286
  * Returns a promise that resolves with an object that contains the record key (if successful) or information about the error that occurred.
@@ -5132,6 +5395,40 @@ export function createDefaultLibrary(context) {
5132
5395
  const event = calcRevokeRecordPermission(recordName, permissionId, options !== null && options !== void 0 ? options : {}, task.taskId);
5133
5396
  return addAsyncAction(task, event);
5134
5397
  }
5398
+ /**
5399
+ * Gets the list of permissions that have been assigned in the given record.
5400
+ *
5401
+ * @param request the request containing the record name and optional filters.
5402
+ * @param options the options for the operation.
5403
+ *
5404
+ * @example List all permissions in a record.
5405
+ * const result = await os.listPermissions({
5406
+ * recordName: 'myRecord'
5407
+ * });
5408
+ *
5409
+ * @example List permissions for a specific marker.
5410
+ * const result = await os.listPermissions({
5411
+ * recordName: 'myRecord',
5412
+ * marker: 'secret'
5413
+ * });
5414
+ *
5415
+ * @example List permissions for a specific resource.
5416
+ * const result = await os.listPermissions({
5417
+ * recordName: 'myRecord',
5418
+ * resourceKind: 'data',
5419
+ * resourceId: 'address'
5420
+ * });
5421
+ *
5422
+ * @dochash actions/os/records
5423
+ * @docgroup 01-records
5424
+ * @docid os.listPermissions
5425
+ * @docname os.listPermissions
5426
+ */
5427
+ function listPermissions(request) {
5428
+ const task = context.createTask();
5429
+ const event = calcListPermissions(request, task.taskId);
5430
+ return addAsyncAction(task, event);
5431
+ }
5135
5432
  /**
5136
5433
  * Attempts to grant the current inst admin permissions in the given record for the rest of the day.
5137
5434
  *
@@ -5568,6 +5865,64 @@ export function createDefaultLibrary(context) {
5568
5865
  const event = listDataRecordByMarker(recordName, marker, startingAddress, options, task.taskId);
5569
5866
  return addAsyncAction(task, event);
5570
5867
  }
5868
+ /**
5869
+ * Gets the list of insts that are in the record with the given name.
5870
+ * Returns a promise that resolves with an object that contains the list of insts (if successful) or information about the error that occurred.
5871
+ * @param recordName the name of the record that the insts should be listed from.
5872
+ * @param startingInst the inst that the list should start at. This can be used to paginate through the list of insts. If omitted, then the list will start from the beginning.
5873
+ * @param endpoint the HTTP Endpoint of the records website that the insts should be listed from.
5874
+ * If omitted, then the preconfigured records endpoint will be used.
5875
+ *
5876
+ * @example List insts in a record
5877
+ * const result = await os.listInsts('myRecord');
5878
+ *
5879
+ * if (result.success) {
5880
+ * os.toast(`Found ${result.insts.length} insts!`);
5881
+ * } else {
5882
+ * os.toast("Failed " + result.errorMessage);
5883
+ * }
5884
+ *
5885
+ * @dochash actions/os/records
5886
+ * @docgroup 01-records
5887
+ * @docname os.listInsts
5888
+ * @docid os.listInsts
5889
+ */
5890
+ function listInsts(recordName, startingInst = null, endpoint = null) {
5891
+ let options = {};
5892
+ if (hasValue(endpoint)) {
5893
+ options.endpoint = endpoint;
5894
+ }
5895
+ const task = context.createTask();
5896
+ const event = calcListInsts(recordName, startingInst, options, task.taskId);
5897
+ return addAsyncAction(task, event);
5898
+ }
5899
+ /**
5900
+ * Gets the list of insts that are in the record with the given name and given marker.
5901
+ * Returns a promise that resolves with an object that contains the list of insts (if successful) or information about the error that occurred.
5902
+ * @param recordName the name of the record that the insts should be listed from.
5903
+ * @param marker the marker that the insts should have.
5904
+ * @param startingInst the inst that the list should start at. This can be used to paginate through the list of insts. If omitted, then the list will start from the beginning.
5905
+ * @param options the options that should be used for the action.
5906
+ *
5907
+ * @example List insts by marker in a record
5908
+ * const result = await os.listInstsByMarker('myRecord', 'public');
5909
+ *
5910
+ * if (result.success) {
5911
+ * os.toast(`Found ${result.insts.length} insts!`);
5912
+ * } else {
5913
+ * os.toast("Failed " + result.errorMessage);
5914
+ * }
5915
+ *
5916
+ * @dochash actions/os/records
5917
+ * @docgroup 01-records
5918
+ * @docname os.listInstsByMarker
5919
+ * @docid os.listInstsByMarker
5920
+ */
5921
+ function listInstsByMarker(recordName, marker, startingInst = null, options = {}) {
5922
+ const task = context.createTask();
5923
+ const event = calcListInstsByMarker(recordName, marker, startingInst, options, task.taskId);
5924
+ return addAsyncAction(task, event);
5925
+ }
5571
5926
  /**
5572
5927
  * Erases the [data](glossary:data-record) stored at the given address in the given [record](glossary:record).
5573
5928
  * Returns a promise that resolves with an object that contains the data (if successful) or information about the error that occurred.
@@ -6987,6 +7342,184 @@ export function createDefaultLibrary(context) {
6987
7342
  }, options, task.taskId);
6988
7343
  return addAsyncAction(task, event);
6989
7344
  }
7345
+ /**
7346
+ * Creates or updates a database in the given record.
7347
+ *
7348
+ * Databases are used to store and manage structured data within a record.
7349
+ * They use the [SQL programming language](https://www.sqlite.org/lang.html), which is a powerful programming language designed to manage relational databases.
7350
+ *
7351
+ * Returns a promise that resolves with the result of the operation.
7352
+ *
7353
+ * @param request The request to create or update the database.
7354
+ * @param options the options for the request.
7355
+ * @returns A promise that resolves with the result of the operation.
7356
+ *
7357
+ * @example Record a database.
7358
+ * const result = await os.recordDatabase({
7359
+ * recordName: 'myRecord',
7360
+ * address: 'myDatabase',
7361
+ * });
7362
+ *
7363
+ * @example Record a private database
7364
+ * const result = await os.recordDatabase({
7365
+ * recordName: 'myRecord',
7366
+ * address: 'myDatabase',
7367
+ * markers: ['private']
7368
+ * });
7369
+ *
7370
+ *
7371
+ * @doctitle Database Actions
7372
+ * @docsidebar Database
7373
+ * @docdescription Database actions allow you to create and manage databases in your records. Databases enable efficient storage and retrieval of structured data within your records, making it easier to manage and query information.
7374
+ * @dochash actions/os/records/database
7375
+ * @docgroup 02-database
7376
+ * @docname os.recordDatabase
7377
+ * @docid recordDatabase
7378
+ */
7379
+ function recordDatabase(request, options = {}) {
7380
+ const task = context.createTask();
7381
+ const event = recordsCallProcedure({
7382
+ recordDatabase: {
7383
+ input: {
7384
+ recordName: request.recordName,
7385
+ item: {
7386
+ address: request.address,
7387
+ markers: request.markers,
7388
+ },
7389
+ },
7390
+ },
7391
+ }, options, task.taskId);
7392
+ return addAsyncAction(task, event);
7393
+ }
7394
+ /**
7395
+ * Deletes a database along with all the data in it.
7396
+ *
7397
+ * Returns a promise that resolves with the result of the operation.
7398
+ *
7399
+ * @param recordName The name of the record to delete the database from.
7400
+ * @param address The address of the database to delete.
7401
+ * @param options the options for the request.
7402
+ * @returns A promise that resolves with the result of the operation.
7403
+ *
7404
+ * @example Erase a database
7405
+ * const result = await os.eraseDatabase('recordName', 'myDatabase');
7406
+ *
7407
+ * @dochash actions/os/records/database
7408
+ * @docgroup 02-database
7409
+ * @docname os.eraseDatabase
7410
+ * @docid eraseDatabase
7411
+ */
7412
+ function eraseDatabase(recordName, address, options = {}) {
7413
+ const task = context.createTask();
7414
+ const event = recordsCallProcedure({
7415
+ eraseDatabase: {
7416
+ input: {
7417
+ recordName,
7418
+ address,
7419
+ },
7420
+ },
7421
+ }, options, task.taskId);
7422
+ return addAsyncAction(task, event);
7423
+ }
7424
+ /**
7425
+ * Lists the databases in a record.
7426
+ *
7427
+ * Returns a promise that resolves with the result of the operation.
7428
+ *
7429
+ * @param recordName The name of the record to delete the search collection from.
7430
+ * @param startingAddress the address that the listing should start after.
7431
+ * @param options the options for the request.
7432
+ * @returns A promise that resolves with the result of the operation.
7433
+ *
7434
+ * @example List databases
7435
+ * const result = await os.listDatabases('recordName', 'myDatabase');
7436
+ *
7437
+ * @dochash actions/os/records/database
7438
+ * @docgroup 02-database
7439
+ * @docname os.listDatabases
7440
+ * @docid listDatabases
7441
+ */
7442
+ function listDatabases(recordName, startingAddress, options = {}) {
7443
+ const task = context.createTask();
7444
+ const event = recordsCallProcedure({
7445
+ listDatabases: {
7446
+ input: {
7447
+ recordName,
7448
+ address: startingAddress,
7449
+ },
7450
+ },
7451
+ }, options, task.taskId);
7452
+ return addAsyncAction(task, event);
7453
+ }
7454
+ /**
7455
+ * Lists the databases in a record by a specific marker.
7456
+ * @param recordName The name of the record to list the databases from.
7457
+ * @param marker The marker to filter the list by.
7458
+ * @param startingAddress The address that the listing should start after.
7459
+ * @param options The options for the request.
7460
+ * @returns A promise that resolves with the result of the operation.
7461
+ *
7462
+ * @example List public read databases
7463
+ * const result = await os.listDatabasesByMarker('recordName', 'publicRead');
7464
+ *
7465
+ * @example List private databases
7466
+ * const result = await os.listDatabasesByMarker('recordName', 'private');
7467
+ *
7468
+ * @dochash actions/os/records/database
7469
+ * @docgroup 02-database
7470
+ * @docname os.listDatabasesByMarker
7471
+ */
7472
+ function listDatabasesByMarker(recordName, marker, startingAddress, options = {}) {
7473
+ const task = context.createTask();
7474
+ const event = recordsCallProcedure({
7475
+ listDatabases: {
7476
+ input: {
7477
+ recordName,
7478
+ marker,
7479
+ address: startingAddress,
7480
+ sort: options === null || options === void 0 ? void 0 : options.sort,
7481
+ },
7482
+ },
7483
+ }, options, task.taskId);
7484
+ return addAsyncAction(task, event);
7485
+ }
7486
+ /**
7487
+ * Gets basic info about a database from the specified record.
7488
+ *
7489
+ * @param recordName The name of the record to retrieve the database from.
7490
+ * @param address The address of the database to retrieve.
7491
+ * @param options The options for the request.
7492
+ *
7493
+ * @returns A promise that resolves with the result of the operation.
7494
+ *
7495
+ * @example Get a database and query a table
7496
+ * const db = os.getDatabase('myRecord', 'myDatabase');
7497
+ * const result = await db.query`SELECT * FROM myTable`;
7498
+ *
7499
+ * @example Insert a new row
7500
+ * const value1 = 'abc';
7501
+ * const value2 = 123;
7502
+ * const result = await db.execute`INSERT INTO myTable (column1, column2) VALUES (${value1}, ${value2})`;
7503
+ *
7504
+ * @example Run multiple queries in a transaction
7505
+ * const values = [
7506
+ * ['apple', 10],
7507
+ * ['car', 25000],
7508
+ * ['strawberry', 1],
7509
+ * ['lego', 5]
7510
+ * ];
7511
+ *
7512
+ * const result = await db.batch(
7513
+ * values.map(([name, value]) => db.sql`INSERT INTO data (name, value) VALUES (${name}, ${value})`)
7514
+ * );
7515
+ *
7516
+ * @dochash actions/os/records/database
7517
+ * @docgroup 02-database
7518
+ * @docname os.getDatabase
7519
+ */
7520
+ function getDatabase(recordName, address, options = {}) {
7521
+ return new ApiDatabase(recordName, address, options, context);
7522
+ }
6990
7523
  /**
6991
7524
  * Gets the list of studios that the currently logged in user has access to.
6992
7525
  *
@@ -7016,6 +7549,41 @@ export function createDefaultLibrary(context) {
7016
7549
  const event = calcListUserStudios(options, task.taskId);
7017
7550
  return addAsyncAction(task, event);
7018
7551
  }
7552
+ /**
7553
+ * Gets the list of records that are in the studio with the given ID.
7554
+ *
7555
+ * Returns a promise that resolves with an object that contains the list of records (if successful) or information about the error that occurred.
7556
+ * The user must be a member of the studio to access its records.
7557
+ *
7558
+ * @param studioId The ID of the studio to list records for.
7559
+ * @param endpoint the HTTP Endpoint of the records website that the data should be retrieved from. If omitted, then the preconfigured records endpoint will be used.
7560
+ *
7561
+ * @example Get the list of records in a studio
7562
+ * const result = await os.listStudioRecords('studioId123');
7563
+ *
7564
+ * if (result.success) {
7565
+ * os.toast(`Found ${result.records.length} records in studio`);
7566
+ * for (const record of result.records) {
7567
+ * os.toast(`Record: ${record.name}`);
7568
+ * }
7569
+ * } else {
7570
+ * os.toast('Failed to list studio records: ' + result.errorMessage);
7571
+ * }
7572
+ *
7573
+ * @dochash actions/os/records
7574
+ * @docgroup 01-records
7575
+ * @docid os.listStudioRecords
7576
+ * @docname os.listStudioRecords
7577
+ */
7578
+ function listStudioRecords(studioId, endpoint) {
7579
+ let options = {};
7580
+ if (hasValue(endpoint)) {
7581
+ options.endpoint = endpoint;
7582
+ }
7583
+ const task = context.createTask();
7584
+ const event = calcListStudioRecords(studioId, options, task.taskId);
7585
+ return addAsyncAction(task, event);
7586
+ }
7019
7587
  /**
7020
7588
  * Gets the default records endpoint. That is, the records endpoint that is used for records actions when no endpoint is specified.
7021
7589
  *
@@ -7550,6 +8118,58 @@ export function createDefaultLibrary(context) {
7550
8118
  const event = calcRemoveMapLayer(layerId, task.taskId);
7551
8119
  return addAsyncAction(task, event);
7552
8120
  }
8121
+ /**
8122
+ * Adds a map layer to a bot with form: "map".
8123
+ *
8124
+ * Returns a promise that resolves with the ID of the layer that was added.
8125
+ *
8126
+ * @param bot The bot that should have the layer added.
8127
+ * @param overlay The overlay configuration.
8128
+ *
8129
+ * @example Add a GeoJSON layer to a map bot
8130
+ * const layerId = await os.addBotMapLayer(bot, {
8131
+ * type: 'geojson',
8132
+ * data: {
8133
+ * type: "FeatureCollection",
8134
+ * features: [...]
8135
+ * }
8136
+ * });
8137
+ */
8138
+ function addBotMapLayer(bot, overlay) {
8139
+ const task = context.createTask();
8140
+ const botId = typeof bot === 'string' ? bot : bot.id;
8141
+ const normalizedOverlay = {
8142
+ ...overlay,
8143
+ overlayType: overlay.overlayType || overlay.type || 'geojson',
8144
+ };
8145
+ const action = {
8146
+ type: 'add_bot_map_layer',
8147
+ botId: botId,
8148
+ overlay: normalizedOverlay,
8149
+ taskId: task.taskId,
8150
+ };
8151
+ return addAsyncAction(task, action);
8152
+ }
8153
+ /**
8154
+ * Removes a layer from a bot with form: "map".
8155
+ *
8156
+ * @param bot The bot that has the layer.
8157
+ * @param overlayId The ID of the overlay to remove.
8158
+ *
8159
+ * @example Remove a layer from a map bot
8160
+ * await os.removeBotMapLayer(bot, 'my-layer-id');
8161
+ */
8162
+ function removeBotMapLayer(bot, overlayId) {
8163
+ const task = context.createTask();
8164
+ const botId = typeof bot === 'string' ? bot : bot.id;
8165
+ const action = {
8166
+ type: 'remove_bot_map_layer',
8167
+ botId: botId,
8168
+ overlayId: overlayId,
8169
+ taskId: task.taskId,
8170
+ };
8171
+ return addAsyncAction(task, action);
8172
+ }
7553
8173
  /**
7554
8174
  * Executes the given shell script on the server.
7555
8175
  * @param script The shell script that should be executed.
@@ -7601,22 +8221,36 @@ export function createDefaultLibrary(context) {
7601
8221
  const event = calcRemote(getRemoteCount(), undefined, undefined, task.taskId);
7602
8222
  return addAsyncAction(task, event);
7603
8223
  }
7604
- function getSharedDocument(recordOrName, inst, name) {
8224
+ function getSharedDocument(recordOrName, inst, name, options) {
7605
8225
  const task = context.createTask();
7606
8226
  let recordName;
7607
8227
  let instName;
7608
8228
  let branchName;
7609
- if (!inst && !name) {
8229
+ let markers;
8230
+ if (typeof inst === 'object' && !name && !options) {
8231
+ // Called as getSharedDocument(name, options)
8232
+ instName = getCurrentServer();
8233
+ recordName = getCurrentInstRecord();
8234
+ branchName = recordOrName;
8235
+ markers = inst === null || inst === void 0 ? void 0 : inst.markers;
8236
+ }
8237
+ else if (!inst && !name) {
8238
+ // Called as getSharedDocument(name)
7610
8239
  instName = getCurrentServer();
7611
8240
  recordName = getCurrentInstRecord();
7612
8241
  branchName = recordOrName;
7613
8242
  }
7614
8243
  else {
8244
+ // Called as getSharedDocument(recordName, inst, name) or getSharedDocument(recordName, inst, name, options)
8245
+ if (typeof inst === 'object') {
8246
+ throw new Error('The second argument (inst) must be a string when calling getSharedDocument() with three or more arguments.');
8247
+ }
7615
8248
  recordName = recordOrName;
7616
8249
  instName = inst;
7617
8250
  branchName = name;
8251
+ markers = options === null || options === void 0 ? void 0 : options.markers;
7618
8252
  }
7619
- const event = loadSharedDocument(recordName, instName, `doc/${branchName}`, task.taskId);
8253
+ const event = loadSharedDocument(recordName, instName, `doc/${branchName}`, task.taskId, markers);
7620
8254
  return addAsyncAction(task, event);
7621
8255
  }
7622
8256
  /**