@flighthq/entity 0.5.1-next.815.cc08b93 → 0.5.1-next.903.f434bc2

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/README.md CHANGED
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/entity`. The `@fligh
13
13
  This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
14
 
15
15
  - [Flight project](https://github.com/flighthq/flight)
16
- - [Source for @flighthq/entity@0.5.1-next.815.cc08b93](https://github.com/flighthq/flight/tree/cc08b93ef981080fa86bdd5143dc61dbdbf2665b/packages/entity)
17
- - [License](https://github.com/flighthq/flight/blob/cc08b93ef981080fa86bdd5143dc61dbdbf2665b/LICENSE.md)
16
+ - [Source for @flighthq/entity@0.5.1-next.903.f434bc2](https://github.com/flighthq/flight/tree/f434bc233778d75aeea61995df3a8cfaec459a85/packages/entity)
17
+ - [License](https://github.com/flighthq/flight/blob/f434bc233778d75aeea61995df3a8cfaec459a85/LICENSE.md)
@@ -1 +1 @@
1
- {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAQ7E,wBAAgB,WAAW,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAI7E;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAI1G"}
1
+ {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAM7E,wBAAgB,WAAW,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAI7E;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,SAAS,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAI1G"}
package/dist/clone.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
- import { createEntity } from './entity';
3
2
  // Allocates a new entity by copying the public data fields of the source, with the runtime
4
3
  // slot reset to undefined. The clone is a fresh, unbound entity — runtime and binding are
5
4
  // intentionally not carried over.
6
5
  export function cloneEntity(source) {
7
6
  const copy = { ...source };
8
7
  copy[EntityRuntimeKey] = undefined;
9
- return createEntity(copy);
8
+ return copy;
10
9
  }
11
10
  // Returns a plain object with the EntityRuntimeKey slot removed, ready to pass to a
12
11
  // serializer or JSON.stringify. The runtime is explicitly non-serializable; this helper
package/dist/clone.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"clone.js","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,2FAA2F;AAC3F,0FAA0F;AAC1F,kCAAkC;AAClC,MAAM,UAAU,WAAW,CAAsB,MAAsB;IACrE,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAkC,CAAC;IAC3D,IAAI,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;IACnC,OAAO,YAAY,CAAC,IAAuB,CAAC,CAAC;AAC/C,CAAC;AAED,oFAAoF;AACpF,wFAAwF;AACxF,wFAAwF;AACxF,sBAAsB;AACtB,MAAM,UAAU,kBAAkB,CAAsB,MAAsB;IAC5E,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAkC,CAAC;IAC3D,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC9B,OAAO,IAA6C,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"clone.js","sourceRoot":"","sources":["../src/clone.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,2FAA2F;AAC3F,0FAA0F;AAC1F,kCAAkC;AAClC,MAAM,UAAU,WAAW,CAAsB,MAAsB;IACrE,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAkC,CAAC;IAC3D,IAAI,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;IACnC,OAAO,IAAY,CAAC;AACtB,CAAC;AAED,oFAAoF;AACpF,wFAAwF;AACxF,wFAAwF;AACxF,sBAAsB;AACtB,MAAM,UAAU,kBAAkB,CAAsB,MAAsB;IAC5E,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAkC,CAAC;IAC3D,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC9B,OAAO,IAA6C,CAAC;AACvD,CAAC"}
package/dist/entity.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- import type { Entity } from '@flighthq/types/contract';
2
- export declare function createEntity<Type extends object>(obj?: Type): Type & Entity;
1
+ import type { Entity, EntityConstruction } from '@flighthq/types/contract';
2
+ export declare function allocateEntity<Type extends Entity>(): EntityConstruction<Type>;
3
+ export declare function finishEntity<Type extends Entity>(out: EntityConstruction<Type>): Type;
3
4
  //# sourceMappingURL=entity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGvD,wBAAgB,YAAY,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAK3E"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAG3E,wBAAgB,cAAc,CAAC,IAAI,SAAS,MAAM,KAAK,kBAAkB,CAAC,IAAI,CAAC,CAI9E;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,MAAM,EAAE,GAAG,EAAE,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,CAErF"}
package/dist/entity.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
- export function createEntity(obj) {
3
- if (!obj)
4
- obj = {};
5
- const entity = obj;
6
- entity[EntityRuntimeKey] = undefined;
7
- return entity;
2
+ export function allocateEntity() {
3
+ const out = {};
4
+ out[EntityRuntimeKey] = undefined;
5
+ return out;
6
+ }
7
+ export function finishEntity(out) {
8
+ return out;
8
9
  }
9
10
  //# sourceMappingURL=entity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,UAAU,YAAY,CAAsB,GAAU;IAC1D,IAAI,CAAC,GAAG;QAAE,GAAG,GAAG,EAAU,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAoB,CAAC;IACpC,MAAM,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,EAA8B,CAAC;IAC3C,GAAG,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;IAClC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAsB,GAA6B;IAC7E,OAAO,GAAW,CAAC;AACrB,CAAC"}
package/dist/host.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- import type { EntityWithoutRuntime, Host } from '@flighthq/types/contract';
1
+ import type { EntityConstruction, EntityWithoutRuntime, Host } from '@flighthq/types/contract';
2
2
  export declare function createHost<Capabilities extends Partial<EntityWithoutRuntime<Host>>>(capabilities?: Readonly<Capabilities>): Host & Capabilities;
3
+ export declare function initializeHost<Capabilities extends Partial<EntityWithoutRuntime<Host>>>(out: EntityConstruction<Host & Capabilities>, capabilities: Readonly<Capabilities>): void;
3
4
  //# sourceMappingURL=host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAI3E,wBAAgB,UAAU,CAAC,YAAY,SAAS,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,EACjF,YAAY,GAAE,QAAQ,CAAC,YAAY,CAAsB,GACxD,IAAI,GAAG,YAAY,CA8BrB"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAI/F,wBAAgB,UAAU,CAAC,YAAY,SAAS,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,EACjF,YAAY,GAAE,QAAQ,CAAC,YAAY,CAAsB,GACxD,IAAI,GAAG,YAAY,CAIrB;AAED,wBAAgB,cAAc,CAAC,YAAY,SAAS,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,EACrF,GAAG,EAAE,kBAAkB,CAAC,IAAI,GAAG,YAAY,CAAC,EAC5C,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,GACnC,IAAI,CA2BN"}
package/dist/host.js CHANGED
@@ -1,33 +1,35 @@
1
- import { createEntity } from './entity';
1
+ import { allocateEntity, finishEntity } from './entity';
2
2
  export function createHost(capabilities = {}) {
3
- return createEntity({
4
- accessibility: {},
5
- app: {},
6
- clipboard: {},
7
- connectivity: {},
8
- dialog: {},
9
- graphics: {},
10
- input: {},
11
- ipc: {},
12
- media: {},
13
- menu: {},
14
- midi: {},
15
- net: {},
16
- notification: {},
17
- power: {},
18
- protocol: {},
19
- screen: {},
20
- share: {},
21
- shell: {},
22
- shortcut: {},
23
- storage: {},
24
- system: {},
25
- text: {},
26
- tray: {},
27
- ui: {},
28
- updater: {},
29
- window: {},
30
- ...capabilities,
31
- });
3
+ const out = allocateEntity();
4
+ initializeHost(out, capabilities);
5
+ return finishEntity(out);
6
+ }
7
+ export function initializeHost(out, capabilities) {
8
+ out.accessibility = (capabilities.accessibility ?? {});
9
+ out.app = (capabilities.app ?? {});
10
+ out.clipboard = (capabilities.clipboard ?? {});
11
+ out.connectivity = (capabilities.connectivity ?? {});
12
+ out.dialog = (capabilities.dialog ?? {});
13
+ out.graphics = (capabilities.graphics ?? {});
14
+ out.input = (capabilities.input ?? {});
15
+ out.ipc = (capabilities.ipc ?? {});
16
+ out.media = (capabilities.media ?? {});
17
+ out.menu = (capabilities.menu ?? {});
18
+ out.midi = (capabilities.midi ?? {});
19
+ out.net = (capabilities.net ?? {});
20
+ out.notification = (capabilities.notification ?? {});
21
+ out.power = (capabilities.power ?? {});
22
+ out.protocol = (capabilities.protocol ?? {});
23
+ out.screen = (capabilities.screen ?? {});
24
+ out.share = (capabilities.share ?? {});
25
+ out.shell = (capabilities.shell ?? {});
26
+ out.shortcut = (capabilities.shortcut ?? {});
27
+ out.storage = (capabilities.storage ?? {});
28
+ out.system = (capabilities.system ?? {});
29
+ out.text = (capabilities.text ?? {});
30
+ out.tray = (capabilities.tray ?? {});
31
+ out.ui = (capabilities.ui ?? {});
32
+ out.updater = (capabilities.updater ?? {});
33
+ out.window = (capabilities.window ?? {});
32
34
  }
33
35
  //# sourceMappingURL=host.js.map
package/dist/host.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,UAAU,UAAU,CACxB,eAAuC,EAAkB;IAEzD,OAAO,YAAY,CAAC;QAClB,aAAa,EAAE,EAAE;QACjB,GAAG,EAAE,EAAE;QACP,SAAS,EAAE,EAAE;QACb,YAAY,EAAE,EAAE;QAChB,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,EAAE;QACT,GAAG,EAAE,EAAE;QACP,KAAK,EAAE,EAAE;QACT,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;QACP,YAAY,EAAE,EAAE;QAChB,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,KAAK,EAAE,EAAE;QACT,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE;QACR,EAAE,EAAE,EAAE;QACN,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,EAAE;QACV,GAAG,YAAY;KAChB,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/entity",
3
- "version": "0.5.1-next.815.cc08b93",
3
+ "version": "0.5.1-next.903.f434bc2",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/types": "0.5.1-next.815.cc08b93"
41
+ "@flighthq/types": "0.5.1-next.903.f434bc2"
42
42
  },
43
43
  "devDependencies": {
44
44
  "typescript": "^5.3.0"
@@ -1,3 +1,4 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
3
 
3
4
  import {
@@ -7,26 +8,30 @@ import {
7
8
  getEntityBindingAs,
8
9
  hasEntityBinding,
9
10
  } from './binding';
10
- import { createEntity } from './entity';
11
+ import { allocateEntity, finishEntity } from './entity';
11
12
  import { createEntityRuntime, getEntityRuntime } from './runtime';
12
13
 
14
+ function createTestEntity(): Entity {
15
+ return finishEntity(allocateEntity<Entity>());
16
+ }
17
+
13
18
  describe('attachEntityBinding', () => {
14
19
  it('creates a runtime object if none is present', () => {
15
- const entity = createEntity();
20
+ const entity = createTestEntity();
16
21
  expect(getEntityRuntime(entity)).toBeUndefined();
17
22
  attachEntityBinding(entity, {});
18
23
  expect(getEntityRuntime(entity)).not.toBeUndefined();
19
24
  });
20
25
 
21
26
  it('assigns to the binding slot', () => {
22
- const entity = createEntity();
27
+ const entity = createTestEntity();
23
28
  const binding = {};
24
29
  attachEntityBinding(entity, binding);
25
30
  expect(getEntityRuntime(entity).binding).toStrictEqual(binding);
26
31
  });
27
32
 
28
33
  it('preserves an existing runtime while assigning its binding', () => {
29
- const entity = createEntity();
34
+ const entity = createTestEntity();
30
35
  const runtime = createEntityRuntime();
31
36
  const binding = {};
32
37
  entity[EntityRuntimeKey] = runtime;
@@ -40,7 +45,7 @@ describe('attachEntityBinding', () => {
40
45
 
41
46
  describe('detachEntityBinding', () => {
42
47
  it('clears the binding while preserving the runtime', () => {
43
- const entity = createEntity();
48
+ const entity = createTestEntity();
44
49
  const runtime = createEntityRuntime();
45
50
  runtime.binding = {};
46
51
  entity[EntityRuntimeKey] = runtime;
@@ -52,7 +57,7 @@ describe('detachEntityBinding', () => {
52
57
  });
53
58
 
54
59
  it('does not allocate a runtime when no binding exists', () => {
55
- const entity = createEntity();
60
+ const entity = createTestEntity();
56
61
 
57
62
  detachEntityBinding(entity);
58
63
 
@@ -62,18 +67,18 @@ describe('detachEntityBinding', () => {
62
67
 
63
68
  describe('getEntityBinding', () => {
64
69
  it('returns null if the entity has no runtime', () => {
65
- const entity = createEntity();
70
+ const entity = createTestEntity();
66
71
  expect(getEntityBinding(entity)).toBeNull();
67
72
  });
68
73
 
69
74
  it('returns null if the binding slot is empty', () => {
70
- const entity = createEntity();
75
+ const entity = createTestEntity();
71
76
  entity[EntityRuntimeKey] = createEntityRuntime();
72
77
  expect(getEntityBinding(entity)).toBeNull();
73
78
  });
74
79
 
75
80
  it('returns the binding slot if set', () => {
76
- const entity = createEntity();
81
+ const entity = createTestEntity();
77
82
  const runtime = createEntityRuntime();
78
83
  runtime.binding = {};
79
84
  entity[EntityRuntimeKey] = runtime;
@@ -81,14 +86,14 @@ describe('getEntityBinding', () => {
81
86
  });
82
87
 
83
88
  it('accepts a readonly entity', () => {
84
- const entity: Readonly<ReturnType<typeof createEntity>> = createEntity();
89
+ const entity: Readonly<Entity> = createTestEntity();
85
90
  expect(getEntityBinding(entity)).toBeNull();
86
91
  });
87
92
  });
88
93
 
89
94
  describe('getEntityBindingAs', () => {
90
95
  it('returns the binding with the caller-owned type', () => {
91
- const entity = createEntity();
96
+ const entity = createTestEntity();
92
97
  const binding = { name: 'wrapper' };
93
98
  attachEntityBinding(entity, binding);
94
99
 
@@ -99,25 +104,25 @@ describe('getEntityBindingAs', () => {
99
104
  });
100
105
 
101
106
  it('returns null if no binding exists', () => {
102
- const entity: Readonly<ReturnType<typeof createEntity>> = createEntity();
107
+ const entity: Readonly<Entity> = createTestEntity();
103
108
  expect(getEntityBindingAs<{ name: string }>(entity)).toBeNull();
104
109
  });
105
110
  });
106
111
 
107
112
  describe('hasEntityBinding', () => {
108
113
  it('returns false if the entity has no runtime', () => {
109
- const entity: Readonly<ReturnType<typeof createEntity>> = createEntity();
114
+ const entity: Readonly<Entity> = createTestEntity();
110
115
  expect(hasEntityBinding(entity)).toBe(false);
111
116
  });
112
117
 
113
118
  it('returns false if the binding slot is empty', () => {
114
- const entity = createEntity();
119
+ const entity = createTestEntity();
115
120
  entity[EntityRuntimeKey] = createEntityRuntime();
116
121
  expect(hasEntityBinding(entity)).toBe(false);
117
122
  });
118
123
 
119
124
  it('returns true if a binding exists', () => {
120
- const entity = createEntity();
125
+ const entity = createTestEntity();
121
126
  attachEntityBinding(entity, {});
122
127
  expect(hasEntityBinding(entity)).toBe(true);
123
128
  });
package/src/clone.test.ts CHANGED
@@ -1,20 +1,27 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
3
 
3
4
  import { attachEntityBinding } from './binding';
4
5
  import { cloneEntity, stripEntityRuntime } from './clone';
5
- import { createEntity } from './entity';
6
+ import { allocateEntity, finishEntity } from './entity';
6
7
  import { hasEntityRuntime } from './runtime';
7
8
 
9
+ function createTestEntity(fields?: Record<string, unknown>): Entity & Record<string, unknown> {
10
+ const out = allocateEntity<Entity>();
11
+ if (fields) Object.assign(out, fields);
12
+ return finishEntity(out) as Entity & Record<string, unknown>;
13
+ }
14
+
8
15
  describe('cloneEntity', () => {
9
16
  it('returns a new entity with the same public data fields', () => {
10
- const source = createEntity({ x: 1, y: 2 });
17
+ const source = createTestEntity({ x: 1, y: 2 });
11
18
  const clone = cloneEntity(source);
12
19
  expect(clone.x).toBe(1);
13
20
  expect(clone.y).toBe(2);
14
21
  });
15
22
 
16
23
  it('resets the runtime slot to undefined on the clone', () => {
17
- const source = createEntity();
24
+ const source = createTestEntity();
18
25
  attachEntityBinding(source, {});
19
26
  expect(hasEntityRuntime(source)).toBe(true);
20
27
  const clone = cloneEntity(source);
@@ -22,20 +29,20 @@ describe('cloneEntity', () => {
22
29
  });
23
30
 
24
31
  it('does not share the runtime between source and clone', () => {
25
- const source = createEntity();
32
+ const source = createTestEntity();
26
33
  const clone = cloneEntity(source);
27
34
  expect(clone[EntityRuntimeKey]).toBeUndefined();
28
35
  expect(clone).not.toBe(source);
29
36
  });
30
37
 
31
38
  it('returns a new object reference', () => {
32
- const source = createEntity();
39
+ const source = createTestEntity();
33
40
  const clone = cloneEntity(source);
34
41
  expect(clone).not.toBe(source);
35
42
  });
36
43
 
37
44
  it('clone of a bound entity yields an unbound clone', () => {
38
- const source = createEntity({ name: 'test' });
45
+ const source = createTestEntity({ name: 'test' });
39
46
  attachEntityBinding(source, { hostRef: 42 });
40
47
  const clone = cloneEntity(source);
41
48
  expect(hasEntityRuntime(clone)).toBe(false);
@@ -45,38 +52,40 @@ describe('cloneEntity', () => {
45
52
 
46
53
  describe('stripEntityRuntime', () => {
47
54
  it('removes the EntityRuntimeKey slot', () => {
48
- const entity = createEntity({ x: 10 });
55
+ const entity = createTestEntity({ x: 10 });
49
56
  const stripped = stripEntityRuntime(entity);
50
57
  expect((stripped as Record<PropertyKey, unknown>)[EntityRuntimeKey]).toBeUndefined();
51
58
  });
52
59
 
53
60
  it('retains the public data fields', () => {
54
- const entity = createEntity({ x: 10, y: 20 });
61
+ const entity = createTestEntity({ x: 10, y: 20 });
55
62
  const stripped = stripEntityRuntime(entity);
56
63
  expect(stripped.x).toBe(10);
57
64
  expect(stripped.y).toBe(20);
58
65
  });
59
66
 
60
67
  it('does not mutate the source entity', () => {
61
- const entity = createEntity({ x: 10 });
68
+ const entity = createTestEntity({ x: 10 });
62
69
  stripEntityRuntime(entity);
63
70
  expect(entity[EntityRuntimeKey]).toBeUndefined();
64
71
  });
65
72
 
66
73
  it('strips bound entity — binding is not in the output', () => {
67
- const entity = createEntity({ label: 'hello' });
74
+ const entity = createTestEntity({ label: 'hello' });
68
75
  attachEntityBinding(entity, { nativeRef: true });
69
76
  const stripped = stripEntityRuntime(entity);
70
77
  expect((stripped as Record<PropertyKey, unknown>)[EntityRuntimeKey]).toBeUndefined();
71
78
  expect(stripped.label).toBe('hello');
72
79
  });
73
80
 
74
- it('round-trips: stripEntityRuntime then createEntity yields a valid unbound entity', () => {
75
- const original = createEntity({ value: 99 });
81
+ it('round-trips: stripEntityRuntime then allocateEntity yields a valid unbound entity', () => {
82
+ const original = createTestEntity({ value: 99 });
76
83
  attachEntityBinding(original, {});
77
84
  const stripped = stripEntityRuntime(original);
78
- const restored = createEntity(stripped);
79
- expect(restored.value).toBe(99);
85
+ const out = allocateEntity<Entity>();
86
+ Object.assign(out, stripped);
87
+ const restored = finishEntity(out);
88
+ expect((restored as unknown as Record<string, unknown>).value).toBe(99);
80
89
  expect(hasEntityRuntime(restored)).toBe(false);
81
90
  });
82
91
  });
@@ -1,11 +1,16 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import type { EntityRuntimeWriteSlot } from '@flighthq/types/contract';
2
3
  import { EntityRuntimeKey } from '@flighthq/types/contract';
3
4
 
4
5
  import { disableEntityRuntimeGuards, enableEntityRuntimeGuards } from './enableEntityRuntimeGuards';
5
- import { createEntity } from './entity';
6
+ import { allocateEntity, finishEntity } from './entity';
6
7
  import { areEntityRuntimeGuardsEnabled, createGuardedEntity, createGuardedEntityRuntime } from './guards';
7
8
  import { createEntityRuntime } from './runtime';
8
9
 
10
+ function createTestEntity(): Entity {
11
+ return finishEntity(allocateEntity<Entity>());
12
+ }
13
+
9
14
  // Every case runs the write under a reporter that records the slot, so what is asserted is what the
10
15
  // caller's reporter actually received — not that some sink somewhere was touched.
11
16
  function recordSlots(write: () => void): readonly EntityRuntimeWriteSlot[] {
@@ -24,7 +29,7 @@ describe('disableEntityRuntimeGuards', () => {
24
29
  const slots: EntityRuntimeWriteSlot[] = [];
25
30
  enableEntityRuntimeGuards((slot) => slots.push(slot));
26
31
  disableEntityRuntimeGuards();
27
- createGuardedEntity(createEntity())[EntityRuntimeKey] = undefined;
32
+ createGuardedEntity(createTestEntity())[EntityRuntimeKey] = undefined;
28
33
  expect(slots).toEqual([]);
29
34
  expect(areEntityRuntimeGuardsEnabled()).toBe(false);
30
35
  });
@@ -32,7 +37,7 @@ describe('disableEntityRuntimeGuards', () => {
32
37
 
33
38
  describe('enableEntityRuntimeGuards', () => {
34
39
  it('REPORTS a direct runtime-slot write to the caller-supplied reporter', () => {
35
- expect(recordSlots(() => (createGuardedEntity(createEntity())[EntityRuntimeKey] = undefined))).toEqual([
40
+ expect(recordSlots(() => (createGuardedEntity(createTestEntity())[EntityRuntimeKey] = undefined))).toEqual([
36
41
  'runtime-slot',
37
42
  ]);
38
43
  });
@@ -45,7 +50,7 @@ describe('enableEntityRuntimeGuards', () => {
45
50
 
46
51
  it('stays SILENT without the guard — the production default', () => {
47
52
  const slots: EntityRuntimeWriteSlot[] = [];
48
- createGuardedEntity(createEntity())[EntityRuntimeKey] = undefined;
53
+ createGuardedEntity(createTestEntity())[EntityRuntimeKey] = undefined;
49
54
  expect(slots).toEqual([]);
50
55
  expect(areEntityRuntimeGuardsEnabled()).toBe(false);
51
56
  });
@@ -1,15 +1,20 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
3
 
3
- import { createEntity } from './entity';
4
+ import { allocateEntity, finishEntity } from './entity';
4
5
 
5
- describe('createEntity', () => {
6
- it('returns an object', () => {
7
- const entity = createEntity();
8
- expect(entity).not.toBeNull();
6
+ describe('allocateEntity', () => {
7
+ it('returns an object with an undefined runtime', () => {
8
+ const out = allocateEntity<Entity>();
9
+ expect(out).not.toBeNull();
10
+ expect(out[EntityRuntimeKey]).toBeUndefined();
9
11
  });
12
+ });
10
13
 
11
- it('has an undefined runtime', () => {
12
- const entity = createEntity();
13
- expect(entity[EntityRuntimeKey]).toBeUndefined();
14
+ describe('finishEntity', () => {
15
+ it('returns the same object', () => {
16
+ const out = allocateEntity<Entity>();
17
+ const entity = finishEntity(out);
18
+ expect(entity).toBe(out);
14
19
  });
15
20
  });
@@ -1,38 +1,43 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
3
 
3
- import { createEntity } from './entity';
4
+ import { allocateEntity, finishEntity } from './entity';
4
5
  import { getEntityUid, setEntityUid } from './entityUid';
5
6
  import { createEntityRuntime } from './runtime';
6
7
 
8
+ function createTestEntity(): Entity {
9
+ return finishEntity(allocateEntity<Entity>());
10
+ }
11
+
7
12
  describe('getEntityUid', () => {
8
13
  it('has no uid property on an untouched runtime before any access', () => {
9
- const entity = createEntity();
14
+ const entity = createTestEntity();
10
15
  entity[EntityRuntimeKey] = createEntityRuntime();
11
16
  expect('uid' in entity[EntityRuntimeKey]!).toBe(false);
12
17
  });
13
18
 
14
19
  it('lazily generates a uid on first access', () => {
15
- const entity = createEntity();
20
+ const entity = createTestEntity();
16
21
  const uid = getEntityUid(entity);
17
22
  expect(uid).toEqual(expect.any(String));
18
23
  expect(uid.length).toBeGreaterThan(0);
19
24
  });
20
25
 
21
26
  it('returns the same uid on repeated access', () => {
22
- const entity = createEntity();
27
+ const entity = createTestEntity();
23
28
  const first = getEntityUid(entity);
24
29
  const second = getEntityUid(entity);
25
30
  expect(second).toBe(first);
26
31
  });
27
32
 
28
33
  it('generates distinct uids for different entities', () => {
29
- const a = createEntity();
30
- const b = createEntity();
34
+ const a = createTestEntity();
35
+ const b = createTestEntity();
31
36
  expect(getEntityUid(a)).not.toBe(getEntityUid(b));
32
37
  });
33
38
 
34
39
  it('creates the runtime if the entity has none', () => {
35
- const entity = createEntity();
40
+ const entity = createTestEntity();
36
41
  expect(entity[EntityRuntimeKey]).toBeUndefined();
37
42
  getEntityUid(entity);
38
43
  expect(entity[EntityRuntimeKey]).toBeDefined();
@@ -41,13 +46,13 @@ describe('getEntityUid', () => {
41
46
 
42
47
  describe('setEntityUid', () => {
43
48
  it('sets a stable id before any get', () => {
44
- const entity = createEntity();
49
+ const entity = createTestEntity();
45
50
  setEntityUid(entity, 'my-stable-id');
46
51
  expect(getEntityUid(entity)).toBe('my-stable-id');
47
52
  });
48
53
 
49
54
  it('replaces a previously generated uid', () => {
50
- const entity = createEntity();
55
+ const entity = createTestEntity();
51
56
  const generated = getEntityUid(entity);
52
57
  setEntityUid(entity, 'override');
53
58
  expect(getEntityUid(entity)).toBe('override');
@@ -55,7 +60,7 @@ describe('setEntityUid', () => {
55
60
  });
56
61
 
57
62
  it('creates the runtime if the entity has none', () => {
58
- const entity = createEntity();
63
+ const entity = createTestEntity();
59
64
  expect(entity[EntityRuntimeKey]).toBeUndefined();
60
65
  setEntityUid(entity, 'pre-bind');
61
66
  expect(entity[EntityRuntimeKey]).toBeDefined();
@@ -1,7 +1,8 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import { EntityRuntimeKey } from '@flighthq/types/contract';
2
3
  import type { EntityRuntimeWriteSlot } from '@flighthq/types/contract';
3
4
 
4
- import { createEntity } from './entity';
5
+ import { allocateEntity, finishEntity } from './entity';
5
6
  import {
6
7
  areEntityRuntimeGuardsEnabled,
7
8
  createGuardedEntity,
@@ -11,6 +12,12 @@ import {
11
12
  } from './guards';
12
13
  import { createEntityRuntime } from './runtime';
13
14
 
15
+ function createTestEntity(fields?: Record<string, unknown>): Entity & Record<string, unknown> {
16
+ const out = allocateEntity<Entity>();
17
+ if (fields) Object.assign(out, fields);
18
+ return finishEntity(out) as Entity & Record<string, unknown>;
19
+ }
20
+
14
21
  describe('areEntityRuntimeGuardsEnabled', () => {
15
22
  it('returns false before guard mode is switched on', () => {
16
23
  // Vitest isolates modules per file, so this starts false in a fresh module import.
@@ -20,7 +27,7 @@ describe('areEntityRuntimeGuardsEnabled', () => {
20
27
 
21
28
  describe('createGuardedEntity', () => {
22
29
  it('returns the entity unchanged when guards are not enabled', () => {
23
- const entity = createEntity({ x: 1 });
30
+ const entity = createTestEntity({ x: 1 });
24
31
  expect(createGuardedEntity(entity)).toBe(entity);
25
32
  });
26
33
  });
@@ -37,7 +44,7 @@ describe('setEntityRuntimeGuardMode', () => {
37
44
  setEntityRuntimeGuardMode(true);
38
45
  try {
39
46
  expect(areEntityRuntimeGuardsEnabled()).toBe(true);
40
- const entity = createEntity({ x: 1 });
47
+ const entity = createTestEntity({ x: 1 });
41
48
  expect(createGuardedEntity(entity).x).toBe(1);
42
49
  expect(createGuardedEntityRuntime(createEntityRuntime()).binding).toBeNull();
43
50
  } finally {
@@ -62,7 +69,7 @@ describe('setEntityRuntimeGuardMode', () => {
62
69
  });
63
70
 
64
71
  it('returns the original values when Proxy disappears after guards are enabled', () => {
65
- const entity = createEntity({ x: 1 });
72
+ const entity = createTestEntity({ x: 1 });
66
73
  const runtime = createEntityRuntime();
67
74
  const originalProxy = globalThis.Proxy;
68
75
  let guardedEntity: typeof entity;
@@ -88,7 +95,7 @@ describe('setEntityRuntimeWriteGuard', () => {
88
95
  setEntityRuntimeGuardMode(true);
89
96
  setEntityRuntimeWriteGuard((slot) => slots.push(slot));
90
97
  try {
91
- const guardedEntity = createGuardedEntity(createEntity());
98
+ const guardedEntity = createGuardedEntity(createTestEntity());
92
99
  guardedEntity[EntityRuntimeKey] = undefined;
93
100
  const guardedRuntime = createGuardedEntityRuntime(createEntityRuntime());
94
101
  guardedRuntime.binding = null;
@@ -107,7 +114,7 @@ describe('setEntityRuntimeWriteGuard', () => {
107
114
  setEntityRuntimeWriteGuard((slot) => slots.push(slot));
108
115
  setEntityRuntimeWriteGuard(null);
109
116
  try {
110
- createGuardedEntity(createEntity())[EntityRuntimeKey] = undefined;
117
+ createGuardedEntity(createTestEntity())[EntityRuntimeKey] = undefined;
111
118
  expect(slots).toEqual([]);
112
119
  } finally {
113
120
  setEntityRuntimeGuardMode(false);
@@ -119,7 +126,7 @@ describe('setEntityRuntimeWriteGuard', () => {
119
126
  setEntityRuntimeGuardMode(true);
120
127
  setEntityRuntimeWriteGuard((slot) => slots.push(slot));
121
128
  try {
122
- const guardedEntity = createGuardedEntity(createEntity({ x: 1 }));
129
+ const guardedEntity = createGuardedEntity(createTestEntity({ x: 1 }));
123
130
  guardedEntity.x = 2;
124
131
  const guardedRuntime = createGuardedEntityRuntime(createEntityRuntime()) as ReturnType<
125
132
  typeof createEntityRuntime
@@ -138,7 +145,7 @@ describe('setEntityRuntimeWriteGuard', () => {
138
145
  const slots: EntityRuntimeWriteSlot[] = [];
139
146
  setEntityRuntimeGuardMode(true);
140
147
  setEntityRuntimeWriteGuard((slot) => slots.push(slot));
141
- const guardedEntity = createGuardedEntity(createEntity());
148
+ const guardedEntity = createGuardedEntity(createTestEntity());
142
149
  const guardedRuntime = createGuardedEntityRuntime(createEntityRuntime());
143
150
  setEntityRuntimeGuardMode(false);
144
151
  try {
@@ -1,10 +1,15 @@
1
+ import type { Entity } from '@flighthq/types/contract';
1
2
  import type { EntityRuntime } from '@flighthq/types/contract';
2
3
  import { EntityRuntimeKey } from '@flighthq/types/contract';
3
4
 
4
5
  import { attachEntityBinding } from './binding';
5
- import { createEntity } from './entity';
6
+ import { allocateEntity, finishEntity } from './entity';
6
7
  import { createEntityRuntime, getEntityRuntime, hasEntityRuntime } from './runtime';
7
8
 
9
+ function createTestEntity(): Entity {
10
+ return finishEntity(allocateEntity<Entity>());
11
+ }
12
+
8
13
  describe('createEntityRuntime', () => {
9
14
  it('returns an object', () => {
10
15
  const runtime = createEntityRuntime();
@@ -19,7 +24,7 @@ describe('createEntityRuntime', () => {
19
24
 
20
25
  describe('getEntityRuntime', () => {
21
26
  it('returns the runtime object', () => {
22
- const entity = createEntity();
27
+ const entity = createTestEntity();
23
28
  expect(getEntityRuntime(entity)).toBeUndefined();
24
29
  const runtime = {} as EntityRuntime;
25
30
  entity[EntityRuntimeKey] = runtime;
@@ -29,12 +34,12 @@ describe('getEntityRuntime', () => {
29
34
 
30
35
  describe('hasEntityRuntime', () => {
31
36
  it('returns false for a fresh entity', () => {
32
- const entity = createEntity();
37
+ const entity = createTestEntity();
33
38
  expect(hasEntityRuntime(entity)).toBe(false);
34
39
  });
35
40
 
36
41
  it('returns true after a binding is attached', () => {
37
- const entity = createEntity();
42
+ const entity = createTestEntity();
38
43
  attachEntityBinding(entity, {});
39
44
  expect(hasEntityRuntime(entity)).toBe(true);
40
45
  });