@graphand/core
Advanced tools
Comparing version 0.3.10 to 0.3.12
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Adapter { | ||
static __modelsMap; | ||
fetcher; | ||
@@ -5,0 +6,0 @@ fieldsMap; |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const DataModel_1 = __importDefault(require("../models/DataModel")); | ||
const Model_1 = __importDefault(require("../lib/Model")); | ||
const model_env_scopes_1 = __importDefault(require("../enums/model-env-scopes")); | ||
@@ -15,4 +15,4 @@ const _controllersMap = { | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -27,4 +27,4 @@ return "project"; | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -39,4 +39,4 @@ return "project"; | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -51,4 +51,4 @@ return "project"; | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -63,4 +63,4 @@ return "project"; | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -75,4 +75,4 @@ return "project"; | ||
scope: ({ model }) => { | ||
const Model = DataModel_1.default.getFromSlug(model); | ||
if (Model.scope === model_env_scopes_1.default.GLOBAL) | ||
const _model = Model_1.default.getFromSlug(model); | ||
if (_model.scope === model_env_scopes_1.default.GLOBAL) | ||
return "global"; | ||
@@ -79,0 +79,0 @@ return "project"; |
@@ -23,24 +23,28 @@ "use strict"; | ||
static __datamodel; | ||
static __modelsMap = new Map(); | ||
static getFromDatamodel(datamodel) { | ||
let model = Data_1.__modelsMap.get(datamodel.slug); | ||
if (!model) { | ||
model = class extends Data_1 { | ||
static __name = datamodel.name; | ||
static slug = datamodel.slug; | ||
static fields = datamodel.fields; | ||
static validators = []; | ||
static configKey = datamodel.configKey; | ||
}; | ||
model.__datamodel = datamodel; | ||
Data_1.__modelsMap.set(datamodel.slug, model); | ||
static getFromDatamodel(datamodel, adapter) { | ||
if (!adapter) { | ||
adapter = datamodel.model.__adapter?.constructor; | ||
} | ||
const adapter = datamodel.model.__adapter?.constructor; | ||
if (adapter) { | ||
return model.withAdapter(adapter); | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
let model = class extends Data_1 { | ||
static __name = datamodel.name; | ||
static slug = datamodel.slug; | ||
static fields = datamodel.fields; | ||
static validators = []; | ||
static configKey = datamodel.configKey; | ||
}; | ||
model.__datamodel = datamodel; | ||
if (adapter) { | ||
model = model.withAdapter(adapter); | ||
} | ||
adapter?.__modelsMap.set(datamodel.slug, model); | ||
return model; | ||
} | ||
static __getFromSlug(slug) { | ||
let model = Data_1.__modelsMap.get(slug); | ||
static __getFromSlug(slug, adapter) { | ||
if (adapter) { | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
let model = adapter?.__modelsMap.get(slug); | ||
if (!model) { | ||
@@ -58,3 +62,4 @@ model = class extends Data_1 { | ||
} | ||
const datamodel = await DataModel_1.default.withAdapter(this.__adapter.constructor).get({ filter: { slug } }, ctx); | ||
const adapter = this.__adapter.constructor; | ||
const datamodel = await DataModel_1.default.withAdapter(adapter).get({ filter: { slug } }, ctx); | ||
if (!datamodel) { | ||
@@ -75,3 +80,6 @@ throw new CoreError_1.default({ | ||
}; | ||
Data_1.__modelsMap.set(slug, model); | ||
if (adapter) { | ||
model = model.withAdapter(adapter); | ||
} | ||
adapter?.__modelsMap.set(slug, model); | ||
} | ||
@@ -78,0 +86,0 @@ return model; |
@@ -12,2 +12,3 @@ "use strict"; | ||
const field_types_1 = __importDefault(require("../enums/field-types")); | ||
const Model_1 = __importDefault(require("./Model")); | ||
describe("Data", () => { | ||
@@ -17,15 +18,46 @@ const adapter = (0, test_utils_1.mockAdapter)({ | ||
}); | ||
it("should get same model from slug and from datamodel instance", async () => { | ||
const slug = faker_1.faker.animal.type(); | ||
const datamodel = new DataModel_1.default({ slug }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel); | ||
const modelFromSlug = Data_1.default.getFromSlug(slug); | ||
expect(modelFromDM).toBe(modelFromSlug); | ||
describe("model unicity", () => { | ||
it("should get same model from slug and from datamodel instance with same adapter", async () => { | ||
const slug = faker_1.faker.animal.type(); | ||
const datamodel = new DataModel_1.default({ slug }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel, adapter); | ||
const modelFromSlug = Data_1.default.getFromSlug(slug, adapter); | ||
expect(modelFromDM).toBe(modelFromSlug); | ||
}); | ||
it("should get different models from slug and from datamodel instance with different adapters", async () => { | ||
const slug = faker_1.faker.animal.type(); | ||
const datamodel = new DataModel_1.default({ slug }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel); | ||
const modelFromSlug = Data_1.default.getFromSlug(slug, adapter); | ||
expect(modelFromDM).not.toBe(modelFromSlug); | ||
}); | ||
it("getFromDatamodel should returns model with the instance adapter", async () => { | ||
const DM = DataModel_1.default.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker_1.faker.animal.type() }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel); | ||
expect(modelFromDM.__adapter?.constructor).toBe(adapter); | ||
}); | ||
it("getFromDatamodel should save adapted model in cache", () => { | ||
const DM = DataModel_1.default.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker_1.faker.animal.type() }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel, adapter); | ||
const modelFromDataSlug = Data_1.default.__getFromSlug(datamodel.slug, adapter); | ||
const modelFromModelSlug = Model_1.default.getFromSlug(datamodel.slug, adapter); | ||
expect(modelFromDM).toBe(modelFromDataSlug); | ||
expect(modelFromDM).toBe(modelFromModelSlug); | ||
expect(modelFromDataSlug).toBe(modelFromModelSlug); | ||
}); | ||
it("getFromDatamodel should override adapted model in cache", () => { | ||
const DM = DataModel_1.default.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker_1.faker.animal.type() }); | ||
const modelFromDataSlug = Data_1.default.__getFromSlug(datamodel.slug, adapter); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel, adapter); | ||
const modelFromModelSlug = Model_1.default.getFromSlug(datamodel.slug, adapter); | ||
expect(modelFromModelSlug).toBe(modelFromDM); | ||
expect(modelFromDM).not.toBe(modelFromDataSlug); | ||
const adaptedModelFromModel = Model_1.default.getAdaptedModel(modelFromDataSlug, adapter); | ||
expect(adaptedModelFromModel).toBe(modelFromModelSlug); | ||
expect(modelFromDM).toBe(modelFromModelSlug); | ||
}); | ||
}); | ||
it("getFromDatamodel should returns model with the instance adapter", async () => { | ||
const DM = DataModel_1.default.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker_1.faker.animal.type() }); | ||
const modelFromDM = Data_1.default.getFromDatamodel(datamodel); | ||
expect(modelFromDM.__adapter?.constructor).toBe(adapter); | ||
}); | ||
it("should throw error at initializing if no adapter", async () => { | ||
@@ -59,3 +91,15 @@ const slug = faker_1.faker.animal.type(); | ||
}); | ||
it("Test", () => { }); | ||
it("Multiple model get should return the same model & initialize once", async () => { | ||
const DM = DataModel_1.default.withAdapter(adapter); | ||
const slug = faker_1.faker.lorem.word(); | ||
await DM.create({ slug }); | ||
const model = Data_1.default.getFromSlug(slug, adapter); | ||
const modelBis = Data_1.default.getFromSlug(slug, adapter); | ||
expect(model).toBe(modelBis); | ||
const spy = jest.spyOn(model, "reloadModel"); | ||
expect(spy).toHaveBeenCalledTimes(0); | ||
await expect(model.initialize()).resolves.toBeUndefined(); | ||
await expect(modelBis.initialize()).resolves.toBeUndefined(); | ||
expect(spy).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
@@ -87,3 +87,3 @@ "use strict"; | ||
const adapter = from.model.__adapter.constructor; | ||
let model = Model_1.default.getFromSlug(this.options.ref).withAdapter(adapter); | ||
let model = Model_1.default.getFromSlug(this.options.ref, adapter); | ||
if (this.options.multiple) { | ||
@@ -90,0 +90,0 @@ const ids = Array.isArray(value) ? value : [value]; |
@@ -40,3 +40,3 @@ "use strict"; | ||
static __baseClass; | ||
static __decorated; | ||
static __modelsMap = new Map(); | ||
__doc; | ||
@@ -181,14 +181,44 @@ _id; | ||
} | ||
static getFromSlug(slug, fallbackData = true) { | ||
static getFromSlug(slug, adapter, fallbackData = true) { | ||
if (!adapter) { | ||
adapter = this.__adapter?.constructor; | ||
} | ||
if (adapter) { | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
const models = require("../index").models; | ||
let model = Object.values(models).find((m) => m.slug === slug); | ||
if (!model && fallbackData) { | ||
if (model) { | ||
let adaptedModel = adapter?.__modelsMap.get(model.slug); | ||
if (!adaptedModel && adapter) { | ||
adaptedModel = model.withAdapter(adapter); | ||
adapter.__modelsMap.set(model.slug, adaptedModel); | ||
} | ||
model = adaptedModel || model; | ||
} | ||
else if (fallbackData) { | ||
const Data = require("./Data").default; | ||
model = Data.__getFromSlug(slug); | ||
model = Data.__getFromSlug(slug, adapter); | ||
} | ||
if (!this.__adapter) { | ||
return model; | ||
return model; | ||
} | ||
static getAdaptedModel(model, adapter, override) { | ||
if (!adapter) { | ||
adapter = this.__adapter?.constructor; | ||
} | ||
const adapter = this.__adapter.constructor; | ||
return model.withAdapter(adapter); | ||
if (!adapter) { | ||
throw new CoreError_1.default({ | ||
message: "Adapter is required in getAdaptedModel method", | ||
}); | ||
} | ||
adapter.__modelsMap ??= new Map(); | ||
let adaptedModel; | ||
if (!override) { | ||
adaptedModel = adapter?.__modelsMap.get(model.slug); | ||
} | ||
if (!adaptedModel) { | ||
adaptedModel = model.withAdapter(adapter); | ||
adapter.__modelsMap.set(model.slug, adaptedModel); | ||
} | ||
return adaptedModel; | ||
} | ||
@@ -195,0 +225,0 @@ /** |
@@ -14,2 +14,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
const Data_1 = __importDefault(require("./Data")); | ||
describe("Test Model", () => { | ||
@@ -337,2 +338,71 @@ let adapter; | ||
}); | ||
describe("Model unicity", () => { | ||
it("should get same model from slug with same adapter", () => { | ||
const model = Model_1.default.getFromSlug("accounts", adapter); | ||
const modelBis = Model_1.default.getFromSlug("accounts", adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should get different models from slug with different adapter", () => { | ||
const model = Model_1.default.getFromSlug("accounts"); | ||
const modelBis = Model_1.default.getFromSlug("accounts", adapter); | ||
expect(model).not.toBe(modelBis); | ||
}); | ||
it("should returns same model from slug and then adapter", () => { | ||
BaseModel = (0, test_utils_1.mockModel)(); | ||
const model = Model_1.default.getFromSlug(BaseModel.slug, adapter); | ||
const modelBis = Model_1.default.getAdaptedModel(BaseModel, adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should returns same model from adapter and then slug", () => { | ||
BaseModel = (0, test_utils_1.mockModel)(); | ||
const model = Model_1.default.getAdaptedModel(BaseModel, adapter); | ||
const modelBis = Model_1.default.getFromSlug(BaseModel.slug, adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should returns first cached model", () => { | ||
const baseAccountFromSlug = Model_1.default.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model_1.default.getAdaptedModel(index_1.models.Account, adapter); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class extends index_1.models.Account { | ||
}; | ||
const extendedAccountFromModel = Model_1.default.getAdaptedModel(extendedAccount, adapter); | ||
expect(extendedAccountFromModel.getBaseClass()).not.toBe(extendedAccount); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(index_1.models.Account); | ||
}); | ||
it("should be able to override model", () => { | ||
const baseAccountFromSlug = Model_1.default.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model_1.default.getAdaptedModel(index_1.models.Account, adapter); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class extends index_1.models.Account { | ||
}; | ||
const extendedAccountFromModel = Model_1.default.getAdaptedModel(extendedAccount, adapter, true); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(extendedAccount); | ||
}); | ||
it("Should be able to get adapted model from slug once it has been adapted from model", () => { | ||
const baseAccountFromSlug = Model_1.default.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model_1.default.getAdaptedModel(index_1.models.Account, adapter); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class ExtendedAccount extends index_1.models.Account { | ||
}; | ||
const extendedAccountFromModel = Model_1.default.getAdaptedModel(extendedAccount, adapter, true); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(extendedAccount); | ||
const extendedAccountFromSlug = Model_1.default.getFromSlug("accounts", adapter); | ||
expect(extendedAccountFromSlug.getBaseClass()).toBe(extendedAccount); | ||
}); | ||
it("Should be able to get adapted model from slug once it has been adapted from model on data", () => { | ||
const slug = "example"; | ||
const ExampleModel = class ExampleModel extends Data_1.default { | ||
static slug = slug; | ||
}; | ||
const baseModelFromSlug = Model_1.default.getFromSlug(slug, adapter); | ||
const baseModelFromModel = Model_1.default.getAdaptedModel(ExampleModel, adapter); | ||
expect(baseModelFromSlug).toBe(baseModelFromModel); | ||
expect(baseModelFromModel.getBaseClass()).not.toBe(ExampleModel); | ||
const extendedModelFromModel = Model_1.default.getAdaptedModel(ExampleModel, adapter, true); | ||
expect(extendedModelFromModel.getBaseClass()).toBe(ExampleModel); | ||
const extendedModelFromSlug = Model_1.default.getFromSlug(slug, adapter); | ||
expect(extendedModelFromSlug.getBaseClass()).toBe(ExampleModel); | ||
expect(extendedModelFromSlug).toBe(extendedModelFromModel); | ||
}); | ||
}); | ||
}); |
@@ -20,3 +20,2 @@ "use strict"; | ||
const field_types_1 = __importDefault(require("../enums/field-types")); | ||
const validator_types_1 = __importDefault(require("../enums/validator-types")); | ||
let Project = class Project extends Model_1.default { | ||
@@ -27,10 +26,10 @@ static __name = "Project"; | ||
static validators = [ | ||
{ type: validator_types_1.default.REQUIRED, options: { field: "name" } }, | ||
{ type: validator_types_1.default.REQUIRED, options: { field: "slug" } }, | ||
{ type: validator_types_1.default.REQUIRED, options: { field: "organization" } }, | ||
{ type: validator_types_1.default.UNIQUE, options: { field: "slug" } }, | ||
{ | ||
type: validator_types_1.default.REGEX, | ||
options: { field: "slug", pattern: "^[a-zA-Z0-9_\\-]+$" }, | ||
}, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "name" } }, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "slug" } }, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "organization" } }, | ||
// { type: ValidatorTypes.UNIQUE, options: { field: "slug" } }, | ||
// { | ||
// type: ValidatorTypes.REGEX, | ||
// options: { field: "slug", pattern: "^[a-zA-Z0-9_\\-]+$" }, | ||
// }, | ||
]; | ||
@@ -37,0 +36,0 @@ name; |
@@ -25,2 +25,3 @@ "use strict"; | ||
static scope = model_env_scopes_1.default.PROJECT; | ||
static configKey = "name"; | ||
static validators = [ | ||
@@ -27,0 +28,0 @@ { type: validator_types_1.default.REQUIRED, options: { field: "name" } }, |
@@ -8,2 +8,3 @@ import { AdapterFetcher } from "../types"; | ||
declare class Adapter { | ||
static __modelsMap: Map<string, typeof Model>; | ||
fetcher: AdapterFetcher; | ||
@@ -10,0 +11,0 @@ fieldsMap: { |
import Model from "./Model"; | ||
import ModelEnvScopes from "../enums/model-env-scopes"; | ||
import DataModel from "../models/DataModel"; | ||
import Adapter from "./Adapter"; | ||
declare class Data extends Model { | ||
@@ -8,7 +9,6 @@ static extendable: boolean; | ||
static __datamodel: DataModel; | ||
static __modelsMap: Map<string, typeof Data>; | ||
static getFromDatamodel(datamodel: DataModel): typeof Data; | ||
static __getFromSlug<M extends typeof Model = typeof Data>(slug: string): M; | ||
static getFromDatamodel(datamodel: DataModel, adapter?: typeof Adapter): typeof Data; | ||
static __getFromSlug<M extends typeof Model = typeof Data>(slug: string, adapter?: typeof Adapter): M; | ||
[prop: string]: any; | ||
} | ||
export default Data; |
@@ -28,3 +28,3 @@ import ModelEnvScopes from "../enums/model-env-scopes"; | ||
static __baseClass: typeof Model; | ||
static __decorated: typeof Model; | ||
static __modelsMap: Map<string, Map<typeof Adapter, typeof Model>>; | ||
__doc: DocumentDefinition; | ||
@@ -50,3 +50,4 @@ _id: FieldIdDefinition; | ||
static verifyAdapter(): void; | ||
static getFromSlug<M extends typeof Model = typeof Model>(slug: string, fallbackData?: boolean): M; | ||
static getFromSlug<M extends typeof Model = typeof Model>(slug: string, adapter?: typeof Adapter, fallbackData?: boolean): M; | ||
static getAdaptedModel<M extends typeof Model = typeof Model>(model: M, adapter?: typeof Adapter, override?: boolean): M; | ||
/** | ||
@@ -53,0 +54,0 @@ * Model instance getter. Returns the value for the specified key |
@@ -10,2 +10,3 @@ import Model from "../lib/Model"; | ||
static scope: ModelEnvScopes; | ||
static configKey: string; | ||
static validators: ValidatorsDefinition; | ||
@@ -12,0 +13,0 @@ name: FieldTextDefinition; |
@@ -192,2 +192,3 @@ import Adapter from "./lib/Adapter"; | ||
}; | ||
__modelsMap: Map<string, typeof Model>; | ||
}; | ||
@@ -237,3 +238,3 @@ export declare const mockModel: ({ scope, fields, validators, }?: { | ||
__baseClass: typeof Model; | ||
__decorated: typeof Model; | ||
__modelsMap: Map<string, Map<typeof Adapter, typeof Model>>; | ||
getBaseClass(): typeof Model; | ||
@@ -248,3 +249,4 @@ hasAdapter(): boolean; | ||
verifyAdapter(): void; | ||
getFromSlug<M extends typeof Model = typeof Model>(slug: string, fallbackData?: boolean): M; | ||
getFromSlug<M extends typeof Model = typeof Model>(slug: string, adapter?: typeof Adapter, fallbackData?: boolean): M; | ||
getAdaptedModel<M_1 extends typeof Model = typeof Model>(model: M_1, adapter?: typeof Adapter, override?: boolean): M_1; | ||
fromString<T_2 extends typeof Model>(this: T_2, str: string, cleanPayload?: boolean): Model; | ||
@@ -260,3 +262,3 @@ count<T_3 extends typeof Model>(this: T_3, query?: string | import("./types").JSONQuery, ctx?: any): Promise<number>; | ||
validate<T_11 extends typeof Model>(this: T_11, input: (import("./types").DocumentDefinition | InstanceType<T_11>)[], ctx?: any): Promise<boolean>; | ||
execute<M_1 extends typeof Model, A_1 extends keyof AdapterFetcher<M_1>, Args extends Parameters<AdapterFetcher<typeof Model>[A_1]>[0]>(this: M_1, action: A_1, args: Args, bindCtx?: any): Promise<ReturnType<AdapterFetcher<M_1>[A_1]>>; | ||
execute<M_2 extends typeof Model, A_1 extends keyof AdapterFetcher<M_2>, Args extends Parameters<AdapterFetcher<typeof Model>[A_1]>[0]>(this: M_2, action: A_1, args: Args, bindCtx?: any): Promise<ReturnType<AdapterFetcher<M_2>[A_1]>>; | ||
}; |
{ | ||
"name": "@graphand/core", | ||
"version": "0.3.10", | ||
"version": "0.3.12", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/graphand/core", |
@@ -9,2 +9,4 @@ import { AdapterFetcher } from "../types"; | ||
class Adapter { | ||
static __modelsMap: Map<string, typeof Model>; | ||
fetcher: AdapterFetcher; | ||
@@ -11,0 +13,0 @@ fieldsMap: { [T in FieldTypes]?: typeof Field<T> }; |
import { ControllerDefinition } from "../types"; | ||
import DataModel from "../models/DataModel"; | ||
import Model from "../lib/Model"; | ||
import ModelEnvScopes from "../enums/model-env-scopes"; | ||
@@ -11,4 +11,4 @@ | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -22,4 +22,4 @@ }, | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -33,4 +33,4 @@ }, | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -44,4 +44,4 @@ }, | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -55,4 +55,4 @@ }, | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -66,4 +66,4 @@ }, | ||
scope: ({ model }) => { | ||
const Model = DataModel.getFromSlug(model); | ||
if (Model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
const _model = Model.getFromSlug(model); | ||
if (_model.scope === ModelEnvScopes.GLOBAL) return "global"; | ||
return "project"; | ||
@@ -70,0 +70,0 @@ }, |
@@ -7,2 +7,3 @@ import DataModel from "../models/DataModel"; | ||
import FieldTypes from "../enums/field-types"; | ||
import Model from "./Model"; | ||
@@ -14,20 +15,66 @@ describe("Data", () => { | ||
it("should get same model from slug and from datamodel instance", async () => { | ||
const slug = faker.animal.type(); | ||
describe("model unicity", () => { | ||
it("should get same model from slug and from datamodel instance with same adapter", async () => { | ||
const slug = faker.animal.type(); | ||
const datamodel = new DataModel({ slug }); | ||
const datamodel = new DataModel({ slug }); | ||
const modelFromDM = Data.getFromDatamodel(datamodel); | ||
const modelFromSlug = Data.getFromSlug(slug); | ||
const modelFromDM = Data.getFromDatamodel(datamodel, adapter); | ||
const modelFromSlug = Data.getFromSlug(slug, adapter); | ||
expect(modelFromDM).toBe(modelFromSlug); | ||
}); | ||
expect(modelFromDM).toBe(modelFromSlug); | ||
}); | ||
it("getFromDatamodel should returns model with the instance adapter", async () => { | ||
const DM = DataModel.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker.animal.type() }); | ||
it("should get different models from slug and from datamodel instance with different adapters", async () => { | ||
const slug = faker.animal.type(); | ||
const modelFromDM = Data.getFromDatamodel(datamodel); | ||
const datamodel = new DataModel({ slug }); | ||
expect(modelFromDM.__adapter?.constructor).toBe(adapter); | ||
const modelFromDM = Data.getFromDatamodel(datamodel); | ||
const modelFromSlug = Data.getFromSlug(slug, adapter); | ||
expect(modelFromDM).not.toBe(modelFromSlug); | ||
}); | ||
it("getFromDatamodel should returns model with the instance adapter", async () => { | ||
const DM = DataModel.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker.animal.type() }); | ||
const modelFromDM = Data.getFromDatamodel(datamodel); | ||
expect(modelFromDM.__adapter?.constructor).toBe(adapter); | ||
}); | ||
it("getFromDatamodel should save adapted model in cache", () => { | ||
const DM = DataModel.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker.animal.type() }); | ||
const modelFromDM = Data.getFromDatamodel(datamodel, adapter); | ||
const modelFromDataSlug = Data.__getFromSlug(datamodel.slug, adapter); | ||
const modelFromModelSlug = Model.getFromSlug(datamodel.slug, adapter); | ||
expect(modelFromDM).toBe(modelFromDataSlug); | ||
expect(modelFromDM).toBe(modelFromModelSlug); | ||
expect(modelFromDataSlug).toBe(modelFromModelSlug); | ||
}); | ||
it("getFromDatamodel should override adapted model in cache", () => { | ||
const DM = DataModel.withAdapter(adapter); | ||
const datamodel = new DM({ slug: faker.animal.type() }); | ||
const modelFromDataSlug = Data.__getFromSlug(datamodel.slug, adapter); | ||
const modelFromDM = Data.getFromDatamodel(datamodel, adapter); | ||
const modelFromModelSlug = Model.getFromSlug(datamodel.slug, adapter); | ||
expect(modelFromModelSlug).toBe(modelFromDM); | ||
expect(modelFromDM).not.toBe(modelFromDataSlug); | ||
const adaptedModelFromModel = Model.getAdaptedModel( | ||
modelFromDataSlug, | ||
adapter | ||
); | ||
expect(adaptedModelFromModel).toBe(modelFromModelSlug); | ||
expect(modelFromDM).toBe(modelFromModelSlug); | ||
}); | ||
}); | ||
@@ -74,3 +121,21 @@ | ||
it("Test", () => {}); | ||
it("Multiple model get should return the same model & initialize once", async () => { | ||
const DM = DataModel.withAdapter(adapter); | ||
const slug = faker.lorem.word(); | ||
await DM.create({ slug }); | ||
const model = Data.getFromSlug(slug, adapter); | ||
const modelBis = Data.getFromSlug(slug, adapter); | ||
expect(model).toBe(modelBis); | ||
const spy = jest.spyOn(model, "reloadModel"); | ||
expect(spy).toHaveBeenCalledTimes(0); | ||
await expect(model.initialize()).resolves.toBeUndefined(); | ||
await expect(modelBis.initialize()).resolves.toBeUndefined(); | ||
expect(spy).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
@@ -15,32 +15,45 @@ import Model from "./Model"; | ||
static __datamodel: DataModel; | ||
static __modelsMap: Map<string, typeof Data> = new Map(); | ||
static getFromDatamodel(datamodel: DataModel): typeof Data { | ||
let model = Data.__modelsMap.get(datamodel.slug); | ||
if (!model) { | ||
model = class extends Data { | ||
static __name = datamodel.name; | ||
static getFromDatamodel( | ||
datamodel: DataModel, | ||
adapter?: typeof Adapter | ||
): typeof Data { | ||
if (!adapter) { | ||
adapter = datamodel.model.__adapter?.constructor as typeof Adapter; | ||
} | ||
static slug = datamodel.slug; | ||
static fields = datamodel.fields; | ||
static validators = []; | ||
static configKey = datamodel.configKey; | ||
}; | ||
if (adapter) { | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
model.__datamodel = datamodel; | ||
let model = class extends Data { | ||
static __name = datamodel.name; | ||
Data.__modelsMap.set(datamodel.slug, model); | ||
} | ||
static slug = datamodel.slug; | ||
static fields = datamodel.fields; | ||
static validators = []; | ||
static configKey = datamodel.configKey; | ||
}; | ||
const adapter = datamodel.model.__adapter?.constructor as typeof Adapter; | ||
model.__datamodel = datamodel; | ||
if (adapter) { | ||
return model.withAdapter(adapter); | ||
model = model.withAdapter(adapter); | ||
} | ||
adapter?.__modelsMap.set(datamodel.slug, model); | ||
return model; | ||
} | ||
static __getFromSlug<M extends typeof Model = typeof Data>(slug: string): M { | ||
let model = Data.__modelsMap.get(slug); | ||
static __getFromSlug<M extends typeof Model = typeof Data>( | ||
slug: string, | ||
adapter?: typeof Adapter | ||
): M { | ||
if (adapter) { | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
let model: typeof Data = adapter?.__modelsMap.get(slug) as typeof Data; | ||
if (!model) { | ||
@@ -61,5 +74,7 @@ model = class extends Data { | ||
const datamodel = await DataModel.withAdapter( | ||
this.__adapter.constructor as typeof Adapter | ||
).get({ filter: { slug } }, ctx); | ||
const adapter = this.__adapter.constructor as typeof Adapter; | ||
const datamodel = await DataModel.withAdapter(adapter).get( | ||
{ filter: { slug } }, | ||
ctx | ||
); | ||
@@ -85,3 +100,7 @@ if (!datamodel) { | ||
Data.__modelsMap.set(slug, model); | ||
if (adapter) { | ||
model = model.withAdapter(adapter); | ||
} | ||
adapter?.__modelsMap.set(slug, model); | ||
} | ||
@@ -88,0 +107,0 @@ |
@@ -109,3 +109,3 @@ import FieldTypes from "../enums/field-types"; | ||
const adapter = from.model.__adapter.constructor as typeof Adapter; | ||
let model = Model.getFromSlug(this.options.ref).withAdapter(adapter); | ||
let model = Model.getFromSlug(this.options.ref, adapter); | ||
@@ -112,0 +112,0 @@ if (this.options.multiple) { |
@@ -9,2 +9,3 @@ import { mockAdapter, mockModel } from "../test-utils"; | ||
import { getRecursiveValidatorsFromModel } from "../utils"; | ||
import Data from "./Data"; | ||
@@ -420,2 +421,127 @@ describe("Test Model", () => { | ||
}); | ||
describe("Model unicity", () => { | ||
it("should get same model from slug with same adapter", () => { | ||
const model = Model.getFromSlug("accounts", adapter); | ||
const modelBis = Model.getFromSlug("accounts", adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should get different models from slug with different adapter", () => { | ||
const model = Model.getFromSlug("accounts"); | ||
const modelBis = Model.getFromSlug("accounts", adapter); | ||
expect(model).not.toBe(modelBis); | ||
}); | ||
it("should returns same model from slug and then adapter", () => { | ||
BaseModel = mockModel(); | ||
const model = Model.getFromSlug(BaseModel.slug, adapter); | ||
const modelBis = Model.getAdaptedModel(BaseModel, adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should returns same model from adapter and then slug", () => { | ||
BaseModel = mockModel(); | ||
const model = Model.getAdaptedModel(BaseModel, adapter); | ||
const modelBis = Model.getFromSlug(BaseModel.slug, adapter); | ||
expect(model).toBe(modelBis); | ||
}); | ||
it("should returns first cached model", () => { | ||
const baseAccountFromSlug = Model.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model.getAdaptedModel( | ||
models.Account, | ||
adapter | ||
); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class extends models.Account {}; | ||
const extendedAccountFromModel = Model.getAdaptedModel( | ||
extendedAccount, | ||
adapter | ||
); | ||
expect(extendedAccountFromModel.getBaseClass()).not.toBe(extendedAccount); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(models.Account); | ||
}); | ||
it("should be able to override model", () => { | ||
const baseAccountFromSlug = Model.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model.getAdaptedModel( | ||
models.Account, | ||
adapter | ||
); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class extends models.Account {}; | ||
const extendedAccountFromModel = Model.getAdaptedModel( | ||
extendedAccount, | ||
adapter, | ||
true | ||
); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(extendedAccount); | ||
}); | ||
it("Should be able to get adapted model from slug once it has been adapted from model", () => { | ||
const baseAccountFromSlug = Model.getFromSlug("accounts", adapter); | ||
const baseAccountFromModel = Model.getAdaptedModel( | ||
models.Account, | ||
adapter | ||
); | ||
expect(baseAccountFromSlug).toBe(baseAccountFromModel); | ||
const extendedAccount = class ExtendedAccount extends models.Account {}; | ||
const extendedAccountFromModel = Model.getAdaptedModel( | ||
extendedAccount, | ||
adapter, | ||
true | ||
); | ||
expect(extendedAccountFromModel.getBaseClass()).toBe(extendedAccount); | ||
const extendedAccountFromSlug = Model.getFromSlug("accounts", adapter); | ||
expect(extendedAccountFromSlug.getBaseClass()).toBe(extendedAccount); | ||
}); | ||
it("Should be able to get adapted model from slug once it has been adapted from model on data", () => { | ||
const slug = "example"; | ||
const ExampleModel = class ExampleModel extends Data { | ||
static slug = slug; | ||
}; | ||
const baseModelFromSlug = Model.getFromSlug(slug, adapter); | ||
const baseModelFromModel = Model.getAdaptedModel(ExampleModel, adapter); | ||
expect(baseModelFromSlug).toBe(baseModelFromModel); | ||
expect(baseModelFromModel.getBaseClass()).not.toBe(ExampleModel); | ||
const extendedModelFromModel = Model.getAdaptedModel( | ||
ExampleModel, | ||
adapter, | ||
true | ||
); | ||
expect(extendedModelFromModel.getBaseClass()).toBe(ExampleModel); | ||
const extendedModelFromSlug = Model.getFromSlug(slug, adapter); | ||
expect(extendedModelFromSlug.getBaseClass()).toBe(ExampleModel); | ||
expect(extendedModelFromSlug).toBe(extendedModelFromModel); | ||
}); | ||
}); | ||
}); |
@@ -52,3 +52,4 @@ import ModelEnvScopes from "../enums/model-env-scopes"; | ||
static __baseClass: typeof Model; | ||
static __decorated: typeof Model; | ||
static __modelsMap: Map<string, Map<typeof Adapter, typeof Model>> = | ||
new Map(); | ||
@@ -263,17 +264,60 @@ __doc: DocumentDefinition; | ||
slug: string, | ||
fallbackData = true | ||
adapter?: typeof Adapter, | ||
fallbackData: boolean = true | ||
): M { | ||
if (!adapter) { | ||
adapter = this.__adapter?.constructor as typeof Adapter; | ||
} | ||
if (adapter) { | ||
adapter.__modelsMap ??= new Map(); | ||
} | ||
const models = require("../index").models as Record<string, typeof Model>; | ||
let model: M = Object.values(models).find((m) => m.slug === slug) as M; | ||
if (!model && fallbackData) { | ||
if (model) { | ||
let adaptedModel = adapter?.__modelsMap.get(model.slug) as M; | ||
if (!adaptedModel && adapter) { | ||
adaptedModel = model.withAdapter(adapter); | ||
adapter.__modelsMap.set(model.slug, adaptedModel); | ||
} | ||
model = adaptedModel || model; | ||
} else if (fallbackData) { | ||
const Data = require("./Data").default; | ||
model = Data.__getFromSlug(slug); | ||
model = Data.__getFromSlug(slug, adapter); | ||
} | ||
if (!this.__adapter) { | ||
return model; | ||
return model; | ||
} | ||
static getAdaptedModel<M extends typeof Model = typeof Model>( | ||
model: M, | ||
adapter?: typeof Adapter, | ||
override?: boolean | ||
): M { | ||
if (!adapter) { | ||
adapter = this.__adapter?.constructor as typeof Adapter; | ||
} | ||
const adapter = this.__adapter.constructor as typeof Adapter; | ||
return model.withAdapter(adapter); | ||
if (!adapter) { | ||
throw new CoreError({ | ||
message: "Adapter is required in getAdaptedModel method", | ||
}); | ||
} | ||
adapter.__modelsMap ??= new Map(); | ||
let adaptedModel: M; | ||
if (!override) { | ||
adaptedModel = adapter?.__modelsMap.get(model.slug) as M; | ||
} | ||
if (!adaptedModel) { | ||
adaptedModel = model.withAdapter(adapter); | ||
adapter.__modelsMap.set(model.slug, adaptedModel); | ||
} | ||
return adaptedModel; | ||
} | ||
@@ -280,0 +324,0 @@ |
@@ -23,10 +23,10 @@ import Model from "../lib/Model"; | ||
static validators: ValidatorsDefinition = [ | ||
{ type: ValidatorTypes.REQUIRED, options: { field: "name" } }, | ||
{ type: ValidatorTypes.REQUIRED, options: { field: "slug" } }, | ||
{ type: ValidatorTypes.REQUIRED, options: { field: "organization" } }, | ||
{ type: ValidatorTypes.UNIQUE, options: { field: "slug" } }, | ||
{ | ||
type: ValidatorTypes.REGEX, | ||
options: { field: "slug", pattern: "^[a-zA-Z0-9_\\-]+$" }, | ||
}, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "name" } }, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "slug" } }, | ||
// { type: ValidatorTypes.REQUIRED, options: { field: "organization" } }, | ||
// { type: ValidatorTypes.UNIQUE, options: { field: "slug" } }, | ||
// { | ||
// type: ValidatorTypes.REGEX, | ||
// options: { field: "slug", pattern: "^[a-zA-Z0-9_\\-]+$" }, | ||
// }, | ||
]; | ||
@@ -33,0 +33,0 @@ |
@@ -21,2 +21,3 @@ import Model from "../lib/Model"; | ||
static scope = ModelEnvScopes.PROJECT; | ||
static configKey = "name"; | ||
static validators: ValidatorsDefinition = [ | ||
@@ -23,0 +24,0 @@ { type: ValidatorTypes.REQUIRED, options: { field: "name" } }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
397250
10643