From 2166ce644d919ec0a9dc057c2ee4a67318ae5c3f Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 13:37:11 +0330 Subject: [PATCH 1/7] :bulb: add sample doc for a document about performance --- examples/whyLesan/performance.ts | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 examples/whyLesan/performance.ts diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts new file mode 100644 index 0000000..dda6ba8 --- /dev/null +++ b/examples/whyLesan/performance.ts @@ -0,0 +1,65 @@ +import { + ActFn, + lesan, + MongoClient, + number, + object, + RelationDataType, + RelationSortOrderType, + string, +} from "../../mod.ts"; + +const coreApp = lesan(); + +const client = await new MongoClient("mongodb://127.0.0.1:27017/").connect(); + +const db = client.db("performance"); + +coreApp.odm.setDb(db); + +// ================== MODEL SECTION ================== +// ------------------ Country Model ------------------ +const locationPure = { + name: string(), + population: number(), + abb: string(), +}; +const countryRelations = {}; +const countries = coreApp.odm.newModel( + "country", + locationPure, + countryRelations, +); + +// ------------------ Province Model ------------------ +const provinceRelations = { + country: { + optional: false, + schemaName: "country", + type: "single" as RelationDataType, + relatedRelations: { + provinces: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + provincesByPopulation: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "population", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, +}; + +const provinces = coreApp.odm.newModel( + "province", + locationPure, + provinceRelations, +); From b406dba283de7db6830406e611f6174b0000e6e6 Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 13:38:09 +0330 Subject: [PATCH 2/7] :bulb: add function for add country for perfomance doc --- examples/whyLesan/performance.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts index dda6ba8..89a17c7 100644 --- a/examples/whyLesan/performance.ts +++ b/examples/whyLesan/performance.ts @@ -63,3 +63,32 @@ const provinces = coreApp.odm.newModel( locationPure, provinceRelations, ); + +// ================== FUNCTIONS SECTION ================== +// ------------------ Country Founctions ------------------ +// ------------------ Add Country ------------------ +const addCountryValidator = () => { + return object({ + set: object(locationPure), + get: coreApp.schemas.selectStruct("country", 1), + }); +}; + +const addCountry: ActFn = async (body) => { + const { name, population, abb } = body.details.set; + return await countries.insertOne({ + doc: { + name, + population, + abb, + }, + projection: body.details.get, + }); +}; + +coreApp.acts.setAct({ + schema: "country", + actName: "addCountry", + validator: addCountryValidator(), + fn: addCountry, +}); From 219a06879afcba9f2b7dd230ca4c8c93367f331e Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 13:59:20 +0330 Subject: [PATCH 3/7] :bulb: add province function for perfomance doc --- examples/whyLesan/performance.ts | 50 +++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts index 89a17c7..1a87dce 100644 --- a/examples/whyLesan/performance.ts +++ b/examples/whyLesan/performance.ts @@ -4,6 +4,8 @@ import { MongoClient, number, object, + ObjectId, + objectIdValidation, RelationDataType, RelationSortOrderType, string, @@ -19,7 +21,7 @@ coreApp.odm.setDb(db); // ================== MODEL SECTION ================== // ------------------ Country Model ------------------ -const locationPure = { +const pure = { name: string(), population: number(), abb: string(), @@ -27,7 +29,7 @@ const locationPure = { const countryRelations = {}; const countries = coreApp.odm.newModel( "country", - locationPure, + pure, countryRelations, ); @@ -60,7 +62,7 @@ const provinceRelations = { const provinces = coreApp.odm.newModel( "province", - locationPure, + pure, provinceRelations, ); @@ -69,7 +71,7 @@ const provinces = coreApp.odm.newModel( // ------------------ Add Country ------------------ const addCountryValidator = () => { return object({ - set: object(locationPure), + set: object(pure), get: coreApp.schemas.selectStruct("country", 1), }); }; @@ -92,3 +94,43 @@ coreApp.acts.setAct({ validator: addCountryValidator(), fn: addCountry, }); + +// ------------------ Province Founctions ------------------ +// ------------------ Add Propvince ------------------ +const addProvinceValidator = () => { + return object({ + set: object({ + ...pure, + countryId: objectIdValidation, + }), + get: coreApp.schemas.selectStruct("province", 1), + }); +}; + +const addProvince: ActFn = async (body) => { + const { name, population, abb, countryId } = body.details.set; + return await provinces.insertOne({ + doc: { + name, + population, + abb, + }, + relations: { + country: { + _ids: new ObjectId(countryId), + relatedRelations: { + provinces: true, + provincesByPopulation: true, + }, + }, + }, + projection: body.details.get, + }); +}; + +coreApp.acts.setAct({ + schema: "province", + actName: "addProvince", + validator: addProvinceValidator(), + fn: addProvince, +}); From db11a2b34dad50da82678c8e2eac3006c4301742 Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 16:59:05 +0330 Subject: [PATCH 4/7] :bulb: add city model for performance doc --- examples/whyLesan/performance.ts | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts index 1a87dce..79cec9f 100644 --- a/examples/whyLesan/performance.ts +++ b/examples/whyLesan/performance.ts @@ -66,6 +66,62 @@ const provinces = coreApp.odm.newModel( provinceRelations, ); +// ------------------ City Model ------------------ +const cityRelations = { + country: { + optional: false, + schemaName: "country", + type: "single" as RelationDataType, + relatedRelations: { + cities: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + citiesByPopulation: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "population", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, + province: { + optional: false, + schemaName: "province", + type: "single" as RelationDataType, + relatedRelations: { + cities: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + citiesByPopulation: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "population", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, +}; + +const cities = coreApp.odm.newModel( + "city", + pure, + cityRelations, +); + // ================== FUNCTIONS SECTION ================== // ------------------ Country Founctions ------------------ // ------------------ Add Country ------------------ From 2971850405a69e0df101681b6a40e3ab6e79d3ec Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 17:02:38 +0330 Subject: [PATCH 5/7] :bulb: add city fn for performance doc --- examples/whyLesan/performance.ts | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts index 79cec9f..bbddef6 100644 --- a/examples/whyLesan/performance.ts +++ b/examples/whyLesan/performance.ts @@ -190,3 +190,52 @@ coreApp.acts.setAct({ validator: addProvinceValidator(), fn: addProvince, }); + +// ------------------ City Founctions ------------------ +// ------------------ Add City ------------------ +const addCityValidator = () => { + return object({ + set: object({ + ...pure, + countryId: objectIdValidation, + provinceId: objectIdValidation, + }), + get: coreApp.schemas.selectStruct("city", 1), + }); +}; + +const addCity: ActFn = async (body) => { + const { name, population, abb, countryId, provinceId } = body.details.set; + + return await cities.insertOne({ + doc: { + name, + population, + abb, + }, + relations: { + country: { + _ids: new ObjectId(countryId), + relatedRelations: { + cities: true, + citiesByPopulation: true, + }, + }, + province: { + _ids: new ObjectId(provinceId), + relatedRelations: { + cities: true, + citiesByPopulation: true, + }, + }, + }, + projection: body.details.get, + }); +}; + +coreApp.acts.setAct({ + schema: "city", + actName: "addCity", + validator: addCityValidator(), + fn: addCity, +}); From 4dde247d7fbe41d5e320e6cf50102dd7abd1f080 Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 4 May 2024 18:43:56 +0330 Subject: [PATCH 6/7] :bulb: add user model for perfomance doc --- examples/whyLesan/performance.ts | 113 +++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/examples/whyLesan/performance.ts b/examples/whyLesan/performance.ts index bbddef6..471c1eb 100644 --- a/examples/whyLesan/performance.ts +++ b/examples/whyLesan/performance.ts @@ -122,6 +122,91 @@ const cities = coreApp.odm.newModel( cityRelations, ); +// ------------------ User Model ------------------ +const userPure = { + name: string(), + family: string(), + age: number(), +}; + +const userRelations = { + country: { + optional: false, + schemaName: "country", + type: "single" as RelationDataType, + relatedRelations: { + users: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + usersByAge: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "age", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, + province: { + optional: false, + schemaName: "province", + type: "single" as RelationDataType, + relatedRelations: { + users: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + usersByAge: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "age", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, + city: { + optional: false, + schemaName: "city", + type: "single" as RelationDataType, + relatedRelations: { + users: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "_id", + order: "desc" as RelationSortOrderType, + }, + }, + usersByAge: { + type: "multiple" as RelationDataType, + limit: 50, + sort: { + field: "age", + order: "desc" as RelationSortOrderType, + }, + }, + }, + }, +}; + +const users = coreApp.odm.newModel( + "user", + userPure, + userRelations, +); + // ================== FUNCTIONS SECTION ================== // ------------------ Country Founctions ------------------ // ------------------ Add Country ------------------ @@ -151,6 +236,34 @@ coreApp.acts.setAct({ fn: addCountry, }); +// ------------------ get Countries ------------------ +const getCountriesValidator = () => { + return object({ + set: object({}), + get: coreApp.schemas.selectStruct("country", 2), + }); +}; +const getCountries: ActFn = async (body) => { + const { + set, + get, + } = body.details; + + return await countries + .aggregation({ + pipeline: [], + projection: get, + }) + .toArray(); +}; + +coreApp.acts.setAct({ + schema: "country", + actName: "getCountries", + validator: getCountriesValidator(), + fn: getCountries, +}); + // ------------------ Province Founctions ------------------ // ------------------ Add Propvince ------------------ const addProvinceValidator = () => { From e88ac3484e14656c4725ddad7ae26e9f3caf6b75 Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Thu, 16 May 2024 18:54:54 +0330 Subject: [PATCH 7/7] :sparkles: add exclude options --- src/models/pure/getPureModel.ts | 3 +- src/models/schema/createStruct.ts | 5 +- .../schema/getFlattenPureFromRelations.ts | 7 ++- src/models/schema/getPureFromMainRelations.ts | 18 ++++-- .../schema/getPureFromRelatedRelations.ts | 5 +- src/models/schema/getPureSchema.ts | 8 ++- src/models/types.ts | 1 + src/odm/mod.ts | 63 ++++++++++--------- src/odm/newModel/mod.ts | 2 + 9 files changed, 67 insertions(+), 45 deletions(-) diff --git a/src/models/pure/getPureModel.ts b/src/models/pure/getPureModel.ts index bbee260..9ef0f9d 100644 --- a/src/models/pure/getPureModel.ts +++ b/src/models/pure/getPureModel.ts @@ -1,4 +1,5 @@ import { throwError } from "../../utils/throwError.ts"; +import { getPureSchema } from "../mod.ts"; import { schemaFns, TSchemas } from "../mod.ts"; /** @@ -8,6 +9,6 @@ import { schemaFns, TSchemas } from "../mod.ts"; export const getPureModel = (schemasObj: TSchemas, name: string) => { const schemas = schemaFns(schemasObj).getSchemas(); return schemas[name] - ? schemas[name].pure + ? getPureSchema(schemas, name) : throwError(`Schema ${name} is not exist in the Schema Object`); }; diff --git a/src/models/schema/createStruct.ts b/src/models/schema/createStruct.ts index eefbf49..13abdff 100644 --- a/src/models/schema/createStruct.ts +++ b/src/models/schema/createStruct.ts @@ -1,7 +1,7 @@ import { assign, object } from "../../npmDeps.ts"; import { createEmbedded } from "./createEmbedded.ts"; import { getSchema } from "./getSchema.ts"; -import { TSchemas } from "./mod.ts"; +import { getPureSchema, TSchemas } from "./mod.ts"; /** * create struct features, struct feature is used for create client of db. @@ -29,9 +29,8 @@ import { TSchemas } from "./mod.ts"; * ), */ export const createStruct = (schemas: TSchemas, schemaName: string) => { - const schema = getSchema(schemas, schemaName); return assign( - object(schema.pure), + object(getPureSchema(schemas, schemaName)), object(createEmbedded(schemas, schemaName)), ); }; diff --git a/src/models/schema/getFlattenPureFromRelations.ts b/src/models/schema/getFlattenPureFromRelations.ts index beaa419..c576225 100644 --- a/src/models/schema/getFlattenPureFromRelations.ts +++ b/src/models/schema/getFlattenPureFromRelations.ts @@ -1,11 +1,12 @@ import { object } from "../../npmDeps.ts"; +import { getPureSchema } from "./getPureSchema.ts"; import { getSchema } from "./getSchema.ts"; import { TSchemas } from "./mod.ts"; export const getFlattenPureFromRelations = ( schemas: TSchemas, schemaName: string, - relationType: "MainRelations" | "RelatedRelations" | "All" + relationType: "MainRelations" | "RelatedRelations" | "All", ) => { const schema = getSchema(schemas, schemaName); let pureSchemas = {}; @@ -15,7 +16,7 @@ export const getFlattenPureFromRelations = ( pureSchemas = { ...pureSchemas, [property]: object( - schemas[schema.mainRelations[property].schemaName]?.pure + getPureSchema(schemas, schema.mainRelations[property].schemaName), ), }; } @@ -25,7 +26,7 @@ export const getFlattenPureFromRelations = ( pureSchemas = { ...pureSchemas, [property]: object( - schemas[schema.relatedRelations[property].schemaName]?.pure + getPureSchema(schemas, schema.relatedRelations[property].schemaName), ), }; } diff --git a/src/models/schema/getPureFromMainRelations.ts b/src/models/schema/getPureFromMainRelations.ts index 15b372f..fd14951 100644 --- a/src/models/schema/getPureFromMainRelations.ts +++ b/src/models/schema/getPureFromMainRelations.ts @@ -1,6 +1,6 @@ import { array, object, optional } from "../../npmDeps.ts"; import { getSchema } from "./getSchema.ts"; -import { TSchemas } from "./mod.ts"; +import { getPureSchema, TSchemas } from "./mod.ts"; export const getPureFromMainRelations = ( schemas: TSchemas, @@ -15,15 +15,23 @@ export const getPureFromMainRelations = ( [property]: schema.mainRelations[property].type === "single" ? schema.mainRelations[property].optional === true ? optional( - object(schemas[schema.mainRelations[property].schemaName]?.pure), + object( + getPureSchema(schemas, schema.mainRelations[property].schemaName), + ), + ) + : object( + getPureSchema(schemas, schema.mainRelations[property].schemaName), ) - : object(schemas[schema.mainRelations[property].schemaName]?.pure) : schema.mainRelations[property].optional === true ? optional(array( - object(schemas[schema.mainRelations[property].schemaName]?.pure), + object( + getPureSchema(schemas, schema.mainRelations[property].schemaName), + ), )) : array( - object(schemas[schema.mainRelations[property].schemaName]?.pure), + object( + getPureSchema(schemas, schema.mainRelations[property].schemaName), + ), ), }; } diff --git a/src/models/schema/getPureFromRelatedRelations.ts b/src/models/schema/getPureFromRelatedRelations.ts index 11883e1..ce25576 100644 --- a/src/models/schema/getPureFromRelatedRelations.ts +++ b/src/models/schema/getPureFromRelatedRelations.ts @@ -1,3 +1,4 @@ +import { getPureSchema } from "https://deno.land/x/lesan@v0.0.98/src/models/mod.ts"; import { array, object } from "../../npmDeps.ts"; import { getSchema } from "./getSchema.ts"; import { TSchemas } from "./mod.ts"; @@ -32,7 +33,9 @@ export const getPureFromRelatedRelations = ( pureSchemas = { ...pureSchemas, [property]: array( - object(schemas[schema.relatedRelations[property].schemaName]?.pure), + object( + getPureSchema(schemas, schema.relatedRelations[property].schemaName), + ), ), }; } diff --git a/src/models/schema/getPureSchema.ts b/src/models/schema/getPureSchema.ts index 0e57ce0..503a79b 100644 --- a/src/models/schema/getPureSchema.ts +++ b/src/models/schema/getPureSchema.ts @@ -17,5 +17,11 @@ export const getPureSchema = (schemas: TSchemas, schemaName: string) => { throw new Error(`Schema ${schemaName} not found`); } - return schema.pure; + const pure = schema.pure; + + if (schema.options && schema.options.excludes) { + schema.options.excludes.forEach((p) => delete pure[p]); + } + + return pure; }; diff --git a/src/models/types.ts b/src/models/types.ts index 1520293..4f8fb3c 100644 --- a/src/models/types.ts +++ b/src/models/types.ts @@ -113,4 +113,5 @@ export interface IModel { relations: Record; mainRelations: Record; relatedRelations: Record; + options?: { excludes?: (string | number)[] }; } diff --git a/src/odm/mod.ts b/src/odm/mod.ts index 8f297c9..a61e4c6 100644 --- a/src/odm/mod.ts +++ b/src/odm/mod.ts @@ -1,9 +1,9 @@ import { Database } from "../deps.ts"; import { - IPureFields, - IRelationsFileds, - TRelation, - TSchemas, + IPureFields, + IRelationsFileds, + TRelation, + TSchemas, } from "../models/mod.ts"; import { schemaFns } from "../models/mod.ts"; import { assert, enums } from "../npmDeps.ts"; @@ -11,37 +11,38 @@ import { throwError } from "../utils/throwError.ts"; import { newModel } from "./newModel/mod.ts"; export const odm = (schemasObj: TSchemas) => { - let mongoDb: Database; + let mongoDb: Database; - const setDb = (db: Database) => (mongoDb = db); + const setDb = (db: Database) => (mongoDb = db); - const getDbClient = () => mongoDb; + const getDbClient = () => mongoDb; - const getCollection = (collection: string) => { - const db = getDbClient(); - const getSchemas = enums(schemaFns(schemasObj).getSchemasKeys()); - assert(collection, getSchemas); - return db - ? db.collection(collection) - : throwError("No database connection"); - }; + const getCollection = (collection: string) => { + const db = getDbClient(); + const getSchemas = enums(schemaFns(schemasObj).getSchemasKeys()); + assert(collection, getSchemas); + return db + ? db.collection(collection) + : throwError("No database connection"); + }; - return { - setDb, - getCollection, - newModel: ( - name: string, - pureFields: PF, - relations: TR, - ) => - newModel( - mongoDb, - schemasObj, - name, - pureFields, - relations, - ), - }; + return { + setDb, + getCollection, + newModel: ( + name: string, + pureFields: PF, + relations: TR, + options?: { excludes?: Partial<(keyof PF)>[] }, + ) => newModel( + mongoDb, + schemasObj, + name, + pureFields, + relations, + options, + ), + }; }; export * from "./utils/mod.ts"; diff --git a/src/odm/newModel/mod.ts b/src/odm/newModel/mod.ts index e42fe63..58f4c7b 100644 --- a/src/odm/newModel/mod.ts +++ b/src/odm/newModel/mod.ts @@ -40,6 +40,7 @@ export const newModel = < name: string, pureFields: PF, relations: TR, + options?: { excludes?: Partial<(keyof PF)>[] }, ) => { type InferPureFieldsType = { [key in keyof PF]?: Infer; @@ -85,6 +86,7 @@ export const newModel = < relations, mainRelations, relatedRelations: {}, + options: (options as { excludes?: (string | number)[] }), }; interface IFindModelInputs {