create-warlock 4.1.9 → 4.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/commands/create-warlock-app/index.mjs +1 -1
- package/esm/commands/create-warlock-app/index.mjs.map +1 -1
- package/esm/helpers/app.mjs +24 -0
- package/esm/helpers/app.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/warlock/src/app/auth/controllers/forgot-password.controller.ts +1 -6
- package/templates/warlock/src/app/auth/controllers/login.controller.ts +1 -4
- package/templates/warlock/src/app/auth/controllers/logout-all.controller.ts +2 -10
- package/templates/warlock/src/app/auth/controllers/logout.controller.ts +2 -10
- package/templates/warlock/src/app/auth/controllers/me.controller.ts +2 -9
- package/templates/warlock/src/app/auth/controllers/refresh-token.controller.ts +1 -5
- package/templates/warlock/src/app/auth/controllers/reset-password.controller.ts +1 -1
- package/templates/warlock/src/app/auth/main.ts +1 -3
- package/templates/warlock/src/app/auth/models/otp/migrations/22-12-2025_10-30-20.otp-migration.ts +1 -8
- package/templates/warlock/src/app/auth/requests/guarded.request.ts +3 -4
- package/templates/warlock/src/app/auth/services/otp.service.ts +5 -15
- package/templates/warlock/src/app/auth/services/reset-password.service.ts +1 -3
- package/templates/warlock/src/app/posts/models/post/migrations/09-01-2026_02-07-51-post.migration.ts +1 -9
- package/templates/warlock/src/app/posts/routes.ts +1 -4
- package/templates/warlock/src/app/shared/components/HomePageComponent.tsx +37 -59
- package/templates/warlock/src/app/shared/controllers/home-page.controller.ts +18 -0
- package/templates/warlock/src/app/shared/controllers/home-page.controller.tsx +2 -9
- package/templates/warlock/src/app/uploads/controllers/fetch-uploaded-file.controller.ts +2 -5
- package/templates/warlock/src/app/users/events/inject-created-by-user.into-model.event.ts +1 -1
- package/templates/warlock/src/app/users/models/user/user.model.ts +4 -8
- package/templates/warlock/src/app/users/routes.ts +1 -4
- package/templates/warlock/src/app/users/services/login-social.ts +1 -4
- package/templates/warlock/src/config/cache.ts +1 -2
- package/templates/warlock/src/config/database.ts +1 -4
|
@@ -8,7 +8,7 @@ async function createWarlockApp(application) {
|
|
|
8
8
|
const { useGit, useJWT, features, aiProviders, databaseDriver } = application.options;
|
|
9
9
|
const templateSpinner = spinner();
|
|
10
10
|
templateSpinner.start(spinnerMessages.copyingTemplate);
|
|
11
|
-
application.init().use("warlock").updatePackageJson().updateDotEnv().configureDatabaseEnv(databaseDriver);
|
|
11
|
+
application.init().use("warlock").updatePackageJson().updateDotEnv().configureDatabaseEnv(databaseDriver).configureHomePage(features.includes("react"));
|
|
12
12
|
templateSpinner.stop(spinnerMessages.templateCopied);
|
|
13
13
|
const installSpinner = spinner();
|
|
14
14
|
installSpinner.start(spinnerMessages.installingDeps);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../@warlock.js/create-warlock/src/commands/create-warlock-app/index.ts"],"sourcesContent":["import { spinner } from \"@clack/prompts\";\r\nimport { App } from \"../../helpers/app\";\r\nimport {\r\n getPackageManager,\r\n runPackageManagerCommand,\r\n} from \"../../helpers/package-manager\";\r\nimport { showSuccessScreen } from \"../../ui/banner\";\r\nimport { spinnerMessages } from \"../../ui/spinners\";\r\n\r\nexport async function createWarlockApp(application: App) {\r\n const options = application.options;\r\n const { useGit, useJWT, features, aiProviders, databaseDriver } = options;\r\n\r\n // Step 1: Initialize and copy template\r\n const templateSpinner = spinner();\r\n templateSpinner.start(spinnerMessages.copyingTemplate);\r\n\r\n application\r\n .init()\r\n .use(\"warlock\")\r\n .updatePackageJson()\r\n .updateDotEnv()\r\n .configureDatabaseEnv(databaseDriver);\r\n\r\n templateSpinner.stop(spinnerMessages.templateCopied);\r\n\r\n // Step 2: Install base dependencies (so the `warlock` binary is available)\r\n const installSpinner = spinner();\r\n installSpinner.start(spinnerMessages.installingDeps);\r\n\r\n await application.install().install;\r\n\r\n installSpinner.stop(spinnerMessages.depsInstalled);\r\n\r\n // Step 3: Add features via `warlock add --no-install`, then one batched install.\r\n // The DB driver, optional features, and AI providers all go through the single\r\n // source of truth (core's feature map) so versions never drift.\r\n const selectedFeatures = [databaseDriver, ...features, ...aiProviders];\r\n\r\n if (selectedFeatures.length > 0) {\r\n const featuresSpinner = spinner();\r\n featuresSpinner.start(spinnerMessages.addingFeatures);\r\n\r\n const added = await application.installFeatures(selectedFeatures);\r\n\r\n if (added) {\r\n await application.install().install;\r\n featuresSpinner.stop(spinnerMessages.featuresAdded);\r\n } else {\r\n featuresSpinner.stop(spinnerMessages.featuresFailed);\r\n }\r\n }\r\n\r\n // Step 4: Initialize Git repository if requested\r\n if (useGit) {\r\n const gitSpinner = spinner();\r\n gitSpinner.start(spinnerMessages.initializingGit);\r\n\r\n await application.git();\r\n\r\n gitSpinner.stop(spinnerMessages.gitInitialized);\r\n }\r\n\r\n // Step 5: Generate JWT or warm cache\r\n if (useJWT) {\r\n const jwtSpinner = spinner();\r\n jwtSpinner.start(spinnerMessages.generatingJwt);\r\n\r\n await application.exec(runPackageManagerCommand(\"jwt\"));\r\n\r\n jwtSpinner.stop(spinnerMessages.jwtGenerated);\r\n } else {\r\n const warmSpinner = spinner();\r\n warmSpinner.start(spinnerMessages.warmingCache);\r\n\r\n await application.exec(\"npx warlock --warm-cache\");\r\n\r\n warmSpinner.stop(spinnerMessages.cacheWarmed);\r\n }\r\n\r\n // Step 6: Show success screen\r\n showSuccessScreen({\r\n projectName: application.name,\r\n database: databaseDriver === \"mongodb\" ? \"MongoDB\" : \"PostgreSQL\",\r\n features: [...features, ...aiProviders],\r\n packageManager: getPackageManager(),\r\n });\r\n}\r\n"],"mappings":";;;;;;AASA,eAAsB,iBAAiB,aAAkB;CAEvD,MAAM,EAAE,QAAQ,QAAQ,UAAU,aAAa,mBAD/B,YAAY;CAI5B,MAAM,kBAAkB,QAAQ;CAChC,gBAAgB,MAAM,gBAAgB,eAAe;CAErD,YACG,KAAK,EACL,IAAI,SAAS,EACb,kBAAkB,EAClB,aAAa,EACb,qBAAqB,cAAc;
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../../../@warlock.js/create-warlock/src/commands/create-warlock-app/index.ts"],"sourcesContent":["import { spinner } from \"@clack/prompts\";\r\nimport { App } from \"../../helpers/app\";\r\nimport {\r\n getPackageManager,\r\n runPackageManagerCommand,\r\n} from \"../../helpers/package-manager\";\r\nimport { showSuccessScreen } from \"../../ui/banner\";\r\nimport { spinnerMessages } from \"../../ui/spinners\";\r\n\r\nexport async function createWarlockApp(application: App) {\r\n const options = application.options;\r\n const { useGit, useJWT, features, aiProviders, databaseDriver } = options;\r\n\r\n // Step 1: Initialize and copy template\r\n const templateSpinner = spinner();\r\n templateSpinner.start(spinnerMessages.copyingTemplate);\r\n\r\n application\r\n .init()\r\n .use(\"warlock\")\r\n .updatePackageJson()\r\n .updateDotEnv()\r\n .configureDatabaseEnv(databaseDriver)\r\n .configureHomePage(features.includes(\"react\"));\r\n\r\n templateSpinner.stop(spinnerMessages.templateCopied);\r\n\r\n // Step 2: Install base dependencies (so the `warlock` binary is available)\r\n const installSpinner = spinner();\r\n installSpinner.start(spinnerMessages.installingDeps);\r\n\r\n await application.install().install;\r\n\r\n installSpinner.stop(spinnerMessages.depsInstalled);\r\n\r\n // Step 3: Add features via `warlock add --no-install`, then one batched install.\r\n // The DB driver, optional features, and AI providers all go through the single\r\n // source of truth (core's feature map) so versions never drift.\r\n const selectedFeatures = [databaseDriver, ...features, ...aiProviders];\r\n\r\n if (selectedFeatures.length > 0) {\r\n const featuresSpinner = spinner();\r\n featuresSpinner.start(spinnerMessages.addingFeatures);\r\n\r\n const added = await application.installFeatures(selectedFeatures);\r\n\r\n if (added) {\r\n await application.install().install;\r\n featuresSpinner.stop(spinnerMessages.featuresAdded);\r\n } else {\r\n featuresSpinner.stop(spinnerMessages.featuresFailed);\r\n }\r\n }\r\n\r\n // Step 4: Initialize Git repository if requested\r\n if (useGit) {\r\n const gitSpinner = spinner();\r\n gitSpinner.start(spinnerMessages.initializingGit);\r\n\r\n await application.git();\r\n\r\n gitSpinner.stop(spinnerMessages.gitInitialized);\r\n }\r\n\r\n // Step 5: Generate JWT or warm cache\r\n if (useJWT) {\r\n const jwtSpinner = spinner();\r\n jwtSpinner.start(spinnerMessages.generatingJwt);\r\n\r\n await application.exec(runPackageManagerCommand(\"jwt\"));\r\n\r\n jwtSpinner.stop(spinnerMessages.jwtGenerated);\r\n } else {\r\n const warmSpinner = spinner();\r\n warmSpinner.start(spinnerMessages.warmingCache);\r\n\r\n await application.exec(\"npx warlock --warm-cache\");\r\n\r\n warmSpinner.stop(spinnerMessages.cacheWarmed);\r\n }\r\n\r\n // Step 6: Show success screen\r\n showSuccessScreen({\r\n projectName: application.name,\r\n database: databaseDriver === \"mongodb\" ? \"MongoDB\" : \"PostgreSQL\",\r\n features: [...features, ...aiProviders],\r\n packageManager: getPackageManager(),\r\n });\r\n}\r\n"],"mappings":";;;;;;AASA,eAAsB,iBAAiB,aAAkB;CAEvD,MAAM,EAAE,QAAQ,QAAQ,UAAU,aAAa,mBAD/B,YAAY;CAI5B,MAAM,kBAAkB,QAAQ;CAChC,gBAAgB,MAAM,gBAAgB,eAAe;CAErD,YACG,KAAK,EACL,IAAI,SAAS,EACb,kBAAkB,EAClB,aAAa,EACb,qBAAqB,cAAc,EACnC,kBAAkB,SAAS,SAAS,OAAO,CAAC;CAE/C,gBAAgB,KAAK,gBAAgB,cAAc;CAGnD,MAAM,iBAAiB,QAAQ;CAC/B,eAAe,MAAM,gBAAgB,cAAc;CAEnD,MAAM,YAAY,QAAQ,EAAE;CAE5B,eAAe,KAAK,gBAAgB,aAAa;CAKjD,MAAM,mBAAmB;EAAC;EAAgB,GAAG;EAAU,GAAG;CAAW;CAErE,IAAI,iBAAiB,SAAS,GAAG;EAC/B,MAAM,kBAAkB,QAAQ;EAChC,gBAAgB,MAAM,gBAAgB,cAAc;EAIpD,IAAI,MAFgB,YAAY,gBAAgB,gBAAgB,GAErD;GACT,MAAM,YAAY,QAAQ,EAAE;GAC5B,gBAAgB,KAAK,gBAAgB,aAAa;EACpD,OACE,gBAAgB,KAAK,gBAAgB,cAAc;CAEvD;CAGA,IAAI,QAAQ;EACV,MAAM,aAAa,QAAQ;EAC3B,WAAW,MAAM,gBAAgB,eAAe;EAEhD,MAAM,YAAY,IAAI;EAEtB,WAAW,KAAK,gBAAgB,cAAc;CAChD;CAGA,IAAI,QAAQ;EACV,MAAM,aAAa,QAAQ;EAC3B,WAAW,MAAM,gBAAgB,aAAa;EAE9C,MAAM,YAAY,KAAK,yBAAyB,KAAK,CAAC;EAEtD,WAAW,KAAK,gBAAgB,YAAY;CAC9C,OAAO;EACL,MAAM,cAAc,QAAQ;EAC5B,YAAY,MAAM,gBAAgB,YAAY;EAE9C,MAAM,YAAY,KAAK,0BAA0B;EAEjD,YAAY,KAAK,gBAAgB,WAAW;CAC9C;CAGA,kBAAkB;EAChB,aAAa,YAAY;EACzB,UAAU,mBAAmB,YAAY,YAAY;EACrD,UAAU,CAAC,GAAG,UAAU,GAAG,WAAW;EACtC,gBAAgB,kBAAkB;CACpC,CAAC;AACH"}
|
package/esm/helpers/app.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { executeCommand, runCommand } from "./exec.mjs";
|
|
|
3
3
|
import { getPackageManager } from "./package-manager.mjs";
|
|
4
4
|
import { packageRoot, template } from "./paths.mjs";
|
|
5
5
|
import { copyDirectory, copyFile, fileExists, getFile, getJsonFile, putFile, putJsonFile, renameFile } from "@warlock.js/fs";
|
|
6
|
+
import { unlinkSync } from "node:fs";
|
|
6
7
|
import path from "path";
|
|
7
8
|
|
|
8
9
|
//#region ../@warlock.js/create-warlock/src/helpers/app.ts
|
|
@@ -66,6 +67,29 @@ var App = class {
|
|
|
66
67
|
return this;
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
70
|
+
* Pick the home page implementation based on whether React was selected.
|
|
71
|
+
*
|
|
72
|
+
* The template ships BOTH a plain JSON controller (`home-page.controller.ts`)
|
|
73
|
+
* and a React-rendered page (`home-page.controller.tsx` + `HomePageComponent.tsx`).
|
|
74
|
+
* Exactly one survives the scaffold: React projects keep the `.tsx` page (its
|
|
75
|
+
* `react`/`react-dom` deps come from the `react` feature), every other project
|
|
76
|
+
* keeps the dependency-free JSON controller — so a fresh project never imports
|
|
77
|
+
* `react` unless it asked for it.
|
|
78
|
+
*/
|
|
79
|
+
configureHomePage(useReact) {
|
|
80
|
+
const controllers = this.path + "/src/app/shared/controllers";
|
|
81
|
+
const components = this.path + "/src/app/shared/components";
|
|
82
|
+
const remove = (file) => {
|
|
83
|
+
if (fileExists(file)) unlinkSync(file);
|
|
84
|
+
};
|
|
85
|
+
if (useReact) remove(controllers + "/home-page.controller.ts");
|
|
86
|
+
else {
|
|
87
|
+
remove(controllers + "/home-page.controller.tsx");
|
|
88
|
+
remove(components + "/HomePageComponent.tsx");
|
|
89
|
+
}
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
69
93
|
* Install the selected optional features by delegating to the project's own
|
|
70
94
|
* `warlock add`. `--no-install` records every dependency in package.json and
|
|
71
95
|
* ejects configs / scripts / setup hooks WITHOUT installing — the caller runs
|
package/esm/helpers/app.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.mjs","names":[],"sources":["../../../../../../@warlock.js/create-warlock/src/helpers/app.ts"],"sourcesContent":["import {\r\n copyDirectory,\r\n copyFile,\r\n fileExists,\r\n getFile,\r\n getJsonFile,\r\n putFile,\r\n putJsonFile,\r\n renameFile,\r\n} from \"@warlock.js/fs\";\r\nimport path from \"path\";\r\nimport { AppOptions, Application } from \"../commands/create-new-app/types\";\r\nimport { getDatabaseDriver } from \"../features/database-drivers\";\r\nimport { executeCommand, runCommand } from \"./exec\";\r\nimport { getPackageManager } from \"./package-manager\";\r\nimport { packageRoot, Template, template } from \"./paths\";\r\n\r\nexport class App {\r\n /**\r\n * Resolved files\r\n */\r\n protected files: Record<string, FileManager> = {};\r\n\r\n /**\r\n * Resolved JSON files\r\n */\r\n protected jsonFiles: Record<string, JsonFileManager> = {};\r\n\r\n public isInstalled = false;\r\n\r\n public constructor(protected app: Application) {}\r\n\r\n public get options(): AppOptions {\r\n return this.app.options;\r\n }\r\n\r\n public use(templateName: Template) {\r\n copyDirectory(template(templateName), this.path);\r\n\r\n if (fileExists(this.path + \"/.env.example\")) {\r\n copyFile(this.path + \"/.env.example\", this.path + \"/.env\");\r\n }\r\n\r\n renameFile(this.path + \"/_.gitignore\", this.path + \"/.gitignore\");\r\n\r\n return this;\r\n }\r\n\r\n public init() {\r\n return this;\r\n }\r\n\r\n public terminate() {\r\n // No longer using outro, using showSuccessScreen instead\r\n }\r\n\r\n public install() {\r\n return runCommand(getPackageManager(), [\"install\"], this.path);\r\n }\r\n\r\n public async exec(command: string) {\r\n const [commandName, ...optionsList] = command.split(\" \");\r\n return await executeCommand(commandName, optionsList, this.path);\r\n }\r\n\r\n public async git() {\r\n const { initializeGitRepository } = await import(\r\n \"./project-builder-helpers\"\r\n );\r\n return await initializeGitRepository(this.path);\r\n }\r\n\r\n public updatePackageJson() {\r\n const pkg = this.package\r\n .replace(\"name\", this.name.replaceAll(\"/\", \"-\"))\r\n .replaceAll(\"yarn\", getPackageManager());\r\n\r\n // Pin every @warlock.js/* dependency to THIS create-warlock release version\r\n // so a scaffolded project always matches the framework version it was created\r\n // with. create-warlock and the framework ship in lockstep, so the scaffolder's\r\n // own version is the single source of truth (the template's hardcoded versions\r\n // are irrelevant — they get overwritten here).\r\n const warlockVersion: string = getJsonFile(packageRoot(\"package.json\")).version;\r\n const content: any = pkg.content;\r\n\r\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\r\n const deps = content[field] as Record<string, string> | undefined;\r\n if (!deps) continue;\r\n\r\n for (const dependency of Object.keys(deps)) {\r\n if (dependency.startsWith(\"@warlock.js/\")) {\r\n deps[dependency] = warlockVersion;\r\n }\r\n }\r\n }\r\n\r\n pkg.save();\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Wire DB_DRIVER and DB_PORT into .env.\r\n *\r\n * The driver's npm package is installed via `warlock add` (single source for\r\n * versions), so this only touches environment configuration — not deps.\r\n */\r\n public configureDatabaseEnv(driverValue: string) {\r\n const driver = getDatabaseDriver(driverValue);\r\n\r\n if (!driver) return this;\r\n\r\n let envContent = getFile(this.path + \"/.env\") as string;\r\n\r\n envContent = envContent.replace(/DB_PORT=\\d+/, `DB_PORT=${driver.defaultPort}`);\r\n\r\n if (envContent.includes(\"DB_DRIVER=\")) {\r\n envContent = envContent.replace(/DB_DRIVER=\\w*/, `DB_DRIVER=${driver.value}`);\r\n } else {\r\n envContent = envContent.replace(\r\n /DB_PORT=\\d+/,\r\n `DB_PORT=${driver.defaultPort}\\nDB_DRIVER=${driver.value}`,\r\n );\r\n }\r\n\r\n putFile(this.path + \"/.env\", envContent);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Install the selected optional features by delegating to the project's own\r\n * `warlock add`. `--no-install` records every dependency in package.json and\r\n * ejects configs / scripts / setup hooks WITHOUT installing — the caller runs\r\n * one batched install afterwards. Versions come from core's feature map, so\r\n * the scaffolder never duplicates them.\r\n *\r\n * `--no-install` is passed LAST on purpose: the CLI parser treats the\r\n * positional after a bare flag as that flag's value, so it must follow the\r\n * feature list, not precede it.\r\n */\r\n public async installFeatures(features: string[]) {\r\n if (features.length === 0) return true;\r\n\r\n return this.exec(`npx warlock add ${features.join(\" \")} --no-install`);\r\n }\r\n\r\n /**\r\n * Get package json file\r\n */\r\n public get package() {\r\n return this.json(\"package.json\");\r\n }\r\n\r\n public updateDotEnv() {\r\n this.file(\".env\").replaceAll(\"appName\", this.name).save();\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Get env file to update\r\n */\r\n public get env() {\r\n return this.file(\".env\");\r\n }\r\n\r\n public get name() {\r\n return this.app.appName;\r\n }\r\n\r\n public get path() {\r\n return this.app.appPath;\r\n }\r\n\r\n public file(relativePath: string) {\r\n const fullPath = path.resolve(this.path, relativePath);\r\n\r\n if (!this.files[fullPath]) {\r\n this.files[fullPath] = file(fullPath);\r\n }\r\n\r\n return this.files[fullPath];\r\n }\r\n\r\n public json(relativePath: string): JsonFileManager {\r\n const fullPath = path.resolve(this.path, relativePath);\r\n\r\n if (!this.jsonFiles[fullPath]) {\r\n this.jsonFiles[fullPath] = jsonFile(fullPath);\r\n }\r\n\r\n return this.jsonFiles[fullPath];\r\n }\r\n}\r\n\r\nexport function app(app: Application) {\r\n return new App(app);\r\n}\r\n\r\nexport class FileManager {\r\n public content!: string;\r\n public constructor(protected filePath: string) {\r\n this.parseContent();\r\n }\r\n\r\n protected parseContent() {\r\n this.content = getFile(this.filePath) as string;\r\n }\r\n\r\n public replace(search: string, replace: string) {\r\n this.content = this.content.replace(search, replace);\r\n\r\n return this;\r\n }\r\n\r\n public replaceAll(search: string, replace: string) {\r\n this.content = this.content.replaceAll(search, replace);\r\n\r\n return this;\r\n }\r\n\r\n public save() {\r\n putFile(this.filePath, this.content);\r\n }\r\n}\r\n\r\nexport class JsonFileManager extends FileManager {\r\n protected parseContent() {\r\n this.content = getJsonFile(this.filePath);\r\n }\r\n\r\n public save() {\r\n putJsonFile(this.filePath, this.content);\r\n }\r\n\r\n public has(key: string) {\r\n return this.content[key] !== undefined;\r\n }\r\n\r\n public replace(key: string, value: any) {\r\n this.content[key] = value;\r\n\r\n return this;\r\n }\r\n\r\n public replaceAll(key: string, value: any) {\r\n const contentAsString = JSON.stringify(this.content);\r\n\r\n this.content = JSON.parse(contentAsString.replaceAll(key, value));\r\n\r\n return this;\r\n }\r\n}\r\n\r\nexport function file(path: string) {\r\n return new FileManager(path);\r\n}\r\n\r\nexport function jsonFile(path: string) {\r\n return new JsonFileManager(path);\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app.mjs","names":[],"sources":["../../../../../../@warlock.js/create-warlock/src/helpers/app.ts"],"sourcesContent":["import {\r\n copyDirectory,\r\n copyFile,\r\n fileExists,\r\n getFile,\r\n getJsonFile,\r\n putFile,\r\n putJsonFile,\r\n renameFile,\r\n} from \"@warlock.js/fs\";\r\nimport { unlinkSync } from \"node:fs\";\r\nimport path from \"path\";\r\nimport { AppOptions, Application } from \"../commands/create-new-app/types\";\r\nimport { getDatabaseDriver } from \"../features/database-drivers\";\r\nimport { executeCommand, runCommand } from \"./exec\";\r\nimport { getPackageManager } from \"./package-manager\";\r\nimport { packageRoot, Template, template } from \"./paths\";\r\n\r\nexport class App {\r\n /**\r\n * Resolved files\r\n */\r\n protected files: Record<string, FileManager> = {};\r\n\r\n /**\r\n * Resolved JSON files\r\n */\r\n protected jsonFiles: Record<string, JsonFileManager> = {};\r\n\r\n public isInstalled = false;\r\n\r\n public constructor(protected app: Application) {}\r\n\r\n public get options(): AppOptions {\r\n return this.app.options;\r\n }\r\n\r\n public use(templateName: Template) {\r\n copyDirectory(template(templateName), this.path);\r\n\r\n if (fileExists(this.path + \"/.env.example\")) {\r\n copyFile(this.path + \"/.env.example\", this.path + \"/.env\");\r\n }\r\n\r\n renameFile(this.path + \"/_.gitignore\", this.path + \"/.gitignore\");\r\n\r\n return this;\r\n }\r\n\r\n public init() {\r\n return this;\r\n }\r\n\r\n public terminate() {\r\n // No longer using outro, using showSuccessScreen instead\r\n }\r\n\r\n public install() {\r\n return runCommand(getPackageManager(), [\"install\"], this.path);\r\n }\r\n\r\n public async exec(command: string) {\r\n const [commandName, ...optionsList] = command.split(\" \");\r\n return await executeCommand(commandName, optionsList, this.path);\r\n }\r\n\r\n public async git() {\r\n const { initializeGitRepository } = await import(\r\n \"./project-builder-helpers\"\r\n );\r\n return await initializeGitRepository(this.path);\r\n }\r\n\r\n public updatePackageJson() {\r\n const pkg = this.package\r\n .replace(\"name\", this.name.replaceAll(\"/\", \"-\"))\r\n .replaceAll(\"yarn\", getPackageManager());\r\n\r\n // Pin every @warlock.js/* dependency to THIS create-warlock release version\r\n // so a scaffolded project always matches the framework version it was created\r\n // with. create-warlock and the framework ship in lockstep, so the scaffolder's\r\n // own version is the single source of truth (the template's hardcoded versions\r\n // are irrelevant — they get overwritten here).\r\n const warlockVersion: string = getJsonFile(packageRoot(\"package.json\")).version;\r\n const content: any = pkg.content;\r\n\r\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\r\n const deps = content[field] as Record<string, string> | undefined;\r\n if (!deps) continue;\r\n\r\n for (const dependency of Object.keys(deps)) {\r\n if (dependency.startsWith(\"@warlock.js/\")) {\r\n deps[dependency] = warlockVersion;\r\n }\r\n }\r\n }\r\n\r\n pkg.save();\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Wire DB_DRIVER and DB_PORT into .env.\r\n *\r\n * The driver's npm package is installed via `warlock add` (single source for\r\n * versions), so this only touches environment configuration — not deps.\r\n */\r\n public configureDatabaseEnv(driverValue: string) {\r\n const driver = getDatabaseDriver(driverValue);\r\n\r\n if (!driver) return this;\r\n\r\n let envContent = getFile(this.path + \"/.env\") as string;\r\n\r\n envContent = envContent.replace(/DB_PORT=\\d+/, `DB_PORT=${driver.defaultPort}`);\r\n\r\n if (envContent.includes(\"DB_DRIVER=\")) {\r\n envContent = envContent.replace(/DB_DRIVER=\\w*/, `DB_DRIVER=${driver.value}`);\r\n } else {\r\n envContent = envContent.replace(\r\n /DB_PORT=\\d+/,\r\n `DB_PORT=${driver.defaultPort}\\nDB_DRIVER=${driver.value}`,\r\n );\r\n }\r\n\r\n putFile(this.path + \"/.env\", envContent);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Pick the home page implementation based on whether React was selected.\r\n *\r\n * The template ships BOTH a plain JSON controller (`home-page.controller.ts`)\r\n * and a React-rendered page (`home-page.controller.tsx` + `HomePageComponent.tsx`).\r\n * Exactly one survives the scaffold: React projects keep the `.tsx` page (its\r\n * `react`/`react-dom` deps come from the `react` feature), every other project\r\n * keeps the dependency-free JSON controller — so a fresh project never imports\r\n * `react` unless it asked for it.\r\n */\r\n public configureHomePage(useReact: boolean) {\r\n const controllers = this.path + \"/src/app/shared/controllers\";\r\n const components = this.path + \"/src/app/shared/components\";\r\n\r\n const remove = (file: string) => {\r\n if (fileExists(file)) unlinkSync(file);\r\n };\r\n\r\n if (useReact) {\r\n remove(controllers + \"/home-page.controller.ts\");\r\n } else {\r\n remove(controllers + \"/home-page.controller.tsx\");\r\n remove(components + \"/HomePageComponent.tsx\");\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Install the selected optional features by delegating to the project's own\r\n * `warlock add`. `--no-install` records every dependency in package.json and\r\n * ejects configs / scripts / setup hooks WITHOUT installing — the caller runs\r\n * one batched install afterwards. Versions come from core's feature map, so\r\n * the scaffolder never duplicates them.\r\n *\r\n * `--no-install` is passed LAST on purpose: the CLI parser treats the\r\n * positional after a bare flag as that flag's value, so it must follow the\r\n * feature list, not precede it.\r\n */\r\n public async installFeatures(features: string[]) {\r\n if (features.length === 0) return true;\r\n\r\n return this.exec(`npx warlock add ${features.join(\" \")} --no-install`);\r\n }\r\n\r\n /**\r\n * Get package json file\r\n */\r\n public get package() {\r\n return this.json(\"package.json\");\r\n }\r\n\r\n public updateDotEnv() {\r\n this.file(\".env\").replaceAll(\"appName\", this.name).save();\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Get env file to update\r\n */\r\n public get env() {\r\n return this.file(\".env\");\r\n }\r\n\r\n public get name() {\r\n return this.app.appName;\r\n }\r\n\r\n public get path() {\r\n return this.app.appPath;\r\n }\r\n\r\n public file(relativePath: string) {\r\n const fullPath = path.resolve(this.path, relativePath);\r\n\r\n if (!this.files[fullPath]) {\r\n this.files[fullPath] = file(fullPath);\r\n }\r\n\r\n return this.files[fullPath];\r\n }\r\n\r\n public json(relativePath: string): JsonFileManager {\r\n const fullPath = path.resolve(this.path, relativePath);\r\n\r\n if (!this.jsonFiles[fullPath]) {\r\n this.jsonFiles[fullPath] = jsonFile(fullPath);\r\n }\r\n\r\n return this.jsonFiles[fullPath];\r\n }\r\n}\r\n\r\nexport function app(app: Application) {\r\n return new App(app);\r\n}\r\n\r\nexport class FileManager {\r\n public content!: string;\r\n public constructor(protected filePath: string) {\r\n this.parseContent();\r\n }\r\n\r\n protected parseContent() {\r\n this.content = getFile(this.filePath) as string;\r\n }\r\n\r\n public replace(search: string, replace: string) {\r\n this.content = this.content.replace(search, replace);\r\n\r\n return this;\r\n }\r\n\r\n public replaceAll(search: string, replace: string) {\r\n this.content = this.content.replaceAll(search, replace);\r\n\r\n return this;\r\n }\r\n\r\n public save() {\r\n putFile(this.filePath, this.content);\r\n }\r\n}\r\n\r\nexport class JsonFileManager extends FileManager {\r\n protected parseContent() {\r\n this.content = getJsonFile(this.filePath);\r\n }\r\n\r\n public save() {\r\n putJsonFile(this.filePath, this.content);\r\n }\r\n\r\n public has(key: string) {\r\n return this.content[key] !== undefined;\r\n }\r\n\r\n public replace(key: string, value: any) {\r\n this.content[key] = value;\r\n\r\n return this;\r\n }\r\n\r\n public replaceAll(key: string, value: any) {\r\n const contentAsString = JSON.stringify(this.content);\r\n\r\n this.content = JSON.parse(contentAsString.replaceAll(key, value));\r\n\r\n return this;\r\n }\r\n}\r\n\r\nexport function file(path: string) {\r\n return new FileManager(path);\r\n}\r\n\r\nexport function jsonFile(path: string) {\r\n return new JsonFileManager(path);\r\n}\r\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
t,
|
|
3
|
-
type Request,
|
|
4
|
-
type RequestHandler,
|
|
5
|
-
type Response,
|
|
6
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { t, type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
7
2
|
import { v } from "@warlock.js/seal";
|
|
8
3
|
import { forgotPasswordService } from "../services/forgot-password.service";
|
|
9
4
|
|
|
@@ -6,10 +6,7 @@ import { loginService } from "../services/auth.service";
|
|
|
6
6
|
* Login controller
|
|
7
7
|
* POST /auth/login
|
|
8
8
|
*/
|
|
9
|
-
export const loginController: RequestHandler<Request<LoginSchema>> = async (
|
|
10
|
-
request,
|
|
11
|
-
response,
|
|
12
|
-
) => {
|
|
9
|
+
export const loginController: RequestHandler<Request<LoginSchema>> = async (request, response) => {
|
|
13
10
|
const result = await loginService(request.validated(), {
|
|
14
11
|
userAgent: request.userAgent,
|
|
15
12
|
ip: request.ip,
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
t,
|
|
3
|
-
type Request,
|
|
4
|
-
type RequestHandler,
|
|
5
|
-
type Response,
|
|
6
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { t, type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
7
2
|
import { logoutAllService } from "../services/auth.service";
|
|
8
3
|
|
|
9
4
|
/**
|
|
10
5
|
* Logout from all devices controller
|
|
11
6
|
* POST /auth/logout-all
|
|
12
7
|
*/
|
|
13
|
-
export const logoutAllController: RequestHandler = async (
|
|
14
|
-
request: Request,
|
|
15
|
-
response: Response,
|
|
16
|
-
) => {
|
|
8
|
+
export const logoutAllController: RequestHandler = async (request: Request, response: Response) => {
|
|
17
9
|
await logoutAllService(request.user);
|
|
18
10
|
|
|
19
11
|
return response.success({
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
t,
|
|
3
|
-
type Request,
|
|
4
|
-
type RequestHandler,
|
|
5
|
-
type Response,
|
|
6
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { t, type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
7
2
|
import { logoutService } from "../services/auth.service";
|
|
8
3
|
|
|
9
4
|
/**
|
|
10
5
|
* Logout controller
|
|
11
6
|
* POST /auth/logout
|
|
12
7
|
*/
|
|
13
|
-
export const logoutController: RequestHandler = async (
|
|
14
|
-
request: Request,
|
|
15
|
-
response: Response,
|
|
16
|
-
) => {
|
|
8
|
+
export const logoutController: RequestHandler = async (request: Request, response: Response) => {
|
|
17
9
|
await logoutService(request.user);
|
|
18
10
|
|
|
19
11
|
return response.success({
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Request,
|
|
3
|
-
type RequestHandler,
|
|
4
|
-
type Response,
|
|
5
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
4
|
* Get current user controller
|
|
9
5
|
* GET /auth/me
|
|
10
6
|
*/
|
|
11
|
-
export const meController: RequestHandler = async (
|
|
12
|
-
request: Request,
|
|
13
|
-
response: Response,
|
|
14
|
-
) => {
|
|
7
|
+
export const meController: RequestHandler = async (request: Request, response: Response) => {
|
|
15
8
|
return response.success({
|
|
16
9
|
user: request.user,
|
|
17
10
|
});
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Request,
|
|
3
|
-
type RequestHandler,
|
|
4
|
-
type Response,
|
|
5
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
6
2
|
import { v } from "@warlock.js/seal";
|
|
7
3
|
import { refreshTokensService } from "../services/auth.service";
|
|
8
4
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t, type Request, type RequestHandler } from "@warlock.js/core";
|
|
2
|
-
import { type ResetPasswordSchema
|
|
2
|
+
import { resetPasswordSchema, type ResetPasswordSchema } from "../schema/reset-password.schema";
|
|
3
3
|
import { resetPasswordService } from "../services/reset-password.service";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -6,6 +6,4 @@ import { cleanupExpiredOtpsService } from "./services/otp.service";
|
|
|
6
6
|
scheduler.newJob("cleanup-expired-otps", cleanupExpiredOtpsService).everyHour();
|
|
7
7
|
|
|
8
8
|
// Cleanup expired refresh tokens every hour
|
|
9
|
-
scheduler
|
|
10
|
-
.newJob("cleanup-expired-tokens", () => authService.cleanupExpiredTokens())
|
|
11
|
-
.everyHour();
|
|
9
|
+
scheduler.newJob("cleanup-expired-tokens", () => authService.cleanupExpiredTokens()).everyHour();
|
package/templates/warlock/src/app/auth/models/otp/migrations/22-12-2025_10-30-20.otp-migration.ts
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
bool,
|
|
3
|
-
integer,
|
|
4
|
-
json,
|
|
5
|
-
Migration,
|
|
6
|
-
string,
|
|
7
|
-
timestamp,
|
|
8
|
-
} from "@warlock.js/cascade";
|
|
1
|
+
import { bool, integer, json, Migration, string, timestamp } from "@warlock.js/cascade";
|
|
9
2
|
import { OTP } from "../otp.model";
|
|
10
3
|
|
|
11
4
|
export default Migration.create(
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Request, RequestHandler } from "@warlock.js/core";
|
|
2
2
|
import type { User } from "app/users/models/user";
|
|
3
3
|
|
|
4
|
-
export type GuardedRequest<RequestPayload = unknown> =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
4
|
+
export type GuardedRequest<RequestPayload = unknown> = Request<RequestPayload> & {
|
|
5
|
+
user: User;
|
|
6
|
+
};
|
|
8
7
|
|
|
9
8
|
export type GuardedRequestHandler<RequestPayload = unknown> = RequestHandler<
|
|
10
9
|
GuardedRequest<RequestPayload>
|
|
@@ -44,10 +44,7 @@ export type CreateOTPOptions = {
|
|
|
44
44
|
/**
|
|
45
45
|
* Generate OTP code
|
|
46
46
|
*/
|
|
47
|
-
function generateCode(
|
|
48
|
-
length: number = 6,
|
|
49
|
-
alphanumeric: boolean = false,
|
|
50
|
-
): string {
|
|
47
|
+
function generateCode(length: number = 6, alphanumeric: boolean = false): string {
|
|
51
48
|
if (alphanumeric) {
|
|
52
49
|
// Generate alphanumeric code
|
|
53
50
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
@@ -66,9 +63,7 @@ function generateCode(
|
|
|
66
63
|
/**
|
|
67
64
|
* Create a new OTP
|
|
68
65
|
*/
|
|
69
|
-
export async function createOtpService(
|
|
70
|
-
options: CreateOTPOptions,
|
|
71
|
-
): Promise<OTP> {
|
|
66
|
+
export async function createOtpService(options: CreateOTPOptions): Promise<OTP> {
|
|
72
67
|
const {
|
|
73
68
|
target,
|
|
74
69
|
channel,
|
|
@@ -140,10 +135,7 @@ export async function verifyOtpService(
|
|
|
140
135
|
return otp;
|
|
141
136
|
}
|
|
142
137
|
|
|
143
|
-
export async function cleanupOtpService(
|
|
144
|
-
target: string,
|
|
145
|
-
type: OTPType,
|
|
146
|
-
): Promise<void> {
|
|
138
|
+
export async function cleanupOtpService(target: string, type: OTPType): Promise<void> {
|
|
147
139
|
await OTP.delete({
|
|
148
140
|
target,
|
|
149
141
|
type,
|
|
@@ -173,11 +165,9 @@ export async function resendOtpService(
|
|
|
173
165
|
* Cleanup expired OTPs
|
|
174
166
|
*/
|
|
175
167
|
export async function cleanupExpiredOtpsService(): Promise<number> {
|
|
176
|
-
const expiredOtps = await OTP.query()
|
|
177
|
-
.where("expiresAt", "<", new Date())
|
|
178
|
-
.get();
|
|
168
|
+
const expiredOtps = await OTP.query().where("expiresAt", "<", new Date()).get();
|
|
179
169
|
|
|
180
|
-
await Promise.all(expiredOtps.map(otp => otp.destroy()));
|
|
170
|
+
await Promise.all(expiredOtps.map((otp) => otp.destroy()));
|
|
181
171
|
|
|
182
172
|
return expiredOtps.length;
|
|
183
173
|
}
|
|
@@ -13,9 +13,7 @@ type ResetPasswordOptions = {
|
|
|
13
13
|
/**
|
|
14
14
|
* Reset user password using OTP verification
|
|
15
15
|
*/
|
|
16
|
-
export async function resetPasswordService(
|
|
17
|
-
options: ResetPasswordOptions,
|
|
18
|
-
): Promise<User> {
|
|
16
|
+
export async function resetPasswordService(options: ResetPasswordOptions): Promise<User> {
|
|
19
17
|
const { email, code, newPassword } = options;
|
|
20
18
|
|
|
21
19
|
// Verify OTP
|
package/templates/warlock/src/app/posts/models/post/migrations/09-01-2026_02-07-51-post.migration.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
bool,
|
|
3
|
-
integer,
|
|
4
|
-
json,
|
|
5
|
-
Migration,
|
|
6
|
-
string,
|
|
7
|
-
text,
|
|
8
|
-
timestamp,
|
|
9
|
-
} from "@warlock.js/cascade";
|
|
1
|
+
import { bool, integer, json, Migration, string, text, timestamp } from "@warlock.js/cascade";
|
|
10
2
|
import { Post } from "../post.model";
|
|
11
3
|
|
|
12
4
|
export default Migration.create(Post, {
|
|
@@ -4,8 +4,5 @@ import { createNewPostController } from "./controllers/create-new-post.controlle
|
|
|
4
4
|
import { updatePostController } from "./controllers/update-post.controller";
|
|
5
5
|
|
|
6
6
|
guarded(() => {
|
|
7
|
-
router
|
|
8
|
-
.route("/posts")
|
|
9
|
-
.create(createNewPostController)
|
|
10
|
-
.update(updatePostController);
|
|
7
|
+
router.route("/posts").create(createNewPostController).update(updatePostController);
|
|
11
8
|
});
|
|
@@ -13,11 +13,7 @@ export function HomePageComponent() {
|
|
|
13
13
|
/>
|
|
14
14
|
<link rel="stylesheet" href={publicUrl("home.css")} />
|
|
15
15
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
16
|
-
<link
|
|
17
|
-
rel="preconnect"
|
|
18
|
-
href="https://fonts.gstatic.com"
|
|
19
|
-
crossOrigin="anonymous"
|
|
20
|
-
/>
|
|
16
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
21
17
|
<link
|
|
22
18
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap"
|
|
23
19
|
rel="stylesheet"
|
|
@@ -33,22 +29,13 @@ export function HomePageComponent() {
|
|
|
33
29
|
<span>Warlock.js</span>
|
|
34
30
|
</a>
|
|
35
31
|
<nav className="warlock-nav">
|
|
36
|
-
<a
|
|
37
|
-
href="https://warlock.js.org"
|
|
38
|
-
target="_blank"
|
|
39
|
-
rel="noopener noreferrer">
|
|
32
|
+
<a href="https://warlock.js.org" target="_blank" rel="noopener noreferrer">
|
|
40
33
|
Docs
|
|
41
34
|
</a>
|
|
42
|
-
<a
|
|
43
|
-
href="https://github.com/warlockjs"
|
|
44
|
-
target="_blank"
|
|
45
|
-
rel="noopener noreferrer">
|
|
35
|
+
<a href="https://github.com/warlockjs" target="_blank" rel="noopener noreferrer">
|
|
46
36
|
GitHub
|
|
47
37
|
</a>
|
|
48
|
-
<a
|
|
49
|
-
href="https://discord.gg/x3W9SN2jvx"
|
|
50
|
-
target="_blank"
|
|
51
|
-
rel="noopener noreferrer">
|
|
38
|
+
<a href="https://discord.gg/x3W9SN2jvx" target="_blank" rel="noopener noreferrer">
|
|
52
39
|
Discord
|
|
53
40
|
</a>
|
|
54
41
|
</nav>
|
|
@@ -61,20 +48,18 @@ export function HomePageComponent() {
|
|
|
61
48
|
with Confidence
|
|
62
49
|
</h1>
|
|
63
50
|
<p>
|
|
64
|
-
A powerful, elegant TypeScript framework designed for developers
|
|
65
|
-
|
|
66
|
-
journey.
|
|
51
|
+
A powerful, elegant TypeScript framework designed for developers who demand
|
|
52
|
+
excellence. Ship faster, scale better, and enjoy the journey.
|
|
67
53
|
</p>
|
|
68
54
|
<div className="warlock-cta">
|
|
69
|
-
<a
|
|
70
|
-
href="https://warlock.js.org"
|
|
71
|
-
className="warlock-btn warlock-btn-primary">
|
|
55
|
+
<a href="https://warlock.js.org" className="warlock-btn warlock-btn-primary">
|
|
72
56
|
<span>Get Started</span>
|
|
73
57
|
<span>→</span>
|
|
74
58
|
</a>
|
|
75
59
|
<a
|
|
76
60
|
href="https://github.com/warlockjs"
|
|
77
|
-
className="warlock-btn warlock-btn-secondary"
|
|
61
|
+
className="warlock-btn warlock-btn-secondary"
|
|
62
|
+
>
|
|
78
63
|
<span>View on GitHub</span>
|
|
79
64
|
</a>
|
|
80
65
|
</div>
|
|
@@ -92,8 +77,8 @@ export function HomePageComponent() {
|
|
|
92
77
|
<span className="warlock-feature-icon">🚀</span>
|
|
93
78
|
<h3>Lightning Fast</h3>
|
|
94
79
|
<p>
|
|
95
|
-
Blazing fast development server with instant hot reload.
|
|
96
|
-
|
|
80
|
+
Blazing fast development server with instant hot reload. Build and deploy
|
|
81
|
+
optimized production bundles in seconds.
|
|
97
82
|
</p>
|
|
98
83
|
</div>
|
|
99
84
|
|
|
@@ -101,9 +86,8 @@ export function HomePageComponent() {
|
|
|
101
86
|
<span className="warlock-feature-icon">🎯</span>
|
|
102
87
|
<h3>Type-Safe</h3>
|
|
103
88
|
<p>
|
|
104
|
-
Built with TypeScript from the ground up. Enjoy full type
|
|
105
|
-
|
|
106
|
-
auto-completion.
|
|
89
|
+
Built with TypeScript from the ground up. Enjoy full type safety across your
|
|
90
|
+
entire application with intelligent auto-completion.
|
|
107
91
|
</p>
|
|
108
92
|
</div>
|
|
109
93
|
|
|
@@ -111,8 +95,8 @@ export function HomePageComponent() {
|
|
|
111
95
|
<span className="warlock-feature-icon">🏗️</span>
|
|
112
96
|
<h3>Battle-Tested Architecture</h3>
|
|
113
97
|
<p>
|
|
114
|
-
Proven patterns and best practices baked in. From routing to
|
|
115
|
-
|
|
98
|
+
Proven patterns and best practices baked in. From routing to database
|
|
99
|
+
management, we've got you covered.
|
|
116
100
|
</p>
|
|
117
101
|
</div>
|
|
118
102
|
|
|
@@ -120,9 +104,8 @@ export function HomePageComponent() {
|
|
|
120
104
|
<span className="warlock-feature-icon">🔌</span>
|
|
121
105
|
<h3>Powerful CLI</h3>
|
|
122
106
|
<p>
|
|
123
|
-
Scaffold components, run migrations, manage seeds, and more
|
|
124
|
-
|
|
125
|
-
productivity.
|
|
107
|
+
Scaffold components, run migrations, manage seeds, and more with an intuitive
|
|
108
|
+
command-line interface that boosts productivity.
|
|
126
109
|
</p>
|
|
127
110
|
</div>
|
|
128
111
|
|
|
@@ -130,8 +113,8 @@ export function HomePageComponent() {
|
|
|
130
113
|
<span className="warlock-feature-icon">🎨</span>
|
|
131
114
|
<h3>Flexible & Extensible</h3>
|
|
132
115
|
<p>
|
|
133
|
-
Plugin architecture allows you to extend core functionality.
|
|
134
|
-
|
|
116
|
+
Plugin architecture allows you to extend core functionality. Build your own
|
|
117
|
+
tools or use community packages.
|
|
135
118
|
</p>
|
|
136
119
|
</div>
|
|
137
120
|
|
|
@@ -139,8 +122,8 @@ export function HomePageComponent() {
|
|
|
139
122
|
<span className="warlock-feature-icon">🌍</span>
|
|
140
123
|
<h3>Multi-Tenant Ready</h3>
|
|
141
124
|
<p>
|
|
142
|
-
Built-in support for multi-tenancy. Scale from single to
|
|
143
|
-
|
|
125
|
+
Built-in support for multi-tenancy. Scale from single to multi-tenant
|
|
126
|
+
applications without architectural changes.
|
|
144
127
|
</p>
|
|
145
128
|
</div>
|
|
146
129
|
</div>
|
|
@@ -166,8 +149,8 @@ export function HomePageComponent() {
|
|
|
166
149
|
</span>
|
|
167
150
|
</code>
|
|
168
151
|
<code className="warlock-code-line">
|
|
169
|
-
<span className="warlock-code-command">npx</span> warlock
|
|
170
|
-
|
|
152
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
153
|
+
<span className="warlock-code-flag">react</span>
|
|
171
154
|
</code>
|
|
172
155
|
<code className="warlock-code-line"> </code>
|
|
173
156
|
<code className="warlock-code-line">
|
|
@@ -176,27 +159,22 @@ export function HomePageComponent() {
|
|
|
176
159
|
</span>
|
|
177
160
|
</code>
|
|
178
161
|
<code className="warlock-code-line">
|
|
179
|
-
<span className="warlock-code-command">npx</span> warlock
|
|
180
|
-
|
|
181
|
-
<span className="warlock-code-flag">
|
|
182
|
-
mongodb redis test
|
|
183
|
-
</span>
|
|
162
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
163
|
+
<span className="warlock-code-flag">mongodb redis test</span>
|
|
184
164
|
</code>
|
|
185
165
|
<code className="warlock-code-line"> </code>
|
|
186
166
|
<code className="warlock-code-line">
|
|
187
|
-
<span className="warlock-code-comment">
|
|
188
|
-
# List all available features
|
|
189
|
-
</span>
|
|
167
|
+
<span className="warlock-code-comment"># List all available features</span>
|
|
190
168
|
</code>
|
|
191
169
|
<code className="warlock-code-line">
|
|
192
|
-
<span className="warlock-code-command">npx</span> warlock
|
|
193
|
-
|
|
170
|
+
<span className="warlock-code-command">npx</span> warlock add{" "}
|
|
171
|
+
<span className="warlock-code-flag">--list</span>
|
|
194
172
|
</code>
|
|
195
173
|
<code className="warlock-code-line"> </code>
|
|
196
174
|
<code className="warlock-code-line">
|
|
197
175
|
<span className="warlock-code-comment">
|
|
198
|
-
# ✨ Features: react, mongodb, postgres, mysql, redis, s3,
|
|
199
|
-
|
|
176
|
+
# ✨ Features: react, mongodb, postgres, mysql, redis, s3, mail, image, test,
|
|
177
|
+
swagger, scheduler & more
|
|
200
178
|
</span>
|
|
201
179
|
</code>
|
|
202
180
|
</div>
|
|
@@ -210,7 +188,8 @@ export function HomePageComponent() {
|
|
|
210
188
|
href="https://discord.gg/x3W9SN2jvx"
|
|
211
189
|
className="warlock-social-link"
|
|
212
190
|
target="_blank"
|
|
213
|
-
rel="noopener noreferrer"
|
|
191
|
+
rel="noopener noreferrer"
|
|
192
|
+
>
|
|
214
193
|
<span className="warlock-social-icon">💬</span>
|
|
215
194
|
<span>Join Discord</span>
|
|
216
195
|
</a>
|
|
@@ -218,7 +197,8 @@ export function HomePageComponent() {
|
|
|
218
197
|
href="https://github.com/warlockjs"
|
|
219
198
|
className="warlock-social-link"
|
|
220
199
|
target="_blank"
|
|
221
|
-
rel="noopener noreferrer"
|
|
200
|
+
rel="noopener noreferrer"
|
|
201
|
+
>
|
|
222
202
|
<span className="warlock-social-icon">⭐</span>
|
|
223
203
|
<span>Star on GitHub</span>
|
|
224
204
|
</a>
|
|
@@ -226,17 +206,15 @@ export function HomePageComponent() {
|
|
|
226
206
|
href="https://warlock.js.org"
|
|
227
207
|
className="warlock-social-link"
|
|
228
208
|
target="_blank"
|
|
229
|
-
rel="noopener noreferrer"
|
|
209
|
+
rel="noopener noreferrer"
|
|
210
|
+
>
|
|
230
211
|
<span className="warlock-social-icon">📚</span>
|
|
231
212
|
<span>Read Docs</span>
|
|
232
213
|
</a>
|
|
233
214
|
</div>
|
|
234
215
|
<p className="warlock-footer-text">
|
|
235
216
|
Built with ⚡ by the{" "}
|
|
236
|
-
<a
|
|
237
|
-
href="https://github.com/warlockjs"
|
|
238
|
-
target="_blank"
|
|
239
|
-
rel="noopener noreferrer">
|
|
217
|
+
<a href="https://github.com/warlockjs" target="_blank" rel="noopener noreferrer">
|
|
240
218
|
Warlock.js Team
|
|
241
219
|
</a>
|
|
242
220
|
{" · "}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Application, type RequestHandler } from "@warlock.js/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default welcome route — a dependency-free JSON response.
|
|
5
|
+
*
|
|
6
|
+
* Projects scaffolded with the `react` feature get the richer HTML welcome
|
|
7
|
+
* page (`home-page.controller.tsx` + `HomePageComponent.tsx`) instead; this
|
|
8
|
+
* plain controller is removed at scaffold time when React is selected.
|
|
9
|
+
*/
|
|
10
|
+
export const homePageController: RequestHandler = async (_request, response) => {
|
|
11
|
+
return response.success({
|
|
12
|
+
message: "Welcome to Warlock 🧙 — your app is up and running!",
|
|
13
|
+
version: Application.version,
|
|
14
|
+
docs: "https://warlock.js.org",
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
homePageController.description = "Welcome Home Page";
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Request,
|
|
3
|
-
type RequestHandler,
|
|
4
|
-
type Response,
|
|
5
|
-
} from "@warlock.js/core";
|
|
1
|
+
import { type Request, type RequestHandler, type Response } from "@warlock.js/core";
|
|
6
2
|
import { HomePageComponent } from "../components/HomePageComponent";
|
|
7
3
|
|
|
8
|
-
export const homePageController: RequestHandler = async (
|
|
9
|
-
_request: Request,
|
|
10
|
-
response: Response,
|
|
11
|
-
) => {
|
|
4
|
+
export const homePageController: RequestHandler = async (_request: Request, response: Response) => {
|
|
12
5
|
return response.render(<HomePageComponent />);
|
|
13
6
|
};
|
|
14
7
|
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { fileExistsAsync } from "@warlock.js/fs";
|
|
2
1
|
import { CACHE_FOR } from "@warlock.js/cache";
|
|
3
2
|
import { Image, type RequestHandler, storage } from "@warlock.js/core";
|
|
3
|
+
import { fileExistsAsync } from "@warlock.js/fs";
|
|
4
4
|
import { v } from "@warlock.js/seal";
|
|
5
5
|
|
|
6
|
-
export const fetchUploadedFileController: RequestHandler = async (
|
|
7
|
-
request,
|
|
8
|
-
response,
|
|
9
|
-
) => {
|
|
6
|
+
export const fetchUploadedFileController: RequestHandler = async (request, response) => {
|
|
10
7
|
const absolutePath = storage.root(request.input("*"));
|
|
11
8
|
|
|
12
9
|
const { w: width, h: height } = request.validated();
|
|
@@ -19,7 +19,7 @@ const saveSubscription = globalEvents.onSaving(async (model, { isInsert }) => {
|
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
const deleteSubscription = globalEvents.onDeleting(async model => {
|
|
22
|
+
const deleteSubscription = globalEvents.onDeleting(async (model) => {
|
|
23
23
|
const user = useCurrentUser();
|
|
24
24
|
|
|
25
25
|
if (!user) return;
|
|
@@ -9,11 +9,7 @@ export const userSchema = globalColumnsSchema.extend({
|
|
|
9
9
|
name: v.string().required(),
|
|
10
10
|
email: v.email().requiredIfEmpty("id"),
|
|
11
11
|
image: v.string(),
|
|
12
|
-
password: v
|
|
13
|
-
.string()
|
|
14
|
-
.min(6)
|
|
15
|
-
.requiredIfEmpty("id")
|
|
16
|
-
.addTransformer(useHashedPassword()),
|
|
12
|
+
password: v.string().min(6).requiredIfEmpty("id").addTransformer(useHashedPassword()),
|
|
17
13
|
});
|
|
18
14
|
|
|
19
15
|
export type UserSchema = Infer<typeof userSchema>;
|
|
@@ -49,15 +45,15 @@ export class User extends Auth<UserSchema> {
|
|
|
49
45
|
|
|
50
46
|
static {
|
|
51
47
|
// Local scopes
|
|
52
|
-
this.addScope("active", query => {
|
|
48
|
+
this.addScope("active", (query) => {
|
|
53
49
|
query.where("isActive", true);
|
|
54
50
|
});
|
|
55
51
|
|
|
56
|
-
this.addScope("admins", query => {
|
|
52
|
+
this.addScope("admins", (query) => {
|
|
57
53
|
query.where("role", "admin");
|
|
58
54
|
});
|
|
59
55
|
|
|
60
|
-
this.addScope("verified", query => {
|
|
56
|
+
this.addScope("verified", (query) => {
|
|
61
57
|
query.where("emailVerified", true);
|
|
62
58
|
});
|
|
63
59
|
|
|
@@ -4,8 +4,5 @@ import { createNewUserController } from "./controllers/create-new-user.controlle
|
|
|
4
4
|
import { listUsersController } from "./controllers/list-users.controller";
|
|
5
5
|
|
|
6
6
|
guarded(() => {
|
|
7
|
-
router
|
|
8
|
-
.route("/users")
|
|
9
|
-
.list(listUsersController)
|
|
10
|
-
.post(createNewUserController);
|
|
7
|
+
router.route("/users").list(listUsersController).post(createNewUserController);
|
|
11
8
|
});
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { Request, Response } from "@warlock.js/core";
|
|
2
2
|
|
|
3
|
-
export default async function loginSocial(
|
|
4
|
-
request: Request,
|
|
5
|
-
response: Response,
|
|
6
|
-
) {
|
|
3
|
+
export default async function loginSocial(request: Request, response: Response) {
|
|
7
4
|
const user = request.user;
|
|
8
5
|
|
|
9
6
|
const auth = await user.generateAccessToken();
|
|
@@ -20,8 +20,7 @@ const globalPrefix = () => {
|
|
|
20
20
|
return cachePrefix;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const domain =
|
|
24
|
-
request.originDomain || request.header("domain") || request.input("domain");
|
|
23
|
+
const domain = request.originDomain || request.header("domain") || request.input("domain");
|
|
25
24
|
|
|
26
25
|
if (!domain) return cachePrefix;
|
|
27
26
|
|
|
@@ -5,10 +5,7 @@ import type {
|
|
|
5
5
|
} from "@warlock.js/cascade";
|
|
6
6
|
import { env } from "@warlock.js/core";
|
|
7
7
|
|
|
8
|
-
const databaseConfigurations: ConnectionOptions<
|
|
9
|
-
MongoDriverOptions,
|
|
10
|
-
MongoClientOptions
|
|
11
|
-
> = {
|
|
8
|
+
const databaseConfigurations: ConnectionOptions<MongoDriverOptions, MongoClientOptions> = {
|
|
12
9
|
driver: env("DB_DRIVER", "mongodb"),
|
|
13
10
|
name: "default",
|
|
14
11
|
database: env("DB_NAME"),
|