@almadar/runtime 4.10.2 → 4.11.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/dist/{OrbitalServerRuntime-B5lfym6T.d.ts → OrbitalServerRuntime-D-b_dg8I.d.ts} +66 -13
- package/dist/OrbitalServerRuntime.d.ts +1 -1
- package/dist/OrbitalServerRuntime.js +2 -308
- package/dist/OrbitalServerRuntime.js.map +1 -1
- package/dist/{chunk-K36736GF.js → chunk-RCWMQH7Y.js} +348 -3
- package/dist/chunk-RCWMQH7Y.js.map +1 -0
- package/dist/index.d.ts +196 -28
- package/dist/index.js +390 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-K36736GF.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveBinding, evaluate, createMinimalContext, evaluateGuard } from '@almadar/evaluator';
|
|
2
2
|
export { createMinimalContext } from '@almadar/evaluator';
|
|
3
3
|
import { isKnownOperator } from '@almadar/std';
|
|
4
|
+
import { faker } from '@faker-js/faker';
|
|
4
5
|
import { OrbitalSchemaSchema, isEntityCall, isEntityReference, parseEntityRef, parseImportedTraitRef, isPageReference, isPageReferenceString, isPageReferenceObject, parsePageRef } from '@almadar/core';
|
|
5
6
|
|
|
6
7
|
// src/EventBus.ts
|
|
@@ -1476,6 +1477,286 @@ function createTestExecutor(overrides = {}) {
|
|
|
1476
1477
|
debug: true
|
|
1477
1478
|
});
|
|
1478
1479
|
}
|
|
1480
|
+
var MockPersistenceAdapter = class {
|
|
1481
|
+
stores = /* @__PURE__ */ new Map();
|
|
1482
|
+
schemas = /* @__PURE__ */ new Map();
|
|
1483
|
+
idCounters = /* @__PURE__ */ new Map();
|
|
1484
|
+
config;
|
|
1485
|
+
constructor(config = {}) {
|
|
1486
|
+
this.config = {
|
|
1487
|
+
defaultSeedCount: 6,
|
|
1488
|
+
debug: false,
|
|
1489
|
+
...config
|
|
1490
|
+
};
|
|
1491
|
+
if (config.seed !== void 0) {
|
|
1492
|
+
faker.seed(config.seed);
|
|
1493
|
+
if (this.config.debug) {
|
|
1494
|
+
console.log(`[MockPersistence] Using seed: ${config.seed}`);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
// ============================================================================
|
|
1499
|
+
// Store Management
|
|
1500
|
+
// ============================================================================
|
|
1501
|
+
getStore(entityName) {
|
|
1502
|
+
const normalized = entityName.toLowerCase();
|
|
1503
|
+
if (!this.stores.has(normalized)) {
|
|
1504
|
+
this.stores.set(normalized, /* @__PURE__ */ new Map());
|
|
1505
|
+
this.idCounters.set(normalized, 0);
|
|
1506
|
+
}
|
|
1507
|
+
return this.stores.get(normalized);
|
|
1508
|
+
}
|
|
1509
|
+
nextId(entityName) {
|
|
1510
|
+
const normalized = entityName.toLowerCase();
|
|
1511
|
+
const counter = (this.idCounters.get(normalized) ?? 0) + 1;
|
|
1512
|
+
this.idCounters.set(normalized, counter);
|
|
1513
|
+
return `${this.capitalizeFirst(entityName)} Id ${counter}`;
|
|
1514
|
+
}
|
|
1515
|
+
// ============================================================================
|
|
1516
|
+
// Schema & Seeding
|
|
1517
|
+
// ============================================================================
|
|
1518
|
+
/**
|
|
1519
|
+
* Register an entity schema and seed mock data.
|
|
1520
|
+
* If the schema has seedData, those instances are used directly.
|
|
1521
|
+
* Otherwise, random mock data is generated with faker.
|
|
1522
|
+
*/
|
|
1523
|
+
registerEntity(schema, seedCount) {
|
|
1524
|
+
const normalized = schema.name.toLowerCase();
|
|
1525
|
+
this.schemas.set(normalized, schema);
|
|
1526
|
+
if (schema.seedData && schema.seedData.length > 0) {
|
|
1527
|
+
this.seedFromInstances(schema.name, schema.seedData);
|
|
1528
|
+
} else {
|
|
1529
|
+
const count = seedCount ?? this.config.defaultSeedCount ?? 6;
|
|
1530
|
+
this.seed(schema.name, schema.fields, count);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Seed an entity with pre-authored instance data.
|
|
1535
|
+
*/
|
|
1536
|
+
seedFromInstances(entityName, instances) {
|
|
1537
|
+
const store = this.getStore(entityName);
|
|
1538
|
+
if (this.config.debug) {
|
|
1539
|
+
console.log(`[MockPersistence] Seeding ${instances.length} ${entityName} from schema instances...`);
|
|
1540
|
+
}
|
|
1541
|
+
for (const instance of instances) {
|
|
1542
|
+
const id = instance.id || this.nextId(entityName);
|
|
1543
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1544
|
+
const item = {
|
|
1545
|
+
...instance,
|
|
1546
|
+
id,
|
|
1547
|
+
createdAt: instance.createdAt || now,
|
|
1548
|
+
updatedAt: now
|
|
1549
|
+
};
|
|
1550
|
+
store.set(id, item);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Seed an entity with mock data.
|
|
1555
|
+
*/
|
|
1556
|
+
seed(entityName, fields, count) {
|
|
1557
|
+
const store = this.getStore(entityName);
|
|
1558
|
+
const normalized = entityName.toLowerCase();
|
|
1559
|
+
if (this.config.debug) {
|
|
1560
|
+
console.log(`[MockPersistence] Seeding ${count} ${entityName}...`);
|
|
1561
|
+
}
|
|
1562
|
+
for (let i = 0; i < count; i++) {
|
|
1563
|
+
const item = this.generateMockItem(normalized, entityName, fields, i + 1);
|
|
1564
|
+
store.set(item.id, item);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Generate a single mock item based on field schemas.
|
|
1569
|
+
*/
|
|
1570
|
+
generateMockItem(normalizedName, entityName, fields, index) {
|
|
1571
|
+
const id = this.nextId(entityName);
|
|
1572
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1573
|
+
const item = {
|
|
1574
|
+
id,
|
|
1575
|
+
createdAt: faker.date.past({ years: 1 }).toISOString(),
|
|
1576
|
+
updatedAt: now
|
|
1577
|
+
};
|
|
1578
|
+
for (const field of fields) {
|
|
1579
|
+
if (field.name === "id" || field.name === "createdAt" || field.name === "updatedAt") {
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
item[field.name] = this.generateFieldValue(entityName, field, index);
|
|
1583
|
+
}
|
|
1584
|
+
return item;
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* Generate a mock value for a field based on its schema.
|
|
1588
|
+
*/
|
|
1589
|
+
generateFieldValue(entityName, field, index) {
|
|
1590
|
+
if (field.default !== void 0) {
|
|
1591
|
+
if (field.default === "@now") {
|
|
1592
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1593
|
+
}
|
|
1594
|
+
return field.default;
|
|
1595
|
+
}
|
|
1596
|
+
const fieldType = field.type.toLowerCase();
|
|
1597
|
+
switch (fieldType) {
|
|
1598
|
+
case "string":
|
|
1599
|
+
return this.generateStringValue(entityName, field, index);
|
|
1600
|
+
case "number":
|
|
1601
|
+
return faker.number.int({ min: 0, max: 100 });
|
|
1602
|
+
case "boolean":
|
|
1603
|
+
return faker.datatype.boolean();
|
|
1604
|
+
case "date":
|
|
1605
|
+
case "timestamp":
|
|
1606
|
+
case "datetime":
|
|
1607
|
+
return this.generateDateValue(field);
|
|
1608
|
+
case "enum":
|
|
1609
|
+
if (field.values && field.values.length > 0) {
|
|
1610
|
+
return faker.helpers.arrayElement(field.values);
|
|
1611
|
+
}
|
|
1612
|
+
return null;
|
|
1613
|
+
case "relation":
|
|
1614
|
+
return null;
|
|
1615
|
+
// Relations need special handling
|
|
1616
|
+
case "array":
|
|
1617
|
+
return [];
|
|
1618
|
+
case "object":
|
|
1619
|
+
return null;
|
|
1620
|
+
default:
|
|
1621
|
+
return this.generateStringValue(entityName, field, index);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* Generate a string value based on the field's declared schema metadata.
|
|
1626
|
+
* Reads `values` (enum) first, then `format` (email/url/phone/uuid/date/
|
|
1627
|
+
* datetime), then falls back to faker.lorem.words. No field-name heuristics
|
|
1628
|
+
* — the schema is the source of truth. If a caller needs a real email, they
|
|
1629
|
+
* declare `format: "email"`; if they need an enum, they declare `values: [...]`.
|
|
1630
|
+
*/
|
|
1631
|
+
generateStringValue(_entityName, field, _index) {
|
|
1632
|
+
if (field.values && field.values.length > 0) {
|
|
1633
|
+
return faker.helpers.arrayElement(field.values);
|
|
1634
|
+
}
|
|
1635
|
+
switch (field.format) {
|
|
1636
|
+
case "email":
|
|
1637
|
+
return faker.internet.email();
|
|
1638
|
+
case "url":
|
|
1639
|
+
return faker.internet.url();
|
|
1640
|
+
case "phone":
|
|
1641
|
+
return faker.phone.number();
|
|
1642
|
+
case "uuid":
|
|
1643
|
+
return faker.string.uuid();
|
|
1644
|
+
case "date":
|
|
1645
|
+
return faker.date.recent().toISOString().split("T")[0];
|
|
1646
|
+
case "datetime":
|
|
1647
|
+
return faker.date.recent().toISOString();
|
|
1648
|
+
default:
|
|
1649
|
+
return faker.lorem.words(2);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Generate a date value. Uses the field's `format` (date vs datetime) to
|
|
1654
|
+
* decide ISO shape; otherwise returns a recent ISO-8601 datetime. No
|
|
1655
|
+
* field-name heuristics.
|
|
1656
|
+
*/
|
|
1657
|
+
generateDateValue(field) {
|
|
1658
|
+
const date = faker.date.recent({ days: 30 });
|
|
1659
|
+
if (field.format === "date") return date.toISOString().split("T")[0];
|
|
1660
|
+
return date.toISOString();
|
|
1661
|
+
}
|
|
1662
|
+
capitalizeFirst(str) {
|
|
1663
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1664
|
+
}
|
|
1665
|
+
// ============================================================================
|
|
1666
|
+
// PersistenceAdapter Implementation
|
|
1667
|
+
// ============================================================================
|
|
1668
|
+
async create(entityType, data) {
|
|
1669
|
+
const store = this.getStore(entityType);
|
|
1670
|
+
const id = this.nextId(entityType);
|
|
1671
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1672
|
+
const withDefaults = this.applyFieldDefaults(entityType, data);
|
|
1673
|
+
const item = {
|
|
1674
|
+
...withDefaults,
|
|
1675
|
+
id,
|
|
1676
|
+
createdAt: now,
|
|
1677
|
+
updatedAt: now
|
|
1678
|
+
};
|
|
1679
|
+
store.set(id, item);
|
|
1680
|
+
return { id };
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Fill in any entity-declared field defaults that the caller omitted.
|
|
1684
|
+
* SAVE payloads coming from form-section only carry the fields the user
|
|
1685
|
+
* edited; persisted rows should still honor `field.default` so downstream
|
|
1686
|
+
* row-content probes (VG11f) see a row whose every declared-default field
|
|
1687
|
+
* is non-empty. `@now` resolves to the current ISO timestamp.
|
|
1688
|
+
*/
|
|
1689
|
+
applyFieldDefaults(entityType, data) {
|
|
1690
|
+
const schema = this.schemas.get(entityType.toLowerCase());
|
|
1691
|
+
if (!schema) return data;
|
|
1692
|
+
const result = { ...data };
|
|
1693
|
+
for (const field of schema.fields) {
|
|
1694
|
+
if (field.name === "id" || field.name === "createdAt" || field.name === "updatedAt") continue;
|
|
1695
|
+
if (result[field.name] !== void 0) continue;
|
|
1696
|
+
if (field.default === void 0) continue;
|
|
1697
|
+
result[field.name] = field.default === "@now" ? (/* @__PURE__ */ new Date()).toISOString() : field.default;
|
|
1698
|
+
}
|
|
1699
|
+
return result;
|
|
1700
|
+
}
|
|
1701
|
+
async update(entityType, id, data) {
|
|
1702
|
+
const store = this.getStore(entityType);
|
|
1703
|
+
const existing = store.get(id);
|
|
1704
|
+
if (!existing) {
|
|
1705
|
+
throw new Error(`Entity ${entityType} with id ${id} not found`);
|
|
1706
|
+
}
|
|
1707
|
+
const updated = {
|
|
1708
|
+
...existing,
|
|
1709
|
+
...data,
|
|
1710
|
+
id,
|
|
1711
|
+
// Preserve original ID
|
|
1712
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1713
|
+
};
|
|
1714
|
+
store.set(id, updated);
|
|
1715
|
+
}
|
|
1716
|
+
async delete(entityType, id) {
|
|
1717
|
+
const store = this.getStore(entityType);
|
|
1718
|
+
if (!store.has(id)) {
|
|
1719
|
+
throw new Error(`Entity ${entityType} with id ${id} not found`);
|
|
1720
|
+
}
|
|
1721
|
+
store.delete(id);
|
|
1722
|
+
}
|
|
1723
|
+
async getById(entityType, id) {
|
|
1724
|
+
const store = this.getStore(entityType);
|
|
1725
|
+
return store.get(id) ?? null;
|
|
1726
|
+
}
|
|
1727
|
+
async list(entityType) {
|
|
1728
|
+
const store = this.getStore(entityType);
|
|
1729
|
+
return Array.from(store.values());
|
|
1730
|
+
}
|
|
1731
|
+
// ============================================================================
|
|
1732
|
+
// Utilities
|
|
1733
|
+
// ============================================================================
|
|
1734
|
+
/**
|
|
1735
|
+
* Clear all data for an entity.
|
|
1736
|
+
*/
|
|
1737
|
+
clear(entityName) {
|
|
1738
|
+
const normalized = entityName.toLowerCase();
|
|
1739
|
+
this.stores.delete(normalized);
|
|
1740
|
+
this.idCounters.delete(normalized);
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Clear all data.
|
|
1744
|
+
*/
|
|
1745
|
+
clearAll() {
|
|
1746
|
+
this.stores.clear();
|
|
1747
|
+
this.idCounters.clear();
|
|
1748
|
+
}
|
|
1749
|
+
/**
|
|
1750
|
+
* Get count of items for an entity.
|
|
1751
|
+
*/
|
|
1752
|
+
count(entityName) {
|
|
1753
|
+
const store = this.getStore(entityName);
|
|
1754
|
+
return store.size;
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1757
|
+
function createMockPersistence(config) {
|
|
1758
|
+
return new MockPersistenceAdapter(config);
|
|
1759
|
+
}
|
|
1479
1760
|
|
|
1480
1761
|
// src/loader/schema-loader.ts
|
|
1481
1762
|
function isElectron() {
|
|
@@ -2843,6 +3124,70 @@ function parseNamespacedEvent(eventName) {
|
|
|
2843
3124
|
return { event: eventName };
|
|
2844
3125
|
}
|
|
2845
3126
|
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
3127
|
+
// src/PersistenceAdapter.ts
|
|
3128
|
+
var InMemoryPersistence = class {
|
|
3129
|
+
data = /* @__PURE__ */ new Map();
|
|
3130
|
+
idCounter = 0;
|
|
3131
|
+
/**
|
|
3132
|
+
* Seed the store with pre-existing rows.
|
|
3133
|
+
*
|
|
3134
|
+
* Accepts either a plain `Record<entityType, EntityRow[]>` or an iterable
|
|
3135
|
+
* of `[entityType, EntityRow[]]` entries. Rows without an `id` get one
|
|
3136
|
+
* generated at insert time; rows with an `id` keep it (so re-seeding
|
|
3137
|
+
* after a schema rebuild preserves identities used in render bindings).
|
|
3138
|
+
*/
|
|
3139
|
+
seed(seedData) {
|
|
3140
|
+
const entries = Symbol.iterator in Object(seedData) ? seedData : Object.entries(seedData);
|
|
3141
|
+
for (const [entityType, rows] of entries) {
|
|
3142
|
+
if (!this.data.has(entityType)) {
|
|
3143
|
+
this.data.set(entityType, /* @__PURE__ */ new Map());
|
|
3144
|
+
}
|
|
3145
|
+
const collection = this.data.get(entityType);
|
|
3146
|
+
for (const row of rows) {
|
|
3147
|
+
const id = row.id || `${entityType}-${++this.idCounter}`;
|
|
3148
|
+
collection.set(id, { ...row, id });
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
async create(entityType, data) {
|
|
3153
|
+
const id = data.id || `${entityType}-${++this.idCounter}`;
|
|
3154
|
+
if (!this.data.has(entityType)) {
|
|
3155
|
+
this.data.set(entityType, /* @__PURE__ */ new Map());
|
|
3156
|
+
}
|
|
3157
|
+
this.data.get(entityType).set(id, { ...data, id });
|
|
3158
|
+
return { id };
|
|
3159
|
+
}
|
|
3160
|
+
async update(entityType, id, data) {
|
|
3161
|
+
const collection = this.data.get(entityType);
|
|
3162
|
+
if (collection?.has(id)) {
|
|
3163
|
+
const existing = collection.get(id);
|
|
3164
|
+
collection.set(id, { ...existing, ...data });
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
async delete(entityType, id) {
|
|
3168
|
+
this.data.get(entityType)?.delete(id);
|
|
3169
|
+
}
|
|
3170
|
+
async getById(entityType, id) {
|
|
3171
|
+
return this.data.get(entityType)?.get(id) || null;
|
|
3172
|
+
}
|
|
3173
|
+
async list(entityType) {
|
|
3174
|
+
const collection = this.data.get(entityType);
|
|
3175
|
+
return collection ? Array.from(collection.values()) : [];
|
|
3176
|
+
}
|
|
3177
|
+
/**
|
|
3178
|
+
* Snapshot the entire store as a plain object (entityType → rows).
|
|
3179
|
+
* Useful for feeding a fresh render-time binding layer with the
|
|
3180
|
+
* current persistence view.
|
|
3181
|
+
*/
|
|
3182
|
+
snapshot() {
|
|
3183
|
+
const out = {};
|
|
3184
|
+
for (const [entityType, collection] of this.data) {
|
|
3185
|
+
out[entityType] = Array.from(collection.values());
|
|
3186
|
+
}
|
|
3187
|
+
return out;
|
|
3188
|
+
}
|
|
3189
|
+
};
|
|
3190
|
+
|
|
3191
|
+
export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, containsBindings, createContextFromBindings, createInitialTraitState, createMockPersistence, createTestExecutor, createUnifiedLoader, extractBindings, findInitialState, findTransition, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isBrowser, isElectron, isNamespacedEvent, isNode, normalizeEventKey, parseNamespacedEvent, preprocessSchema, processEvent };
|
|
3192
|
+
//# sourceMappingURL=chunk-RCWMQH7Y.js.map
|
|
3193
|
+
//# sourceMappingURL=chunk-RCWMQH7Y.js.map
|