@furo/open-models 1.14.0 → 1.15.0
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/custom-elements.json +313 -0
- package/dist/decorators/EntityServiceTypes.d.ts +133 -0
- package/dist/decorators/EntityServiceTypes.js +2 -0
- package/dist/decorators/EntityServiceTypes.js.map +1 -0
- package/dist/decorators/FieldBindings.d.ts +104 -0
- package/dist/decorators/FieldBindings.js +229 -0
- package/dist/decorators/FieldBindings.js.map +1 -0
- package/dist/decorators/ModelDecorators.d.ts +100 -0
- package/dist/decorators/ModelDecorators.js +227 -0
- package/dist/decorators/ModelDecorators.js.map +1 -0
- package/dist/decorators/SchemaBuilder.d.ts +15 -0
- package/dist/decorators/SchemaBuilder.js +89 -0
- package/dist/decorators/SchemaBuilder.js.map +1 -0
- package/dist/decorators/ServiceDecorators.d.ts +79 -0
- package/dist/decorators/ServiceDecorators.js +203 -0
- package/dist/decorators/ServiceDecorators.js.map +1 -0
- package/dist/decorators/defaultServiceEventHandlers.d.ts +89 -0
- package/dist/decorators/defaultServiceEventHandlers.js +100 -0
- package/dist/decorators/defaultServiceEventHandlers.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/custom-elements.json
CHANGED
|
@@ -1209,6 +1209,271 @@
|
|
|
1209
1209
|
"declarations": [],
|
|
1210
1210
|
"exports": []
|
|
1211
1211
|
},
|
|
1212
|
+
{
|
|
1213
|
+
"kind": "javascript-module",
|
|
1214
|
+
"path": "dist/decorators/EntityServiceTypes.js",
|
|
1215
|
+
"declarations": [],
|
|
1216
|
+
"exports": []
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
"kind": "javascript-module",
|
|
1220
|
+
"path": "dist/decorators/EntityServiceTypes.js.map",
|
|
1221
|
+
"declarations": [],
|
|
1222
|
+
"exports": []
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
"kind": "javascript-module",
|
|
1226
|
+
"path": "dist/decorators/FieldBindings.js",
|
|
1227
|
+
"declarations": [
|
|
1228
|
+
{
|
|
1229
|
+
"kind": "variable",
|
|
1230
|
+
"name": "fieldBindings",
|
|
1231
|
+
"type": {
|
|
1232
|
+
"text": "object"
|
|
1233
|
+
},
|
|
1234
|
+
"default": "{ /** * Decorator for the `model` property. * * Handles: * - Binding/unbinding when model changes * - Resolving reader/writer functions based on model type * - Calling reader on model value changes * - Providing `writeToModel()` method */ model() { return function modelDecorator(target, propertyKey) { const ctor = target.constructor; // Patch lifecycle patchLifecycle(ctor); // Add writeToModel helper method if (!Object.prototype.hasOwnProperty.call(target, \"writeToModel\")) { Object.defineProperty(target, \"writeToModel\", { value: function writeToModel() { const writeFn = this[MODEL_WRITE_FN]; if (writeFn) { try { writeFn(); } catch (e) { // eslint-disable-next-line no-console console.error(\"Failed to write to model:\", e); } } }, writable: false, enumerable: false, configurable: true, }); } // Create getter/setter for the model property Object.defineProperty(target, propertyKey, { get() { return this[CURRENT_MODEL]; }, set(value) { const oldModel = this[CURRENT_MODEL]; if (value === oldModel) return; // Unbind from old model if (oldModel) { unbindFromModel(this, oldModel); } // Store new model this[CURRENT_MODEL] = value; // Resolve reader/writer functions based on type if (value) { const typeName = value.__meta?.typeName ?? \"primitives.STRING\"; // Resolve reader const reader = this.modelReaders?.get(typeName); if (reader) { this[MODEL_READ_FN] = reader.bind(this); } else { // eslint-disable-next-line no-console console.warn(`No modelReader for type \"${typeName}\". Available: ${[...(this.modelReaders?.keys() ?? [])].join(\", \")}`); this[MODEL_READ_FN] = undefined; } // Resolve writer const writer = this.modelWriters?.get(typeName); if (writer) { this[MODEL_WRITE_FN] = writer.bind(this); } else { // eslint-disable-next-line no-console console.warn(`No modelWriter for type \"${typeName}\". Available: ${[...(this.modelWriters?.keys() ?? [])].join(\", \")}`); this[MODEL_WRITE_FN] = undefined; } } else { this[MODEL_READ_FN] = undefined; this[MODEL_WRITE_FN] = undefined; } // Bind to new model (if connected) if (value && this.isConnected) { bindToModel(this, value); } // Trigger Lit update this.requestUpdate(); }, enumerable: true, configurable: true, }); }; }, /** * Binds a method to an event on the model. * When the event fires, the method is called with the event detail. * * @param eventType - The event type to listen for */ onEvent(eventType) { return function onEventDecorator(target, propertyKey, descriptor) { const originalMethod = descriptor.value; const ctor = target.constructor; let events = ctor[FIELD_EVENTS]; if (!events) { events = []; ctor[FIELD_EVENTS] = events; } events.push({ propertyKey, eventType, method: originalMethod }); patchLifecycle(ctor); }; }, }",
|
|
1235
|
+
"description": "### fieldBindings\n\nDecorators for creating reusable components that bind to FieldNode models.\n\nThe component provides `modelReaders` and `modelWriters` maps keyed by\n`__meta.typeName`. The decorator handles:\n- Binding/unbinding on model change\n- Calling the correct reader when model value changes\n- Providing `writeToModel()` method that calls the correct writer"
|
|
1236
|
+
}
|
|
1237
|
+
],
|
|
1238
|
+
"exports": [
|
|
1239
|
+
{
|
|
1240
|
+
"kind": "js",
|
|
1241
|
+
"name": "fieldBindings",
|
|
1242
|
+
"declaration": {
|
|
1243
|
+
"name": "fieldBindings",
|
|
1244
|
+
"module": "dist/decorators/FieldBindings.js"
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
]
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
"kind": "javascript-module",
|
|
1251
|
+
"path": "dist/decorators/FieldBindings.js.map",
|
|
1252
|
+
"declarations": [],
|
|
1253
|
+
"exports": []
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
"kind": "javascript-module",
|
|
1257
|
+
"path": "dist/decorators/ModelDecorators.js",
|
|
1258
|
+
"declarations": [
|
|
1259
|
+
{
|
|
1260
|
+
"kind": "function",
|
|
1261
|
+
"name": "modelBindings",
|
|
1262
|
+
"parameters": [
|
|
1263
|
+
{
|
|
1264
|
+
"name": "model",
|
|
1265
|
+
"description": "The FieldNode model to bind to"
|
|
1266
|
+
}
|
|
1267
|
+
],
|
|
1268
|
+
"description": "### modelBindings Factory\n\nCreates type-safe decorators bound to a specific FieldNode model.\nUse this to bind component properties and methods to model events.\n\nUsage:\n```typescript\nimport { modelBindings } from \"@x/furo/open-models/ModelDecorators\";\nimport { CubeEntityModel } from \"./CubeEntityModel\";\n\nconst cubeModel = modelBindings(CubeEntityModel.model);\n\nclass MyComponent extends LitElement {\n // Bind to a nested field value - updates when cube.length changes",
|
|
1269
|
+
"return": {
|
|
1270
|
+
"type": {
|
|
1271
|
+
"text": ""
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
],
|
|
1276
|
+
"exports": [
|
|
1277
|
+
{
|
|
1278
|
+
"kind": "js",
|
|
1279
|
+
"name": "modelBindings",
|
|
1280
|
+
"declaration": {
|
|
1281
|
+
"name": "modelBindings",
|
|
1282
|
+
"module": "dist/decorators/ModelDecorators.js"
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
]
|
|
1286
|
+
},
|
|
1287
|
+
{
|
|
1288
|
+
"kind": "javascript-module",
|
|
1289
|
+
"path": "dist/decorators/ModelDecorators.js.map",
|
|
1290
|
+
"declarations": [],
|
|
1291
|
+
"exports": []
|
|
1292
|
+
},
|
|
1293
|
+
{
|
|
1294
|
+
"kind": "javascript-module",
|
|
1295
|
+
"path": "dist/decorators/SchemaBuilder.js",
|
|
1296
|
+
"declarations": [
|
|
1297
|
+
{
|
|
1298
|
+
"kind": "class",
|
|
1299
|
+
"description": "",
|
|
1300
|
+
"name": "SchemaBuilder",
|
|
1301
|
+
"members": [
|
|
1302
|
+
{
|
|
1303
|
+
"kind": "method",
|
|
1304
|
+
"name": "generate",
|
|
1305
|
+
"static": true,
|
|
1306
|
+
"parameters": [
|
|
1307
|
+
{
|
|
1308
|
+
"name": "model"
|
|
1309
|
+
}
|
|
1310
|
+
]
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
"kind": "method",
|
|
1314
|
+
"name": "getProps",
|
|
1315
|
+
"static": true,
|
|
1316
|
+
"parameters": [
|
|
1317
|
+
{
|
|
1318
|
+
"name": "model"
|
|
1319
|
+
}
|
|
1320
|
+
]
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
"kind": "method",
|
|
1324
|
+
"name": "getRequiredFields",
|
|
1325
|
+
"static": true,
|
|
1326
|
+
"parameters": [
|
|
1327
|
+
{
|
|
1328
|
+
"name": "descriptors"
|
|
1329
|
+
}
|
|
1330
|
+
]
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
"kind": "method",
|
|
1334
|
+
"name": "getConstraints",
|
|
1335
|
+
"static": true,
|
|
1336
|
+
"parameters": [
|
|
1337
|
+
{
|
|
1338
|
+
"name": "constraints"
|
|
1339
|
+
}
|
|
1340
|
+
]
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
"kind": "method",
|
|
1344
|
+
"name": "createFieldNodeFromSchema",
|
|
1345
|
+
"static": true,
|
|
1346
|
+
"parameters": [
|
|
1347
|
+
{
|
|
1348
|
+
"name": "schema"
|
|
1349
|
+
}
|
|
1350
|
+
]
|
|
1351
|
+
}
|
|
1352
|
+
]
|
|
1353
|
+
}
|
|
1354
|
+
],
|
|
1355
|
+
"exports": [
|
|
1356
|
+
{
|
|
1357
|
+
"kind": "js",
|
|
1358
|
+
"name": "SchemaBuilder",
|
|
1359
|
+
"declaration": {
|
|
1360
|
+
"name": "SchemaBuilder",
|
|
1361
|
+
"module": "dist/decorators/SchemaBuilder.js"
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
]
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
"kind": "javascript-module",
|
|
1368
|
+
"path": "dist/decorators/SchemaBuilder.js.map",
|
|
1369
|
+
"declarations": [],
|
|
1370
|
+
"exports": []
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
"kind": "javascript-module",
|
|
1374
|
+
"path": "dist/decorators/ServiceDecorators.js",
|
|
1375
|
+
"declarations": [
|
|
1376
|
+
{
|
|
1377
|
+
"kind": "function",
|
|
1378
|
+
"name": "serviceBindings",
|
|
1379
|
+
"parameters": [
|
|
1380
|
+
{
|
|
1381
|
+
"name": "service",
|
|
1382
|
+
"description": "The EventTarget service to bind to"
|
|
1383
|
+
}
|
|
1384
|
+
],
|
|
1385
|
+
"description": "### serviceBindings Factory\n\nCreates type-safe decorators bound to a specific service instance.\nUse this to bind component properties and methods to service events.\n\nThe factory is generic and works with any `EventTarget`.\nEvent types and their detail payloads are type-checked at compile time\nvia the `TEventMap` type parameter.\n\nUsage:\n```typescript\nimport { cubeEntityService } from \"./CubeEntityService\";\nimport { serviceBindings } from \"./ServiceDecorators.js\";\n\nconst cube = serviceBindings(cubeEntityService);\n\nclass MyComponent extends LitElement {\n // Property binding - type-safe event name, auto-extracts from detail",
|
|
1386
|
+
"return": {
|
|
1387
|
+
"type": {
|
|
1388
|
+
"text": ""
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
],
|
|
1393
|
+
"exports": [
|
|
1394
|
+
{
|
|
1395
|
+
"kind": "js",
|
|
1396
|
+
"name": "serviceBindings",
|
|
1397
|
+
"declaration": {
|
|
1398
|
+
"name": "serviceBindings",
|
|
1399
|
+
"module": "dist/decorators/ServiceDecorators.js"
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
]
|
|
1403
|
+
},
|
|
1404
|
+
{
|
|
1405
|
+
"kind": "javascript-module",
|
|
1406
|
+
"path": "dist/decorators/ServiceDecorators.js.map",
|
|
1407
|
+
"declarations": [],
|
|
1408
|
+
"exports": []
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
"kind": "javascript-module",
|
|
1412
|
+
"path": "dist/decorators/defaultServiceEventHandlers.js",
|
|
1413
|
+
"declarations": [
|
|
1414
|
+
{
|
|
1415
|
+
"kind": "function",
|
|
1416
|
+
"name": "defaultServiceEventHandlers",
|
|
1417
|
+
"parameters": [
|
|
1418
|
+
{
|
|
1419
|
+
"name": "dispatch",
|
|
1420
|
+
"description": "Function to dispatch events (typically bound to the service's dispatchEvent)"
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
"name": "options",
|
|
1424
|
+
"default": "{}",
|
|
1425
|
+
"description": "Optional configuration"
|
|
1426
|
+
}
|
|
1427
|
+
],
|
|
1428
|
+
"description": "### defaultServiceEventHandlers\n\nCreates default service handlers that dispatch standard events.\nUse this to reduce boilerplate when setting up service handlers.\n\nThe `onResponse` handler is intentionally NOT included - you must provide your own\nimplementation since response handling is typically service-specific.\n\nUsage:\n```typescript\nclass MyEntityService extends EventTarget {\n private dispatch = createDispatch(this);\n\n setupHandlers() {\n this.service.Get.setHandlers({\n ...defaultServiceEventHandlers(this.dispatch),\n onResponse: (response, serverResponse) => {\n // Your custom response handling\n this.entity.fromLiteral(response.entity);\n this.dispatch(\"response-received\", { response, serverResponse });\n },\n });\n }\n}\n```\n\nWith loading check:\n```typescript\nthis.service.Get.setHandlers({\n ...defaultServiceEventHandlers(this.dispatch, {\n isLoading: () => this.service.Get.isLoading || this.service.Update.isLoading,\n }),\n onResponse: (response, serverResponse) => { ... },\n});\n```",
|
|
1429
|
+
"return": {
|
|
1430
|
+
"type": {
|
|
1431
|
+
"text": ""
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
},
|
|
1435
|
+
{
|
|
1436
|
+
"kind": "function",
|
|
1437
|
+
"name": "createDispatch",
|
|
1438
|
+
"parameters": [
|
|
1439
|
+
{
|
|
1440
|
+
"name": "target",
|
|
1441
|
+
"description": "The EventTarget to dispatch events on"
|
|
1442
|
+
}
|
|
1443
|
+
],
|
|
1444
|
+
"description": "### createDispatch\n\nHelper to create a typed dispatch function for an EventTarget.\n\nUsage:\n```typescript\nclass MyService extends EventTarget {\n private dispatch = createDispatch(this);\n\n doSomething() {\n this.dispatch(\"busy-changed\", { busy: true });\n }\n}\n```",
|
|
1445
|
+
"return": {
|
|
1446
|
+
"type": {
|
|
1447
|
+
"text": ""
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
],
|
|
1452
|
+
"exports": [
|
|
1453
|
+
{
|
|
1454
|
+
"kind": "js",
|
|
1455
|
+
"name": "defaultServiceEventHandlers",
|
|
1456
|
+
"declaration": {
|
|
1457
|
+
"name": "defaultServiceEventHandlers",
|
|
1458
|
+
"module": "dist/decorators/defaultServiceEventHandlers.js"
|
|
1459
|
+
}
|
|
1460
|
+
},
|
|
1461
|
+
{
|
|
1462
|
+
"kind": "js",
|
|
1463
|
+
"name": "createDispatch",
|
|
1464
|
+
"declaration": {
|
|
1465
|
+
"name": "createDispatch",
|
|
1466
|
+
"module": "dist/decorators/defaultServiceEventHandlers.js"
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
]
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
"kind": "javascript-module",
|
|
1473
|
+
"path": "dist/decorators/defaultServiceEventHandlers.js.map",
|
|
1474
|
+
"declarations": [],
|
|
1475
|
+
"exports": []
|
|
1476
|
+
},
|
|
1212
1477
|
{
|
|
1213
1478
|
"kind": "javascript-module",
|
|
1214
1479
|
"path": "dist/index.js",
|
|
@@ -1501,6 +1766,54 @@
|
|
|
1501
1766
|
"name": "RECURSION",
|
|
1502
1767
|
"module": "./proxies/RECURSION.js"
|
|
1503
1768
|
}
|
|
1769
|
+
},
|
|
1770
|
+
{
|
|
1771
|
+
"kind": "js",
|
|
1772
|
+
"name": "serviceBindings",
|
|
1773
|
+
"declaration": {
|
|
1774
|
+
"name": "serviceBindings",
|
|
1775
|
+
"module": "./decorators/ServiceDecorators.js"
|
|
1776
|
+
}
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
"kind": "js",
|
|
1780
|
+
"name": "modelBindings",
|
|
1781
|
+
"declaration": {
|
|
1782
|
+
"name": "modelBindings",
|
|
1783
|
+
"module": "./decorators/ModelDecorators.js"
|
|
1784
|
+
}
|
|
1785
|
+
},
|
|
1786
|
+
{
|
|
1787
|
+
"kind": "js",
|
|
1788
|
+
"name": "fieldBindings",
|
|
1789
|
+
"declaration": {
|
|
1790
|
+
"name": "fieldBindings",
|
|
1791
|
+
"module": "./decorators/FieldBindings.js"
|
|
1792
|
+
}
|
|
1793
|
+
},
|
|
1794
|
+
{
|
|
1795
|
+
"kind": "js",
|
|
1796
|
+
"name": "SchemaBuilder",
|
|
1797
|
+
"declaration": {
|
|
1798
|
+
"name": "SchemaBuilder",
|
|
1799
|
+
"module": "./decorators/SchemaBuilder.js"
|
|
1800
|
+
}
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
"kind": "js",
|
|
1804
|
+
"name": "defaultServiceEventHandlers",
|
|
1805
|
+
"declaration": {
|
|
1806
|
+
"name": "defaultServiceEventHandlers",
|
|
1807
|
+
"module": "./decorators/defaultServiceEventHandlers.js"
|
|
1808
|
+
}
|
|
1809
|
+
},
|
|
1810
|
+
{
|
|
1811
|
+
"kind": "js",
|
|
1812
|
+
"name": "createDispatch",
|
|
1813
|
+
"declaration": {
|
|
1814
|
+
"name": "createDispatch",
|
|
1815
|
+
"module": "./decorators/defaultServiceEventHandlers.js"
|
|
1816
|
+
}
|
|
1504
1817
|
}
|
|
1505
1818
|
]
|
|
1506
1819
|
},
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ### EntityServiceEventType
|
|
3
|
+
*
|
|
4
|
+
* Standard event types dispatched by entity services.
|
|
5
|
+
* These events cover the full lifecycle of REST API operations.
|
|
6
|
+
*
|
|
7
|
+
* #### Request Lifecycle Events
|
|
8
|
+
* | Event | Description |
|
|
9
|
+
* |--------------------|-------------------------------------------------------|
|
|
10
|
+
* | `busy-changed` | Loading/saving state changed |
|
|
11
|
+
* | `request-started` | Request has been initiated |
|
|
12
|
+
* | `request-finished` | Request completed (success, error, or abort) |
|
|
13
|
+
* | `request-aborted` | Request was aborted (navigation, timeout, new request)|
|
|
14
|
+
*
|
|
15
|
+
* #### Success Events
|
|
16
|
+
* | Event | Description |
|
|
17
|
+
* |--------------------|-------------------------------------------------------|
|
|
18
|
+
* | `response-received`| Successful response with parsed data |
|
|
19
|
+
* | `raw-response` | Successful response (raw, before parsing) |
|
|
20
|
+
*
|
|
21
|
+
* #### Error Events
|
|
22
|
+
* | Event | Description |
|
|
23
|
+
* |--------------------|-------------------------------------------------------|
|
|
24
|
+
* | `response-error` | Any error response (4xx/5xx) with parsed body |
|
|
25
|
+
* | `raw-error` | Any error response (raw, before parsing) |
|
|
26
|
+
* | `error-404` | Resource not found (404) |
|
|
27
|
+
* | `error-5xx` | Server error (500+) |
|
|
28
|
+
* | `fatal-error` | Unhandled/unexpected error |
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* ```typescript
|
|
32
|
+
* export type MyServiceEventType = EntityServiceEventType;
|
|
33
|
+
* // Or extend with custom events:
|
|
34
|
+
* export type MyServiceEventType = EntityServiceEventType | "custom-event";
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type EntityServiceEventType = "busy-changed" | "request-started" | "request-finished" | "request-aborted" | "response-received" | "raw-response" | "response-error" | "raw-error" | "error-404" | "error-5xx" | "fatal-error";
|
|
38
|
+
/**
|
|
39
|
+
* ### EntityServiceEventMap
|
|
40
|
+
*
|
|
41
|
+
* Maps each event type to its detail payload type.
|
|
42
|
+
* This enables type-safe event handling with `storeBindings`.
|
|
43
|
+
*
|
|
44
|
+
* #### Request Lifecycle Events
|
|
45
|
+
* | Event | Detail Type |
|
|
46
|
+
* |--------------------|--------------------------------------------------|
|
|
47
|
+
* | `busy-changed` | `{ busy: boolean }` |
|
|
48
|
+
* | `request-started` | `{ request: unknown }` |
|
|
49
|
+
* | `request-finished` | `{ request: unknown }` |
|
|
50
|
+
* | `request-aborted` | `{ reason: string }` |
|
|
51
|
+
*
|
|
52
|
+
* #### Success Events
|
|
53
|
+
* | Event | Detail Type |
|
|
54
|
+
* |--------------------|--------------------------------------------------|
|
|
55
|
+
* | `response-received`| `{ response: unknown, serverResponse: Response }`|
|
|
56
|
+
* | `raw-response` | `{ serverResponse: Response }` |
|
|
57
|
+
*
|
|
58
|
+
* #### Error Events
|
|
59
|
+
* | Event | Detail Type |
|
|
60
|
+
* |--------------------|--------------------------------------------------|
|
|
61
|
+
* | `response-error` | `{ parsedResponse: unknown, serverResponse: Response }` |
|
|
62
|
+
* | `raw-error` | `{ serverResponse: Response }` |
|
|
63
|
+
* | `error-404` | `{ serverResponse: Response }` |
|
|
64
|
+
* | `error-5xx` | `{ serverResponse: Response }` |
|
|
65
|
+
* | `fatal-error` | `{ error: unknown }` |
|
|
66
|
+
*
|
|
67
|
+
* Usage:
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // Extend with custom events:
|
|
70
|
+
* interface MyServiceEventMap extends EntityServiceEventMap {
|
|
71
|
+
* "custom-event": { data: string };
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export interface EntityServiceEventMap {
|
|
76
|
+
"busy-changed": {
|
|
77
|
+
busy: boolean;
|
|
78
|
+
};
|
|
79
|
+
"request-started": {
|
|
80
|
+
request: unknown;
|
|
81
|
+
};
|
|
82
|
+
"request-finished": {
|
|
83
|
+
request: unknown;
|
|
84
|
+
};
|
|
85
|
+
"request-aborted": {
|
|
86
|
+
reason: string;
|
|
87
|
+
};
|
|
88
|
+
"response-received": {
|
|
89
|
+
response: unknown;
|
|
90
|
+
serverResponse: Response;
|
|
91
|
+
};
|
|
92
|
+
"raw-response": {
|
|
93
|
+
serverResponse: Response;
|
|
94
|
+
};
|
|
95
|
+
"response-error": {
|
|
96
|
+
parsedResponse: unknown;
|
|
97
|
+
serverResponse: Response;
|
|
98
|
+
};
|
|
99
|
+
"raw-error": {
|
|
100
|
+
serverResponse: Response;
|
|
101
|
+
};
|
|
102
|
+
"error-404": {
|
|
103
|
+
serverResponse: Response;
|
|
104
|
+
};
|
|
105
|
+
"error-5xx": {
|
|
106
|
+
serverResponse: Response;
|
|
107
|
+
};
|
|
108
|
+
"fatal-error": {
|
|
109
|
+
error: unknown;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* ### TypedEntityService
|
|
114
|
+
*
|
|
115
|
+
* Type alias for entity services with type-safe event handling.
|
|
116
|
+
* Use this when you need to type a variable or parameter that holds a service.
|
|
117
|
+
*
|
|
118
|
+
* Note: Services extend `EventTarget` at runtime, but this type provides
|
|
119
|
+
* compile-time type safety for event names when used with `storeBindings`.
|
|
120
|
+
*
|
|
121
|
+
* Usage:
|
|
122
|
+
* ```typescript
|
|
123
|
+
* // Type a variable
|
|
124
|
+
* const service: TypedEntityService = cubeEntityService;
|
|
125
|
+
*
|
|
126
|
+
* // With custom events
|
|
127
|
+
* interface MyEventMap extends EntityServiceEventMap {
|
|
128
|
+
* "custom-event": { data: string };
|
|
129
|
+
* }
|
|
130
|
+
* const myService: TypedEntityService<MyEventMap> = myEntityService;
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export type TypedEntityService<_TEventMap extends EntityServiceEventMap = EntityServiceEventMap> = EventTarget;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityServiceTypes.js","sourceRoot":"","sources":["../../src/decorators/EntityServiceTypes.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * ### EntityServiceEventType\n *\n * Standard event types dispatched by entity services.\n * These events cover the full lifecycle of REST API operations.\n *\n * #### Request Lifecycle Events\n * | Event | Description |\n * |--------------------|-------------------------------------------------------|\n * | `busy-changed` | Loading/saving state changed |\n * | `request-started` | Request has been initiated |\n * | `request-finished` | Request completed (success, error, or abort) |\n * | `request-aborted` | Request was aborted (navigation, timeout, new request)|\n *\n * #### Success Events\n * | Event | Description |\n * |--------------------|-------------------------------------------------------|\n * | `response-received`| Successful response with parsed data |\n * | `raw-response` | Successful response (raw, before parsing) |\n *\n * #### Error Events\n * | Event | Description |\n * |--------------------|-------------------------------------------------------|\n * | `response-error` | Any error response (4xx/5xx) with parsed body |\n * | `raw-error` | Any error response (raw, before parsing) |\n * | `error-404` | Resource not found (404) |\n * | `error-5xx` | Server error (500+) |\n * | `fatal-error` | Unhandled/unexpected error |\n *\n * Usage:\n * ```typescript\n * export type MyServiceEventType = EntityServiceEventType;\n * // Or extend with custom events:\n * export type MyServiceEventType = EntityServiceEventType | \"custom-event\";\n * ```\n */\nexport type EntityServiceEventType =\n // Request lifecycle\n | \"busy-changed\"\n | \"request-started\"\n | \"request-finished\"\n | \"request-aborted\"\n // Success\n | \"response-received\"\n | \"raw-response\"\n // Errors\n | \"response-error\"\n | \"raw-error\"\n | \"error-404\"\n | \"error-5xx\"\n | \"fatal-error\";\n\n/**\n * ### EntityServiceEventMap\n *\n * Maps each event type to its detail payload type.\n * This enables type-safe event handling with `storeBindings`.\n *\n * #### Request Lifecycle Events\n * | Event | Detail Type |\n * |--------------------|--------------------------------------------------|\n * | `busy-changed` | `{ busy: boolean }` |\n * | `request-started` | `{ request: unknown }` |\n * | `request-finished` | `{ request: unknown }` |\n * | `request-aborted` | `{ reason: string }` |\n *\n * #### Success Events\n * | Event | Detail Type |\n * |--------------------|--------------------------------------------------|\n * | `response-received`| `{ response: unknown, serverResponse: Response }`|\n * | `raw-response` | `{ serverResponse: Response }` |\n *\n * #### Error Events\n * | Event | Detail Type |\n * |--------------------|--------------------------------------------------|\n * | `response-error` | `{ parsedResponse: unknown, serverResponse: Response }` |\n * | `raw-error` | `{ serverResponse: Response }` |\n * | `error-404` | `{ serverResponse: Response }` |\n * | `error-5xx` | `{ serverResponse: Response }` |\n * | `fatal-error` | `{ error: unknown }` |\n *\n * Usage:\n * ```typescript\n * // Extend with custom events:\n * interface MyServiceEventMap extends EntityServiceEventMap {\n * \"custom-event\": { data: string };\n * }\n * ```\n */\nexport interface EntityServiceEventMap {\n // Request lifecycle\n \"busy-changed\": { busy: boolean };\n \"request-started\": { request: unknown };\n \"request-finished\": { request: unknown };\n \"request-aborted\": { reason: string };\n // Success\n \"response-received\": { response: unknown; serverResponse: Response };\n \"raw-response\": { serverResponse: Response };\n // Errors\n \"response-error\": { parsedResponse: unknown; serverResponse: Response };\n \"raw-error\": { serverResponse: Response };\n \"error-404\": { serverResponse: Response };\n \"error-5xx\": { serverResponse: Response };\n \"fatal-error\": { error: unknown };\n}\n\n/**\n * ### TypedEntityService\n *\n * Type alias for entity services with type-safe event handling.\n * Use this when you need to type a variable or parameter that holds a service.\n *\n * Note: Services extend `EventTarget` at runtime, but this type provides\n * compile-time type safety for event names when used with `storeBindings`.\n *\n * Usage:\n * ```typescript\n * // Type a variable\n * const service: TypedEntityService = cubeEntityService;\n *\n * // With custom events\n * interface MyEventMap extends EntityServiceEventMap {\n * \"custom-event\": { data: string };\n * }\n * const myService: TypedEntityService<MyEventMap> = myEntityService;\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport type TypedEntityService<_TEventMap extends EntityServiceEventMap = EntityServiceEventMap> = EventTarget;\n"]}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import type { ModelEventType } from "./ModelDecorators.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interface for FieldNode-like objects that support event listening.
|
|
5
|
+
*/
|
|
6
|
+
export interface FieldNodeLike {
|
|
7
|
+
__addEventListener(type: string, listener: (e: CustomEvent) => void): void;
|
|
8
|
+
__removeEventListener(type: string, listener: (e: CustomEvent) => void): void;
|
|
9
|
+
__meta?: {
|
|
10
|
+
typeName?: string;
|
|
11
|
+
};
|
|
12
|
+
value?: unknown;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Interface for components that bind to FieldNode models.
|
|
16
|
+
*
|
|
17
|
+
* Components implement `modelReaders` and `modelWriters` maps
|
|
18
|
+
* keyed by `__meta.typeName` (e.g., "primitives.STRING", "furo.fat.String").
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* export class MyInput extends LitElement implements BindableComponent {
|
|
23
|
+
* @fieldBindings.model()
|
|
24
|
+
* model: STRING | XString | undefined;
|
|
25
|
+
*
|
|
26
|
+
* // Provided by decorator
|
|
27
|
+
* declare writeToModel: () => void;
|
|
28
|
+
*
|
|
29
|
+
* modelReaders = new Map<string, () => void>([
|
|
30
|
+
* ["primitives.STRING", () => { this.value = (this.model as STRING).value ?? ""; }],
|
|
31
|
+
* ["furo.fat.String", () => { this.value = (this.model as XString).value.value ?? ""; }],
|
|
32
|
+
* ]);
|
|
33
|
+
*
|
|
34
|
+
* modelWriters = new Map<string, () => void>([
|
|
35
|
+
* ["primitives.STRING", () => { (this.model as STRING).value = this.value; }],
|
|
36
|
+
* ["furo.fat.String", () => { (this.model as XString).value.value = this.value; }],
|
|
37
|
+
* ]);
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export interface BindableComponent extends LitElement {
|
|
42
|
+
model: FieldNodeLike | undefined;
|
|
43
|
+
/** Map of typeName → reader function (model → component) */
|
|
44
|
+
modelReaders: Map<string, () => void>;
|
|
45
|
+
/** Map of typeName → writer function (component → model) */
|
|
46
|
+
modelWriters: Map<string, () => void>;
|
|
47
|
+
/** Helper to write current value to model (provided by decorator) */
|
|
48
|
+
writeToModel: () => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* ### fieldBindings
|
|
52
|
+
*
|
|
53
|
+
* Decorators for creating reusable components that bind to FieldNode models.
|
|
54
|
+
*
|
|
55
|
+
* The component provides `modelReaders` and `modelWriters` maps keyed by
|
|
56
|
+
* `__meta.typeName`. The decorator handles:
|
|
57
|
+
* - Binding/unbinding on model change
|
|
58
|
+
* - Calling the correct reader when model value changes
|
|
59
|
+
* - Providing `writeToModel()` method that calls the correct writer
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* export class MyInput extends LitElement implements BindableComponent {
|
|
64
|
+
* @fieldBindings.model()
|
|
65
|
+
* model: STRING | XString | undefined;
|
|
66
|
+
*
|
|
67
|
+
* declare writeToModel: () => void;
|
|
68
|
+
*
|
|
69
|
+
* modelReaders = new Map([
|
|
70
|
+
* ["primitives.STRING", () => { this.value = (this.model as STRING).value ?? ""; }],
|
|
71
|
+
* ["furo.fat.String", () => { this.value = (this.model as XString).value.value ?? ""; }],
|
|
72
|
+
* ]);
|
|
73
|
+
*
|
|
74
|
+
* modelWriters = new Map([
|
|
75
|
+
* ["primitives.STRING", () => { (this.model as STRING).value = this.value; }],
|
|
76
|
+
* ["furo.fat.String", () => { (this.model as XString).value.value = this.value; }],
|
|
77
|
+
* ]);
|
|
78
|
+
*
|
|
79
|
+
* private _onInput(e: Event) {
|
|
80
|
+
* this.value = (e.target as HTMLInputElement).value;
|
|
81
|
+
* this.writeToModel();
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare const fieldBindings: {
|
|
87
|
+
/**
|
|
88
|
+
* Decorator for the `model` property.
|
|
89
|
+
*
|
|
90
|
+
* Handles:
|
|
91
|
+
* - Binding/unbinding when model changes
|
|
92
|
+
* - Resolving reader/writer functions based on model type
|
|
93
|
+
* - Calling reader on model value changes
|
|
94
|
+
* - Providing `writeToModel()` method
|
|
95
|
+
*/
|
|
96
|
+
model(): <T extends FieldNodeLike>(target: object, propertyKey: string) => void;
|
|
97
|
+
/**
|
|
98
|
+
* Binds a method to an event on the model.
|
|
99
|
+
* When the event fires, the method is called with the event detail.
|
|
100
|
+
*
|
|
101
|
+
* @param eventType - The event type to listen for
|
|
102
|
+
*/
|
|
103
|
+
onEvent(eventType: ModelEventType): (target: object, propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
104
|
+
};
|