@avstantso/utils-flags-decorator 1.1.0 → 1.2.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+
4
+ ## [1.2.2] - 2026-01-31
5
+
6
+ ### Changed
7
+
8
+ - Updated `@avstantso/ts` dependency (Updated @avstantso/ts dependency (fix String, Filter))
9
+
10
+
11
+ ## [1.2.1] - 2026-01-18
12
+
13
+ ### Changed
14
+
15
+ - Fix publishing
16
+
3
17
  All notable changes to this project will be documented in this file.
4
18
 
5
19
  ## [1.1.0] - 2026-01-18
@@ -0,0 +1,106 @@
1
+ declare namespace AVStantso {
2
+ /**
3
+ * @summary Add/Remove control of entity extension by boolean fields from flags value
4
+ * @example
5
+ * export const UserFlagsDecorator = FlagsDecorator([
6
+ * 'system', // = 1 << 0
7
+ * 'test', // = 1 << 1
8
+ * 'no_login', // = 1 << 2
9
+ * 'no_author', // = 1 << 3
10
+ * 'demo', // = 1 << 4
11
+ * ]);
12
+ *
13
+ * const user = {flags: 7} // system | test | no_login
14
+ *
15
+ * function print(caption: string) {
16
+ * console.log(`${caption}: %O`, {
17
+ * system: user.system,
18
+ * test: user.test,
19
+ * no_login: user.no_login,
20
+ * no_author: user.no_author,
21
+ * demo: user.demo,
22
+ * });
23
+ * }
24
+ *
25
+ * print(`Without extension`);
26
+ * // Outputs: Without extension
27
+ * // {
28
+ * // system: undefined,
29
+ * // test: undefined,
30
+ * // no_login: undefined,
31
+ * // no_author: undefined,
32
+ * // demo: undefined,
33
+ * // }
34
+ *
35
+ * // Add properties
36
+ * UserFlagsDecorator.expand(user);
37
+ *
38
+ * print(`With extension`);
39
+ * // Outputs: With extension
40
+ * // {
41
+ * // system: true, // 👈 (user.flags & 1 << 0) > 0
42
+ * // test: true, // 👈 (user.flags & 1 << 1) > 0
43
+ * // no_login: true, // 👈 (user.flags & 1 << 2) > 0
44
+ * // no_author: false, // 👈 (user.flags & 1 << 3) > 0
45
+ * // demo: false, // 👈 (user.flags & 1 << 4) > 0
46
+ * // }
47
+ *
48
+ * user.no_login = false; // ≡ user.flags = user.flags & ~4;
49
+ *
50
+ * // Remove properties
51
+ * UserFlagsDecorator.omit(user);
52
+ *
53
+ * print(`After omit`);
54
+ * // Outputs: After omit
55
+ * // {
56
+ * // system: undefined,
57
+ * // test: undefined,
58
+ * // no_login: undefined,
59
+ * // no_author: undefined,
60
+ * // demo: undefined,
61
+ * // }
62
+ */
63
+ namespace FlagsDecorator {
64
+ type Map = {
65
+ [x: number]: string;
66
+ };
67
+ type Readable = boolean | (() => number);
68
+ type Writable = boolean | ((flags: number) => void);
69
+ type Options<TFlagsFieldName extends string = string> = {
70
+ field?: TFlagsFieldName;
71
+ flags?: number;
72
+ readable?: Readable;
73
+ writable?: Writable;
74
+ };
75
+ }
76
+ type FlagsDecorator<TMap extends FlagsDecorator.Map> = {
77
+ /**
78
+ * @summary Add properties by `Object.defineProperty` to `entity`. Mutate `entity`
79
+ */
80
+ expand<T extends object>(entity: T): T & Record<keyof TS.Structure.Reverse<TMap>, boolean>;
81
+ /**
82
+ * @summary Remove propertiyes by `delete`. Mutate `entity`
83
+ */
84
+ omit<T extends object>(entity: T): Omit<T, keyof TS.Structure.Reverse<TMap>>;
85
+ };
86
+ namespace Code {
87
+ /**
88
+ * @summary FlagsDecorator utilities
89
+ */
90
+ namespace FlagsDecorator {
91
+ type Overload = {
92
+ <TMap extends AVStantso.FlagsDecorator.Map, TFlagsFieldName extends string = 'flags'>(map: TMap, options?: AVStantso.FlagsDecorator.Options<TFlagsFieldName>): FlagsDecorator<TMap>;
93
+ <TMap extends AVStantso.FlagsDecorator.Map, TFlagsFieldName extends string = 'flags'>(map: TMap, field?: TFlagsFieldName): FlagsDecorator<TMap>;
94
+ <TMap extends AVStantso.FlagsDecorator.Map>(map: TMap, flags: number): FlagsDecorator<TMap>;
95
+ is<TMap extends AVStantso.FlagsDecorator.Map = AVStantso.FlagsDecorator.Map>(candidate: unknown): candidate is FlagsDecorator<TMap>;
96
+ };
97
+ }
98
+ }
99
+ interface Code {
100
+ /**
101
+ * @summary FlagsDecorator utilities
102
+ */
103
+ FlagsDecorator: Code.FlagsDecorator.Overload;
104
+ }
105
+ const FlagsDecorator: Code.FlagsDecorator.Overload;
106
+ }
@@ -0,0 +1 @@
1
+ import './_register';
@@ -0,0 +1,2 @@
1
+ import FlagsDecorator = AVStantso.FlagsDecorator;
2
+ export { FlagsDecorator };
@@ -0,0 +1,4 @@
1
+ import '@avstantso/errors';
2
+ import '@avstantso/js';
3
+ import './_global';
4
+ export * from './export';
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ 'use strict';
2
+
3
+ require('@avstantso/errors');
4
+ require('@avstantso/js');
5
+
6
+ var AVStantso$1;
7
+ (function (AVStantso) {
8
+ AVStantso.FlagsDecorator = avstantso._reg.FlagsDecorator(({ JS }) => {
9
+ function isFlagsDecorator(candidate) {
10
+ return (candidate
11
+ && JS.is.object(candidate)
12
+ && JS.is.function(candidate.expand)
13
+ && JS.is.function(candidate.omit));
14
+ }
15
+ /* eslint-disable @typescript-eslint/no-explicit-any */
16
+ const FlagsDecorator = (map, param) => {
17
+ const clearMap = Object.entries(map).reduce((r, [key, name]) => {
18
+ const flag = Number.parseInt(key, 10);
19
+ if (!Number.isNaN(flag))
20
+ r.push([flag, name]);
21
+ return r;
22
+ }, []);
23
+ function expand(entity) {
24
+ const options = JS.is.object(param)
25
+ ? param
26
+ : undefined;
27
+ const initialFlags = JS.is.number(param) ? param : options?.flags;
28
+ const field = (JS.is.string(param) ? param : options?.field) || 'flags';
29
+ const read = JS.is.number(initialFlags) && !options?.readable
30
+ ? () => initialFlags
31
+ : JS.is.function(options?.readable)
32
+ ? options.readable
33
+ : () => entity[field];
34
+ const write = !options?.writable
35
+ ? undefined
36
+ : JS.is.function(options.writable)
37
+ ? options.writable
38
+ : (flags) => Object.assign(entity, { [field]: flags });
39
+ for (const [flag, name] of clearMap)
40
+ Object.defineProperty(entity, name, Object.assign(
41
+ /* eslint-disable no-bitwise */
42
+ { get: () => (read() & (1 << flag)) > 0 }, write && {
43
+ set: (value) => {
44
+ write(value ? read() | (1 << flag) : read() & ~(1 << flag));
45
+ }
46
+ }
47
+ /* eslint-enable no-bitwise */
48
+ ));
49
+ return entity;
50
+ }
51
+ function omit(entity) {
52
+ for (const [, name] of clearMap)
53
+ delete entity[name];
54
+ return entity;
55
+ }
56
+ return { expand, omit };
57
+ };
58
+ FlagsDecorator.is = isFlagsDecorator;
59
+ return FlagsDecorator;
60
+ });
61
+ })(AVStantso$1 || (AVStantso$1 = {}));
62
+
63
+ var FlagsDecorator = AVStantso.FlagsDecorator;
64
+
65
+ exports.FlagsDecorator = FlagsDecorator;
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/_global/_register.ts","../src/export.ts"],"sourcesContent":["namespace AVStantso {\n /**\n * @summary Add/Remove control of entity extension by boolean fields from flags value\n * @example\n * export const UserFlagsDecorator = FlagsDecorator([\n * 'system', // = 1 << 0\n * 'test', // = 1 << 1\n * 'no_login', // = 1 << 2\n * 'no_author', // = 1 << 3\n * 'demo', // = 1 << 4\n * ]);\n *\n * const user = {flags: 7} // system | test | no_login\n *\n * function print(caption: string) {\n * console.log(`${caption}: %O`, {\n * system: user.system,\n * test: user.test,\n * no_login: user.no_login,\n * no_author: user.no_author,\n * demo: user.demo,\n * });\n * }\n *\n * print(`Without extension`);\n * // Outputs: Without extension\n * // {\n * // system: undefined,\n * // test: undefined,\n * // no_login: undefined,\n * // no_author: undefined,\n * // demo: undefined,\n * // }\n *\n * // Add properties\n * UserFlagsDecorator.expand(user);\n *\n * print(`With extension`);\n * // Outputs: With extension\n * // {\n * // system: true, // 👈 (user.flags & 1 << 0) > 0\n * // test: true, // 👈 (user.flags & 1 << 1) > 0\n * // no_login: true, // 👈 (user.flags & 1 << 2) > 0\n * // no_author: false, // 👈 (user.flags & 1 << 3) > 0\n * // demo: false, // 👈 (user.flags & 1 << 4) > 0\n * // }\n *\n * user.no_login = false; // ≡ user.flags = user.flags & ~4;\n *\n * // Remove properties\n * UserFlagsDecorator.omit(user);\n *\n * print(`After omit`);\n * // Outputs: After omit\n * // {\n * // system: undefined,\n * // test: undefined,\n * // no_login: undefined,\n * // no_author: undefined,\n * // demo: undefined,\n * // }\n */\n export namespace FlagsDecorator {\n export type Map = { [x: number]: string };\n\n export type Readable = boolean | (() => number);\n\n export type Writable = boolean | ((flags: number) => void);\n\n export type Options<TFlagsFieldName extends string = string> = {\n field?: TFlagsFieldName;\n flags?: number;\n readable?: Readable;\n writable?: Writable;\n };\n }\n\n export type FlagsDecorator<TMap extends FlagsDecorator.Map> = {\n /**\n * @summary Add properties by `Object.defineProperty` to `entity`. Mutate `entity`\n */\n expand<T extends object>(entity: T): T & Record<keyof TS.Structure.Reverse<TMap>, boolean>;\n\n /**\n * @summary Remove propertiyes by `delete`. Mutate `entity`\n */\n omit<T extends object>(entity: T): Omit<T, keyof TS.Structure.Reverse<TMap>>;\n };\n\n export namespace Code {\n /**\n * @summary FlagsDecorator utilities\n */\n export namespace FlagsDecorator {\n export type Overload = {\n <TMap extends AVStantso.FlagsDecorator.Map, TFlagsFieldName extends string = 'flags'>(\n map: TMap,\n options?: AVStantso.FlagsDecorator.Options<TFlagsFieldName>\n ): FlagsDecorator<TMap>;\n\n <TMap extends AVStantso.FlagsDecorator.Map, TFlagsFieldName extends string = 'flags'>(\n map: TMap,\n field?: TFlagsFieldName\n ): FlagsDecorator<TMap>;\n\n <TMap extends AVStantso.FlagsDecorator.Map>(map: TMap, flags: number): FlagsDecorator<TMap>;\n\n is<\n TMap extends AVStantso.FlagsDecorator.Map = AVStantso.FlagsDecorator.Map\n >(candidate: unknown): candidate is FlagsDecorator<TMap>;\n };\n }\n }\n\n export interface Code {\n /**\n * @summary FlagsDecorator utilities\n */\n FlagsDecorator: Code.FlagsDecorator.Overload;\n }\n\n export const FlagsDecorator: Code.FlagsDecorator.Overload = avstantso._reg.FlagsDecorator(\n ({ JS }) => {\n function isFlagsDecorator<\n TMap extends AVStantso.FlagsDecorator.Map = AVStantso.FlagsDecorator.Map\n >(candidate: unknown): candidate is FlagsDecorator<TMap> {\n return (\n candidate\n && JS.is.object<FlagsDecorator<TMap>>(candidate)\n && JS.is.function(candidate.expand)\n && JS.is.function(candidate.omit)\n );\n }\n\n /* eslint-disable @typescript-eslint/no-explicit-any */\n\n const FlagsDecorator: Code.FlagsDecorator.Overload = (\n map: any,\n param: any\n ) => {\n const clearMap = Object.entries(map).reduce((r, [key, name]) => {\n const flag = Number.parseInt(key, 10);\n if (!Number.isNaN(flag)) r.push([flag, name as string]);\n\n return r;\n }, [] as [number, string][]);\n\n function expand<T extends object>(entity: T): any {\n const options: FlagsDecorator.Options = JS.is.object(param)\n ? param\n : undefined;\n\n const initialFlags = JS.is.number(param) ? param : options?.flags;\n const field = (JS.is.string(param) ? param : options?.field) || 'flags';\n\n const read: () => number =\n JS.is.number(initialFlags) && !options?.readable\n ? () => initialFlags\n : JS.is.function(options?.readable)\n ? options.readable\n : () => (entity as any)[field];\n\n const write = !options?.writable\n ? undefined\n : JS.is.function(options.writable)\n ? options.writable\n : (flags: number) => Object.assign(entity, { [field]: flags });\n\n for (const [flag, name] of clearMap)\n Object.defineProperty(entity, name as keyof T,\n Object.assign(\n /* eslint-disable no-bitwise */\n { get: () => (read() & (1 << flag)) > 0 },\n write && {\n set: (value: boolean) => {\n write(value ? read() | (1 << flag) : read() & ~(1 << flag));\n }\n }\n /* eslint-enable no-bitwise */\n )\n );\n\n return entity;\n }\n\n function omit<T extends object>(entity: T): any {\n for (const [, name] of clearMap)\n delete entity[name as keyof T];\n\n return entity;\n }\n\n return { expand, omit };\n };\n\n FlagsDecorator.is = isFlagsDecorator;\n return FlagsDecorator;\n });\n\n}\n","import FlagsDecorator = AVStantso.FlagsDecorator;\n\nexport {\n FlagsDecorator\n};\n"],"names":["AVStantso"],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@avstantso/utils-flags-decorator",
3
3
  "license": "MIT",
4
4
  "author": "avstantso",
5
- "version": "1.1.0",
5
+ "version": "1.2.2",
6
6
  "description": "AVStantso framework utils: FlagsDecorator",
7
7
  "keywords": [
8
8
  "FlagsDecorator"
@@ -23,12 +23,12 @@
23
23
  "test": "NODE_ENV=test jest --coverage"
24
24
  },
25
25
  "dependencies": {
26
- "@avstantso/concepts": "1.1.0",
27
- "@avstantso/core": "1.1.0",
28
- "@avstantso/errors": "1.1.0",
29
- "@avstantso/js": "1.1.0",
30
- "@avstantso/std-ext": "1.1.0",
31
- "@avstantso/ts": "1.1.0"
26
+ "@avstantso/concepts": "1.2.2",
27
+ "@avstantso/core": "1.2.1",
28
+ "@avstantso/errors": "1.2.1",
29
+ "@avstantso/js": "1.2.2",
30
+ "@avstantso/std-ext": "1.2.1",
31
+ "@avstantso/ts": "1.3.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@avstantso/dev-basic": "1.0.0"