roboto-js 1.9.5 → 1.9.7

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-12-08T03:12:14.784Z
1
+ 2025-12-31T10:58:16.804Z
package/README.md ADDED
@@ -0,0 +1,580 @@
1
+ # roboto-js
2
+
3
+ JavaScript/TypeScript SDK for the Roboto platform - a unified client library for managing objects, files, users, and real-time data synchronization.
4
+
5
+ **Version:** 1.9.5
6
+
7
+ ## Features
8
+
9
+ - **Object Management**: Create, read, update, and delete platform objects with a simple API
10
+ - **File Handling**: Upload and manage files with resumable uploads via tus protocol
11
+ - **User Authentication**: Login, registration, OAuth, and session management
12
+ - **Real-time Sync**: WebSocket-based live updates for collaborative applications
13
+ - **Access Control**: Fine-grained permissions with user, group, and organization-level sharing
14
+ - **Storage Adapters**: Flexible authentication storage (cookies, localStorage, custom)
15
+ - **Metrics & Analytics**: Built-in metrics API for tracking and analytics
16
+ - **Dual Module Support**: Works in both CommonJS and ES Module environments
17
+ - **Browser & Node.js**: Runs in browsers and Node.js server environments
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install roboto-js
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Basic Initialization
28
+
29
+ ```javascript
30
+ import Roboto from 'roboto-js';
31
+
32
+ const roboto = new Roboto({
33
+ host: 'your-api-host.com',
34
+ accessKey: 'your-access-key'
35
+ });
36
+ ```
37
+
38
+ ### Authentication
39
+
40
+ ```javascript
41
+ // Login
42
+ const user = await roboto.login({
43
+ email: 'user@example.com',
44
+ password: 'password'
45
+ });
46
+
47
+ // Get current user
48
+ const currentUser = await roboto.loadCurrentUser();
49
+
50
+ // Logout
51
+ await roboto.logout();
52
+ ```
53
+
54
+ ### Working with Objects
55
+
56
+ ```javascript
57
+ // Create a new object
58
+ const site = await roboto.create('<@doc_website.site>', {
59
+ configs: {
60
+ label: 'My Website',
61
+ domain: 'example.com'
62
+ }
63
+ });
64
+
65
+ // Load an object
66
+ const loadedSite = await roboto.load('<@doc_website.site>', 'site-id-123');
67
+
68
+ // Update and save
69
+ site.set('configs.label', 'Updated Website');
70
+ await site.save();
71
+
72
+ // Query objects
73
+ const sites = await roboto.query('<@doc_website.site>', {
74
+ where: 'configs.status=active'
75
+ });
76
+ ```
77
+
78
+ ### File Uploads
79
+
80
+ ```javascript
81
+ // Create a file object
82
+ const file = await roboto.createFile({
83
+ filename: 'document.pdf',
84
+ mimetype: 'application/pdf'
85
+ });
86
+
87
+ // Upload with progress tracking
88
+ await file.upload(fileBlob, {
89
+ onProgress: (bytesUploaded, bytesTotal) => {
90
+ const percent = (bytesUploaded / bytesTotal) * 100;
91
+ console.log(`Upload progress: ${percent.toFixed(2)}%`);
92
+ }
93
+ });
94
+ ```
95
+
96
+ ## Configuration Options
97
+
98
+ ```javascript
99
+ const roboto = new Roboto({
100
+ host: 'api.example.com', // API host (required)
101
+ accessKey: 'your-access-key', // Access key (required)
102
+ authToken: 'token', // Optional: pre-set auth token
103
+ apiKey: 'key', // Optional: API key for service calls
104
+ useCookies: true, // Use cookies for auth (default: true)
105
+ cookieDomain: 'auto', // Cookie domain: 'auto', 'none', or explicit domain
106
+ localStorageAdaptor: customAdaptor, // Custom storage adapter
107
+ disableWebSocket: false, // Disable WebSocket connections
108
+ metricsHost: 'metrics.example.com' // Separate metrics host (optional)
109
+ });
110
+ ```
111
+
112
+ ## Core API Methods
113
+
114
+ ### Object Operations
115
+
116
+ - `create(type, data)` - Create a new object
117
+ - `load(type, ids, options)` - Load object(s) by ID
118
+ - `query(type, params)` - Query objects with filters
119
+ - `wrapAsRbtObjects(data)` - Convert raw JSON to RbtObject instances
120
+
121
+ ### User Management
122
+
123
+ - `login(params)` - Authenticate user
124
+ - `loginWithOauth(params)` - OAuth authentication
125
+ - `logout()` - End session
126
+ - `registerUser(params)` - Create new user account
127
+ - `loadCurrentUser()` - Get authenticated user
128
+ - `confirmUserEmail(params)` - Verify email address
129
+
130
+ ### Organization Management
131
+
132
+ - `loadCurrentOrganization(forceReload)` - Load user's current organization
133
+ - `switchOrganization(orgId)` - Switch to a different organization
134
+ - `getCurrentOrganization()` - Get cached current organization
135
+ - `currentOrganization` - Getter for current organization
136
+
137
+ ### File Operations
138
+
139
+ - `createFile(data)` - Create file object
140
+ - `loadFile(id)` - Load file by ID
141
+ - `loadFiles(ids)` - Load multiple files
142
+
143
+ ### Task Execution
144
+
145
+ - `runTask(params, callbacks)` - Execute background task
146
+ - `stopJob(params)` - Cancel running job
147
+ - `pollTaskProgress(params)` - Check task status
148
+
149
+ ### HTTP Methods
150
+
151
+ - `get(endpoint, params)` - GET request with auto-wrapping
152
+ - `post(endpoint, data)` - POST request with auto-wrapping
153
+
154
+ ## RbtObject Methods
155
+
156
+ RbtObject is the core class for working with platform data:
157
+
158
+ ```javascript
159
+ // Data access
160
+ object.get('path.to.property') // Get value
161
+ object.getData(['key1', 'key2']) // Get multiple values
162
+ object.set('path.to.property', value) // Set value
163
+ object.set('path', value, { merge: true }) // Merge objects
164
+
165
+ // Persistence
166
+ await object.save() // Save changes
167
+ await object.delete() // Delete object
168
+ await object.reload() // Refresh from server
169
+
170
+ // Metadata
171
+ object.id // Object ID
172
+ object.getType() // Object type
173
+ object.getRevision() // Revision number
174
+ object.hasUnsavedChanges() // Check for pending changes
175
+
176
+ // Real-time sync
177
+ object.enableRealtime() // Enable live updates
178
+ object.disableRealtime() // Disable live updates
179
+ object.on('change', callback) // Listen for changes
180
+ object.broadcastChange('path') // Broadcast to other clients
181
+ ```
182
+
183
+ ## Access Control & Sharing
184
+
185
+ Control who can access your objects:
186
+
187
+ ```javascript
188
+ // Make object public
189
+ await object.publishObject();
190
+ await object.unpublishObject();
191
+
192
+ // Check if published
193
+ if (object.isPublished()) {
194
+ console.log('Object is public');
195
+ }
196
+
197
+ // Grant access to users
198
+ await object.grantAccess({
199
+ userIds: ['user1', 'user2'],
200
+ write: false // read-only
201
+ });
202
+
203
+ // Grant access to groups
204
+ await object.grantAccess({
205
+ groupIds: ['grpAdmins'],
206
+ write: true // read and write
207
+ });
208
+
209
+ // Revoke access
210
+ await object.revokeAccess({
211
+ userIds: ['user1'],
212
+ groupIds: ['grpViewers']
213
+ });
214
+
215
+ // Get current permissions
216
+ const perms = object.getSharing();
217
+ console.log(perms.readGrants.users);
218
+ console.log(perms.writeGrants.userGroups);
219
+ ```
220
+
221
+ See [SHARING_GUIDE.md](./SHARING_GUIDE.md) for detailed examples and patterns.
222
+
223
+ ## Organization Management
224
+
225
+ Manage the current organization context for multi-tenant applications:
226
+
227
+ ```javascript
228
+ // Load current organization (automatic on login)
229
+ const org = await roboto.loadCurrentOrganization();
230
+ console.log('Current org:', org.get('name'));
231
+
232
+ // Access organization data
233
+ const orgName = org.get('name');
234
+ const taxId = org.get('profile.taxId');
235
+
236
+ // Access module-specific settings
237
+ const fiscalYearEnd = org.get('mod.accounting.fiscalYearEnd');
238
+ const defaultPipeline = org.get('mod.crm.defaultPipeline');
239
+
240
+ // Update organization data
241
+ org.set('name', 'Updated Company Name');
242
+ org.set('mod.accounting.baseCurrency', 'USD');
243
+ await org.save();
244
+
245
+ // Switch to a different organization
246
+ const newOrg = await roboto.switchOrganization('org-456');
247
+ console.log('Switched to:', newOrg.get('name'));
248
+
249
+ // Get cached organization (no API call)
250
+ const cached = roboto.getCurrentOrganization();
251
+ // or
252
+ const cached = roboto.currentOrganization;
253
+ ```
254
+
255
+ ### Organization on Login
256
+
257
+ Organizations are automatically loaded after successful login:
258
+
259
+ ```javascript
260
+ await roboto.login({
261
+ email: 'user@example.com',
262
+ password: 'password'
263
+ });
264
+
265
+ // Organization is now available
266
+ const org = roboto.currentOrganization;
267
+ console.log('Logged in to:', org.get('name'));
268
+
269
+ // Disable automatic organization load
270
+ await roboto.login({
271
+ email: 'user@example.com',
272
+ password: 'password',
273
+ loadOrganization: false // Skip org loading
274
+ });
275
+ ```
276
+
277
+ ### Server-Side Organization Context
278
+
279
+ ```javascript
280
+ // Express middleware with per-request organization
281
+ app.use((req, res, next) => {
282
+ req.roboto = new Roboto({
283
+ host: 'api.example.com',
284
+ accessKey: process.env.ROBOTO_ACCESS_KEY
285
+ }, req);
286
+ next();
287
+ });
288
+
289
+ // Use in routes
290
+ app.get('/api/accounts', async (req, res) => {
291
+ const org = await req.roboto.loadCurrentOrganization();
292
+
293
+ // Query automatically scoped to organization via IAC
294
+ const accounts = await req.roboto.query('<@accounting.account>', {});
295
+
296
+ res.json({
297
+ organization: org.get('name'),
298
+ accounts
299
+ });
300
+ });
301
+ ```
302
+
303
+ ### Multi-Tenant Data Scoping
304
+
305
+ Organization context enables automatic multi-tenant data scoping:
306
+
307
+ ```javascript
308
+ // All queries are automatically scoped to current organization
309
+ const org = await roboto.loadCurrentOrganization();
310
+
311
+ // These queries only return data the organization has access to
312
+ const accounts = await roboto.query('<@accounting.account>', {});
313
+ const invoices = await roboto.query('<@accounting.invoice>', {});
314
+ const contacts = await roboto.query('<@crm.contact>', {});
315
+
316
+ // Switch organizations and queries update automatically
317
+ await roboto.switchOrganization('different-org-id');
318
+ const newAccounts = await roboto.query('<@accounting.account>', {});
319
+ // Now returns accounts for the new organization
320
+ ```
321
+
322
+ ## Real-time Collaboration
323
+
324
+ Enable live updates across clients:
325
+
326
+ ```javascript
327
+ // Enable real-time on an object
328
+ const doc = await roboto.load('<@doc.document>', 'doc-123');
329
+ doc.enableRealtime();
330
+
331
+ // Listen for changes
332
+ doc.on('change', (path, value) => {
333
+ console.log(`${path} changed to`, value);
334
+ });
335
+
336
+ // Broadcast changes to other clients
337
+ doc.set('content.text', 'Updated text');
338
+ doc.broadcastChange('content.text'); // Others receive this immediately
339
+
340
+ // Disable when done
341
+ doc.disableRealtime();
342
+ ```
343
+
344
+ ## Storage Adapters
345
+
346
+ ### Cookie Storage (Default for Browser)
347
+
348
+ ```javascript
349
+ import Roboto, { CookieStorageAdaptor } from 'roboto-js';
350
+
351
+ const roboto = new Roboto({
352
+ host: 'api.example.com',
353
+ accessKey: 'key',
354
+ useCookies: true, // Enabled by default
355
+ cookieDomain: 'auto' // Auto-detect root domain
356
+ });
357
+
358
+ // Custom cookie configuration
359
+ const cookieAdaptor = new CookieStorageAdaptor({
360
+ secure: true,
361
+ sameSite: 'Lax',
362
+ maxAge: 86400, // 24 hours
363
+ domain: '.example.com'
364
+ });
365
+
366
+ const roboto = new Roboto({
367
+ host: 'api.example.com',
368
+ accessKey: 'key',
369
+ localStorageAdaptor: cookieAdaptor
370
+ });
371
+ ```
372
+
373
+ ### Custom Storage Adapter
374
+
375
+ ```javascript
376
+ const customAdaptor = {
377
+ getItem: async (key) => {
378
+ // Return stored value
379
+ },
380
+ setItem: async (key, value) => {
381
+ // Store value
382
+ },
383
+ removeItem: async (key) => {
384
+ // Remove value
385
+ }
386
+ };
387
+
388
+ const roboto = new Roboto({
389
+ host: 'api.example.com',
390
+ accessKey: 'key',
391
+ localStorageAdaptor: customAdaptor
392
+ });
393
+ ```
394
+
395
+ ## Server-Side Usage (Node.js)
396
+
397
+ Use with Express middleware for per-request instances:
398
+
399
+ ```javascript
400
+ import Roboto from 'roboto-js';
401
+
402
+ // Middleware to attach roboto to each request
403
+ app.use((req, res, next) => {
404
+ // proxyReq allows per-request authentication
405
+ req.roboto = new Roboto({
406
+ host: 'api.example.com',
407
+ accessKey: process.env.ROBOTO_ACCESS_KEY
408
+ }, req); // Pass request object
409
+
410
+ next();
411
+ });
412
+
413
+ // Use in routes
414
+ app.get('/api/sites', async (req, res) => {
415
+ const sites = await req.roboto.query('<@doc_website.site>', {});
416
+ res.json(sites);
417
+ });
418
+ ```
419
+
420
+ ## Metrics API
421
+
422
+ Track events and analytics:
423
+
424
+ ```javascript
425
+ // Using default metrics endpoint
426
+ await roboto.metrics.logEvent({
427
+ event: 'user_action',
428
+ properties: {
429
+ action: 'button_click',
430
+ page: 'home'
431
+ }
432
+ });
433
+
434
+ // Custom metrics host
435
+ roboto.setMetricsHost('metrics.example.com');
436
+ ```
437
+
438
+ ## Environment-Specific Features
439
+
440
+ ### Browser
441
+
442
+ - Automatic WebSocket connection
443
+ - IndexedDB for local caching
444
+ - Cookie-based authentication by default
445
+ - Cross-subdomain cookie support
446
+
447
+ ### Node.js
448
+
449
+ - Per-request instances with `proxyReq`
450
+ - Custom header support for authentication
451
+ - No WebSocket auto-connection
452
+
453
+ ## Advanced Features
454
+
455
+ ### Auto-Wrapping Responses
456
+
457
+ The SDK automatically converts doctree objects to RbtObject instances:
458
+
459
+ ```javascript
460
+ // Raw API call returns plain objects
461
+ const response = await fetch('/api/custom-endpoint');
462
+ const data = await response.json();
463
+
464
+ // Wrap for RbtObject functionality
465
+ const objects = roboto.wrapAsRbtObjects(data.items);
466
+
467
+ // Now use RbtObject methods
468
+ objects[0].set('title', 'New Title');
469
+ await objects[0].save();
470
+ ```
471
+
472
+ ### Object Caching
473
+
474
+ Objects are cached automatically to prevent duplicate instances:
475
+
476
+ ```javascript
477
+ // Both calls return the same instance
478
+ const obj1 = await roboto.load('<@doc.item>', 'abc123');
479
+ const obj2 = await roboto.load('<@doc.item>', 'abc123');
480
+
481
+ console.log(obj1 === obj2); // true
482
+ ```
483
+
484
+ ### Error Handling
485
+
486
+ Set a custom error handler:
487
+
488
+ ```javascript
489
+ roboto.setErrorHandler((error, context) => {
490
+ console.error('API Error:', error.message);
491
+ console.error('Context:', context);
492
+
493
+ // Custom error reporting
494
+ errorReporter.report(error);
495
+ });
496
+ ```
497
+
498
+ ## Build & Development
499
+
500
+ ```bash
501
+ # Install dependencies
502
+ npm install
503
+
504
+ # Build for production (strips console.log, keeps console.error)
505
+ npm run build
506
+
507
+ # Build CommonJS only
508
+ npm run build:cjs
509
+
510
+ # Build ES Modules only
511
+ npm run build:esm
512
+
513
+ # Update version
514
+ npm run update-version
515
+
516
+ # Clean install
517
+ npm run clean
518
+ ```
519
+
520
+ See [BUILD_NOTES.md](./BUILD_NOTES.md) for build configuration details.
521
+
522
+ ## Module Formats
523
+
524
+ The package supports both module systems:
525
+
526
+ **ES Modules (import)**
527
+ ```javascript
528
+ import Roboto, { RbtObject, RbtFile } from 'roboto-js';
529
+ ```
530
+
531
+ **CommonJS (require)**
532
+ ```javascript
533
+ const Roboto = require('roboto-js');
534
+ const { RbtObject, RbtFile } = require('roboto-js');
535
+ ```
536
+
537
+ ## TypeScript Support
538
+
539
+ While this is a JavaScript library, it works seamlessly with TypeScript projects. Type definitions may be added in future versions.
540
+
541
+ ## Examples
542
+
543
+ See the [examples](./examples) directory for complete working examples:
544
+
545
+ - [sharing-example.js](./examples/sharing-example.js) - Access control patterns
546
+
547
+ ## Exports
548
+
549
+ ```javascript
550
+ import Roboto, {
551
+ RbtApi, // Low-level API client
552
+ RbtObject, // Object wrapper class
553
+ RbtFile, // File wrapper class
554
+ CookieStorageAdaptor // Cookie-based storage
555
+ } from 'roboto-js';
556
+ ```
557
+
558
+ ## Browser Compatibility
559
+
560
+ - Modern browsers with ES6+ support
561
+ - IndexedDB support for local caching
562
+ - WebSocket support for real-time features
563
+ - Cookie support for authentication
564
+
565
+ ## Node.js Compatibility
566
+
567
+ - Node.js 14+ recommended
568
+ - ES Modules or CommonJS
569
+ - No browser-specific APIs used in core functionality
570
+
571
+ ## License
572
+
573
+ ISC
574
+
575
+ ## Version History
576
+
577
+ Current version: **1.9.5**
578
+
579
+ Version is automatically synced from `package.json` during build.
580
+
@@ -48,6 +48,16 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
48
48
  // Keys that should be stored without prefix for server-side access
49
49
  serverAccessKeys: (_options$serverAccess = options.serverAccessKeys) !== null && _options$serverAccess !== void 0 ? _options$serverAccess : ['authtoken', 'accessKey', 'apikey']
50
50
  }, options);
51
+ /*
52
+ console.log('[CookieStorageAdaptor] Initialized with options:', {
53
+ secure: this.options.secure,
54
+ sameSite: this.options.sameSite,
55
+ path: this.options.path,
56
+ maxAge: this.options.maxAge,
57
+ domain: this.options.domain,
58
+ prefix: this.options.prefix,
59
+ serverAccessKeys: this.options.serverAccessKeys
60
+ })*/
51
61
  }
52
62
 
53
63
  /**
@@ -72,7 +82,8 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
72
82
  cookieName = usePrefix ? this.options.prefix + key : key;
73
83
  name = cookieName + '=';
74
84
  decodedCookie = decodeURIComponent(document.cookie);
75
- cookies = decodedCookie.split(';');
85
+ cookies = decodedCookie.split(';'); //console.log(`[CookieStorageAdaptor] getItem(${key}): looking for cookie "${cookieName}" ${usePrefix ? '(prefixed)' : '(server-accessible)'}`)
86
+ //console.log(`[CookieStorageAdaptor] Available cookies:`, cookies.map(c => c.trim().split('=')[0]).join(', '))
76
87
  _iterator = _createForOfIteratorHelper(cookies);
77
88
  _context.prev = 8;
78
89
  _iterator.s();
@@ -87,9 +98,10 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
87
98
  _context.next = 23;
88
99
  break;
89
100
  }
90
- rawValue = cookie.substring(name.length, cookie.length);
101
+ rawValue = cookie.substring(name.length, cookie.length); //console.log(`[CookieStorageAdaptor] Found cookie "${cookieName}" with raw value:`, rawValue)
102
+ // Handle JSON values (like rbtUser)
91
103
  _context.prev = 15;
92
- parsedValue = JSON.parse(rawValue);
104
+ parsedValue = JSON.parse(rawValue); //console.log(`[CookieStorageAdaptor] getItem(${key}): returning parsed JSON:`, parsedValue)
93
105
  return _context.abrupt("return", parsedValue);
94
106
  case 20:
95
107
  _context.prev = 20;
@@ -143,12 +155,14 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
143
155
  // Check if this key should be stored without prefix for server access
144
156
  usePrefix = !this.options.serverAccessKeys.includes(key);
145
157
  cookieName = usePrefix ? this.options.prefix + key : key; // Stringify objects/arrays like localStorage does
146
- cookieValue = _typeof(value) === 'object' ? JSON.stringify(value) : String(value);
158
+ cookieValue = _typeof(value) === 'object' ? JSON.stringify(value) : String(value); //console.log(`[CookieStorageAdaptor] setItem(${key}): storing as "${cookieName}" ${usePrefix ? '(prefixed)' : '(server-accessible)'}`)
159
+ //console.log(`[CookieStorageAdaptor] Original value:`, value)
160
+ //console.log(`[CookieStorageAdaptor] Cookie value:`, cookieValue)
147
161
  // Build cookie string with security options
148
162
  secureFlag = this.options.secure ? '; Secure' : '';
149
163
  domainFlag = this.options.domain ? "; Domain=".concat(this.options.domain) : '';
150
164
  httpOnlyFlag = this.options.httpOnly ? '; HttpOnly' : '';
151
- cookieString = "".concat(cookieName, "=").concat(encodeURIComponent(cookieValue), "; path=").concat(this.options.path, "; max-age=").concat(this.options.maxAge, "; SameSite=").concat(this.options.sameSite).concat(secureFlag).concat(domainFlag).concat(httpOnlyFlag);
165
+ cookieString = "".concat(cookieName, "=").concat(encodeURIComponent(cookieValue), "; path=").concat(this.options.path, "; max-age=").concat(this.options.maxAge, "; SameSite=").concat(this.options.sameSite).concat(secureFlag).concat(domainFlag).concat(httpOnlyFlag); //console.log(`[CookieStorageAdaptor] Full cookie string:`, cookieString)
152
166
  document.cookie = cookieString;
153
167
 
154
168
  // Verify the cookie was set by immediately reading it back
@@ -190,7 +204,8 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
190
204
  case 2:
191
205
  // Check if this key should be stored without prefix for server access
192
206
  usePrefix = !this.options.serverAccessKeys.includes(key);
193
- cookieName = usePrefix ? this.options.prefix + key : key;
207
+ cookieName = usePrefix ? this.options.prefix + key : key; //console.log(`[CookieStorageAdaptor] removeItem(${key}): removing cookie "${cookieName}" ${usePrefix ? '(prefixed)' : '(server-accessible)'}`)
208
+ // Check if cookie exists before removal
194
209
  _context3.next = 6;
195
210
  return this.getItem(key);
196
211
  case 6:
@@ -198,7 +213,7 @@ var CookieStorageAdaptor = exports["default"] = /*#__PURE__*/function () {
198
213
  if (existingValue !== null) {} else {}
199
214
  secureFlag = this.options.secure ? '; Secure' : '';
200
215
  domainFlag = this.options.domain ? "; Domain=".concat(this.options.domain) : '';
201
- removalString = "".concat(cookieName, "=; path=").concat(this.options.path, "; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=").concat(this.options.sameSite).concat(secureFlag).concat(domainFlag);
216
+ removalString = "".concat(cookieName, "=; path=").concat(this.options.path, "; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=").concat(this.options.sameSite).concat(secureFlag).concat(domainFlag); //console.log(`[CookieStorageAdaptor] Removal cookie string:`, removalString)
202
217
  document.cookie = removalString;
203
218
 
204
219
  // Verify the cookie was removed