roboto-js 1.8.1 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.last-build CHANGED
@@ -1 +1 @@
1
- 2025-10-08T10:39:00.776Z
1
+ 2025-10-08T11:01:38.750Z
@@ -595,14 +595,16 @@ var RbtObject = exports["default"] = /*#__PURE__*/function () {
595
595
  publish,
596
596
  _options$save2,
597
597
  save,
598
+ currentIac,
598
599
  iac,
599
600
  _args5 = arguments;
600
601
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
601
602
  while (1) switch (_context5.prev = _context5.next) {
602
603
  case 0:
603
604
  options = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : {};
604
- _options$publish = options.publish, publish = _options$publish === void 0 ? true : _options$publish, _options$save2 = options.save, save = _options$save2 === void 0 ? true : _options$save2; // Get current IAC settings
605
- iac = this.get('iac') || {}; // Initialize readGrants if it doesn't exist
605
+ _options$publish = options.publish, publish = _options$publish === void 0 ? true : _options$publish, _options$save2 = options.save, save = _options$save2 === void 0 ? true : _options$save2; // Get current IAC settings and create a deep clone to ensure change detection
606
+ currentIac = this.get('iac') || {};
607
+ iac = _lodash["default"].cloneDeep(currentIac); // Initialize readGrants if it doesn't exist
606
608
  if (!iac.readGrants) {
607
609
  iac.readGrants = {};
608
610
  }
@@ -623,21 +625,21 @@ var RbtObject = exports["default"] = /*#__PURE__*/function () {
623
625
  });
624
626
  }
625
627
 
626
- // Update the object
628
+ // Update the object with the cloned and modified IAC
627
629
  this.set('iac', iac);
628
630
 
629
631
  // Save if requested
630
632
  if (!save) {
631
- _context5.next = 11;
633
+ _context5.next = 12;
632
634
  break;
633
635
  }
634
- _context5.next = 10;
636
+ _context5.next = 11;
635
637
  return this.save();
636
- case 10:
637
- return _context5.abrupt("return", _context5.sent);
638
638
  case 11:
639
- return _context5.abrupt("return", this);
639
+ return _context5.abrupt("return", _context5.sent);
640
640
  case 12:
641
+ return _context5.abrupt("return", this);
642
+ case 13:
641
643
  case "end":
642
644
  return _context5.stop();
643
645
  }
@@ -434,8 +434,9 @@ export default class RbtObject {
434
434
  save = true
435
435
  } = options;
436
436
 
437
- // Get current IAC settings
438
- const iac = this.get('iac') || {};
437
+ // Get current IAC settings and create a deep clone to ensure change detection
438
+ const currentIac = this.get('iac') || {};
439
+ const iac = _.cloneDeep(currentIac);
439
440
 
440
441
  // Initialize readGrants if it doesn't exist
441
442
  if (!iac.readGrants) {
@@ -456,7 +457,7 @@ export default class RbtObject {
456
457
  iac.readGrants.users = iac.readGrants.users.filter(userId => userId !== 'public_user');
457
458
  }
458
459
 
459
- // Update the object
460
+ // Update the object with the cloned and modified IAC
460
461
  this.set('iac', iac);
461
462
 
462
463
  // Save if requested
@@ -583,14 +583,16 @@ var RbtObject = /*#__PURE__*/function () {
583
583
  publish,
584
584
  _options$save2,
585
585
  save,
586
+ currentIac,
586
587
  iac,
587
588
  _args5 = arguments;
588
589
  return _regenerator().w(function (_context5) {
589
590
  while (1) switch (_context5.n) {
590
591
  case 0:
591
592
  options = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : {};
592
- _options$publish = options.publish, publish = _options$publish === void 0 ? true : _options$publish, _options$save2 = options.save, save = _options$save2 === void 0 ? true : _options$save2; // Get current IAC settings
593
- iac = this.get('iac') || {}; // Initialize readGrants if it doesn't exist
593
+ _options$publish = options.publish, publish = _options$publish === void 0 ? true : _options$publish, _options$save2 = options.save, save = _options$save2 === void 0 ? true : _options$save2; // Get current IAC settings and create a deep clone to ensure change detection
594
+ currentIac = this.get('iac') || {};
595
+ iac = _.cloneDeep(currentIac); // Initialize readGrants if it doesn't exist
594
596
  if (!iac.readGrants) {
595
597
  iac.readGrants = {};
596
598
  }
@@ -611,7 +613,7 @@ var RbtObject = /*#__PURE__*/function () {
611
613
  });
612
614
  }
613
615
 
614
- // Update the object
616
+ // Update the object with the cloned and modified IAC
615
617
  this.set('iac', iac);
616
618
 
617
619
  // Save if requested
@@ -0,0 +1,424 @@
1
+ /**
2
+ * Examples demonstrating object sharing and publishing in roboto-js
3
+ *
4
+ * These examples show how to use the new shareObject() and publishObject() methods
5
+ * to control access to your rbtObjects using the mod-iac system.
6
+ */
7
+
8
+ // Import roboto-js
9
+ import Roboto from 'roboto-js';
10
+
11
+ // Initialize roboto instance
12
+ const roboto = new Roboto({
13
+ host: 'your-host.com',
14
+ accessKey: 'your-access-key'
15
+ });
16
+
17
+ // Wait for authentication
18
+ await roboto.api.loadCurrentUser();
19
+
20
+ // ============================================================================
21
+ // EXAMPLE 1: Publishing an Object (Making it Public)
22
+ // ============================================================================
23
+
24
+ async function example1_PublishObject() {
25
+ console.log('\n=== Example 1: Publishing an Object ===\n');
26
+
27
+ // Load an existing object
28
+ const myAgent = await roboto.api.load('<@doc_agent.bot>', 'agent_123');
29
+
30
+ // Check if it's currently published
31
+ console.log('Is published?', myAgent.isPublished());
32
+
33
+ // Publish it (make it publicly accessible)
34
+ await myAgent.publishObject();
35
+ console.log('✓ Agent is now public!');
36
+
37
+ // Verify it's published
38
+ console.log('Is published?', myAgent.isPublished());
39
+
40
+ // Later, you can unpublish it (explicit method)
41
+ await myAgent.unpublishObject();
42
+ console.log('✓ Agent is now private (using unpublishObject)');
43
+
44
+ // Alternative: using publishObject with flag
45
+ // await myAgent.publishObject({ publish: false });
46
+ }
47
+
48
+ // ============================================================================
49
+ // EXAMPLE 2: Sharing with Specific Users
50
+ // ============================================================================
51
+
52
+ async function example2_ShareWithUsers() {
53
+ console.log('\n=== Example 2: Sharing with Specific Users ===\n');
54
+
55
+ const myDocument = await roboto.api.load('<@doc.document>', 'doc_456');
56
+
57
+ // Share with specific users (read access)
58
+ await myDocument.shareObject({
59
+ userIds: ['user_123', 'user_456', 'user_789']
60
+ });
61
+
62
+ console.log('✓ Document shared with 3 users');
63
+
64
+ // View current permissions
65
+ const permissions = myDocument.getSharing();
66
+ console.log('Read users:', permissions.readGrants.users);
67
+ }
68
+
69
+ // ============================================================================
70
+ // EXAMPLE 3: Sharing with User Groups
71
+ // ============================================================================
72
+
73
+ async function example3_ShareWithGroups() {
74
+ console.log('\n=== Example 3: Sharing with User Groups ===\n');
75
+
76
+ const myTemplate = await roboto.api.load('<@doc_agent.bot>', 'template_789');
77
+
78
+ // Share with user groups (read access)
79
+ await myTemplate.shareObject({
80
+ groupIds: ['grpRngAccount', 'grpPremiumUsers']
81
+ });
82
+
83
+ console.log('✓ Template shared with 2 user groups');
84
+
85
+ // View permissions
86
+ const permissions = myTemplate.getSharing();
87
+ console.log('Read groups:', permissions.readGrants.userGroups);
88
+ }
89
+
90
+ // ============================================================================
91
+ // EXAMPLE 4: Granting Write Access
92
+ // ============================================================================
93
+
94
+ async function example4_GrantWriteAccess() {
95
+ console.log('\n=== Example 4: Granting Write Access ===\n');
96
+
97
+ const myProject = await roboto.api.load('<@doc.project>', 'proj_abc');
98
+
99
+ // Share with read access (default)
100
+ await myProject.shareObject({
101
+ groupIds: ['grpViewers']
102
+ });
103
+
104
+ // Share with write access for editors
105
+ await myProject.shareObject({
106
+ groupIds: ['grpEditors'],
107
+ write: true
108
+ });
109
+
110
+ console.log('✓ Viewers can read, editors can write');
111
+
112
+ // View all permissions
113
+ const permissions = myProject.getSharing();
114
+ console.log('Read groups:', permissions.readGrants.userGroups);
115
+ console.log('Write groups:', permissions.writeGrants.userGroups);
116
+ }
117
+
118
+ // ============================================================================
119
+ // EXAMPLE 5: Combining Users and Groups
120
+ // ============================================================================
121
+
122
+ async function example5_CombineUsersAndGroups() {
123
+ console.log('\n=== Example 5: Combining Users and Groups ===\n');
124
+
125
+ const myContent = await roboto.api.load('<@doc.content>', 'content_xyz');
126
+
127
+ // Share with both users and groups
128
+ await myContent.shareObject({
129
+ userIds: ['user_special_123'],
130
+ groupIds: ['grpSubscribers', 'grpPremium']
131
+ });
132
+
133
+ console.log('✓ Shared with 1 user and 2 groups');
134
+
135
+ const permissions = myContent.getSharing();
136
+ console.log('Read users:', permissions.readGrants.users);
137
+ console.log('Read groups:', permissions.readGrants.userGroups);
138
+ }
139
+
140
+ // ============================================================================
141
+ // EXAMPLE 6: Replacing vs. Merging Permissions
142
+ // ============================================================================
143
+
144
+ async function example6_ReplaceVsMerge() {
145
+ console.log('\n=== Example 6: Replacing vs. Merging ===\n');
146
+
147
+ const myObject = await roboto.api.load('<@doc.item>', 'item_001');
148
+
149
+ // First share with some users (merges with existing)
150
+ await myObject.shareObject({
151
+ userIds: ['user_a', 'user_b']
152
+ });
153
+ console.log('After merge:', myObject.getSharing().readGrants.users);
154
+
155
+ // Add more users (merges again)
156
+ await myObject.shareObject({
157
+ userIds: ['user_c']
158
+ });
159
+ console.log('After another merge:', myObject.getSharing().readGrants.users);
160
+
161
+ // Replace all permissions
162
+ await myObject.shareObject({
163
+ userIds: ['user_x', 'user_y'],
164
+ replace: true
165
+ });
166
+ console.log('After replace:', myObject.getSharing().readGrants.users);
167
+ }
168
+
169
+ // ============================================================================
170
+ // EXAMPLE 7: Batch Updates Without Auto-Save
171
+ // ============================================================================
172
+
173
+ async function example7_BatchUpdates() {
174
+ console.log('\n=== Example 7: Batch Updates Without Auto-Save ===\n');
175
+
176
+ const myAgent = await roboto.api.load('<@doc_agent.bot>', 'agent_multi');
177
+
178
+ // Update permissions without saving
179
+ await myAgent.shareObject({
180
+ groupIds: ['grpUsers'],
181
+ save: false
182
+ });
183
+ console.log('✓ Added group (not saved)');
184
+
185
+ // Publish without saving
186
+ await myAgent.publishObject({ save: false });
187
+ console.log('✓ Published (not saved)');
188
+
189
+ // Make other changes
190
+ myAgent.set('configs.title', 'Updated Title');
191
+ console.log('✓ Updated title (not saved)');
192
+
193
+ // Save once with all changes
194
+ await myAgent.save();
195
+ console.log('✓ All changes saved at once!');
196
+ }
197
+
198
+ // ============================================================================
199
+ // EXAMPLE 8: Tiered Access Control
200
+ // ============================================================================
201
+
202
+ async function example8_TieredAccess() {
203
+ console.log('\n=== Example 8: Tiered Access Control ===\n');
204
+
205
+ const myContent = await roboto.api.load('<@doc.content>', 'content_tiered');
206
+
207
+ // Public can read
208
+ await myContent.publishObject({ save: false });
209
+
210
+ // Editors can write
211
+ await myContent.shareObject({
212
+ groupIds: ['grpEditors'],
213
+ write: true,
214
+ save: false
215
+ });
216
+
217
+ // Admins can write
218
+ await myContent.shareObject({
219
+ groupIds: ['grpAdmins'],
220
+ write: true,
221
+ save: true
222
+ });
223
+
224
+ console.log('✓ Tiered access configured:');
225
+ console.log(' - Public: read');
226
+ console.log(' - Editors: write');
227
+ console.log(' - Admins: write');
228
+
229
+ const permissions = myContent.getSharing();
230
+ console.log('\nRead users:', permissions.readGrants.users);
231
+ console.log('Write groups:', permissions.writeGrants.userGroups);
232
+ }
233
+
234
+ // ============================================================================
235
+ // EXAMPLE 9: Template Publishing Pattern (like Ringable)
236
+ // ============================================================================
237
+
238
+ async function example9_TemplatePublishing() {
239
+ console.log('\n=== Example 9: Template Publishing Pattern ===\n');
240
+
241
+ const template = await roboto.api.load('<@doc_agent.bot>', 'template_rng');
242
+
243
+ // Function to publish/unpublish a template
244
+ async function setTemplatePublished(agent, isPublished) {
245
+ if (isPublished) {
246
+ // Share with all account users
247
+ await agent.shareObject({
248
+ groupIds: ['grpRngAccount']
249
+ });
250
+ console.log('✓ Template published to all account users');
251
+ } else {
252
+ // Remove the group
253
+ const current = agent.getSharing();
254
+ const remainingGroups = current.readGrants.userGroups
255
+ .filter(g => g !== 'grpRngAccount');
256
+
257
+ await agent.shareObject({
258
+ groupIds: remainingGroups,
259
+ replace: true
260
+ });
261
+ console.log('✓ Template unpublished from account users');
262
+ }
263
+ }
264
+
265
+ // Publish the template
266
+ await setTemplatePublished(template, true);
267
+
268
+ // Later, unpublish it
269
+ await setTemplatePublished(template, false);
270
+ }
271
+
272
+ // ============================================================================
273
+ // EXAMPLE 10: Getting and Inspecting Permissions
274
+ // ============================================================================
275
+
276
+ async function example10_InspectPermissions() {
277
+ console.log('\n=== Example 10: Inspecting Permissions ===\n');
278
+
279
+ const myObject = await roboto.api.load('<@doc.item>', 'item_inspect');
280
+
281
+ // Get all permissions
282
+ const permissions = myObject.getSharing();
283
+
284
+ console.log('Read Permissions:');
285
+ console.log(' Users:', permissions.readGrants.users);
286
+ console.log(' Groups:', permissions.readGrants.userGroups);
287
+ console.log(' Organizations:', permissions.readGrants.organizations);
288
+
289
+ console.log('\nWrite Permissions:');
290
+ console.log(' Users:', permissions.writeGrants.users);
291
+ console.log(' Groups:', permissions.writeGrants.userGroups);
292
+ console.log(' Organizations:', permissions.writeGrants.organizations);
293
+
294
+ // Check if public
295
+ console.log('\nIs Published?', myObject.isPublished());
296
+
297
+ // Get raw IAC data
298
+ const iac = myObject.get('iac');
299
+ console.log('\nRaw IAC data:', JSON.stringify(iac, null, 2));
300
+ }
301
+
302
+ // ============================================================================
303
+ // EXAMPLE 11: Removing Access with unshareObject
304
+ // ============================================================================
305
+
306
+ async function example11_RemovingAccess() {
307
+ console.log('\n=== Example 11: Removing Access with unshareObject ===\n');
308
+
309
+ const myObject = await roboto.api.load('<@doc.item>', 'item_remove');
310
+
311
+ // Get current permissions
312
+ const current = myObject.getSharing();
313
+ console.log('Current users:', current.readGrants.users);
314
+ console.log('Current groups:', current.readGrants.userGroups);
315
+
316
+ // Remove specific users from read access (easy way)
317
+ await myObject.unshareObject({
318
+ userIds: ['user_123', 'user_456']
319
+ });
320
+ console.log('✓ Removed specific users');
321
+ console.log('Remaining users:', myObject.getSharing().readGrants.users);
322
+
323
+ // Remove specific groups from read access
324
+ await myObject.unshareObject({
325
+ groupIds: ['grpViewers']
326
+ });
327
+ console.log('✓ Removed specific groups');
328
+ console.log('Remaining groups:', myObject.getSharing().readGrants.userGroups);
329
+
330
+ // Remove write access from groups
331
+ await myObject.unshareObject({
332
+ groupIds: ['grpEditors'],
333
+ write: true
334
+ });
335
+ console.log('✓ Removed write access from editors');
336
+
337
+ // Alternative: using replace with shareObject
338
+ const currentAfter = myObject.getSharing();
339
+ const keepUsers = currentAfter.readGrants.users.filter(id => id !== 'user_789');
340
+ await myObject.shareObject({
341
+ userIds: keepUsers,
342
+ replace: true
343
+ });
344
+ console.log('✓ Removed user_789 using replace method');
345
+ }
346
+
347
+ // ============================================================================
348
+ // EXAMPLE 12: Creating and Sharing a New Object
349
+ // ============================================================================
350
+
351
+ async function example12_CreateAndShare() {
352
+ console.log('\n=== Example 12: Creating and Sharing a New Object ===\n');
353
+
354
+ // Create a new object
355
+ const newAgent = await roboto.api.create('<@doc_agent.bot>', {
356
+ configs: {
357
+ title: 'My New Public Agent',
358
+ description: 'This agent will be shared with everyone'
359
+ }
360
+ });
361
+
362
+ console.log('✓ Created new agent:', newAgent.id);
363
+
364
+ // Immediately publish it
365
+ await newAgent.publishObject();
366
+
367
+ console.log('✓ Published new agent');
368
+ console.log('Is published?', newAgent.isPublished());
369
+ }
370
+
371
+ // ============================================================================
372
+ // Run all examples
373
+ // ============================================================================
374
+
375
+ async function runAllExamples() {
376
+ console.log('╔════════════════════════════════════════════════════════════╗');
377
+ console.log('║ roboto-js Sharing & Publishing Examples ║');
378
+ console.log('╚════════════════════════════════════════════════════════════╝');
379
+
380
+ try {
381
+ // Uncomment the examples you want to run:
382
+
383
+ // await example1_PublishObject();
384
+ // await example2_ShareWithUsers();
385
+ // await example3_ShareWithGroups();
386
+ // await example4_GrantWriteAccess();
387
+ // await example5_CombineUsersAndGroups();
388
+ // await example6_ReplaceVsMerge();
389
+ // await example7_BatchUpdates();
390
+ // await example8_TieredAccess();
391
+ // await example9_TemplatePublishing();
392
+ // await example10_InspectPermissions();
393
+ // await example11_RemovingAccess();
394
+ // await example12_CreateAndShare();
395
+
396
+ console.log('\n✓ All examples completed!');
397
+ } catch (error) {
398
+ console.error('\n✗ Error running examples:', error);
399
+ console.error(error.stack);
400
+ }
401
+ }
402
+
403
+ // Run examples if this file is executed directly
404
+ if (import.meta.url === `file://${process.argv[1]}`) {
405
+ runAllExamples();
406
+ }
407
+
408
+ // Export examples for use in other files
409
+ export {
410
+ example1_PublishObject,
411
+ example2_ShareWithUsers,
412
+ example3_ShareWithGroups,
413
+ example4_GrantWriteAccess,
414
+ example5_CombineUsersAndGroups,
415
+ example6_ReplaceVsMerge,
416
+ example7_BatchUpdates,
417
+ example8_TieredAccess,
418
+ example9_TemplatePublishing,
419
+ example10_InspectPermissions,
420
+ example11_RemovingAccess,
421
+ example12_CreateAndShare,
422
+ runAllExamples
423
+ };
424
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roboto-js",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "main": "dist/cjs/index.cjs",
package/src/rbt_object.js CHANGED
@@ -449,8 +449,9 @@ export default class RbtObject{
449
449
  save = true
450
450
  } = options;
451
451
 
452
- // Get current IAC settings
453
- const iac = this.get('iac') || {};
452
+ // Get current IAC settings and create a deep clone to ensure change detection
453
+ const currentIac = this.get('iac') || {};
454
+ const iac = _.cloneDeep(currentIac);
454
455
 
455
456
  // Initialize readGrants if it doesn't exist
456
457
  if (!iac.readGrants) {
@@ -472,7 +473,7 @@ export default class RbtObject{
472
473
  iac.readGrants.users = iac.readGrants.users.filter(userId => userId !== 'public_user');
473
474
  }
474
475
 
475
- // Update the object
476
+ // Update the object with the cloned and modified IAC
476
477
  this.set('iac', iac);
477
478
 
478
479
  // Save if requested