seatable-html-page-sdk 0.0.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.
@@ -0,0 +1,356 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
6
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
7
+ var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
8
+ var _createClass = require('@babel/runtime/helpers/createClass');
9
+ var _regeneratorRuntime = require('@babel/runtime/regenerator');
10
+
11
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+
13
+ var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator);
14
+ var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
15
+ var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
16
+ var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
17
+ var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);
18
+
19
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
20
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
21
+ var POST_MESSAGE_TYPE = {
22
+ HTML_PAGE_REQUEST: 'HTML_PAGE_REQUEST',
23
+ HTML_PAGE_RESPONSE: 'HTML_PAGE_RESPONSE',
24
+ HTML_PAGE_EVENT: 'HTML_PAGE_EVENT',
25
+ WINDOW_EVENT: 'WINDOW_EVENT'
26
+ };
27
+ var POST_MESSAGE_REQUEST_TYPE = {
28
+ GET_SERVER: 'get_server',
29
+ GET_ACCESS_TOKEN: 'get_access_token',
30
+ GET_APP_UUID: 'get_app_uuid',
31
+ GET_PAGE_ID: 'get_page_id'
32
+ };
33
+ var WINDOW_EVENT_SOURCE_TYPE = {
34
+ APP: 'app',
35
+ IFRAME: 'iframe'
36
+ };
37
+ var SUPPORT_WINDOW_MOUSE_EVENT_TYPES = ['click', 'dblclick', 'mousemove', 'mouseenter', 'mouseleave', 'mousedown', 'mouseup', 'contextmenu'];
38
+ var SUPPORT_WINDOW_KEYBOARD_EVENT_TYPES = ['keydown', 'keyup', 'keypress'];
39
+ var SUPPORT_WINDOW_DRAG_EVENT_TYPES = ['dragstart', 'dragover', 'drag', 'dragend', 'dragenter', 'dragleave', 'drop'];
40
+ var HIGH_FREQUENCY_WINDOW_EVENT_TYPES = ['mousemove', 'dragover'];
41
+ var hasOwnProperty = function hasOwnProperty(obj, key) {
42
+ return Object.prototype.hasOwnProperty.call(obj, key);
43
+ };
44
+ var generatorBase64Code = function generatorBase64Code() {
45
+ var keyLength = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;
46
+ var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz0123456789';
47
+ var key = '';
48
+ for (var i = 0; i < keyLength; i++) {
49
+ key += possible.charAt(Math.floor(Math.random() * possible.length));
50
+ }
51
+ return key;
52
+ };
53
+ var createWindowEventData = function createWindowEventData(_ref) {
54
+ var eventType = _ref.eventType,
55
+ event = _ref.event;
56
+ if (SUPPORT_WINDOW_MOUSE_EVENT_TYPES.includes(eventType)) {
57
+ return {
58
+ type: eventType,
59
+ x: event.x,
60
+ y: event.y,
61
+ button: event.button,
62
+ buttons: event.buttons
63
+ };
64
+ }
65
+ if (SUPPORT_WINDOW_KEYBOARD_EVENT_TYPES.includes(eventType)) {
66
+ return {
67
+ type: eventType,
68
+ key: event.key,
69
+ code: event.code,
70
+ keyCode: event.keyCode,
71
+ ctrlKey: event.ctrlKey,
72
+ shiftKey: event.shiftKey,
73
+ altKey: event.altKey,
74
+ metaKey: event.metaKey,
75
+ repeat: event.repeat
76
+ };
77
+ }
78
+ if (SUPPORT_WINDOW_DRAG_EVENT_TYPES.includes(eventType)) {
79
+ return {
80
+ type: eventType,
81
+ x: event.x,
82
+ y: event.y
83
+ };
84
+ }
85
+ return null;
86
+ };
87
+
88
+ /**
89
+ * IframeAdapter – enables secure postMessage communication in production environments
90
+ * For HTML page running inside an iframe
91
+ */
92
+ var IframeAdapter = /*#__PURE__*/function () {
93
+ function IframeAdapter() {
94
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
95
+ _classCallCheck__default["default"](this, IframeAdapter);
96
+ this.selfWindow = window.parent === window.self;
97
+ this.targetOrigin = options.targetOrigin || '*';
98
+ this.pendingRequests = {};
99
+ this.eventHandlers = {};
100
+ this.timeout = options.timeout || 10000;
101
+ this.setupMessageListener();
102
+ }
103
+ return _createClass__default["default"](IframeAdapter, [{
104
+ key: "generatorRequestId",
105
+ value: function generatorRequestId() {
106
+ var id = generatorBase64Code();
107
+ while (hasOwnProperty(this.pendingRequests, id)) {
108
+ id = generatorBase64Code();
109
+ }
110
+ return id;
111
+ }
112
+ }, {
113
+ key: "setupMessageListener",
114
+ value: function setupMessageListener() {
115
+ if (this.selfWindow) return;
116
+ window.addEventListener('message', this.handleMessage.bind(this));
117
+ this.setEventsListener();
118
+ }
119
+ }, {
120
+ key: "postWindowEvent",
121
+ value: function postWindowEvent(eventData) {
122
+ if (!eventData) return;
123
+ window.parent.postMessage({
124
+ type: POST_MESSAGE_TYPE.WINDOW_EVENT,
125
+ params: {
126
+ event_data: _objectSpread(_objectSpread({}, eventData), {}, {
127
+ source: WINDOW_EVENT_SOURCE_TYPE.IFRAME
128
+ })
129
+ }
130
+ }, this.targetOrigin);
131
+ }
132
+ }, {
133
+ key: "setEventsListener",
134
+ value: function setEventsListener() {
135
+ var _this = this;
136
+ var rafId = null;
137
+ var pendingEvent = null;
138
+ [].concat(SUPPORT_WINDOW_MOUSE_EVENT_TYPES, SUPPORT_WINDOW_KEYBOARD_EVENT_TYPES, SUPPORT_WINDOW_DRAG_EVENT_TYPES).forEach(function (eventType) {
139
+ window.addEventListener(eventType, function (event) {
140
+ if (event.source === WINDOW_EVENT_SOURCE_TYPE.APP) return;
141
+ if (HIGH_FREQUENCY_WINDOW_EVENT_TYPES.includes(eventType)) {
142
+ // High-frequency events that need throttling (use RAF to limit to 60fps)
143
+ // Use requestAnimationFrame for throttling high-frequency events
144
+ // Store the latest event with necessary data
145
+ pendingEvent = createWindowEventData({
146
+ eventType: eventType,
147
+ event: event
148
+ });
149
+
150
+ // Only schedule a new frame if one isn't already scheduled
151
+ if (rafId === null) {
152
+ rafId = requestAnimationFrame(function () {
153
+ if (pendingEvent) {
154
+ _this.postWindowEvent(pendingEvent);
155
+ pendingEvent = null;
156
+ rafId = null;
157
+ }
158
+ });
159
+ }
160
+ return;
161
+ }
162
+
163
+ // Low-frequency events
164
+ _this.postWindowEvent(createWindowEventData({
165
+ eventType: eventType,
166
+ event: event
167
+ }));
168
+ }, true);
169
+ });
170
+ }
171
+ }, {
172
+ key: "request",
173
+ value: function () {
174
+ var _request = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee(method, params) {
175
+ var _this2 = this;
176
+ var requestId;
177
+ return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
178
+ while (1) switch (_context.prev = _context.next) {
179
+ case 0:
180
+ if (!this.selfWindow) {
181
+ _context.next = 2;
182
+ break;
183
+ }
184
+ return _context.abrupt("return", new Promise(function (resolve) {
185
+ resolve(null);
186
+ }));
187
+ case 2:
188
+ requestId = this.generatorRequestId();
189
+ return _context.abrupt("return", new Promise(function (resolve, reject) {
190
+ _this2.pendingRequests[requestId] = {
191
+ resolve: resolve,
192
+ reject: reject
193
+ };
194
+ window.parent.postMessage({
195
+ type: POST_MESSAGE_TYPE.HTML_PAGE_REQUEST,
196
+ requestId: requestId,
197
+ method: method,
198
+ params: params
199
+ }, _this2.targetOrigin);
200
+
201
+ // request timeout
202
+ // reject and clear the pending request
203
+ var timeoutId = setTimeout(function () {
204
+ if (hasOwnProperty(_this2.pendingRequests, requestId)) {
205
+ delete _this2.pendingRequests[requestId];
206
+ reject(new Error("Request timeout: ".concat(method)));
207
+ }
208
+ }, _this2.timeout);
209
+
210
+ // save timeoutId for the pending request
211
+ var pending = _this2.pendingRequests[requestId];
212
+ if (pending) {
213
+ pending.timeoutId = timeoutId;
214
+ }
215
+ }));
216
+ case 4:
217
+ case "end":
218
+ return _context.stop();
219
+ }
220
+ }, _callee, this);
221
+ }));
222
+ function request(_x, _x2) {
223
+ return _request.apply(this, arguments);
224
+ }
225
+ return request;
226
+ }()
227
+ }, {
228
+ key: "handleMessage",
229
+ value: function handleMessage(event) {
230
+ var _event$data = event.data,
231
+ type = _event$data.type,
232
+ requestId = _event$data.requestId,
233
+ data = _event$data.data,
234
+ error = _event$data.error,
235
+ eventType = _event$data.eventType,
236
+ payload = _event$data.payload;
237
+ if (type === POST_MESSAGE_TYPE.HTML_PAGE_RESPONSE) {
238
+ var pending = this.pendingRequests[requestId];
239
+ if (pending) {
240
+ clearTimeout(pending.timeoutId);
241
+ delete this.pendingRequests[requestId];
242
+ if (error) {
243
+ pending.reject(new Error(error));
244
+ } else {
245
+ pending.resolve(data ? JSON.parse(data) : null);
246
+ }
247
+ }
248
+ } else if (type === POST_MESSAGE_TYPE.HTML_PAGE_EVENT) {
249
+ this.emitEvent(eventType, payload);
250
+ } else if (type === POST_MESSAGE_TYPE.WINDOW_EVENT) {
251
+ var eventData = data.event_data;
252
+ if (!eventData) return;
253
+ var syntheticEvent;
254
+ var targetElement;
255
+ if (SUPPORT_WINDOW_KEYBOARD_EVENT_TYPES.includes(eventData.type)) {
256
+ syntheticEvent = new KeyboardEvent(eventData.type, {
257
+ bubbles: true,
258
+ cancelable: true,
259
+ key: eventData.key,
260
+ code: eventData.code,
261
+ keyCode: eventData.keyCode,
262
+ ctrlKey: eventData.ctrlKey,
263
+ shiftKey: eventData.shiftKey,
264
+ altKey: eventData.altKey,
265
+ metaKey: eventData.metaKey,
266
+ repeat: eventData.repeat,
267
+ view: window
268
+ });
269
+ targetElement = document.activeElement || document.body;
270
+ } else if (SUPPORT_WINDOW_MOUSE_EVENT_TYPES.includes(eventData.type)) {
271
+ syntheticEvent = new MouseEvent(eventData.type, {
272
+ bubbles: true,
273
+ cancelable: true,
274
+ view: window,
275
+ clientX: eventData.x,
276
+ clientY: eventData.y,
277
+ screenX: eventData.x,
278
+ screenY: eventData.y,
279
+ button: eventData.button,
280
+ buttons: eventData.buttons
281
+ });
282
+ var elementAtPoint = document.elementFromPoint(eventData.x, eventData.y);
283
+ targetElement = elementAtPoint || document.body;
284
+ } else if (SUPPORT_WINDOW_DRAG_EVENT_TYPES.includes(eventData.type)) {
285
+ syntheticEvent = new DragEvent(eventData.type, {
286
+ bubbles: true,
287
+ cancelable: true,
288
+ view: window,
289
+ clientX: eventData.x,
290
+ clientY: eventData.y,
291
+ screenX: eventData.x,
292
+ screenY: eventData.y,
293
+ button: eventData.button,
294
+ buttons: eventData.buttons
295
+ });
296
+ var _elementAtPoint = document.elementFromPoint(eventData.x, eventData.y);
297
+ targetElement = _elementAtPoint || document.body;
298
+ }
299
+ if (!targetElement || !syntheticEvent) return;
300
+
301
+ // Dispatch once on the target element, it will bubble up naturally
302
+ syntheticEvent.source = eventData.source;
303
+ targetElement.dispatchEvent(syntheticEvent);
304
+ }
305
+ }
306
+ }, {
307
+ key: "on",
308
+ value: function on(eventType, handler) {
309
+ var _this3 = this;
310
+ if (!hasOwnProperty(this.eventHandlers, eventType)) {
311
+ this.eventHandlers[eventType] = [];
312
+ }
313
+ this.eventHandlers[eventType].push(handler);
314
+ return function () {
315
+ return _this3.off(eventType, handler);
316
+ };
317
+ }
318
+ }, {
319
+ key: "off",
320
+ value: function off(eventType, handler) {
321
+ var handlers = this.eventHandlers[eventType];
322
+ if (handlers) {
323
+ var index = handlers.indexOf(handler);
324
+ if (index !== -1) {
325
+ handlers.splice(index, 1);
326
+ }
327
+ }
328
+ }
329
+ }, {
330
+ key: "emitEvent",
331
+ value: function emitEvent(eventType, payload) {
332
+ var handlers = this.eventHandlers[eventType] || [];
333
+ handlers.forEach(function (handler) {
334
+ try {
335
+ handler(payload);
336
+ } catch (error) {
337
+ // eslint-disable-next-line
338
+ console.error("Error in event handler for ".concat(eventType, ":"), error);
339
+ }
340
+ });
341
+ }
342
+ }, {
343
+ key: "destroy",
344
+ value: function destroy() {
345
+ this.pendingRequests.forEach(function (pending) {
346
+ clearTimeout(pending.timeoutId);
347
+ pending.reject(new Error('Adapter destroyed'));
348
+ });
349
+ this.pendingRequests = {};
350
+ this.eventHandlers = {};
351
+ }
352
+ }]);
353
+ }();
354
+
355
+ exports.IframeAdapter = IframeAdapter;
356
+ exports.POST_MESSAGE_REQUEST_TYPE = POST_MESSAGE_REQUEST_TYPE;
package/lib/index.js ADDED
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var sdk = require('./sdk.js');
6
+
7
+
8
+
9
+ exports.HTMLPageSDK = sdk.HTMLPageSDK;
package/lib/sdk.js ADDED
@@ -0,0 +1,154 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
6
+ var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
7
+ var _createClass = require('@babel/runtime/helpers/createClass');
8
+ var _regeneratorRuntime = require('@babel/runtime/regenerator');
9
+ var universalAppApi = require('./apis/universal-app-api.js');
10
+ var iframeAdapter = require('./iframe-adapter.js');
11
+
12
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
+
14
+ var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator);
15
+ var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
16
+ var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
17
+ var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);
18
+
19
+ var HTMLPageSDK = /*#__PURE__*/function () {
20
+ function HTMLPageSDK() {
21
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22
+ _classCallCheck__default["default"](this, HTMLPageSDK);
23
+ this.options = options || {};
24
+ this.iframeAdapter = new iframeAdapter.IframeAdapter(options);
25
+ }
26
+ return _createClass__default["default"](HTMLPageSDK, [{
27
+ key: "init",
28
+ value: function () {
29
+ var _init = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() {
30
+ var _this$options, server, accessToken, appUuid;
31
+ return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
32
+ while (1) switch (_context.prev = _context.next) {
33
+ case 0:
34
+ if (this.options.server) {
35
+ _context.next = 4;
36
+ break;
37
+ }
38
+ _context.next = 3;
39
+ return this.iframeAdapter.request(iframeAdapter.POST_MESSAGE_REQUEST_TYPE.GET_SERVER);
40
+ case 3:
41
+ this.options.server = _context.sent;
42
+ case 4:
43
+ if (this.options.accessToken) {
44
+ _context.next = 8;
45
+ break;
46
+ }
47
+ _context.next = 7;
48
+ return this.iframeAdapter.request(iframeAdapter.POST_MESSAGE_REQUEST_TYPE.GET_ACCESS_TOKEN);
49
+ case 7:
50
+ this.options.accessToken = _context.sent;
51
+ case 8:
52
+ if (this.options.appUuid) {
53
+ _context.next = 12;
54
+ break;
55
+ }
56
+ _context.next = 11;
57
+ return this.iframeAdapter.request(iframeAdapter.POST_MESSAGE_REQUEST_TYPE.GET_APP_UUID);
58
+ case 11:
59
+ this.options.appUuid = _context.sent;
60
+ case 12:
61
+ if (this.options.pageId) {
62
+ _context.next = 16;
63
+ break;
64
+ }
65
+ _context.next = 15;
66
+ return this.iframeAdapter.request(iframeAdapter.POST_MESSAGE_REQUEST_TYPE.GET_PAGE_ID);
67
+ case 15:
68
+ this.options.pageId = _context.sent;
69
+ case 16:
70
+ _this$options = this.options, server = _this$options.server, accessToken = _this$options.accessToken, appUuid = _this$options.appUuid;
71
+ this.universalAppAPI = new universalAppApi["default"]({
72
+ server: server,
73
+ accessToken: accessToken,
74
+ appUuid: appUuid
75
+ });
76
+ case 18:
77
+ case "end":
78
+ return _context.stop();
79
+ }
80
+ }, _callee, this);
81
+ }));
82
+ function init() {
83
+ return _init.apply(this, arguments);
84
+ }
85
+ return init;
86
+ }()
87
+ }, {
88
+ key: "listRows",
89
+ value: function listRows(_ref) {
90
+ var tableName = _ref.tableName,
91
+ start = _ref.start,
92
+ limit = _ref.limit;
93
+ return this.universalAppAPI.listRows(this.options.pageId, tableName, start, limit);
94
+ }
95
+ }, {
96
+ key: "addRow",
97
+ value: function addRow(_ref2) {
98
+ var tableName = _ref2.tableName,
99
+ rowData = _ref2.rowData,
100
+ rowLinksData = _ref2.rowLinksData;
101
+ return this.universalAppAPI.addRow(this.options.pageId, tableName, rowData, rowLinksData);
102
+ }
103
+ }, {
104
+ key: "updateRow",
105
+ value: function updateRow(_ref3) {
106
+ var tableName = _ref3.tableName,
107
+ rowId = _ref3.rowId,
108
+ rowData = _ref3.rowData;
109
+ var rowsData = [{
110
+ id: rowId,
111
+ row: rowData
112
+ }];
113
+ this.batchUpdateRows({
114
+ tableName: tableName,
115
+ rowsData: rowsData
116
+ });
117
+ }
118
+ }, {
119
+ key: "deleteRow",
120
+ value: function deleteRow(_ref4) {
121
+ var tableName = _ref4.tableName,
122
+ rowId = _ref4.rowId;
123
+ var rowsIds = [rowId];
124
+ return this.batchDeleteRows({
125
+ tableName: tableName,
126
+ rowsIds: rowsIds
127
+ });
128
+ }
129
+ }, {
130
+ key: "batchAddRows",
131
+ value: function batchAddRows(_ref5) {
132
+ var tableName = _ref5.tableName,
133
+ rowsData = _ref5.rowsData,
134
+ rowsLinksData = _ref5.rowsLinksData;
135
+ return this.universalAppAPI.addRows(this.options.pageId, tableName, rowsData, rowsLinksData);
136
+ }
137
+ }, {
138
+ key: "batchUpdateRows",
139
+ value: function batchUpdateRows(_ref6) {
140
+ var tableName = _ref6.tableName,
141
+ rowsData = _ref6.rowsData;
142
+ return this.universalAppAPI.updateRows(this.options.pageId, tableName, rowsData);
143
+ }
144
+ }, {
145
+ key: "batchDeleteRows",
146
+ value: function batchDeleteRows(_ref7) {
147
+ var tableName = _ref7.tableName,
148
+ rowsIds = _ref7.rowsIds;
149
+ return this.universalAppAPI.deleteRows(this.options.pageId, tableName, rowsIds);
150
+ }
151
+ }]);
152
+ }();
153
+
154
+ exports.HTMLPageSDK = HTMLPageSDK;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "seatable-html-page-sdk",
3
+ "version": "0.0.1",
4
+ "description": "JavaScript SDK for embedding HTML pages within SeaTable Universal Apps.",
5
+ "main": "./lib/index.js",
6
+ "module": "./es/index.js",
7
+ "private": false,
8
+ "scripts": {
9
+ "test": "jest --watchAll",
10
+ "test-cov": "jest --coverage",
11
+ "eslint": "eslint ./src/**",
12
+ "eslint-fix": "eslint ./src/** --fix",
13
+ "build": "rm -rf dist lib es && NODE_ENV=production rollup -c",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "HTML page"
18
+ ],
19
+ "author": "SeaTable",
20
+ "files": [
21
+ "dist",
22
+ "lib",
23
+ "es",
24
+ "package.json"
25
+ ],
26
+ "dependencies": {
27
+ "axios": "~1.12.*"
28
+ },
29
+ "devDependencies": {
30
+ "@babel/core": "^7.26.0",
31
+ "@babel/plugin-transform-runtime": "^7.26.0",
32
+ "@babel/preset-env": "^7.26.0",
33
+ "@babel/runtime": "^7.26.0",
34
+ "@rollup/plugin-babel": "^6.0.4",
35
+ "@rollup/plugin-commonjs": "^28.0.1",
36
+ "@rollup/plugin-eslint": "^9.0.5",
37
+ "@rollup/plugin-json": "^6.1.0",
38
+ "@rollup/plugin-node-resolve": "^15.3.0",
39
+ "@rollup/plugin-terser": "^0.4.4",
40
+ "@types/jest": "^30.0.0",
41
+ "babel-jest": "^30.2.0",
42
+ "eslint": "^8.57.1",
43
+ "eslint-config-airbnb": "^19.0.4",
44
+ "jest": "^30.2.0",
45
+ "rollup": "2.79.2"
46
+ }
47
+ }