From 6d1e3cc0285ef157fd6486060e8b32c00c01aa80 Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Thu, 21 Dec 2023 07:56:20 +0100 Subject: [PATCH] feat(types,module-sdk): setup authentication module skeleton (#5943) **What** - add authentication module skeleton --- .changeset/angry-pigs-shop.md | 6 ++ packages/authentication/.gitignore | 6 ++ packages/authentication/CHANGELOG.md | 0 packages/authentication/README.md | 3 + .../integration-tests/__tests__/index.spec.ts | 5 ++ .../integration-tests/setup-env.js | 6 ++ .../authentication/integration-tests/setup.js | 3 + .../integration-tests/utils/config.ts | 6 ++ .../integration-tests/utils/database.ts | 18 ++++++ .../integration-tests/utils/index.ts | 2 + packages/authentication/jest.config.js | 21 +++++++ .../authentication/mikro-orm.config.dev.ts | 8 +++ packages/authentication/package.json | 63 +++++++++++++++++++ packages/authentication/src/index.ts | 7 +++ .../authentication/src/initialize/index.ts | 27 ++++++++ packages/authentication/src/joiner-config.ts | 31 +++++++++ .../authentication/src/loaders/connection.ts | 36 +++++++++++ .../authentication/src/loaders/container.ts | 38 +++++++++++ packages/authentication/src/loaders/index.ts | 2 + .../.snapshot-medusa-authentication.json | 36 +++++++++++ .../src/migrations/Migration20231220132440.ts | 13 ++++ .../authentication/src/models/auth-user.ts | 18 ++++++ packages/authentication/src/models/index.ts | 1 + .../authentication/src/module-definition.ts | 12 ++++ .../authentication/src/repositories/index.ts | 1 + .../src/scripts/bin/run-migration-down.ts | 8 +++ .../src/scripts/bin/run-migration-up.ts | 8 +++ .../src/scripts/bin/run-seed.ts | 19 ++++++ packages/authentication/src/scripts/index.ts | 2 + .../src/scripts/migration-down.ts | 50 +++++++++++++++ .../src/scripts/migration-up.ts | 62 ++++++++++++++++++ packages/authentication/src/scripts/seed.ts | 63 +++++++++++++++++++ .../src/services/__tests__/index.spec.ts | 5 ++ .../src/services/authentication-module.ts | 32 ++++++++++ packages/authentication/src/services/index.ts | 1 + packages/authentication/src/types/index.ts | 5 ++ packages/authentication/tsconfig.json | 36 +++++++++++ packages/authentication/tsconfig.spec.json | 8 +++ packages/modules-sdk/src/definitions.ts | 17 +++++ packages/types/src/authentication/index.ts | 1 + packages/types/src/authentication/service.ts | 3 + packages/types/src/bundles.ts | 1 + packages/types/src/index.ts | 1 + yarn.lock | 29 +++++++++ 44 files changed, 720 insertions(+) create mode 100644 .changeset/angry-pigs-shop.md create mode 100644 packages/authentication/.gitignore create mode 100644 packages/authentication/CHANGELOG.md create mode 100644 packages/authentication/README.md create mode 100644 packages/authentication/integration-tests/__tests__/index.spec.ts create mode 100644 packages/authentication/integration-tests/setup-env.js create mode 100644 packages/authentication/integration-tests/setup.js create mode 100644 packages/authentication/integration-tests/utils/config.ts create mode 100644 packages/authentication/integration-tests/utils/database.ts create mode 100644 packages/authentication/integration-tests/utils/index.ts create mode 100644 packages/authentication/jest.config.js create mode 100644 packages/authentication/mikro-orm.config.dev.ts create mode 100644 packages/authentication/package.json create mode 100644 packages/authentication/src/index.ts create mode 100644 packages/authentication/src/initialize/index.ts create mode 100644 packages/authentication/src/joiner-config.ts create mode 100644 packages/authentication/src/loaders/connection.ts create mode 100644 packages/authentication/src/loaders/container.ts create mode 100644 packages/authentication/src/loaders/index.ts create mode 100644 packages/authentication/src/migrations/.snapshot-medusa-authentication.json create mode 100644 packages/authentication/src/migrations/Migration20231220132440.ts create mode 100644 packages/authentication/src/models/auth-user.ts create mode 100644 packages/authentication/src/models/index.ts create mode 100644 packages/authentication/src/module-definition.ts create mode 100644 packages/authentication/src/repositories/index.ts create mode 100644 packages/authentication/src/scripts/bin/run-migration-down.ts create mode 100644 packages/authentication/src/scripts/bin/run-migration-up.ts create mode 100644 packages/authentication/src/scripts/bin/run-seed.ts create mode 100644 packages/authentication/src/scripts/index.ts create mode 100644 packages/authentication/src/scripts/migration-down.ts create mode 100644 packages/authentication/src/scripts/migration-up.ts create mode 100644 packages/authentication/src/scripts/seed.ts create mode 100644 packages/authentication/src/services/__tests__/index.spec.ts create mode 100644 packages/authentication/src/services/authentication-module.ts create mode 100644 packages/authentication/src/services/index.ts create mode 100644 packages/authentication/src/types/index.ts create mode 100644 packages/authentication/tsconfig.json create mode 100644 packages/authentication/tsconfig.spec.json create mode 100644 packages/types/src/authentication/index.ts create mode 100644 packages/types/src/authentication/service.ts diff --git a/.changeset/angry-pigs-shop.md b/.changeset/angry-pigs-shop.md new file mode 100644 index 0000000000..035a5b5f6a --- /dev/null +++ b/.changeset/angry-pigs-shop.md @@ -0,0 +1,6 @@ +--- +"@medusajs/modules-sdk": patch +"@medusajs/types": patch +--- + +feat(modules-sdk, types): add initial authentication module configuration diff --git a/packages/authentication/.gitignore b/packages/authentication/.gitignore new file mode 100644 index 0000000000..874c6c69d3 --- /dev/null +++ b/packages/authentication/.gitignore @@ -0,0 +1,6 @@ +/dist +node_modules +.DS_store +.env* +.env +*.sql diff --git a/packages/authentication/CHANGELOG.md b/packages/authentication/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/authentication/README.md b/packages/authentication/README.md new file mode 100644 index 0000000000..2a50e750d4 --- /dev/null +++ b/packages/authentication/README.md @@ -0,0 +1,3 @@ +# Authentication Module + +The Authentication Module is Medusa’s authentication engine engine. It provides functions to authenticate users through identity providers and store metadata about users that can be used for authorization purposes. diff --git a/packages/authentication/integration-tests/__tests__/index.spec.ts b/packages/authentication/integration-tests/__tests__/index.spec.ts new file mode 100644 index 0000000000..728f6245c6 --- /dev/null +++ b/packages/authentication/integration-tests/__tests__/index.spec.ts @@ -0,0 +1,5 @@ +describe("Noop test", () => { + it("noop check", async () => { + expect(true).toBe(true) + }) +}) diff --git a/packages/authentication/integration-tests/setup-env.js b/packages/authentication/integration-tests/setup-env.js new file mode 100644 index 0000000000..2379774654 --- /dev/null +++ b/packages/authentication/integration-tests/setup-env.js @@ -0,0 +1,6 @@ +if (typeof process.env.DB_TEMP_NAME === "undefined") { + const tempName = parseInt(process.env.JEST_WORKER_ID || "1") + process.env.DB_TEMP_NAME = `medusa-authentication-integration-${tempName}` +} + +process.env.MEDUSA_AUTHENTICATION_DB_SCHEMA = "public" diff --git a/packages/authentication/integration-tests/setup.js b/packages/authentication/integration-tests/setup.js new file mode 100644 index 0000000000..43f99aab4a --- /dev/null +++ b/packages/authentication/integration-tests/setup.js @@ -0,0 +1,3 @@ +import { JestUtils } from "medusa-test-utils" + +JestUtils.afterAllHookDropDatabase() diff --git a/packages/authentication/integration-tests/utils/config.ts b/packages/authentication/integration-tests/utils/config.ts new file mode 100644 index 0000000000..b57bd91f48 --- /dev/null +++ b/packages/authentication/integration-tests/utils/config.ts @@ -0,0 +1,6 @@ +import { ModuleServiceInitializeOptions } from "@medusajs/types" + +export const databaseOptions: ModuleServiceInitializeOptions["database"] = { + schema: "public", + clientUrl: "medusa-authentication-test", +} diff --git a/packages/authentication/integration-tests/utils/database.ts b/packages/authentication/integration-tests/utils/database.ts new file mode 100644 index 0000000000..f6f8739da7 --- /dev/null +++ b/packages/authentication/integration-tests/utils/database.ts @@ -0,0 +1,18 @@ +import { TestDatabaseUtils } from "medusa-test-utils" + +import * as AuthenticationModels from "@models" + +const pathToMigrations = "../../src/migrations" +const mikroOrmEntities = AuthenticationModels as unknown as any[] + +export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper( + mikroOrmEntities, + pathToMigrations +) + +export const MikroOrmConfig = TestDatabaseUtils.getMikroOrmConfig( + mikroOrmEntities, + pathToMigrations +) + +export const DB_URL = TestDatabaseUtils.getDatabaseURL() diff --git a/packages/authentication/integration-tests/utils/index.ts b/packages/authentication/integration-tests/utils/index.ts new file mode 100644 index 0000000000..5ca5d1bdc0 --- /dev/null +++ b/packages/authentication/integration-tests/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./config" +export * from "./database" diff --git a/packages/authentication/jest.config.js b/packages/authentication/jest.config.js new file mode 100644 index 0000000000..860ba90a49 --- /dev/null +++ b/packages/authentication/jest.config.js @@ -0,0 +1,21 @@ +module.exports = { + moduleNameMapper: { + "^@models": "/src/models", + "^@services": "/src/services", + "^@repositories": "/src/repositories", + }, + transform: { + "^.+\\.[jt]s?$": [ + "ts-jest", + { + tsConfig: "tsconfig.spec.json", + isolatedModules: true, + }, + ], + }, + testEnvironment: `node`, + moduleFileExtensions: [`js`, `ts`], + modulePathIgnorePatterns: ["dist/"], + setupFiles: ["/integration-tests/setup-env.js"], + setupFilesAfterEnv: ["/integration-tests/setup.js"], +} diff --git a/packages/authentication/mikro-orm.config.dev.ts b/packages/authentication/mikro-orm.config.dev.ts new file mode 100644 index 0000000000..c2b7f3839d --- /dev/null +++ b/packages/authentication/mikro-orm.config.dev.ts @@ -0,0 +1,8 @@ +import * as entities from "./src/models" + +module.exports = { + entities: Object.values(entities), + schema: "public", + clientUrl: "postgres://postgres@localhost/medusa-authentication", + type: "postgresql", +} diff --git a/packages/authentication/package.json b/packages/authentication/package.json new file mode 100644 index 0000000000..962cae6438 --- /dev/null +++ b/packages/authentication/package.json @@ -0,0 +1,63 @@ +{ + "name": "@medusajs/authentication", + "version": "0.0.1", + "description": "Medusa Authentication module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "engines": { + "node": ">=16" + }, + "bin": { + "medusa-authentication-migrations-down": "dist/scripts/bin/run-migration-down.js", + "medusa-authentication-migrations-up": "dist/scripts/bin/run-migration-up.js", + "medusa-authentication-seed": "dist/scripts/bin/run-seed.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/medusajs/medusa", + "directory": "packages/authentication" + }, + "publishConfig": { + "access": "public" + }, + "author": "Medusa", + "license": "MIT", + "scripts": { + "watch": "tsc --build --watch", + "watch:test": "tsc --build tsconfig.spec.json --watch", + "prepublishOnly": "cross-env NODE_ENV=production tsc --build && tsc-alias -p tsconfig.json", + "build": "rimraf dist && tsc --build && tsc-alias -p tsconfig.json", + "test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts", + "test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts", + "migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate", + "migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial", + "migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create", + "migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up", + "orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear" + }, + "devDependencies": { + "@mikro-orm/cli": "5.7.12", + "cross-env": "^5.2.1", + "jest": "^29.6.3", + "medusa-test-utils": "^1.1.40", + "rimraf": "^3.0.2", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "tsc-alias": "^1.8.6", + "typescript": "^5.1.6" + }, + "dependencies": { + "@medusajs/modules-sdk": "^1.12.5", + "@medusajs/types": "^1.11.9", + "@medusajs/utils": "^1.11.2", + "@mikro-orm/core": "5.7.12", + "@mikro-orm/migrations": "5.7.12", + "@mikro-orm/postgresql": "5.7.12", + "awilix": "^8.0.0", + "dotenv": "^16.1.4", + "knex": "2.4.2" + } +} diff --git a/packages/authentication/src/index.ts b/packages/authentication/src/index.ts new file mode 100644 index 0000000000..4ea0e7c3e3 --- /dev/null +++ b/packages/authentication/src/index.ts @@ -0,0 +1,7 @@ +import { moduleDefinition } from "./module-definition" + +export default moduleDefinition + +export * from "./initialize" +export * from "./loaders" +export * from "./scripts" diff --git a/packages/authentication/src/initialize/index.ts b/packages/authentication/src/initialize/index.ts new file mode 100644 index 0000000000..2e651756d8 --- /dev/null +++ b/packages/authentication/src/initialize/index.ts @@ -0,0 +1,27 @@ +import { + ExternalModuleDeclaration, + InternalModuleDeclaration, + MedusaModule, + MODULE_PACKAGE_NAMES, + Modules, +} from "@medusajs/modules-sdk" +import { IAuthenticationModuleService, ModulesSdkTypes } from "@medusajs/types" +import { moduleDefinition } from "../module-definition" +import { InitializeModuleInjectableDependencies } from "../types" + +export const initialize = async ( + options?: ModulesSdkTypes.ModuleBootstrapDeclaration, + injectedDependencies?: InitializeModuleInjectableDependencies +): Promise => { + const loaded = await MedusaModule.bootstrap({ + moduleKey: Modules.AUTHENTICATION, + defaultPath: MODULE_PACKAGE_NAMES[Modules.AUTHENTICATION], + declaration: options as + | InternalModuleDeclaration + | ExternalModuleDeclaration, // TODO: Add provider configuration + injectedDependencies, + moduleExports: moduleDefinition, + }) + + return loaded[Modules.AUTHENTICATION] +} diff --git a/packages/authentication/src/joiner-config.ts b/packages/authentication/src/joiner-config.ts new file mode 100644 index 0000000000..29368001fa --- /dev/null +++ b/packages/authentication/src/joiner-config.ts @@ -0,0 +1,31 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleJoinerConfig } from "@medusajs/types" +import { MapToConfig } from "@medusajs/utils" +import { AuthUser } from "@models" + +export const LinkableKeys = { + auth_user_id: AuthUser.name, +} + +const entityLinkableKeysMap: MapToConfig = {} +Object.entries(LinkableKeys).forEach(([key, value]) => { + entityLinkableKeysMap[value] ??= [] + entityLinkableKeysMap[value].push({ + mapTo: key, + valueFrom: key.split("_").pop()!, + }) +}) + +export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap + +export const joinerConfig: ModuleJoinerConfig = { + serviceName: Modules.AUTHENTICATION, + primaryKeys: ["id"], + linkableKeys: LinkableKeys, + alias: { + name: ["auth_user", "auth_users"], + args: { + entity: AuthUser.name, + }, + }, +} diff --git a/packages/authentication/src/loaders/connection.ts b/packages/authentication/src/loaders/connection.ts new file mode 100644 index 0000000000..cb859f1f98 --- /dev/null +++ b/packages/authentication/src/loaders/connection.ts @@ -0,0 +1,36 @@ +import { + InternalModuleDeclaration, + LoaderOptions, + Modules, +} from "@medusajs/modules-sdk" +import { ModulesSdkTypes } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" +import { EntitySchema } from "@mikro-orm/core" +import * as AuthenticationModules from "../models" + +export default async ( + { + options, + container, + logger, + }: LoaderOptions< + | ModulesSdkTypes.ModuleServiceInitializeOptions + | ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions + >, + moduleDeclaration?: InternalModuleDeclaration +): Promise => { + const entities = Object.values( + AuthenticationModules + ) as unknown as EntitySchema[] + const pathToMigrations = __dirname + "/../migrations" + + await ModulesSdkUtils.mikroOrmConnectionLoader({ + moduleName: Modules.AUTHENTICATION, + entities, + container, + options, + moduleDeclaration, + logger, + pathToMigrations, + }) +} diff --git a/packages/authentication/src/loaders/container.ts b/packages/authentication/src/loaders/container.ts new file mode 100644 index 0000000000..22b26b451c --- /dev/null +++ b/packages/authentication/src/loaders/container.ts @@ -0,0 +1,38 @@ +import * as defaultRepositories from "@repositories" + +import { LoaderOptions } from "@medusajs/modules-sdk" +import { ModulesSdkTypes } from "@medusajs/types" +import { loadCustomRepositories } from "@medusajs/utils" +import { asClass } from "awilix" + +export default async ({ + container, + options, +}: LoaderOptions< + | ModulesSdkTypes.ModuleServiceInitializeOptions + | ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions +>): Promise => { + const customRepositories = ( + options as ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions + )?.repositories + + container.register({ + // authenticationService: asClass(defaultServices.AuthenticationService).singleton(), + }) + + if (customRepositories) { + loadCustomRepositories({ + defaultRepositories, + customRepositories, + container, + }) + } else { + loadDefaultRepositories({ container }) + } +} + +function loadDefaultRepositories({ container }) { + container.register({ + baseRepository: asClass(defaultRepositories.BaseRepository).singleton(), + }) +} diff --git a/packages/authentication/src/loaders/index.ts b/packages/authentication/src/loaders/index.ts new file mode 100644 index 0000000000..3614963d8c --- /dev/null +++ b/packages/authentication/src/loaders/index.ts @@ -0,0 +1,2 @@ +export * from "./connection" +export * from "./container" diff --git a/packages/authentication/src/migrations/.snapshot-medusa-authentication.json b/packages/authentication/src/migrations/.snapshot-medusa-authentication.json new file mode 100644 index 0000000000..c7d860b742 --- /dev/null +++ b/packages/authentication/src/migrations/.snapshot-medusa-authentication.json @@ -0,0 +1,36 @@ +{ + "namespaces": [ + "public" + ], + "name": "public", + "tables": [ + { + "columns": { + "id": { + "name": "id", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "text" + } + }, + "name": "auth_user", + "schema": "public", + "indexes": [ + { + "keyName": "auth_user_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {} + } + ] +} diff --git a/packages/authentication/src/migrations/Migration20231220132440.ts b/packages/authentication/src/migrations/Migration20231220132440.ts new file mode 100644 index 0000000000..0ff613b274 --- /dev/null +++ b/packages/authentication/src/migrations/Migration20231220132440.ts @@ -0,0 +1,13 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20231220132440 extends Migration { + + async up(): Promise { + this.addSql('create table "auth_user" ("id" text not null, constraint "auth_user_pkey" primary key ("id"));'); + } + + async down(): Promise { + this.addSql('drop table if exists "auth_user" cascade;'); + } + +} diff --git a/packages/authentication/src/models/auth-user.ts b/packages/authentication/src/models/auth-user.ts new file mode 100644 index 0000000000..72f165a84a --- /dev/null +++ b/packages/authentication/src/models/auth-user.ts @@ -0,0 +1,18 @@ +import { generateEntityId } from "@medusajs/utils" +import { BeforeCreate, Entity, OnInit, PrimaryKey } from "@mikro-orm/core" + +@Entity() +export default class AuthUser { + @PrimaryKey({ columnType: "text" }) + id!: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "authusr") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "authusr") + } +} diff --git a/packages/authentication/src/models/index.ts b/packages/authentication/src/models/index.ts new file mode 100644 index 0000000000..e5b8ee0f1c --- /dev/null +++ b/packages/authentication/src/models/index.ts @@ -0,0 +1 @@ +export { default as AuthUser } from "./auth-user" diff --git a/packages/authentication/src/module-definition.ts b/packages/authentication/src/module-definition.ts new file mode 100644 index 0000000000..9b7854ba0a --- /dev/null +++ b/packages/authentication/src/module-definition.ts @@ -0,0 +1,12 @@ +import { ModuleExports } from "@medusajs/types" +import { AuthenticationModuleService } from "@services" +import loadConnection from "./loaders/connection" +import loadContainer from "./loaders/container" + +const service = AuthenticationModuleService +const loaders = [loadContainer, loadConnection] as any + +export const moduleDefinition: ModuleExports = { + service, + loaders, +} diff --git a/packages/authentication/src/repositories/index.ts b/packages/authentication/src/repositories/index.ts new file mode 100644 index 0000000000..147c9cc259 --- /dev/null +++ b/packages/authentication/src/repositories/index.ts @@ -0,0 +1 @@ +export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils" diff --git a/packages/authentication/src/scripts/bin/run-migration-down.ts b/packages/authentication/src/scripts/bin/run-migration-down.ts new file mode 100644 index 0000000000..e352048fd4 --- /dev/null +++ b/packages/authentication/src/scripts/bin/run-migration-down.ts @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +export default (async () => { + const { revertMigration } = await import("../migration-down") + const { config } = await import("dotenv") + config() + await revertMigration() +})() diff --git a/packages/authentication/src/scripts/bin/run-migration-up.ts b/packages/authentication/src/scripts/bin/run-migration-up.ts new file mode 100644 index 0000000000..35f3bee853 --- /dev/null +++ b/packages/authentication/src/scripts/bin/run-migration-up.ts @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +export default (async () => { + const { runMigrations } = await import("../migration-up") + const { config } = await import("dotenv") + config() + await runMigrations() +})() diff --git a/packages/authentication/src/scripts/bin/run-seed.ts b/packages/authentication/src/scripts/bin/run-seed.ts new file mode 100644 index 0000000000..468808169a --- /dev/null +++ b/packages/authentication/src/scripts/bin/run-seed.ts @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +import { EOL } from "os" +import { run } from "../seed" + +const args = process.argv +const path = args.pop() as string + +export default (async () => { + const { config } = await import("dotenv") + config() + if (!path) { + throw new Error( + `filePath is required.${EOL}Example: medusa-authentication-seed ` + ) + } + + await run({ path }) +})() diff --git a/packages/authentication/src/scripts/index.ts b/packages/authentication/src/scripts/index.ts new file mode 100644 index 0000000000..cfa5c5ddf5 --- /dev/null +++ b/packages/authentication/src/scripts/index.ts @@ -0,0 +1,2 @@ +export * from "./migration-up" +export * from "./migration-down" diff --git a/packages/authentication/src/scripts/migration-down.ts b/packages/authentication/src/scripts/migration-down.ts new file mode 100644 index 0000000000..84fcd75e35 --- /dev/null +++ b/packages/authentication/src/scripts/migration-down.ts @@ -0,0 +1,50 @@ +import { Modules } from "@medusajs/modules-sdk"; +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"; +import { DALUtils, ModulesSdkUtils } from "@medusajs/utils"; +import { EntitySchema } from "@mikro-orm/core"; +import * as AuthenticationModels from "@models"; + +/** + * This script is only valid for mikro orm managers. If a user provide a custom manager + * he is in charge of reverting the migrations. + * @param options + * @param logger + * @param moduleDeclaration + */ +export async function revertMigration({ + options, + logger, +}: Pick< + LoaderOptions, + "options" | "logger" +> = {}) { + logger ??= console as unknown as Logger + + const dbData = ModulesSdkUtils.loadDatabaseConfig( + Modules.AUTHENTICATION, + options + )! + const entities = Object.values( + AuthenticationModels + ) as unknown as EntitySchema[] + const pathToMigrations = __dirname + "/../migrations" + + const orm = await DALUtils.mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + + try { + const migrator = orm.getMigrator() + await migrator.down() + + logger?.info("Authentication module migration executed") + } catch (error) { + logger?.error( + `Authentication module migration failed to run - Error: ${error}` + ) + } + + await orm.close() +} diff --git a/packages/authentication/src/scripts/migration-up.ts b/packages/authentication/src/scripts/migration-up.ts new file mode 100644 index 0000000000..5f3cda160e --- /dev/null +++ b/packages/authentication/src/scripts/migration-up.ts @@ -0,0 +1,62 @@ +import { Modules } from "@medusajs/modules-sdk"; +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types"; +import { DALUtils, ModulesSdkUtils } from "@medusajs/utils"; +import { EntitySchema } from "@mikro-orm/core"; +import * as AuthenticationModels from "@models"; + +/** + * This script is only valid for mikro orm managers. If a user provide a custom manager + * he is in charge of running the migrations. + * @param options + * @param logger + * @param moduleDeclaration + */ +export async function runMigrations({ + options, + logger, +}: Pick< + LoaderOptions, + "options" | "logger" +> = {}) { + logger ??= console as unknown as Logger + + const dbData = ModulesSdkUtils.loadDatabaseConfig( + Modules.AUTHENTICATION, + options + )! + const entities = Object.values( + AuthenticationModels + ) as unknown as EntitySchema[] + const pathToMigrations = __dirname + "/../migrations" + + const orm = await DALUtils.mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + + try { + const migrator = orm.getMigrator() + + const pendingMigrations = await migrator.getPendingMigrations() + logger.info( + `Running pending migrations: ${JSON.stringify( + pendingMigrations, + null, + 2 + )}` + ) + + await migrator.up({ + migrations: pendingMigrations.map((m) => m.name), + }) + + logger.info("Authentication module migration executed") + } catch (error) { + logger.error( + `Authentication module migration failed to run - Error: ${error}` + ) + } + + await orm.close() +} diff --git a/packages/authentication/src/scripts/seed.ts b/packages/authentication/src/scripts/seed.ts new file mode 100644 index 0000000000..ac32d4d595 --- /dev/null +++ b/packages/authentication/src/scripts/seed.ts @@ -0,0 +1,63 @@ +import { Modules } from "@medusajs/modules-sdk" +import { LoaderOptions, Logger, ModulesSdkTypes } from "@medusajs/types" +import { DALUtils, ModulesSdkUtils } from "@medusajs/utils" +import { EntitySchema } from "@mikro-orm/core" +import * as AuthenticationModels from "@models" +import { EOL } from "os" +import { resolve } from "path" + +export async function run({ + options, + logger, + path, +}: Partial< + Pick< + LoaderOptions, + "options" | "logger" + > +> & { + path: string +}) { + logger ??= console as unknown as Logger + + logger.info(`Loading seed data from ${path}...`) + + const { authenticationData } = await import( + resolve(process.cwd(), path) + ).catch((e) => { + logger?.error( + `Failed to load seed data from ${path}. Please, provide a relative path and check that you export the following: authenticationData.${EOL}${e}` + ) + throw e + }) + + const dbData = ModulesSdkUtils.loadDatabaseConfig( + Modules.AUTHENTICATION, + options + )! + const entities = Object.values( + AuthenticationModels + ) as unknown as EntitySchema[] + const pathToMigrations = __dirname + "/../migrations" + + const orm = await DALUtils.mikroOrmCreateConnection( + dbData, + entities, + pathToMigrations + ) + + const manager = orm.em.fork() + + try { + logger.info("Seeding authentication data..") + + // TODO: implement authentication seed data + // await createAuthUsers(manager, authUsersData) + } catch (e) { + logger.error( + `Failed to insert the seed data in the PostgreSQL database ${dbData.clientUrl}.${EOL}${e}` + ) + } + + await orm.close(true) +} diff --git a/packages/authentication/src/services/__tests__/index.spec.ts b/packages/authentication/src/services/__tests__/index.spec.ts new file mode 100644 index 0000000000..728f6245c6 --- /dev/null +++ b/packages/authentication/src/services/__tests__/index.spec.ts @@ -0,0 +1,5 @@ +describe("Noop test", () => { + it("noop check", async () => { + expect(true).toBe(true) + }) +}) diff --git a/packages/authentication/src/services/authentication-module.ts b/packages/authentication/src/services/authentication-module.ts new file mode 100644 index 0000000000..5e48f4ba12 --- /dev/null +++ b/packages/authentication/src/services/authentication-module.ts @@ -0,0 +1,32 @@ +import { + AuthenticationTypes, + DAL, + InternalModuleDeclaration, + ModuleJoinerConfig, +} from "@medusajs/types" + +import { AuthUser } from "@models" + +import { joinerConfig } from "../joiner-config" + +type InjectedDependencies = { + baseRepository: DAL.RepositoryService +} + +export default class AuthenticationModuleService< + TAuthUser extends AuthUser = AuthUser +> implements AuthenticationTypes.IAuthenticationModuleService +{ + protected baseRepository_: DAL.RepositoryService + + constructor( + { baseRepository }: InjectedDependencies, + protected readonly moduleDeclaration: InternalModuleDeclaration + ) { + this.baseRepository_ = baseRepository + } + + __joinerConfig(): ModuleJoinerConfig { + return joinerConfig + } +} diff --git a/packages/authentication/src/services/index.ts b/packages/authentication/src/services/index.ts new file mode 100644 index 0000000000..70e0f87be0 --- /dev/null +++ b/packages/authentication/src/services/index.ts @@ -0,0 +1 @@ +export { default as AuthenticationModuleService } from "./authentication-module" diff --git a/packages/authentication/src/types/index.ts b/packages/authentication/src/types/index.ts new file mode 100644 index 0000000000..0f252977b0 --- /dev/null +++ b/packages/authentication/src/types/index.ts @@ -0,0 +1,5 @@ +import { Logger } from "@medusajs/types" + +export type InitializeModuleInjectableDependencies = { + logger?: Logger +} diff --git a/packages/authentication/tsconfig.json b/packages/authentication/tsconfig.json new file mode 100644 index 0000000000..213e38fc55 --- /dev/null +++ b/packages/authentication/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "lib": ["es2020"], + "target": "es2020", + "outDir": "./dist", + "esModuleInterop": true, + "declaration": true, + "module": "commonjs", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": false, + "noImplicitReturns": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "allowJs": true, + "skipLibCheck": true, + "downlevelIteration": true, // to use ES5 specific tooling + "baseUrl": ".", + "resolveJsonModule": true, + "paths": { + "@models": ["./src/models"], + "@services": ["./src/services"], + "@repositories": ["./src/repositories"] + } + }, + "include": ["src"], + "exclude": [ + "dist", + "./src/**/__tests__", + "./src/**/__mocks__", + "./src/**/__fixtures__", + "node_modules" + ] +} diff --git a/packages/authentication/tsconfig.spec.json b/packages/authentication/tsconfig.spec.json new file mode 100644 index 0000000000..48e47e8cbb --- /dev/null +++ b/packages/authentication/tsconfig.spec.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": ["src", "integration-tests"], + "exclude": ["node_modules", "dist"], + "compilerOptions": { + "sourceMap": true + } +} diff --git a/packages/modules-sdk/src/definitions.ts b/packages/modules-sdk/src/definitions.ts index 60b19f4905..6b7355319e 100644 --- a/packages/modules-sdk/src/definitions.ts +++ b/packages/modules-sdk/src/definitions.ts @@ -14,6 +14,7 @@ export enum Modules { PRODUCT = "productService", PRICING = "pricingService", PROMOTION = "promotion", + AUTHENTICATION = "authentication", } export enum ModuleRegistrationName { @@ -24,6 +25,7 @@ export enum ModuleRegistrationName { PRODUCT = "productModuleService", PRICING = "pricingModuleService", PROMOTION = "promotionModuleService", + AUTHENTICATION = "authenticationModuleService", } export const MODULE_PACKAGE_NAMES = { @@ -34,6 +36,7 @@ export const MODULE_PACKAGE_NAMES = { [Modules.CACHE]: "@medusajs/cache-inmemory", [Modules.PRICING]: "@medusajs/pricing", [Modules.PROMOTION]: "@medusajs/promotion", + [Modules.AUTHENTICATION]: "@medusajs/authentication", } export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = @@ -137,6 +140,20 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = resources: MODULE_RESOURCE_TYPE.SHARED, }, }, + [Modules.AUTHENTICATION]: { + key: Modules.AUTHENTICATION, + registrationName: ModuleRegistrationName.AUTHENTICATION, + defaultPackage: false, + label: upperCaseFirst(ModuleRegistrationName.AUTHENTICATION), + isRequired: false, + canOverride: true, + isQueryable: true, + dependencies: ["logger"], + defaultModuleDeclaration: { + scope: MODULE_SCOPE.INTERNAL, + resources: MODULE_RESOURCE_TYPE.SHARED, + }, + }, } export const MODULE_DEFINITIONS: ModuleDefinition[] = diff --git a/packages/types/src/authentication/index.ts b/packages/types/src/authentication/index.ts new file mode 100644 index 0000000000..9376fea807 --- /dev/null +++ b/packages/types/src/authentication/index.ts @@ -0,0 +1 @@ +export * from "./service" diff --git a/packages/types/src/authentication/service.ts b/packages/types/src/authentication/service.ts new file mode 100644 index 0000000000..eb172bca5d --- /dev/null +++ b/packages/types/src/authentication/service.ts @@ -0,0 +1,3 @@ +import { IModuleService } from "../modules-sdk" + +export interface IAuthenticationModuleService extends IModuleService {} diff --git a/packages/types/src/bundles.ts b/packages/types/src/bundles.ts index 198bb2684d..0737179515 100644 --- a/packages/types/src/bundles.ts +++ b/packages/types/src/bundles.ts @@ -1,3 +1,4 @@ +export * as AuthenticationTypes from "./authentication" export * as CacheTypes from "./cache" export * as CommonTypes from "./common" export * as CustomerTypes from "./customer" diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 829c57461b..82f14d6ab5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,4 +1,5 @@ export * from "./address" +export * from "./authentication" export * from "./bundles" export * from "./cache" export * from "./cart" diff --git a/yarn.lock b/yarn.lock index bab445b0c9..9c87e6b189 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7405,6 +7405,35 @@ __metadata: languageName: unknown linkType: soft +"@medusajs/authentication@workspace:packages/authentication": + version: 0.0.0-use.local + resolution: "@medusajs/authentication@workspace:packages/authentication" + dependencies: + "@medusajs/modules-sdk": ^1.12.5 + "@medusajs/types": ^1.11.9 + "@medusajs/utils": ^1.11.2 + "@mikro-orm/cli": 5.7.12 + "@mikro-orm/core": 5.7.12 + "@mikro-orm/migrations": 5.7.12 + "@mikro-orm/postgresql": 5.7.12 + awilix: ^8.0.0 + cross-env: ^5.2.1 + dotenv: ^16.1.4 + jest: ^29.6.3 + knex: 2.4.2 + medusa-test-utils: ^1.1.40 + rimraf: ^3.0.2 + ts-jest: ^29.1.1 + ts-node: ^10.9.1 + tsc-alias: ^1.8.6 + typescript: ^5.1.6 + bin: + medusa-authentication-migrations-down: dist/scripts/bin/run-migration-down.js + medusa-authentication-migrations-up: dist/scripts/bin/run-migration-up.js + medusa-authentication-seed: dist/scripts/bin/run-seed.js + languageName: unknown + linkType: soft + "@medusajs/cache-inmemory@workspace:*, @medusajs/cache-inmemory@workspace:packages/cache-inmemory": version: 0.0.0-use.local resolution: "@medusajs/cache-inmemory@workspace:packages/cache-inmemory"