@adobe/data 0.8.6 → 0.9.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.
Files changed (93) hide show
  1. package/dist/ecs/database/calculate-system-order.d.ts +18 -0
  2. package/dist/ecs/database/calculate-system-order.js +113 -0
  3. package/dist/ecs/database/calculate-system-order.js.map +1 -0
  4. package/dist/ecs/database/calculate-system-order.test.d.ts +1 -0
  5. package/dist/ecs/database/calculate-system-order.test.js +168 -0
  6. package/dist/ecs/database/calculate-system-order.test.js.map +1 -0
  7. package/dist/ecs/database/create-plugin.d.ts +67 -0
  8. package/dist/ecs/database/create-plugin.js +47 -0
  9. package/dist/ecs/database/create-plugin.js.map +1 -0
  10. package/dist/ecs/database/create-plugin.test.d.ts +1 -0
  11. package/dist/ecs/database/create-plugin.test.js +435 -0
  12. package/dist/ecs/database/create-plugin.test.js.map +1 -0
  13. package/dist/ecs/database/database-schema/create-database-schema.d.ts +3 -3
  14. package/dist/ecs/database/database-schema/database-schema.d.ts +4 -3
  15. package/dist/ecs/database/database.d.ts +56 -18
  16. package/dist/ecs/database/database.js +42 -0
  17. package/dist/ecs/database/database.js.map +1 -1
  18. package/dist/ecs/database/database.test.d.ts +1 -0
  19. package/dist/ecs/database/database.test.js +200 -0
  20. package/dist/ecs/database/database.test.js.map +1 -0
  21. package/dist/ecs/database/observe-select-entities.test.js +3 -3
  22. package/dist/ecs/database/observe-select-entities.test.js.map +1 -1
  23. package/dist/ecs/database/observed/create-observed-database.js +6 -1
  24. package/dist/ecs/database/observed/create-observed-database.js.map +1 -1
  25. package/dist/ecs/database/observed/create-observed-database.test.js +105 -49
  26. package/dist/ecs/database/observed/create-observed-database.test.js.map +1 -1
  27. package/dist/ecs/database/observed/observed-database.d.ts +3 -0
  28. package/dist/ecs/database/public/create-database-from-schema.test.d.ts +1 -0
  29. package/dist/ecs/database/public/create-database-from-schema.test.js +153 -0
  30. package/dist/ecs/database/public/create-database-from-schema.test.js.map +1 -0
  31. package/dist/ecs/database/public/create-database.d.ts +17 -2
  32. package/dist/ecs/database/public/create-database.js +283 -79
  33. package/dist/ecs/database/public/create-database.js.map +1 -1
  34. package/dist/ecs/database/public/create-database.test.js +178 -47
  35. package/dist/ecs/database/public/create-database.test.js.map +1 -1
  36. package/dist/ecs/database/reconciling/create-reconciling-database.d.ts +2 -2
  37. package/dist/ecs/database/reconciling/create-reconciling-database.js +7 -2
  38. package/dist/ecs/database/reconciling/create-reconciling-database.js.map +1 -1
  39. package/dist/ecs/database/reconciling/create-reconciling-database.test.js +18 -9
  40. package/dist/ecs/database/reconciling/create-reconciling-database.test.js.map +1 -1
  41. package/dist/ecs/database/reconciling/reconciling-database.d.ts +5 -3
  42. package/dist/ecs/database/transactional-store/coalesce-actions.d.ts +16 -0
  43. package/dist/ecs/database/transactional-store/coalesce-actions.js +140 -0
  44. package/dist/ecs/database/transactional-store/coalesce-actions.js.map +1 -0
  45. package/dist/ecs/database/transactional-store/coalesce-actions.test.d.ts +1 -0
  46. package/dist/ecs/database/transactional-store/coalesce-actions.test.js +433 -0
  47. package/dist/ecs/database/transactional-store/coalesce-actions.test.js.map +1 -0
  48. package/dist/ecs/database/transactional-store/create-transactional-store.js +18 -2
  49. package/dist/ecs/database/transactional-store/create-transactional-store.js.map +1 -1
  50. package/dist/ecs/database/transactional-store/create-transactional-store.test.js +13 -3
  51. package/dist/ecs/database/transactional-store/create-transactional-store.test.js.map +1 -1
  52. package/dist/ecs/database/transactional-store/transactional-store.d.ts +2 -0
  53. package/dist/ecs/database/type-inference-example.d.ts +1 -0
  54. package/dist/ecs/database/type-inference-example.js +2 -0
  55. package/dist/ecs/database/type-inference-example.js.map +1 -0
  56. package/dist/ecs/plugins/index.d.ts +1 -0
  57. package/dist/ecs/plugins/index.js +23 -0
  58. package/dist/ecs/plugins/index.js.map +1 -0
  59. package/dist/ecs/plugins/scheduler/index.d.ts +1 -0
  60. package/dist/ecs/plugins/scheduler/index.js +23 -0
  61. package/dist/ecs/plugins/scheduler/index.js.map +1 -0
  62. package/dist/ecs/plugins/scheduler/scheduler.d.ts +8 -0
  63. package/dist/ecs/plugins/scheduler/scheduler.js +52 -0
  64. package/dist/ecs/plugins/scheduler/scheduler.js.map +1 -0
  65. package/dist/ecs/store/action-functions.d.ts +21 -0
  66. package/dist/ecs/store/action-functions.js +2 -0
  67. package/dist/ecs/store/action-functions.js.map +1 -0
  68. package/dist/ecs/store/create-store-schema-test.js +70 -8
  69. package/dist/ecs/store/create-store-schema-test.js.map +1 -1
  70. package/dist/ecs/store/public/create-store.js +9 -8
  71. package/dist/ecs/store/public/create-store.js.map +1 -1
  72. package/dist/ecs/store/public/create-store.test.js +5 -0
  73. package/dist/ecs/store/public/create-store.test.js.map +1 -1
  74. package/dist/ecs/store/store.d.ts +46 -13
  75. package/dist/ecs/store/store.js +35 -2
  76. package/dist/ecs/store/store.js.map +1 -1
  77. package/dist/ecs/store/store.test.d.ts +1 -0
  78. package/dist/ecs/store/store.test.js +211 -0
  79. package/dist/ecs/store/store.test.js.map +1 -0
  80. package/dist/ecs/undo-redo-service/create-undo-redo-service.js +1 -1
  81. package/dist/ecs/undo-redo-service/create-undo-redo-service.js.map +1 -1
  82. package/dist/lit/hooks/use-drag-transaction.d.ts +1 -1
  83. package/dist/samples/todo/services/main-service/todo-main-service.d.ts +1 -1
  84. package/dist/samples/todo/services/state-service/create-todo-database.d.ts +3 -3
  85. package/dist/samples/todo/services/state-service/create-todo-database.js +2 -2
  86. package/dist/samples/todo/services/state-service/create-todo-database.js.map +1 -1
  87. package/dist/samples/todo/services/state-service/create-todo-store.d.ts +1 -1
  88. package/dist/samples/todo/services/state-service/transactions/toggle-complete.js +1 -1
  89. package/dist/samples/todo/services/state-service/transactions/toggle-complete.js.map +1 -1
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/dist/types/types.d.ts +2 -0
  92. package/dist/types/types.js.map +1 -1
  93. package/package.json +1 -1
@@ -0,0 +1,18 @@
1
+ type SystemDeclaration = {
2
+ readonly create: (...args: any[]) => any;
3
+ readonly schedule?: {
4
+ readonly before?: readonly string[];
5
+ readonly after?: readonly string[];
6
+ };
7
+ };
8
+ /**
9
+ * Calculates the execution order for systems based on their scheduling constraints.
10
+ * Returns a 2D array where each sub-array represents a tier of systems that can
11
+ * execute in parallel.
12
+ *
13
+ * @param systems - Object mapping system names to their declarations
14
+ * @returns Array of tiers, where each tier is an array of system names that can run in parallel
15
+ * @throws Error if circular dependencies are detected
16
+ */
17
+ export declare const calculateSystemOrder: <S extends string>(systems: { readonly [K in S]: SystemDeclaration; }) => S[][];
18
+ export {};
@@ -0,0 +1,113 @@
1
+ /*MIT License
2
+
3
+ © Copyright 2025 Adobe. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.*/
22
+ /**
23
+ * Calculates the execution order for systems based on their scheduling constraints.
24
+ * Returns a 2D array where each sub-array represents a tier of systems that can
25
+ * execute in parallel.
26
+ *
27
+ * @param systems - Object mapping system names to their declarations
28
+ * @returns Array of tiers, where each tier is an array of system names that can run in parallel
29
+ * @throws Error if circular dependencies are detected
30
+ */
31
+ export const calculateSystemOrder = (systems) => {
32
+ const systemNames = Object.keys(systems);
33
+ if (systemNames.length === 0) {
34
+ return [];
35
+ }
36
+ // Build dependency graph: dependsOn[system] = set of systems that must run before it
37
+ const dependsOn = new Map();
38
+ for (const name of systemNames) {
39
+ dependsOn.set(name, new Set());
40
+ }
41
+ // Process scheduling constraints
42
+ for (const name of systemNames) {
43
+ const system = systems[name];
44
+ const schedule = system.schedule;
45
+ if (schedule?.after) {
46
+ for (const dep of schedule.after) {
47
+ dependsOn.get(name).add(dep);
48
+ }
49
+ }
50
+ if (schedule?.before) {
51
+ for (const dependent of schedule.before) {
52
+ dependsOn.get(dependent).add(name);
53
+ }
54
+ }
55
+ }
56
+ // Topological sort with tier grouping
57
+ const tiers = [];
58
+ const processed = new Set();
59
+ const inProgress = new Set();
60
+ const detectCycle = (node, visited, stack) => {
61
+ if (stack.has(node)) {
62
+ return true;
63
+ }
64
+ if (visited.has(node)) {
65
+ return false;
66
+ }
67
+ visited.add(node);
68
+ stack.add(node);
69
+ const deps = dependsOn.get(node);
70
+ for (const dep of deps) {
71
+ if (detectCycle(dep, visited, stack)) {
72
+ return true;
73
+ }
74
+ }
75
+ stack.delete(node);
76
+ return false;
77
+ };
78
+ // Check for cycles
79
+ const visited = new Set();
80
+ const stack = new Set();
81
+ for (const name of systemNames) {
82
+ if (detectCycle(name, visited, stack)) {
83
+ throw new Error("Circular dependency detected in system scheduling");
84
+ }
85
+ }
86
+ // Build tiers
87
+ while (processed.size < systemNames.length) {
88
+ const currentTier = [];
89
+ for (const name of systemNames) {
90
+ if (processed.has(name)) {
91
+ continue;
92
+ }
93
+ // Check if all dependencies are processed
94
+ const deps = dependsOn.get(name);
95
+ const allDepsProcessed = Array.from(deps).every(dep => processed.has(dep));
96
+ if (allDepsProcessed) {
97
+ currentTier.push(name);
98
+ }
99
+ }
100
+ if (currentTier.length === 0) {
101
+ // Should never happen if cycle detection works
102
+ throw new Error("Unable to resolve system dependencies");
103
+ }
104
+ // Sort tier alphabetically for deterministic output
105
+ currentTier.sort();
106
+ tiers.push(currentTier);
107
+ for (const name of currentTier) {
108
+ processed.add(name);
109
+ }
110
+ }
111
+ return tiers;
112
+ };
113
+ //# sourceMappingURL=calculate-system-order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculate-system-order.js","sourceRoot":"","sources":["../../../src/ecs/database/calculate-system-order.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,168 @@
1
+ /*MIT License
2
+
3
+ © Copyright 2025 Adobe. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.*/
22
+ import { assert } from "riteway/vitest";
23
+ import { describe, test, expect } from "vitest";
24
+ import { calculateSystemOrder } from "./calculate-system-order.js";
25
+ describe("calculateSystemOrder", () => {
26
+ test("empty systems object", async () => {
27
+ const systems = {};
28
+ const actual = calculateSystemOrder(systems);
29
+ const expected = [];
30
+ await assert({
31
+ given: "empty systems object",
32
+ should: "return empty order array",
33
+ actual,
34
+ expected,
35
+ });
36
+ });
37
+ test("single system with no constraints", async () => {
38
+ const systems = {
39
+ renderSystem: { create: () => () => { } },
40
+ };
41
+ const actual = calculateSystemOrder(systems);
42
+ const expected = [["renderSystem"]];
43
+ await assert({
44
+ given: "single system with no constraints",
45
+ should: "return single tier with that system",
46
+ actual,
47
+ expected,
48
+ });
49
+ });
50
+ test("multiple systems with no constraints", async () => {
51
+ const systems = {
52
+ inputSystem: { create: () => () => { } },
53
+ physicsSystem: { create: () => () => { } },
54
+ renderSystem: { create: () => () => { } },
55
+ };
56
+ const actual = calculateSystemOrder(systems);
57
+ const expected = [["inputSystem", "physicsSystem", "renderSystem"]];
58
+ await assert({
59
+ given: "multiple systems with no constraints",
60
+ should: "return single tier with all systems in parallel",
61
+ actual,
62
+ expected,
63
+ });
64
+ });
65
+ test("render system scheduled after physics", async () => {
66
+ const systems = {
67
+ physicsSystem: { create: () => () => { } },
68
+ renderSystem: {
69
+ create: () => () => { },
70
+ schedule: { after: ["physicsSystem"] }
71
+ },
72
+ };
73
+ const actual = calculateSystemOrder(systems);
74
+ const expected = [["physicsSystem"], ["renderSystem"]];
75
+ await assert({
76
+ given: "render system scheduled after physics",
77
+ should: "return physics in first tier, render in second",
78
+ actual,
79
+ expected,
80
+ });
81
+ });
82
+ test("physics system scheduled before render", async () => {
83
+ const systems = {
84
+ physicsSystem: {
85
+ create: () => () => { },
86
+ schedule: { before: ["renderSystem"] }
87
+ },
88
+ renderSystem: { create: () => () => { } },
89
+ };
90
+ const actual = calculateSystemOrder(systems);
91
+ const expected = [["physicsSystem"], ["renderSystem"]];
92
+ await assert({
93
+ given: "physics system scheduled before render",
94
+ should: "return physics in first tier, render in second",
95
+ actual,
96
+ expected,
97
+ });
98
+ });
99
+ test("complex dependency graph with parallel systems", async () => {
100
+ const systems = {
101
+ inputSystem: { create: () => () => { } },
102
+ physicsSystem: {
103
+ create: () => () => { },
104
+ schedule: { after: ["inputSystem"] }
105
+ },
106
+ aiSystem: {
107
+ create: () => () => { },
108
+ schedule: { after: ["inputSystem"] }
109
+ },
110
+ renderSystem: {
111
+ create: () => () => { },
112
+ schedule: { after: ["physicsSystem", "aiSystem"] }
113
+ },
114
+ };
115
+ const actual = calculateSystemOrder(systems);
116
+ const expected = [
117
+ ["inputSystem"],
118
+ ["aiSystem", "physicsSystem"],
119
+ ["renderSystem"]
120
+ ];
121
+ await assert({
122
+ given: "complex dependency graph with parallel systems",
123
+ should: "return correct multi-tier execution order with alphabetical sorting within tiers",
124
+ actual,
125
+ expected,
126
+ });
127
+ });
128
+ test("greedy scheduling with mixed independent and dependent systems", async () => {
129
+ const systems = {
130
+ systemA: { create: () => () => { } }, // No dependencies
131
+ systemB: {
132
+ create: () => () => { },
133
+ schedule: { after: ["systemA"] } // Depends on A
134
+ },
135
+ systemC: { create: () => () => { } }, // Independent! Should run in tier 0
136
+ systemD: {
137
+ create: () => () => { },
138
+ schedule: { after: ["systemB"] } // Depends on B
139
+ },
140
+ };
141
+ const actual = calculateSystemOrder(systems);
142
+ const expected = [
143
+ ["systemA", "systemC"], // Both independent, run together ASAP
144
+ ["systemB"], // Runs after A
145
+ ["systemD"] // Runs after B
146
+ ];
147
+ await assert({
148
+ given: "mixed independent and dependent systems",
149
+ should: "schedule independent systems in earliest tier (greedy scheduling)",
150
+ actual,
151
+ expected,
152
+ });
153
+ });
154
+ test("circular dependency between systems", () => {
155
+ const systems = {
156
+ systemA: {
157
+ create: () => () => { },
158
+ schedule: { after: ["systemB"] }
159
+ },
160
+ systemB: {
161
+ create: () => () => { },
162
+ schedule: { after: ["systemA"] }
163
+ },
164
+ };
165
+ expect(() => calculateSystemOrder(systems)).toThrow("Circular dependency detected in system scheduling");
166
+ });
167
+ });
168
+ //# sourceMappingURL=calculate-system-order.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculate-system-order.test.js","sourceRoot":"","sources":["../../../src/ecs/database/calculate-system-order.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import type { Database } from "./database.js";
2
+ import type { ComponentSchemas } from "../component-schemas.js";
3
+ import type { ResourceSchemas } from "../resource-schemas.js";
4
+ import type { ArchetypeComponents } from "../store/archetype-components.js";
5
+ import type { ActionDeclarations, ToActionFunctions } from "../store/action-functions.js";
6
+ import type { FromSchemas } from "../../schema/index.js";
7
+ import type { StringKeyof, IntersectTuple } from "../../types/types.js";
8
+ import type { OptionalComponents } from "../optional-components.js";
9
+ type SystemFunction = () => void | Promise<void>;
10
+ type RemoveIndexSignature<T> = {
11
+ [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
12
+ };
13
+ type ExtractSystemNames<P> = P extends Database.Plugin<any, any, any, any, infer S> ? S : never;
14
+ type PluginDatabase<CS extends ComponentSchemas, RS extends ResourceSchemas, A extends ArchetypeComponents<StringKeyof<CS & OptionalComponents>>, TD extends ActionDeclarations<any, any, any>, S extends string> = Database<FromSchemas<RemoveIndexSignature<CS>>, FromSchemas<RemoveIndexSignature<RS>>, RemoveIndexSignature<{
15
+ readonly [K in keyof A as string extends K ? never : K]: A[K];
16
+ } & ArchetypeComponents<StringKeyof<FromSchemas<RemoveIndexSignature<CS>> & OptionalComponents>>>, ToActionFunctions<TD>, S>;
17
+ type MergeDependencies<D extends readonly Database.Plugin<any, any, any, any, any>[]> = {
18
+ components: {} & IntersectTuple<{
19
+ [K in keyof D]: D[K] extends Database.Plugin<infer C, any, any, any, any> ? (C extends undefined ? {} : C) : never;
20
+ }>;
21
+ resources: {} & IntersectTuple<{
22
+ [K in keyof D]: D[K] extends Database.Plugin<any, infer R, any, any, any> ? (R extends undefined ? {} : R) : never;
23
+ }>;
24
+ archetypes: {} & IntersectTuple<{
25
+ [K in keyof D]: D[K] extends Database.Plugin<any, any, infer A, any, any> ? (A extends undefined ? {} : A) : never;
26
+ }>;
27
+ transactions: {} & IntersectTuple<{
28
+ [K in keyof D]: D[K] extends Database.Plugin<any, any, any, infer TD, any> ? (TD extends undefined ? Record<never, never> : TD) : never;
29
+ }>;
30
+ systemNames: Extract<{
31
+ [K in keyof D]: ExtractSystemNames<D[K]>;
32
+ }[number], string>;
33
+ };
34
+ export declare function createPlugin<const CS extends ComponentSchemas, const RS extends ResourceSchemas, const A extends ArchetypeComponents<StringKeyof<CS & OptionalComponents>>, const TD extends ActionDeclarations<any, any, any>, const SYS extends {
35
+ readonly [K in string]: {
36
+ readonly create: (db: PluginDatabase<CS, RS, A, TD, string>) => SystemFunction;
37
+ readonly schedule?: {
38
+ readonly before?: readonly Extract<keyof SYS, string>[];
39
+ readonly after?: readonly Extract<keyof SYS, string>[];
40
+ };
41
+ };
42
+ }>(descriptor: {
43
+ components?: CS;
44
+ resources?: RS;
45
+ archetypes?: A;
46
+ transactions?: TD;
47
+ systems?: SYS;
48
+ }): Required<Database.Plugin<CS, RS, A, TD, StringKeyof<SYS>>>;
49
+ export declare function createPlugin<const D extends readonly any[], const CS extends ComponentSchemas, const RS extends ResourceSchemas, const A extends ArchetypeComponents<StringKeyof<CS & MergeDependencies<D>['components'] & OptionalComponents>>, const TD extends ActionDeclarations<any, any, any>, const SYS extends {
50
+ readonly [K in string]: {
51
+ readonly create: (db: PluginDatabase<CS & MergeDependencies<D>['components'], RS & MergeDependencies<D>['resources'], A, TD & MergeDependencies<D>['transactions'], MergeDependencies<D>['systemNames'] | string>) => SystemFunction;
52
+ readonly schedule?: {
53
+ readonly before?: readonly MergeDependencies<D>['systemNames'][];
54
+ readonly after?: readonly MergeDependencies<D>['systemNames'][];
55
+ };
56
+ };
57
+ }>(descriptor: {
58
+ components?: CS;
59
+ resources?: RS;
60
+ archetypes?: A;
61
+ transactions?: TD;
62
+ systems?: SYS;
63
+ }, dependencies: D): Database.Plugin.Intersect<[
64
+ ...D,
65
+ Database.Plugin<CS & MergeDependencies<D>['components'], RS, A, TD, StringKeyof<SYS>>
66
+ ]>;
67
+ export {};
@@ -0,0 +1,47 @@
1
+ /*MIT License
2
+
3
+ © Copyright 2025 Adobe. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.*/
22
+ // Implementation
23
+ export function createPlugin(descriptor, dependencies) {
24
+ const requireIdentity = new Set(['components', 'resources', 'archetypes']);
25
+ const merge = (base, next) => Object.fromEntries(keys.map(key => {
26
+ const baseObj = base[key] ?? {};
27
+ const nextObj = next[key] ?? {};
28
+ if (requireIdentity.has(key)) {
29
+ const merged = { ...baseObj };
30
+ for (const [k, v] of Object.entries(nextObj)) {
31
+ if (k in baseObj && baseObj[k] !== v) {
32
+ throw new Error(`Plugin merge conflict: ${key}.${k} must be identical (===) across plugins`);
33
+ }
34
+ merged[k] = v;
35
+ }
36
+ return [key, merged];
37
+ }
38
+ return [key, { ...baseObj, ...nextObj }];
39
+ }));
40
+ // Merge dependencies first
41
+ const mergedDeps = (dependencies ?? []).reduce(merge, emptyPlugin);
42
+ // Merge descriptor on top of dependencies
43
+ return merge(mergedDeps, descriptor);
44
+ }
45
+ const keys = ['components', 'resources', 'archetypes', 'transactions', 'systems'];
46
+ const emptyPlugin = { components: {}, resources: {}, archetypes: {}, transactions: {}, systems: {} };
47
+ //# sourceMappingURL=create-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-plugin.js","sourceRoot":"","sources":["../../../src/ecs/database/create-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;WAoBW;AA2HX,iBAAiB;AACjB,MAAM,UAAU,YAAY,CACxB,UAAe,EACf,YAAkB;IAElB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3E,MAAM,KAAK,GAAG,CAAC,IAAS,EAAE,IAAS,EAAE,EAAE,CACnC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAEhC,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnC,MAAM,IAAI,KAAK,CACX,0BAA0B,GAAG,IAAI,CAAC,yCAAyC,CAC9E,CAAC;gBACN,CAAC;gBACD,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACzB,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC,CAAC;IAER,2BAA2B;IAC3B,MAAM,UAAU,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAEnE,0CAA0C;IAC1C,OAAO,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACzC,CAAC;AACD,MAAM,IAAI,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,CAAU,CAAC;AAC3F,MAAM,WAAW,GAA2B,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ export {};