diff --git a/.eslintignore b/.eslintignore index 28f92eb7..ce55757a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,5 @@ # temporary system/ components/ -nsx/ \ No newline at end of file +nsx/ +mock/ \ No newline at end of file diff --git a/lib/actions/actions-init.tsx b/lib/actions/actions-init.tsx index 59f0baa3..9c388e67 100644 --- a/lib/actions/actions-init.tsx +++ b/lib/actions/actions-init.tsx @@ -1,14 +1,22 @@ // actions-init.tsx /* eslint-disable react-hooks/exhaustive-deps, react-hooks/rules-of-hooks */ 'use client'; -import type { ISupportedContexts, IActionBack, IAction, IStatus, ICreateAction, IDispatch, IPayload } from '@types'; +import type { + ISupportedContexts, + IActionBack, + IActionDispatch, + IStatus, + ICreateAction, + IDispatch, + IPayload, +} from '@types'; import { createLogMessage, fluxLog as log } from '@log'; import { useState, useEffect, useContext, useRef } from 'react'; export const CreateAction: ICreateAction = ({ action, type, verb, context }: IActionBack) => - ({ cb }: IAction) => { + ({ cb }: IActionDispatch) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const noop: IDispatch = async (...payload: IPayload): Promise => {}; diff --git a/lib/actions/db-users-actions.tsx b/lib/actions/db-users-actions.tsx index 8b68bed8..9b22d2e8 100644 --- a/lib/actions/db-users-actions.tsx +++ b/lib/actions/db-users-actions.tsx @@ -9,7 +9,7 @@ import { AuthContext } from '@state'; /* public */ export const ALoadUserMeta = BuildAction(CreateAction, { action: 'hydrate', - type: 'users', + type: 'database', verb: 'load user meta', context: AuthContext, }); diff --git a/lib/model/interfaces/constants.ts b/lib/model/constants.ts similarity index 97% rename from lib/model/interfaces/constants.ts rename to lib/model/constants.ts index d4dd5c12..275234ca 100644 --- a/lib/model/interfaces/constants.ts +++ b/lib/model/constants.ts @@ -5,7 +5,7 @@ let usersDatabase = ''; let defaultOrg = ''; let DATABASE_USERS_STRING = ''; let DATABASE_ORGS_STRING = ''; -let DEFAULT_ORG = 'demo'; +let DEFAULT_ORG = 'community'; /* lean */ if (process.env.NEXUS_MODE !== 'full') { diff --git a/lib/model/index.ts b/lib/model/index.ts index 84f192ea..2fe4d8f2 100644 --- a/lib/model/index.ts +++ b/lib/model/index.ts @@ -10,7 +10,8 @@ export { DATABASE_STRING, DATABASE_USERS_STRING, DATABASE_ORGS_STRING, -} from './interfaces'; + DEFAULT_ORG, +} from './constants'; /* rm-decorators */ export { decorateRMCharacters } from './decorators'; diff --git a/lib/model/interfaces/index.ts b/lib/model/interfaces/index.ts index 325b6807..4a55ecd1 100644 --- a/lib/model/interfaces/index.ts +++ b/lib/model/interfaces/index.ts @@ -3,7 +3,6 @@ /* mdb-ifaces */ /* const */ -export { DATABASE_STRING, DATABASE_USERS_STRING, DATABASE_ORGS_STRING } from './constants'; // default methods export { NexusInterface } from './mdb-init-interface'; diff --git a/lib/model/interfaces/mdb-init-interface.ts b/lib/model/interfaces/mdb-init-interface.ts index 3f238658..9f1a3214 100644 --- a/lib/model/interfaces/mdb-init-interface.ts +++ b/lib/model/interfaces/mdb-init-interface.ts @@ -2,20 +2,15 @@ // mdb-init-interface.ts import { v4 as uuid } from 'uuid'; import type { UserSchema, INCharacter, UserDecoration, OrgDecoration, ILogger, ILogContext } from '@types'; +import { ECollections } from '@constants'; import { default as MongoConnector, _setDb as setDb } from '../mdb-connector'; -import { - DATABASE_STRING as databaseName, - DATABASE_USERS_STRING as userDatabaseName, - DATABASE_ORGS_STRING as orgsDatabaseName, - DEFAULT_ORG as defaultOrg, -} from './constants'; +import { DEFAULT_ORG as defaultOrg } from '@model'; +import { EDBs } from '@constants'; + import { patience } from './helpers'; import { dbLog } from '@log'; -/* to-do: move types to declaration file */ -type Tdbs = 'nexus' | 'organizations' | 'test' | string; - interface IDBGeneric { [x: string]: { db: unknown; @@ -44,7 +39,7 @@ oplog._.decorateLog = ({ type, action, verb, status, message, priority }) => { // console.log("@@@ decorating log @@@") if (!messageState.get) return { type, action, verb, status, message, priority }; const statusMessage: ILogContext = { - type: type || 'mongodb', + type: type || 'database', action: action || messageState.get().action, verb: verb || messageState.get().verb, status: status || messageState.get().status, @@ -196,6 +191,15 @@ const _UserSchema: UserDecoration = { const _OrgSchema: OrgDecoration = { name: defaultOrg, members: [], + projects: { + active: [], + inactive: [], + archived: [], + }, + services: { + enabled: [], + available: [], + }, rickmorty_meta: { favorites: { characters: [] as INCharacter['id'][], @@ -205,12 +209,12 @@ const _OrgSchema: OrgDecoration = { /* private */ -const prepare = async (name: Tdbs): Promise => { +async function prepare(name: (typeof EDBs)[DB]): Promise { const conn = await MongoConnector; const db_conn = await setDb(name); const db = await db_conn.db(name); return db; -}; +} // IMPORTANT: to-do: to enforce on existing docs (not on insert only) const createSchemaQuery = () => { @@ -247,7 +251,7 @@ const Instance: any = {}; /* private methods */ /* 0. init */ const init = async ({ name }: { name: string }) => { - const usersDb = userDatabaseName || databaseName; + const usersDb = EDBs.USERS || EDBs.DEFAULT; const _users = { status: 'loading', @@ -259,7 +263,7 @@ const init = async ({ name }: { name: string }) => { if (process.env.NEXUS_MODE === 'full') { const _orgs = { status: 'loading', - db: await prepare(orgsDatabaseName), + db: await prepare(EDBs.ORGS), }; Instance.orgs = _orgs; @@ -267,11 +271,11 @@ const init = async ({ name }: { name: string }) => { Instance.private = {}; Instance.private.loadUsers = async () => { - const users = await Instance.users.db.collection('users'); + const users = await Instance.users.db.collection(ECollections.USERS); return users; }; Instance.private.reloadUsers = async () => { - const users = await Instance.users.db.collection('users'); + const users = await Instance.users.db.collection(ECollections.USERS); Instance.private.users = users; return users; }; @@ -280,11 +284,11 @@ const init = async ({ name }: { name: string }) => { /* (PVT) orgs */ if (process.env.NEXUS_MODE === 'full') { Instance.private.loadOrgs = async () => { - const orgs = await Instance.orgs.db.collection('organizations'); + const orgs = await Instance.orgs.db.collection(ECollections.ORGS); return orgs; }; Instance.private.reloadOrgs = async () => { - const orgs = await Instance.orgs.db.collection('organizations'); + const orgs = await Instance.orgs.db.collection(ECollections.ORGS); Instance.private.orgs = orgs; return orgs; }; @@ -297,8 +301,8 @@ const init = async ({ name }: { name: string }) => { Instance.private.defineUserSchema = await defineSchema( { - db: userDatabaseName || databaseName, - collection: 'users', + db: EDBs.USERS || EDBs.DEFAULT, + collection: ECollections.USERS, schema: _UserSchema, docQuery: undefined, }, @@ -312,8 +316,8 @@ const init = async ({ name }: { name: string }) => { const initiator = await defineSchema( { - db: userDatabaseName || databaseName, - collection: 'users', + db: EDBs.USERS || EDBs.DEFAULT, + collection: ECollections.USERS, schema: _UserSchema, docQuery: { email }, }, @@ -328,8 +332,8 @@ const init = async ({ name }: { name: string }) => { Instance.private.defineOrgSchema = await defineSchema( { - db: orgsDatabaseName || databaseName, - collection: 'organizations', + db: EDBs.ORGS || EDBs.DEFAULT, + collection: ECollections.ORGS, schema: _OrgSchema, }, Instance.private.orgs, @@ -355,8 +359,8 @@ const init = async ({ name }: { name: string }) => { /* IMPORTANT: to-do: extract method to add to org */ const userQuerySchema = { - db: userDatabaseName || databaseName, - collection: 'users', + db: EDBs.USERS || EDBs.DEFAULT, + collection: ECollections.USERS, schema: _userQuerySchema, }; diff --git a/lib/model/mdb-connector.ts b/lib/model/mdb-connector.ts index 0beabade..2ec1f9eb 100644 --- a/lib/model/mdb-connector.ts +++ b/lib/model/mdb-connector.ts @@ -37,9 +37,9 @@ const genPromise = (name = '') => { } log({ - type: 'connector', + type: 'database', action: 'init', - verb: 'connect', + verb: 'connect to database', status: 'connecting-to', message: domain, }); diff --git a/lib/model/schemas/org.ts b/lib/model/schemas/org.ts new file mode 100644 index 00000000..ed08cdcc --- /dev/null +++ b/lib/model/schemas/org.ts @@ -0,0 +1,86 @@ +// org.ts +import type { + NexusActionTypes, + IActionTypes, + IServiceUserAmbiRelation, + IFeatureSet, + OrgDecoration, + INCharacter, +} from '@types'; +import { EFeatureStatus, EServiceTypes, EServiceStatus, EServiceNames } from '@constants'; +import { DEFAULT_ORG } from '@model'; +import { defaultAbilities } from '@schema/user'; + +interface INexusSet extends Set { + gimme?: (value: string) => string[] | []; +} + +const publicNexusActions: Set = new Set(['init', 'login', 'logout', 'hydrate'] as NexusActionTypes[]); +const iterablePublicActions: NexusActionTypes[] = Array.from(publicNexusActions); + +const commonActions: INexusSet = new Set(['like']); +commonActions.gimme = (value: string) => { + if (commonActions.has(value)) return [value]; + return []; +}; + +export const nominalRMActions = [...iterablePublicActions, commonActions.gimme('like')]; + +export const defaultRMActions = nominalRMActions.reduce((acc, actionType: IActionTypes) => { + return { + ...acc, + [actionType]: true, + }; +}, {}); + +export const defaultRMFeatures: IFeatureSet = { + 'love-characters': { + name: 'love-characters', + status: EFeatureStatus.active, + version: '0.0.1', + abilities: defaultAbilities, + }, +}; + +export const RMServiceSchema: IServiceUserAmbiRelation = { + name: EServiceNames.SERV_RM, + type: EServiceTypes.RM, + createdOn: new Date(), + status: EServiceStatus.active, + statusModified: new Date(), + version: '1.0.0', + features: defaultRMFeatures, +}; + +export const defaultServices = { + [EServiceNames.SERV_RM]: RMServiceSchema, +}; + +export const defaultProjects = { + [EServiceNames.SERV_RM]: { + name: 'myorg-default-rm-index', + status: 'active', + /* + to-finish: walk the default services + service: defaultServices.get(‘rickmorty’).name, + sid: unknown (NEEDS DEFINE RELATIONS) + */ + }, +}; + +export const _OrgSchema: OrgDecoration = { + name: DEFAULT_ORG, + members: [], + services: { + enabled: defaultServices, + available: defaultServices, + }, + projects: { + active: defaultProjects, + }, + rickmorty_meta: { + favorites: { + characters: [] as INCharacter['id'][], + }, + }, +}; diff --git a/lib/model/schemas/relations.ts b/lib/model/schemas/relations.ts new file mode 100644 index 00000000..4142309c --- /dev/null +++ b/lib/model/schemas/relations.ts @@ -0,0 +1,13 @@ +// relations.ts +import { EUserOrgRoles } from '@constants'; +import { defaultAbilities } from '@schema/user'; +import { defaultProjects, defaultServices } from '@schema/org'; + +export const defaultOrgMemberRelation = { + role: [EUserOrgRoles.MEMBER], + abilities: defaultAbilities, + services: defaultServices, + projects: defaultProjects, + org: 'name', + user: 'email', +}; diff --git a/lib/model/schemas/user.ts b/lib/model/schemas/user.ts new file mode 100644 index 00000000..83dfb644 --- /dev/null +++ b/lib/model/schemas/user.ts @@ -0,0 +1,27 @@ +// user.ts +/* schemas */ +import type { IFuzzyAbilities, UserDecoration, INCharacter, DUserOrgAmbiRelation } from '@types'; +import { EUserOrgRoles, EAbilityStatus } from '@constants'; +import { defaultRMActions } from '@schema/org'; + +/* to finish, use hashmap */ +export const defaultAbilities: IFuzzyAbilities = [ + { + name: 'like-stuff', + contexts: ['all'], + actions: defaultRMActions, + roles: [EUserOrgRoles.EVERYONE], + restrictions: {}, + allowances: {}, + status: EAbilityStatus.active, + }, +]; + +export const _UserSchema: UserDecoration = { + rickmorty: { + favorites: { + characters: [] as INCharacter['id'][], + }, + }, + organizations: [] as DUserOrgAmbiRelation[], +}; diff --git a/lib/types/actions.d.ts b/lib/types/actions.d.ts index 72f8f424..4cca0824 100644 --- a/lib/types/actions.d.ts +++ b/lib/types/actions.d.ts @@ -1,24 +1,32 @@ // actions.d.ts import type { Context } from 'react'; -export type ActionT = 'init' | 'login' | 'logout' | 'hydrate' | 'update_db' | 'schema-enforcing'; -export type ActionTypes = 'init' | 'auth' | 'rickmorty' | string; -export type ActionAuthNames = - | 'load user' - | 'load user meta' - | 'unload user' - | 'load characters' - | 'unload characters' - | 'decorate characters' - | 'add char to favorites'; - -export type ActionDBNames = 'database' | 'collection' | 'relations' | 'connect'; +export type _NexusActionTypes = 'update_db' | 'schema-enforcing'; +export type NexusActionTypes = 'init' | 'login' | 'logout' | 'hydrate'; +export type CommonIAction = 'like'; +export type RMActionTypes = CommonIAction<'like'>; +export type IActionTypes = NexusActionTypes | RMActionTypes; + +export type NexusActionContexts = 'init' | 'auth' | 'ubiquity' | 'database'; +export type ServicesActionContexts = 'rickmorty' | 'image-uploader'; +export type ActionContexts = NexusActionContexts | ServicesActionContexts; + +export type ActionAuthVerbs = 'load user' | 'load user meta' | 'unload user'; +export type ActionDBVerbs = 'load database' | 'load collection' | 'define relations' | 'connect to database'; +export type ActionRMVerbs = 'load characters' | 'unload characters' | 'decorate characters' | 'add char to favorites'; + +export type ActionVerbs = ActionAuthVerbs | ActionRMVerbs | ActionDBVerbs; + +export interface IAction { + action: IActionTypes; + type: ActionContexts; +} export type ISupportedContexts = IAuthContext | IRMContext | ILogContext; export interface ILogContext { - action?: ActionT; - type?: ActionTypes; - verb?: ActionAuthNames | ActionDBNames; + action?: IActionTypes; + type?: ActionContexts; + verb?: ActionVerbs; status?: string; message?: string; category?: string; @@ -47,7 +55,7 @@ export interface IActionBack extends ILogContext { context: Context; } -export interface IAction { +export interface IActionDispatch { cb?: Array<() => void>; } @@ -76,7 +84,7 @@ export interface IACharacterPayload { cid?: number; } -export type ICreateAction = (options: IActionBack) => (_options: IAction) => [boolean | undefined, IDispatch]; +export type ICreateAction = (options: IActionBack) => (_options: IActionDispatch) => [boolean | undefined, IDispatch]; export type IAPayload = IALoginPayload | IACharacterPayload; export type IDPayload = IDAddToFavPayload; diff --git a/lib/types/authorization.d.ts b/lib/types/authorization.d.ts new file mode 100644 index 00000000..d4769a9b --- /dev/null +++ b/lib/types/authorization.d.ts @@ -0,0 +1,41 @@ +// authorization.d.ts +import type { IActionTypes } from '@types'; +import type { EAbilityStatus, EFeatures } from '@constants'; + +export interface IAbility { + actions: IActionTypes[]; + roles: EUserOrgRoles[]; + contexts: IService<'name'>[]; + restrictions: IFuzzyAbilities; + name: string; + status: EAbilityStatus; +} + +export interface IUniversalAbilityMap { + none: IFuzzyAbilities; +} + +export type IFuzzyAbilities = { + [x in keyof EFeatures]: EFeatures; +}; + +export type AbilityFuzziesT = 'age' | 'idv' | 'addv' | 'role'; + +/* e.g. geoRestrictions +ICountryAbilitiesMap { + [country]: IFuzzyAbilities +} + +use cases: +feature geoRestrictions, +service geoRestrictions, +projects geoRestrictions (allows user set) + +IAnyAbilityMap { + [yourCriteria]: IFuzzyAbilities +} + +abilities can belong to projects, features or services +abilities can map to roles, which is more performant than roles mapping to abilities. + +*/ diff --git a/lib/types/billing.d.ts b/lib/types/billing.d.ts new file mode 100644 index 00000000..edec70d9 --- /dev/null +++ b/lib/types/billing.d.ts @@ -0,0 +1,31 @@ +/* eslint-disable @typescript-eslint/no-empty-interface */ +// IMPORTANT: above rule is temporary ^, until file split + schema wrap +// billing.d.ts +/* nexus db: to-do: billing collection */ + +export interface IBillingData {} + +export enum EBillingCycles { + /* core */ + '1m' = 0, + '1H' = 1, + '1D' = 2, + '1W' = 3, + '2W' = 4, + '1M' = 5, + '2M' = 6, + '1Q' = 7, + '2Q' = 8, + '3Q' = 9, + '1Y' = 10, + /* pending */ + '2Y' = 11, + '3Y' = 12, + '4Y' = 13, + '5Y' = 14, + '10Y' = 15, +} + +export interface IBillingData {} + +export interface DBillingOrgRelation {} diff --git a/lib/types/common.d.ts b/lib/types/common.d.ts new file mode 100644 index 00000000..3ddceb47 --- /dev/null +++ b/lib/types/common.d.ts @@ -0,0 +1,4 @@ +// common.d.ts +import type { PostalAddress } from '@types/json-schmea'; + +export type IAddress = PostalAddress; diff --git a/lib/types/constants/authorization.ts b/lib/types/constants/authorization.ts new file mode 100644 index 00000000..28bda57b --- /dev/null +++ b/lib/types/constants/authorization.ts @@ -0,0 +1,16 @@ +// authorization.ts +export enum EAbilityStatus { + 'inactive' = 0, + 'active' = 1, + 'deprecated' = 2, +} + +export enum EUserOrgRoles { + 'SUPERUSER' = 0, + 'ADMIN' = 1, + 'MANAGER' = 2, + 'PRODUCER' = 3, + 'MEMBER' = 4, + 'SPECTATOR' = 5, + 'EVERYONE' = 6, +} diff --git a/lib/types/constants/db.ts b/lib/types/constants/db.ts new file mode 100644 index 00000000..e6db09ef --- /dev/null +++ b/lib/types/constants/db.ts @@ -0,0 +1,26 @@ +// db.enums.ts +import { DATABASE_STRING, DATABASE_USERS_STRING, DATABASE_ORGS_STRING } from '@model'; + +export const EDBs = { + DEFAULT: DATABASE_STRING || 'test', + USERS: DATABASE_USERS_STRING || DATABASE_STRING || 'auth', + ORGS: DATABASE_ORGS_STRING || DATABASE_STRING || 'organizations', +}; + +enum ENexusCollections { + USERS = 'users', + ABILITIES = 'abilities', + FINCORE = 'fincore', +} + +enum EOrgCollections { + ORGS = 'organizations', + BILLING = 'billing', + SERVICES = 'services', + FEATURES = 'features', +} + +export const ECollections = { + ...ENexusCollections, + ...EOrgCollections, +}; diff --git a/lib/types/constants/index.ts b/lib/types/constants/index.ts new file mode 100644 index 00000000..9e44f183 --- /dev/null +++ b/lib/types/constants/index.ts @@ -0,0 +1,5 @@ +// index.ts + +export { ECollections, EDBs } from './db'; +export { EServiceTypes, EServiceStatus, EFeatureStatus, EServiceNames, EFeatures } from './services'; +export { EAbilityStatus, EUserOrgRoles } from './authorization'; diff --git a/lib/types/constants/services.ts b/lib/types/constants/services.ts new file mode 100644 index 00000000..dcec3331 --- /dev/null +++ b/lib/types/constants/services.ts @@ -0,0 +1,61 @@ +// services.ts +export enum EServiceNames { + /* core */ + SERV_VBM = 'The Vibe Modulator', + /* extra */ + SERV_RM = 'The Rick and Morty Index', + SERV_EC = 'The Eezy Content Uploader', +} + +export enum EServiceTypes { + /* core */ + 'DCS' = 0, + 'DBS' = 1, + 'DWS' = 2, + 'DVS' = 3, + 'DFS' = 4, + /* extra */ + 'RM' = 999999999, + 'EC' = 999999998, +} + +export enum EServiceStatus { + 'deactivated' = 0, + 'created' = 1, + 'active' = 2, + 'enabled' = 3, + 'running' = 4, + 'paused' = 5, + 'stopped' = 6, + 'disabled' = 7, + 'inactive' = 8, + 'deleted' = 9, + 'delinquent' = 10, +} + +export enum ERMFeatures { + 'love-characters' = 0, +} + +export const EFeatures = { + ...ERMFeatures, +}; + +export enum EFeatureStatus { + 'inactive' = 0, + 'ghost' = 1, + 'active' = 2, + 'beta' = 3, + 'nightly' = 4, +} + +export const EServices = { + [EServiceNames.SERV_VBM]: { + name: EServiceNames.SERV_VBM, + type: EServiceTypes.DCS, + }, + [EServiceNames.SERV_RM]: { + name: EServiceNames.SERV_RM, + type: EServiceTypes.RM, + }, +}; diff --git a/lib/types/model.d.ts b/lib/types/currencies.d.ts similarity index 58% rename from lib/types/model.d.ts rename to lib/types/currencies.d.ts index 53dce7da..ce37b8af 100644 --- a/lib/types/model.d.ts +++ b/lib/types/currencies.d.ts @@ -1,168 +1,11 @@ -/* eslint-disable @typescript-eslint/no-empty-interface */ -// IMPORTANT: above rule is temporary ^, until file split + schema wrap -// model.d.ts -import type { User } from 'next-auth'; -import type { INCharacter } from '@types'; -import type { ObjectID } from 'mongodb'; -import type { PostalAddress } from '@types/json-schmea'; - -export { User }; - -/* nexus db */ -export interface UserDecoration { - _id?: ObjectID /* uid */; - /* temp optional */ - username?: string; - bio?: string; - organizations: DUserOrgAmbiRelation[]; - rickmorty: { - favorites: { - characters: INCharacter['id'][]; - }; - }; -} - -export interface OrgDecoration { - _id?: ObjectID /* uid */; - /* temp optional */ - name?: string; - bio?: string; - members: DUserOrgAmbiRelation[]; - rickmorty_meta: { - favorites: { - characters: INCharacter['id'][]; - }; - }; -} - -export enum EUserOrgRoles { - 'SUPERUSER' = 0, - 'ADMIN' = 1, - 'MANAGER' = 2, - 'PRODUCER' = 3, - 'MEMBER' = 4, - 'SPECTATOR' = 5, -} - -export interface DUserOrgAmbiRelation { - role: EUserOrgRoles[]; - _id: ObjectID /* uid */; - org: string; - name: string; -} - -export type IAddress = PostalAddress; - -/* nexus db: billing collection */ - -export interface IBillingData {} - -export enum EBillingCycles { - /* core */ - '1M' = 0, - '1H' = 1, - '1D' = 2, - '1W' = 3, - '2W' = 4, - '1M' = 5, - '2M' = 6, - '1Q' = 7, - '2Q' = 8, - '3Q' = 9, - '1Y' = 10, - /* pending */ - '2Y' = 11, - '3Y' = 12, - '4Y' = 13, - '5Y' = 14, - '10Y' = 15, -} - -/* org db: projects collection */ -export interface IProject { - _id: ObjectID /* pid */; - name: string; - services: DProjectServiceRelation[]; -} - -export interface DProjectOrgRelation {} - -/* nexus db: services collection */ -export enum EServiceTypes { - /* core */ - 'DCS' = 0, - 'DBS' = 1, - 'DWS' = 2, - 'DVS' = 3, - 'DFS' = 4, - /* extra */ - 'RM' = 999999999, - 'EC' = 999999998, -} - -export enum EServiceStatuses { - 'deactivated' = 0, - 'created' = 1, - 'activated' = 2, - 'enabled' = 3, - 'running' = 4, - 'paused' = 5, - 'stopped' = 6, - 'disabled' = 7, - 'deactivated' = 8, - 'deleted' = 9, - 'deliquent' = 10, -} - -export interface IService { - _id: ObjectID /* sid */; - name: string; - type: EServiceTypes; - createdOn: Date; - status: EServiceStatuses; - statusModified: Date; - cost: number; - cycle: EBillingCycles; - version: string; - features: IFeature[]; -} - -export interface IFeature { - name: string; - status: IFeatureStatus; - version: string; -} - -export enum IFeatureStatus { - 'inactive' = 0, - 'ghost' = 1, - 'active' = 2, - 'beta' = 3, - 'nightly' = 4, -} - -export interface IServiceFeatureStatus { - status: EServiceStatuses; - name: IService['name']; - sid: IService['_id']; -} - -export type DProjectServiceRelation = IServiceFeatureStatus[]; - -export interface DServiceOrgRelation { - enabled: IServiceFeatureStatus[]; -} - -/* nexus db: to-do: billing collection */ -export interface IBillingData {} - -export interface DBillingOrgRelation {} - -/* currencies: to-do: move to a different type file */ - +// currencies.d.ts /* trad IMPORTANT: still need to be completely validated */ +// Example usage +// const usdCurrency: TraditionalCurrencies = TraditionalCurrencies.USD; +// const btcCryptocurrency: Cryptocurrencies = Cryptocurrencies.BTC; + export enum ETraditionalCurrencies { AED = 'United Arab Emirates Dirham', AFN = 'Afghan Afghani', @@ -366,58 +209,3 @@ export enum ECryptoCurrencies { } export type ECurrency = ETraditionalCurrencies | ECryptoCurrencies; - -// Example usage -// const usdCurrency: TraditionalCurrencies = TraditionalCurrencies.USD; -// const btcCryptocurrency: Cryptocurrencies = Cryptocurrencies.BTC; - -/* nexus db: to-do: krn collection */ - -export interface IToken { - value: number; - currency: ECurrency; -} - -/* -OpenTokenValue -timeOpen -timeClose -closeTokenValue openOrgCap -closeOrgCap status -dividend -*/ -export interface IOrgTokenData {} - -/* -OpenTokenValue -timeOpen -timeClose -closeTokenValue openOrgCap -closeOrgCap status -dividend -*/ -export interface IUserTokenData {} - -export interface DOrgUserRelation {} - -/* orgs collection */ -export interface OrgSchema { - _id: ObjectID /* oid */; - name: string; - billing: IBillingData; - krn: IOrgTokenData; - addresses: IAddress[]; - websites: string[]; - members: DUserOrgAmbiRelation[]; - projects: DProjectOrgRelation[]; - services: { - available: DServiceOrgRelation[]; - }; - rickmorty: { - favorites: { - characters: INCharacter['id'][]; - }; - }; -} - -export interface UserSchema extends User, UserDecoration {} diff --git a/lib/types/db.d.ts b/lib/types/db.d.ts new file mode 100644 index 00000000..0508b96a --- /dev/null +++ b/lib/types/db.d.ts @@ -0,0 +1,3 @@ +// db.d.ts +import type { ECollections } from './constants'; +export type ICollections = typeof ECollections; diff --git a/lib/types/fincore.d.ts b/lib/types/fincore.d.ts new file mode 100644 index 00000000..86ecbb08 --- /dev/null +++ b/lib/types/fincore.d.ts @@ -0,0 +1,29 @@ +/* eslint-disable @typescript-eslint/no-empty-interface */ +// IMPORTANT: above rule is temporary ^, until file split + schema wrap +// fincore.d.ts +/* nexus db: to-do: krn collection */ + +export interface IToken { + value: number; + currency: ECurrency; +} + +/* +OpenTokenValue +timeOpen +timeClose +closeTokenValue openOrgCap +closeOrgCap status +dividend +*/ +export interface IOrgTokenData {} + +/* +OpenTokenValue +timeOpen +timeClose +closeTokenValue openOrgCap +closeOrgCap status +dividend +*/ +export interface IUserTokenData {} diff --git a/lib/types/index.ts b/lib/types/index.ts index 79b539ee..e7b898e2 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -3,17 +3,23 @@ // contexts export type { IAuthContext, IRMContext, INCharacter, IDCharacter, History } from './contexts'; -// model -export type { UserSchema, User, UserDecoration, OrgDecoration, IFeature } from './model'; +// db +export type { ICollections } from './db'; + +// users +export type { UserSchema, User, UserDecoration, DUserOrgAmbiRelation } from './users'; + +// orgs +export type { OrgDecoration } from './orgs'; // actions export type { - ActionT, - ActionTypes, - ActionAuthNames, + IAction, + IActionTypes, + ActionAuthVerbs, ISupportedContexts, + IActionDispatch, IActionBack, - IAction, IStatus, IALoginPayload, IDAddToFavPayload, @@ -26,7 +32,14 @@ export type { IDispatchPayload, ILogContext, ILogger, + NexusActionTypes, } from './actions'; +// authorization +export type { IAbility, IFuzzyAbilities } from './authorization'; + +// services +export type { IFeature, IFeatureSet, IProject, IServiceUserAmbiRelation } from './services'; + // system export type { Tposition, TpositionX, TpositionY, Tsize, Tthemes } from './atoms'; diff --git a/lib/types/orgs.d.ts b/lib/types/orgs.d.ts new file mode 100644 index 00000000..395f4e11 --- /dev/null +++ b/lib/types/orgs.d.ts @@ -0,0 +1,27 @@ +// orgs.d.ts +import type { DUserOrgAmbiRelation, DProjectOrgRelation, DServiceOrgRelation, INCharacter } from '@types'; + +export interface OrgDecoration { + _id?: ObjectID /* uid */; + /* temp optional */ + name?: string; + // billing: IBillingData; + // krn: IOrgTokenData; + // addresses: IAddress[]; + // websites: string[]; + members: DUserOrgAmbiRelation[]; + projects: { + active?: DProjectOrgRelation; + inactive?: DProjectOrgRelation; + archived?: DProjectOrgRelation; + }; + services: { + available?: DServiceOrgRelation; + enabled?: DServiceOrgRelation; + }; + rickmorty_meta: { + favorites: { + characters: INCharacter['id'][]; + }; + }; +} diff --git a/lib/types/services.d.ts b/lib/types/services.d.ts new file mode 100644 index 00000000..a923528d --- /dev/null +++ b/lib/types/services.d.ts @@ -0,0 +1,55 @@ +// services.d.ts +import type { IFuzzyAbilities } from '@types'; +import type { EServiceTypes, EServiceStatus, EFeatureStatus } from '@constants'; + +export interface IService { + _id?: ObjectID /* sid */; + name: string; + type: Record; + createdOn: Date; + status: Record; + statusModified: Date; + // cost: number; + // currency: ECurrency + // cycle: EBillingCycles; + version: string; + features: IFeature[]; + abilities: IFuzzyAbilities; +} + +/* facading sensitive service-> org data */ +export interface IServiceUserAmbiRelation { + _id?: ObjectID /* sid */; + name: string; + type: EServiceTypes; + createdOn: Date; + status: EServiceStatus; + statusModified: Date; + version: string; + features: IFeatureSet; +} + +/* features */ +export interface IFeature { + name: string; + status: EFeatureStatus; + version: string; + abilities: IFuzzyAbilities; +} + +export type IFeatureSet = { + [x in keyof IFeature]: IFeature; +}; + +export type AbilityFuzziesT = 'age' | 'idv' | 'addv' | 'role'; + +export interface IProject { + name: string; + status: Record; + service: IService<'name'>; + abilities: IFuzzyAbilities; + sid: IService<'_id'>; +} + +export type DProjectOrgRelation = Record, IProject>; +export type DServiceOrgRelation = Record, IService>; diff --git a/lib/types/users.d.ts b/lib/types/users.d.ts new file mode 100644 index 00000000..1d9ce442 --- /dev/null +++ b/lib/types/users.d.ts @@ -0,0 +1,30 @@ +// users.d.ts +import type { IProject, IServiceUserAmbiRelation, EUserOrgRoles, INCharacter } from '@types'; +import type { User } from 'next-auth'; +export { User }; + +export interface UserDecoration { + /* email comes from next auth */ + _id?: ObjectID /* uid */; + /* temp optional */ + username?: string; + bio?: string; + organizations: DUserOrgAmbiRelation[]; + rickmorty: { + favorites: { + characters: INCharacter['id'][]; + }; + }; +} + +export interface DUserOrgAmbiRelation { + role: EUserOrgRoles[]; + abilities: IFuzzyAbilities; + services: IServiceUserAmbiRelation[]; + projects: IProject[]; + _id: ObjectID /* uid */; + org: string; + user: string; +} + +export interface UserSchema extends User, UserDecoration {} diff --git a/src/app/components/system/molecules/divider/client/divider-view.tsx b/src/app/components/system/molecules/divider/client/divider-view.tsx new file mode 100644 index 00000000..3fe6951d --- /dev/null +++ b/src/app/components/system/molecules/divider/client/divider-view.tsx @@ -0,0 +1,15 @@ +// // @atoms/button-view.tsx +// 'use client'; +// import { clsx } from "clsx" +// import styles from "./divider.module.css" + +// interface VDividerProps extends React.HTMLProps { +// } + +// export const NVDivider = ({ children, ...regularHtmlProps }: VDividerProps) => { +// const classes = clsx({ +// [styles.nexus__divider]: regularHtmlProps.type !== "hidden", +// }) +// /* remember server/client isomorphism */ +// return
; +// }; diff --git a/src/app/components/system/molecules/divider/client/divider.module.css b/src/app/components/system/molecules/divider/client/divider.module.css new file mode 100644 index 00000000..673f5cf3 --- /dev/null +++ b/src/app/components/system/molecules/divider/client/divider.module.css @@ -0,0 +1,10 @@ +/* button.module.css */ +/* +.nexus__divider { +widht: 100; +color: var(--nexus-main-fg); +border: 1px solid var(--nexus-main-fg); +margin-top: 32px; +margin-bottom: 32px; +} +*/ \ No newline at end of file diff --git a/src/app/components/system/molecules/divider/client/index.ts b/src/app/components/system/molecules/divider/client/index.ts new file mode 100644 index 00000000..c55c3785 --- /dev/null +++ b/src/app/components/system/molecules/divider/client/index.ts @@ -0,0 +1,2 @@ +// // @atoms/button/client/index.ts +// export { NVDivider } from './divider-view'; diff --git a/src/app/components/system/molecules/divider/divider.tsx b/src/app/components/system/molecules/divider/divider.tsx new file mode 100644 index 00000000..c9175028 --- /dev/null +++ b/src/app/components/system/molecules/divider/divider.tsx @@ -0,0 +1,9 @@ +// // button.tsx +// 'use server'; +// import { NCInput } from './server'; + +// export const Input = () => { +// return
+// +//
; +// }; diff --git a/src/app/components/system/molecules/divider/index.ts b/src/app/components/system/molecules/divider/index.ts new file mode 100644 index 00000000..d7c5b624 --- /dev/null +++ b/src/app/components/system/molecules/divider/index.ts @@ -0,0 +1,2 @@ +// // index.ts +// export { NVDivider as Divider } from './client'; diff --git a/src/app/components/system/molecules/divider/server/divider-controller.tsx b/src/app/components/system/molecules/divider/server/divider-controller.tsx new file mode 100644 index 00000000..7a4312a9 --- /dev/null +++ b/src/app/components/system/molecules/divider/server/divider-controller.tsx @@ -0,0 +1,16 @@ +// // @atoms/button-controller.ts +// 'use server'; +// // import "server-only" + +// // import type { UserSchema } from "@types" +// // import { NVButton } from "./button-view"; + +// interface NCButtonProps {} + +// export const NCButton = async ({}: NCButtonProps) => { +// console.log('--- button controller'); +// // const props: ISignInData = await getProvidersData(); +// // const providers: IAuthProviders[] = props?.providers || []; +// return
LOREM SERVER
; +// // return ; +// }; diff --git a/src/app/components/system/molecules/divider/server/index.ts b/src/app/components/system/molecules/divider/server/index.ts new file mode 100644 index 00000000..996545f2 --- /dev/null +++ b/src/app/components/system/molecules/divider/server/index.ts @@ -0,0 +1,2 @@ +// // @atoms/button/server/index.ts +// export { NCButton } from './button-controller'; diff --git a/src/app/components/system/molecules/index.ts b/src/app/components/system/molecules/index.ts new file mode 100644 index 00000000..636562ec --- /dev/null +++ b/src/app/components/system/molecules/index.ts @@ -0,0 +1,4 @@ +// @atoms/index.ts +export { Button } from './button' +export { Input } from './input' +export { Divider } from './divider' \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index a679384e..78c76d04 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,8 @@ "@atoms/*": ["./src/app/components/system/atoms/*"], "@model": ["./lib/model"], "@model/*": ["./lib/model/*"], + "@schema": ["./lib/model/schemas"], + "@schema/*": ["./lib/model/schemas/*"], "@view": ["./lib/view"], "@view/*": ["./lib/view/*"], "@pragmas": ["./lib/view/adapters/"], @@ -33,6 +35,8 @@ "@log/*": ["./lib/log/*"], "@types": ["./lib/types"], "@types/*": ["./lib/types/*"], + "@constants": ["./lib/types/constants"], + "@constants/*": ["./lib/types/constants/*"], "@auth": ["./lib/auth"], "@auth/adapter": ["./src/app/api/auth/[...nextauth]"], "@auth/adapter/*": ["./src/app/api/auth/[...nextauth]/*"], @@ -51,5 +55,5 @@ }, }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules", "**/nsx/**/*", "**/system/**/*"], + "exclude": ["node_modules", "**/nsx/**/*", "**/system/**/*", "**/mock/**/*"], }