@vworlds/vecs 1.0.61 → 1.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,129 @@
1
+ var _a;
2
+ import { assertMemberType } from "./member_types.js";
3
+ const DECLARATIONS = Symbol("vecs.members");
4
+ const declarationsByClass = new WeakMap();
5
+ // Standard decorators store their declarations in `context.metadata`, which
6
+ // TypeScript and esbuild provide only when `Symbol.metadata` exists. Defining it
7
+ // here, before any decorated class can be evaluated, lets `world.component(C)`
8
+ // read them without constructing an instance.
9
+ (_a = Symbol).metadata ?? (_a.metadata = Symbol.for("Symbol.metadata"));
10
+ /**
11
+ * Declare a member's type. Every member that carries metadata needs one.
12
+ *
13
+ * ```ts
14
+ * class Position {
15
+ * @type("i32") @range(-100, 100) public x = 0;
16
+ * }
17
+ * ```
18
+ *
19
+ * @param memberType - A scalar type name, a nested component class, or an array `[type]`.
20
+ */
21
+ export function type(memberType) {
22
+ assertMemberType(memberType, "@type");
23
+ return memberDecorator("@type", { type: memberType });
24
+ }
25
+ /**
26
+ * Declare a numeric member's inclusive `[min, max]` range.
27
+ *
28
+ * Ranges are metadata: nothing checks them on `set`. The default `validate`
29
+ * and `normalize` hooks check and clamp to them.
30
+ */
31
+ export function range(min, max) {
32
+ return memberDecorator("@range", { range: [min, max] });
33
+ }
34
+ /** Declare a member's human-readable description. */
35
+ export function description(text) {
36
+ return memberDecorator("@description", { description: text });
37
+ }
38
+ /** Declare a member's unit of measure, for example `"m"`. */
39
+ export function unit(text) {
40
+ return memberDecorator("@unit", { unit: text });
41
+ }
42
+ /** Declare the allowed values of an `enum` member. */
43
+ export function values(allowed) {
44
+ return memberDecorator("@values", { values: [...allowed] });
45
+ }
46
+ /** @internal Read the decorator declarations `Class` itself makes, in declaration order. */
47
+ export function _ownDecoratedMembers(Class) {
48
+ return [...(declarationsByClass.get(Class) ?? []), ...(ownMetadataDeclarations(Class) ?? [])];
49
+ }
50
+ function memberDecorator(name, declaration) {
51
+ return ((target, key) => {
52
+ if (isStandardFieldContext(key)) {
53
+ declareStandard(name, key, declaration);
54
+ return;
55
+ }
56
+ if (typeof key !== "string") {
57
+ throw new TypeError(`${name} only supports string property keys`);
58
+ }
59
+ const Class = target.constructor;
60
+ let declarations = declarationsByClass.get(Class);
61
+ if (declarations === undefined) {
62
+ declarations = new Map();
63
+ declarationsByClass.set(Class, declarations);
64
+ }
65
+ addDeclaration(declarations, `${Class.name}.${key}`, key, declaration);
66
+ });
67
+ }
68
+ function declareStandard(name, context, declaration) {
69
+ if (context.kind !== "field" || context.static || context.private) {
70
+ throw new TypeError(`${name} only supports public instance fields`);
71
+ }
72
+ if (typeof context.name !== "string") {
73
+ throw new TypeError(`${name} only supports string property keys`);
74
+ }
75
+ const key = context.name;
76
+ const metadata = context.metadata;
77
+ if (metadata !== undefined) {
78
+ if (!Object.prototype.hasOwnProperty.call(metadata, DECLARATIONS)) {
79
+ metadata[DECLARATIONS] = new Map();
80
+ }
81
+ addDeclaration(metadata[DECLARATIONS], key, key, declaration);
82
+ return;
83
+ }
84
+ // Without metadata, fall back to registering on first construction.
85
+ context.addInitializer(function declareMember() {
86
+ const Class = this.constructor;
87
+ let declarations = declarationsByClass.get(Class);
88
+ if (declarations === undefined) {
89
+ declarations = new Map();
90
+ declarationsByClass.set(Class, declarations);
91
+ }
92
+ if (!declarations.has(key) || !hasFields(declarations.get(key), declaration)) {
93
+ addDeclaration(declarations, `${Class.name}.${key}`, key, declaration);
94
+ }
95
+ });
96
+ }
97
+ function addDeclaration(declarations, where, key, declaration) {
98
+ const current = declarations.get(key) ?? {};
99
+ for (const field of Object.keys(declaration)) {
100
+ if (current[field] !== undefined) {
101
+ throw new Error(`VecsStruct ${where}: ${field} is declared twice`);
102
+ }
103
+ }
104
+ declarations.set(key, { ...current, ...declaration });
105
+ }
106
+ function hasFields(current, declaration) {
107
+ return Object.keys(declaration).every((field) => current[field] !== undefined);
108
+ }
109
+ function ownMetadataDeclarations(constructor) {
110
+ const metadataKey = Symbol.metadata;
111
+ if (!Object.prototype.hasOwnProperty.call(constructor, metadataKey)) {
112
+ return undefined;
113
+ }
114
+ const metadata = constructor[metadataKey];
115
+ if (typeof metadata !== "object" ||
116
+ metadata === null ||
117
+ !Object.prototype.hasOwnProperty.call(metadata, DECLARATIONS)) {
118
+ return undefined;
119
+ }
120
+ return metadata[DECLARATIONS];
121
+ }
122
+ function isStandardFieldContext(value) {
123
+ return (typeof value === "object" &&
124
+ value !== null &&
125
+ "kind" in value &&
126
+ "name" in value &&
127
+ "addInitializer" in value);
128
+ }
129
+ //# sourceMappingURL=decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/reflection/decorators.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAoC,MAAM,mBAAmB,CAAC;AAqBvF,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAC5C,MAAM,mBAAmB,GAAG,IAAI,OAAO,EAA0B,CAAC;AAElE,4EAA4E;AAC5E,iFAAiF;AACjF,+EAA+E;AAC/E,8CAA8C;AAC9C,MAAC,MAAgC,EAAC,QAAQ,QAAR,QAAQ,GAAK,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAC;AAE7E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,IAAI,CAAC,UAAsB;IACzC,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,eAAe,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,GAAe,EAAE,GAAe;IACpD,OAAO,eAAe,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,eAAe,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,eAAe,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,MAAM,CAAC,OAA0B;IAC/C,OAAO,eAAe,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,oBAAoB,CAAC,KAAe;IAClD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,WAA8B;IACnE,OAAO,CAAC,CAAC,MAAc,EAAE,GAAY,EAAE,EAAE;QACvC,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,qCAAqC,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,KAAK,GAAI,MAAoC,CAAC,WAAW,CAAC;QAChE,IAAI,YAAY,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;YACzB,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC;QACD,cAAc,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IACzE,CAAC,CAAoB,CAAC;AACxB,CAAC;AAED,SAAS,eAAe,CACtB,IAAY,EACZ,OAA6B,EAC7B,WAA8B;IAE9B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,uCAAuC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,qCAAqC,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;YAClE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QACrC,CAAC;QACD,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IACD,oEAAoE;IACpE,OAAO,CAAC,cAAc,CAAC,SAAS,aAAa;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;QAC/B,IAAI,YAAY,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;YACzB,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,WAAW,CAAC,EAAE,CAAC;YAC9E,cAAc,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CACrB,YAA0B,EAC1B,KAAa,EACb,GAAW,EACX,WAA8B;IAE9B,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAgC,EAAE,CAAC;QAC5E,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,cAAc,KAAK,KAAK,KAAK,oBAAoB,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IACD,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,OAA0B,EAAE,WAA8B;IAC3E,OAAQ,MAAM,CAAC,IAAI,CAAC,WAAW,CAAiC,CAAC,KAAK,CACpE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS,CACxC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,WAAqB;IACpD,MAAM,WAAW,GAAI,MAAgC,CAAC,QAAS,CAAC;IAChE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,QAAQ,GAAI,WAAkD,CAAC,WAAW,CAAC,CAAC;IAClF,IACE,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,KAAK,IAAI;QACjB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAC7D,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAQ,QAAyC,CAAC,YAAY,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACf,MAAM,IAAI,KAAK;QACf,gBAAgB,IAAI,KAAK,CAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Violations returned by a failing `validate` hook: one message or a list of them. */
2
+ export type Violations = string | readonly string[];
3
+ /** What a `validate` hook returns: `true` when valid, otherwise the violations. */
4
+ export type ValidationResult = true | Violations;
@@ -0,0 +1,149 @@
1
+ // Default `validate` / `normalize` hooks derived from member metadata.
2
+ import { INTEGER_BOUNDS, elementType, isArrayType, isBigIntType, isIntegerType, isNumericType, } from "./member_types.js";
3
+ import { _structMembers } from "./vecs_struct.js";
4
+ /**
5
+ * @internal Whether the definition of `Class` declares a range or an integer
6
+ * type, so a default hook has something to check.
7
+ */
8
+ export function _hasDefaultChecks(Class) {
9
+ return checks(Class).length > 0;
10
+ }
11
+ /**
12
+ * @internal Build the default `validate` hook. It derives its checks from the
13
+ * live definition on every call, so members declared later, in any world or on
14
+ * a base class, are checked too.
15
+ */
16
+ export function _defaultValidate(Class) {
17
+ return (component) => {
18
+ const violations = [];
19
+ for (const check of checks(Class)) {
20
+ const value = component[check.name];
21
+ if (!check.array) {
22
+ validateValue(check, check.name, value, violations);
23
+ }
24
+ else if (!Array.isArray(value)) {
25
+ violations.push(`${check.name}: expected an array`);
26
+ }
27
+ else {
28
+ value.forEach((item, i) => validateValue(check, `${check.name}[${i}]`, item, violations));
29
+ }
30
+ }
31
+ return violations.length === 0 ? true : violations;
32
+ };
33
+ }
34
+ /**
35
+ * @internal Build the default `normalize` hook: truncate integers and clamp to
36
+ * bounds. Like the default `validate`, it reads the live definition.
37
+ */
38
+ export function _defaultNormalize(Class) {
39
+ return (component) => {
40
+ const record = component;
41
+ for (const check of checks(Class)) {
42
+ const value = record[check.name];
43
+ if (!check.array) {
44
+ record[check.name] = normalizeValue(check, value);
45
+ }
46
+ else if (Array.isArray(value)) {
47
+ for (let i = 0; i < value.length; i++) {
48
+ value[i] = normalizeValue(check, value[i]);
49
+ }
50
+ }
51
+ }
52
+ };
53
+ }
54
+ function checks(Class) {
55
+ const result = [];
56
+ for (const [name, member] of _structMembers(Class) ?? []) {
57
+ const check = checkFor(name, member);
58
+ if (check !== undefined) {
59
+ result.push(check);
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ function checkFor(name, member) {
65
+ const element = elementType(member.type);
66
+ if (!isNumericType(element) || (member.range === undefined && !isIntegerType(element))) {
67
+ return undefined;
68
+ }
69
+ const integer = isIntegerType(element);
70
+ const bigint = isBigIntType(element);
71
+ let min = bigint ? 0n : -Infinity;
72
+ let max = bigint ? 0n : Infinity;
73
+ if (integer) {
74
+ [min, max] = INTEGER_BOUNDS[element];
75
+ }
76
+ if (member.range !== undefined) {
77
+ const [rangeMin, rangeMax] = member.range;
78
+ if (!integer || rangeMin > min) {
79
+ min = rangeMin;
80
+ }
81
+ if (!integer || rangeMax < max) {
82
+ max = rangeMax;
83
+ }
84
+ }
85
+ if (integer && !bigint) {
86
+ // A fractional range bound leaves only the integers inside it.
87
+ min = Math.ceil(min);
88
+ max = Math.floor(max);
89
+ }
90
+ return {
91
+ name,
92
+ array: isArrayType(member.type),
93
+ integer,
94
+ bigint,
95
+ min,
96
+ max,
97
+ values: member.values,
98
+ };
99
+ }
100
+ function validateValue(check, path, value, violations) {
101
+ if (check.bigint) {
102
+ if (typeof value !== "bigint") {
103
+ violations.push(`${path}: expected a bigint`);
104
+ return;
105
+ }
106
+ }
107
+ else if (typeof value !== "number" || isNaN(value)) {
108
+ violations.push(`${path}: expected a number`);
109
+ return;
110
+ }
111
+ else if (check.integer && !Number.isInteger(value)) {
112
+ violations.push(`${path}: ${value} is not an integer`);
113
+ return;
114
+ }
115
+ if (check.values !== undefined && !check.values.includes(value)) {
116
+ violations.push(`${path}: ${value} is not one of [${check.values.join(", ")}]`);
117
+ return;
118
+ }
119
+ if (value < check.min) {
120
+ violations.push(`${path}: ${value} is below the minimum ${check.min}`);
121
+ }
122
+ else if (value > check.max) {
123
+ violations.push(`${path}: ${value} is above the maximum ${check.max}`);
124
+ }
125
+ }
126
+ function normalizeValue(check, value) {
127
+ if (check.bigint) {
128
+ let n;
129
+ if (typeof value === "bigint") {
130
+ n = value;
131
+ }
132
+ else if (typeof value === "number" && Number.isFinite(value)) {
133
+ n = BigInt(Math.trunc(value));
134
+ }
135
+ else {
136
+ return value;
137
+ }
138
+ return n < check.min ? check.min : n > check.max ? check.max : n;
139
+ }
140
+ if (typeof value !== "number") {
141
+ return value;
142
+ }
143
+ let n = isNaN(value) ? 0 : value;
144
+ if (check.integer) {
145
+ n = Math.trunc(n);
146
+ }
147
+ return n < check.min ? check.min : n > check.max ? check.max : n;
148
+ }
149
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/reflection/defaults.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,GAGd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAkBlD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAe;IAC/C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAe;IAC9C,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GAAI,SAAqC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACjB,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YACtD,CAAC;iBAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,qBAAqB,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAe;IAC/C,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,MAAM,GAAG,SAAoC,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACpD,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,KAAK,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,KAAe;IAC7B,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,MAAkB;IAChD,MAAM,OAAO,GAAsB,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACvF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,GAAG,GAAoB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACnD,IAAI,GAAG,GAAoB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,IAAI,OAAO,EAAE,CAAC;QACZ,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,cAAc,CAAC,OAAO,CAAE,CAAC;IACxC,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1C,IAAI,CAAC,OAAO,IAAI,QAAQ,GAAG,GAAG,EAAE,CAAC;YAC/B,GAAG,GAAG,QAAQ,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,QAAQ,GAAG,GAAG,EAAE,CAAC;YAC/B,GAAG,GAAG,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,+DAA+D;QAC/D,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;QAC/B,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAa,CAAC,CAAC;IAClC,CAAC;IACD,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;QAC/B,OAAO;QACP,MAAM;QACN,GAAG;QACH,GAAG;QACH,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAY,EAAE,IAAY,EAAE,KAAc,EAAE,UAAoB;IACrF,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,qBAAqB,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,qBAAqB,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,oBAAoB,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAe,CAAC,EAAE,CAAC;QAC1E,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,mBAAmB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChF,OAAO;IACT,CAAC;IACD,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QACtB,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,yBAAyB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;SAAM,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,yBAAyB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAY,EAAE,KAAc;IAClD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAS,CAAC;QACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,CAAC,GAAG,KAAK,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/D,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACjC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A scalar member type.
3
+ *
4
+ * Integer types (`u8` … `i64`, `enum`) have fixed bounds; `u64` and `i64` hold
5
+ * `bigint` values. `enum` is an `i32` whose allowed values a member may list.
6
+ * `entity` holds an entity reference.
7
+ */
8
+ export type MemberScalarType = "bool" | "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "enum" | "f32" | "f64" | "string" | "bytes" | "any" | "entity";
9
+ /** A nested component class used as a member type. */
10
+ export type MemberClass<T = unknown> = new () => T;
11
+ /** The type of one array element: a scalar or a nested component class. */
12
+ export type MemberElementType = MemberScalarType | MemberClass;
13
+ /** A member type: a scalar, a nested component class, or an array `[type]`. */
14
+ export type MemberType = MemberElementType | readonly [MemberElementType];
15
+ /** A range bound. `u64` and `i64` members accept `bigint` bounds. */
16
+ export type RangeBound = number | bigint;
17
+ /**
18
+ * Reflection metadata for one component member, as stored in
19
+ * {@link VecsStruct.members}.
20
+ */
21
+ export interface VecsMember {
22
+ /** The member's type. */
23
+ readonly type: MemberType;
24
+ /** Inclusive `[min, max]` bounds. Metadata only: nothing checks it on `set`. */
25
+ readonly range?: readonly [min: RangeBound, max: RangeBound];
26
+ /** Human-readable description. */
27
+ readonly description?: string;
28
+ /** Unit of measure, for example `"m"` or `"deg"`. */
29
+ readonly unit?: string;
30
+ /** Allowed values of an `enum` member. */
31
+ readonly values?: readonly number[];
32
+ }
@@ -0,0 +1,86 @@
1
+ // Member type vocabulary shared by reflection, decorators and default hooks.
2
+ //
3
+ // The names match `lib/vecs-wire/src/decorators.ts` (`WireScalarType`): until
4
+ // vecs-wire reads them from core, both packages carry the same list.
5
+ /** @internal Integer bounds per integer scalar type. */
6
+ export const INTEGER_BOUNDS = {
7
+ u8: [0, 0xff],
8
+ i8: [-0x80, 0x7f],
9
+ u16: [0, 0xffff],
10
+ i16: [-0x8000, 0x7fff],
11
+ u32: [0, 0xffffffff],
12
+ i32: [-0x80000000, 0x7fffffff],
13
+ enum: [-0x80000000, 0x7fffffff],
14
+ u64: [0n, 0xffffffffffffffffn],
15
+ i64: [-0x8000000000000000n, 0x7fffffffffffffffn],
16
+ };
17
+ const SCALAR_TYPES = new Set([
18
+ "bool",
19
+ "u8",
20
+ "i8",
21
+ "u16",
22
+ "i16",
23
+ "u32",
24
+ "i32",
25
+ "u64",
26
+ "i64",
27
+ "enum",
28
+ "f32",
29
+ "f64",
30
+ "string",
31
+ "bytes",
32
+ "any",
33
+ "entity",
34
+ ]);
35
+ /** @internal Whether `type` is an array member type. */
36
+ export function isArrayType(type) {
37
+ return Array.isArray(type);
38
+ }
39
+ /** @internal The element type of an array member, or the type itself. */
40
+ export function elementType(type) {
41
+ return isArrayType(type) ? type[0] : type;
42
+ }
43
+ /** @internal Whether `type` is a numeric scalar: an integer type, `f32` or `f64`. */
44
+ export function isNumericType(type) {
45
+ return type === "f32" || type === "f64" || isIntegerType(type);
46
+ }
47
+ /** @internal Whether `type` is an integer scalar, including `enum`, `u64` and `i64`. */
48
+ export function isIntegerType(type) {
49
+ return typeof type === "string" && INTEGER_BOUNDS[type] !== undefined;
50
+ }
51
+ /** @internal Whether `type` holds `bigint` values. */
52
+ export function isBigIntType(type) {
53
+ return type === "u64" || type === "i64";
54
+ }
55
+ /** @internal Throw a `TypeError` unless `type` is a valid member type. */
56
+ export function assertMemberType(type, where) {
57
+ if (Array.isArray(type)) {
58
+ if (type.length !== 1) {
59
+ throw new TypeError(`${where}: an array type must contain exactly one element type`);
60
+ }
61
+ assertElementType(type[0], where);
62
+ return;
63
+ }
64
+ assertElementType(type, where);
65
+ }
66
+ /** @internal Compare two member types: same scalar, same class, or arrays of the same element. */
67
+ export function memberTypesEqual(left, right) {
68
+ if (isArrayType(left) || isArrayType(right)) {
69
+ return isArrayType(left) && isArrayType(right) && left[0] === right[0];
70
+ }
71
+ return left === right;
72
+ }
73
+ /** @internal Render a member type for error messages. */
74
+ export function formatMemberType(type) {
75
+ if (isArrayType(type)) {
76
+ return `[${formatMemberType(type[0])}]`;
77
+ }
78
+ return typeof type === "function" ? type.name || "anonymous class" : type;
79
+ }
80
+ function assertElementType(type, where) {
81
+ if (typeof type === "function" || (typeof type === "string" && SCALAR_TYPES.has(type))) {
82
+ return;
83
+ }
84
+ throw new TypeError(`${where}: unsupported member type ${String(type)}`);
85
+ }
86
+ //# sourceMappingURL=member_types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member_types.js","sourceRoot":"","sources":["../../src/reflection/member_types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type MemberType, type RangeBound, type VecsMember } from "./member_types.js";
2
+ /**
3
+ * Core component holding a component class's member reflection metadata.
4
+ *
5
+ * `world.component(C)` attaches it to the **component entity** of `C` as soon
6
+ * as `C` or a base class declares a member, through decorators ({@link type},
7
+ * {@link range}, …) or the fluent {@link Component.member} API. Query it like
8
+ * any component:
9
+ *
10
+ * ```ts
11
+ * world.component(Position).get(VecsStruct)?.members.x; // { type: "i32", range: [-100, 100] }
12
+ * ```
13
+ *
14
+ * The definition is per class for the whole process: every world attaches the
15
+ * same frozen instance, so `getMut(VecsStruct, …)` on it throws. Members are
16
+ * inherited, whichever way the base class declared them, and are listed base
17
+ * class first, then in declaration order. A declaration that contradicts the
18
+ * definition throws, naming the class and the member.
19
+ */
20
+ export declare class VecsStruct {
21
+ /** Member metadata keyed by member name. */
22
+ readonly members: Readonly<Record<string, VecsMember>>;
23
+ }
24
+ /** A member declaration whose fields may still be incomplete. */
25
+ export interface MemberDeclaration {
26
+ type?: MemberType;
27
+ range?: readonly [RangeBound, RangeBound];
28
+ description?: string;
29
+ unit?: string;
30
+ values?: readonly number[];
31
+ }