generated from gxc-solutions/gxc-template-repo
Compare commits
2 commits
5d1c47815a
...
0f8546bc69
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f8546bc69 | ||
|
|
41a325f5e1 |
12 changed files with 152 additions and 4 deletions
|
|
@ -41,7 +41,7 @@ jobs:
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: gxc-math-${{ github.sha }}
|
name: gxc-model-base-${{ github.sha }}
|
||||||
path: ./dist/
|
path: ./dist/
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
|
|
@ -53,7 +53,7 @@ jobs:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: gxc-math-${{ github.sha }}
|
name: gxc-model-base-${{ github.sha }}
|
||||||
path: ./artifact
|
path: ./artifact
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|
|
||||||
2
.npmrc
2
.npmrc
|
|
@ -1 +1 @@
|
||||||
regestry=https://npm.gxc-solutions.ru/
|
@gxc-solutions:registry=https://npm.gxc-solutions.ru/
|
||||||
15
lib/src/decorators/ignore.ts
Normal file
15
lib/src/decorators/ignore.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { ModelConstructor } from "../interfaces";
|
||||||
|
|
||||||
|
export const IGNORABLE_FIELDS = new WeakMap<ModelConstructor, Set<string>>();
|
||||||
|
|
||||||
|
export function ignore(value: unknown, context: ClassFieldDecoratorContext) {
|
||||||
|
context.addInitializer(function () {
|
||||||
|
const ctor = this.constructor as ModelConstructor;
|
||||||
|
let set = IGNORABLE_FIELDS.get(ctor);
|
||||||
|
if (!set) {
|
||||||
|
set = new Set<string>();
|
||||||
|
IGNORABLE_FIELDS.set(ctor, set);
|
||||||
|
}
|
||||||
|
set.add(context.name as string);
|
||||||
|
});
|
||||||
|
}
|
||||||
15
lib/src/decorators/immutable.ts
Normal file
15
lib/src/decorators/immutable.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { ModelConstructor } from "../interfaces";
|
||||||
|
|
||||||
|
export const IMMUTABLE_FIELDS = new WeakMap<ModelConstructor, Set<string>>();
|
||||||
|
|
||||||
|
export function immutable(value: unknown, context: ClassFieldDecoratorContext) {
|
||||||
|
context.addInitializer(function () {
|
||||||
|
const ctor = this.constructor as ModelConstructor;
|
||||||
|
let set = IMMUTABLE_FIELDS.get(ctor);
|
||||||
|
if (!set) {
|
||||||
|
set = new Set<string>();
|
||||||
|
IMMUTABLE_FIELDS.set(ctor, set);
|
||||||
|
}
|
||||||
|
set.add(context.name as string);
|
||||||
|
});
|
||||||
|
}
|
||||||
3
lib/src/decorators/index.ts
Normal file
3
lib/src/decorators/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from "./ignore";
|
||||||
|
export * from "./immutable";
|
||||||
|
export * from "./utils";
|
||||||
11
lib/src/decorators/property.ts
Normal file
11
lib/src/decorators/property.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
export class PropertyMetadata {
|
||||||
|
get(object: any, property: string) {
|
||||||
|
console.warn(object, property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function property() {
|
||||||
|
return function (target: object, property: string) {
|
||||||
|
console.warn(target, property);
|
||||||
|
};
|
||||||
|
}
|
||||||
17
lib/src/decorators/utils.ts
Normal file
17
lib/src/decorators/utils.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { IMMUTABLE_FIELDS } from "./immutable";
|
||||||
|
import { IGNORABLE_FIELDS } from "./ignore";
|
||||||
|
|
||||||
|
export const getImmutableKeys = (obj: any): string[] => {
|
||||||
|
const ctor = obj.constructor;
|
||||||
|
return IMMUTABLE_FIELDS.has(ctor) ? Array.from(IMMUTABLE_FIELDS.get(ctor) as Set<string>) : [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isImmutableKey = (object: any, key: string) => getImmutableKeys(object).includes(key);
|
||||||
|
|
||||||
|
export const getIgnorableKeys = (obj: any): string[] => {
|
||||||
|
const ctor = obj.constructor;
|
||||||
|
|
||||||
|
return IGNORABLE_FIELDS.has(ctor) ? Array.from(IGNORABLE_FIELDS.get(ctor) as Set<string>) : [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isIgnorableKey = (object: any, key: string) => getIgnorableKeys(object).includes(key);
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from "./models";
|
||||||
|
export * from "./decorators";
|
||||||
|
export * from "./interfaces";
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
export type ModelConstructor = new (...args: any[]) => IModel;
|
||||||
|
|
||||||
|
export type TypeOfModel = "collection";
|
||||||
|
|
||||||
|
export interface IModel {
|
||||||
|
readonly id: string;
|
||||||
|
readonly type: TypeOfModel;
|
||||||
|
}
|
||||||
75
lib/src/models/collection.ts
Normal file
75
lib/src/models/collection.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { ignore } from "../decorators/ignore";
|
||||||
|
|
||||||
|
export class Collection<T> {
|
||||||
|
@ignore readonly id = crypto.randomUUID();
|
||||||
|
private _store: Record<number, T> = {};
|
||||||
|
|
||||||
|
get length() {
|
||||||
|
return Object.keys(this._store).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(args: T[] = []) {
|
||||||
|
args.forEach((item, index) => (this._store[index] = item));
|
||||||
|
}
|
||||||
|
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
const array = this.toArray();
|
||||||
|
for (const item of array) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push(...args: T[]) {
|
||||||
|
const diff: Record<number, T> = {};
|
||||||
|
args.forEach((item) => {
|
||||||
|
const index = this.length;
|
||||||
|
this._store[index] = item;
|
||||||
|
diff[index] = item;
|
||||||
|
});
|
||||||
|
return { ...diff, length: this.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(item: T) {
|
||||||
|
const backup: Record<number, T> = { ...this._store };
|
||||||
|
|
||||||
|
Object.keys(this._store).forEach((key) => {
|
||||||
|
const index = Number(key);
|
||||||
|
const itemOfIndex = this.get(index);
|
||||||
|
if (item !== itemOfIndex) return;
|
||||||
|
|
||||||
|
Reflect.deleteProperty(this._store, Number(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
const diff: Record<number, T> = {};
|
||||||
|
const values = Object.values(this._store);
|
||||||
|
const newStore: Record<number, T> = {};
|
||||||
|
|
||||||
|
for (let index = 0; index < values.length; index++) {
|
||||||
|
newStore[index] = values[index];
|
||||||
|
|
||||||
|
if (backup[index] !== newStore[index]) {
|
||||||
|
diff[index] = newStore[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._store = newStore;
|
||||||
|
|
||||||
|
return { ...diff, length: this.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
indexOf(item: T) {
|
||||||
|
return this.toArray().indexOf(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(index: number): T {
|
||||||
|
return this._store[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
set(index: number, value: T) {
|
||||||
|
this._store[index] = value;
|
||||||
|
return { [index]: value, length: this.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
toArray(): T[] {
|
||||||
|
return Object.keys(this._store).map((index) => this._store[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
lib/src/models/index.ts
Normal file
1
lib/src/models/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./collection";
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@gxc-solutions/lib",
|
"name": "@gxc-solutions/model-base",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "GXC Solutions",
|
"author": "GXC Solutions",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue