adminforth 1.5.9-next.12 → 1.5.9-next.14

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/commands/cli.js CHANGED
@@ -3,10 +3,14 @@
3
3
  const args = process.argv.slice(2);
4
4
  const command = args[0];
5
5
 
6
- import generateModels from "./generateModels.js";
7
6
  import bundle from "./bundle.js";
7
+ import createApp from "./createApp/main.js";
8
+ import generateModels from "./generateModels.js";
8
9
 
9
10
  switch (command) {
11
+ case "create-app":
12
+ createApp(args);
13
+ break;
10
14
  case "generate-models":
11
15
  generateModels();
12
16
  break;
@@ -14,5 +18,5 @@ switch (command) {
14
18
  bundle();
15
19
  break;
16
20
  default:
17
- console.log("Unknown command. Available commands: generate-models, bundle");
18
- }
21
+ console.log("Unknown command. Available commands: create-app, generate-models, bundle");
22
+ }
@@ -0,0 +1,19 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_1_8)">
3
+ <path d="M8.034 6.006V13H6.097V12.194C5.59433 12.8007 4.86633 13.104 3.913 13.104C3.25433 13.104 2.65633 12.9567 2.119 12.662C1.59033 12.3673 1.17433 11.947 0.871 11.401C0.567667 10.855 0.416 10.2223 0.416 9.503C0.416 8.78367 0.567667 8.151 0.871 7.605C1.17433 7.059 1.59033 6.63867 2.119 6.344C2.65633 6.04933 3.25433 5.902 3.913 5.902C4.80567 5.902 5.50333 6.18367 6.006 6.747V6.006H8.034ZM4.264 11.44C4.77533 11.44 5.2 11.2667 5.538 10.92C5.876 10.5647 6.045 10.0923 6.045 9.503C6.045 8.91367 5.876 8.44567 5.538 8.099C5.2 7.74367 4.77533 7.566 4.264 7.566C3.744 7.566 3.315 7.74367 2.977 8.099C2.639 8.44567 2.47 8.91367 2.47 9.503C2.47 10.0923 2.639 10.5647 2.977 10.92C3.315 11.2667 3.744 11.44 4.264 11.44Z" fill="url(#paint0_linear_1_8)"/>
4
+ <path d="M13.317 5.538C12.589 5.538 12.0387 5.69833 11.666 6.019C11.2933 6.331 11.107 6.80333 11.107 7.436V7.995H14.851V9.685H11.107V13H9.001V7.449C9.001 6.279 9.365 5.369 10.093 4.719C10.8297 4.069 11.8567 3.744 13.174 3.744C13.694 3.744 14.1837 3.80033 14.643 3.913C15.1023 4.017 15.501 4.173 15.839 4.381L15.189 6.045C14.669 5.707 14.045 5.538 13.317 5.538Z" fill="url(#paint1_linear_1_8)"/>
5
+ </g>
6
+ <defs>
7
+ <linearGradient id="paint0_linear_1_8" x1="1.5" y1="6.93333" x2="7.31883" y2="11.8926" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#656E7A"/>
9
+ <stop offset="1" stop-color="#99A6B8"/>
10
+ </linearGradient>
11
+ <linearGradient id="paint1_linear_1_8" x1="12.5" y1="3.73333" x2="9.68642" y2="12.7016" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#48C5FF"/>
13
+ <stop offset="1" stop-color="#A1E1FF"/>
14
+ </linearGradient>
15
+ <clipPath id="clip0_1_8">
16
+ <rect width="16" height="16" fill="white"/>
17
+ </clipPath>
18
+ </defs>
19
+ </svg>
@@ -0,0 +1,27 @@
1
+ import chalk from 'chalk';
2
+
3
+ import {
4
+ parseArgumentsIntoOptions,
5
+ prepareWorkflow,
6
+ promptForMissingOptions,
7
+ } from './utils.js';
8
+
9
+
10
+ export default async function createApp(args) {
11
+ // Step 1: Parse CLI arguments with `arg`
12
+ let options = parseArgumentsIntoOptions(args);
13
+
14
+ // Step 2: Ask for missing arguments via `inquirer`
15
+ options = await promptForMissingOptions(options);
16
+
17
+ // Step 3: Prepare a Listr-based workflow
18
+ const tasks = prepareWorkflow(options)
19
+
20
+ // Step 4: Run tasks
21
+ try {
22
+ await tasks.run();
23
+ } catch (err) {
24
+ console.error(chalk.red(`\nāŒ ${err.message}\n`));
25
+ process.exit(1);
26
+ }
27
+ }
@@ -0,0 +1,326 @@
1
+ export function gitignore() {
2
+ return `# Dependency directories
3
+ node_modules/
4
+
5
+ # dotenv environment variable files
6
+ .env
7
+ `;
8
+ }
9
+
10
+ export function env(dbUrl, prismaDbUrl) {
11
+ const base = `
12
+ ADMINFORTH_SECRET=123
13
+ NODE_ENV=development
14
+ DATABASE_URL=${dbUrl}
15
+ `
16
+ if (prismaDbUrl)
17
+ return base + `PRISMA_DATABASE_URL=${prismaDbUrl}`;
18
+ return base;
19
+ }
20
+
21
+ export function envSample(dbUrl, prismaDbUrl) {
22
+ return env(dbUrl, prismaDbUrl);
23
+ }
24
+
25
+ export function indexTs(appName) {
26
+ return `import express from 'express';
27
+ import AdminForth, { Filters } from 'adminforth';
28
+ import usersResource from "./resources/users";
29
+
30
+ const ADMIN_BASE_URL = '';
31
+
32
+ export const admin = new AdminForth({
33
+ baseUrl : ADMIN_BASE_URL,
34
+ auth: {
35
+ usersResourceId: 'users', // resource to get user during login
36
+ usernameField: 'email', // field where username is stored, should exist in resource
37
+ passwordHashField: 'password_hash',
38
+ rememberMeDays: 30, // users who will check "remember me" will stay logged in for 30 days
39
+ loginBackgroundImage: 'https://images.unsplash.com/photo-1534239697798-120952b76f2b?q=80&w=3389&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
40
+ loginBackgroundPosition: '1/2', // over, 3/4, 2/5, 3/5 (tailwind grid)
41
+ demoCredentials: "adminforth:adminforth", // never use it for production
42
+ loginPromptHTML: "Use email <b>adminforth</b> and password <b>adminforth</b> to login",
43
+ },
44
+ customization: {
45
+ brandName: '${appName}',
46
+ title: '${appName}',
47
+ favicon: '@@/assets/favicon.png',
48
+ brandLogo: '@@/assets/logo.svg',
49
+ datesFormat: 'DD MMM',
50
+ timeFormat: 'HH:mm a',
51
+ showBrandNameInSidebar: true,
52
+ styles: {
53
+ colors: {
54
+ light: {
55
+ // color for links, icons etc.
56
+ primary: '#B400B8',
57
+ // color for sidebar and text
58
+ sidebar: {main:'#571E58', text:'white'},
59
+ },
60
+ dark: {
61
+ primary: '#82ACFF',
62
+ sidebar: {main:'#1f2937', text:'#9ca3af'},
63
+ }
64
+ }
65
+ },
66
+ },
67
+ dataSources: [
68
+ {
69
+ id: 'maindb',
70
+ url: \`\${process.env.DATABASE_URL}\`
71
+ },
72
+ ],
73
+ resources: [
74
+ usersResource,
75
+ ],
76
+ menu: [
77
+ {
78
+ type: 'heading',
79
+ label: 'SYSTEM',
80
+ },
81
+ {
82
+ label: 'Users',
83
+ icon: 'flowbite:user-solid', // any icon from iconify supported in format <setname>:<icon>, e.g. from here https://icon-sets.iconify.design/flowbite/
84
+ resourceId: 'users',
85
+ }
86
+ ],
87
+ });
88
+
89
+ if (import.meta.url === \`file://\${process.argv[1]}\`) {
90
+ // if script is executed directly e.g. node index.ts or npm start
91
+
92
+ const app = express()
93
+ app.use(express.json());
94
+ const port = 3500;
95
+
96
+ // needed to compile SPA. Call it here or from a build script e.g. in Docker build time to reduce downtime
97
+ await admin.bundleNow({ hotReload: process.env.NODE_ENV === 'development'});
98
+ console.log('Bundling AdminForth done. For faster serving consider calling bundleNow() from a build script.');
99
+
100
+ // serve after you added all api
101
+ admin.express.serve(app)
102
+
103
+ admin.discoverDatabases().then(async () => {
104
+ if (!await admin.resource('users').get([Filters.EQ('email', 'adminforth')])) {
105
+ await admin.resource('users').create({
106
+ email: 'adminforth',
107
+ password_hash: await AdminForth.Utils.generatePasswordHash('adminforth'),
108
+ role: 'superadmin',
109
+ });
110
+ }
111
+ });
112
+
113
+ admin.express.listen(port, () => {
114
+ console.log(\`Example app listening at http://localhost:\${port}\`)
115
+ console.log(\`\\n⚔ AdminForth is available at http://localhost:\${port}\${ADMIN_BASE_URL}\n\`)
116
+ });
117
+ }
118
+ `;
119
+ }
120
+
121
+ export function schemaPrisma(provider, dbUrl) {
122
+ return `generator client {
123
+ provider = "prisma-client-js"
124
+ }
125
+
126
+ datasource db {
127
+ provider = "${provider}"
128
+ url = env("PRISMA_DATABASE_URL")
129
+ }
130
+
131
+ model adminuser {
132
+ id String @id
133
+ email String @unique
134
+ password_hash String
135
+ role String
136
+ created_at DateTime
137
+ }
138
+ `;
139
+ }
140
+
141
+ export function usersResource() {
142
+ return `import AdminForth, { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth';
143
+ import type { AdminUser } from 'adminforth';
144
+
145
+ async function canModifyUsers({ adminUser }: { adminUser: AdminUser }): Promise<boolean> {
146
+ return adminUser.dbUser.role === 'superadmin';
147
+ }
148
+
149
+ export default {
150
+ dataSource: 'maindb',
151
+ table: 'adminuser',
152
+ resourceId: 'users',
153
+ label: 'Users',
154
+ recordLabel: (r) => \`šŸ‘¤ \${r.email}\`,
155
+ options: {
156
+ allowedActions: {
157
+ edit: canModifyUsers,
158
+ delete: canModifyUsers,
159
+ },
160
+ },
161
+ columns: [
162
+ {
163
+ name: 'id',
164
+ primaryKey: true,
165
+ type: AdminForthDataTypes.STRING,
166
+ fillOnCreate: ({ initialRecord, adminUser }) => Math.random().toString(36).substring(7),
167
+ showIn: ['list', 'filter', 'show'],
168
+ },
169
+ {
170
+ name: 'email',
171
+ required: true,
172
+ isUnique: true,
173
+ type: AdminForthDataTypes.STRING,
174
+ validation: [
175
+ // you can also use AdminForth.Utils.EMAIL_VALIDATOR which is alias to this object
176
+ {
177
+ regExp: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
178
+ message: 'Email is not valid, must be in format example@test.com'
179
+ },
180
+ ]
181
+ },
182
+ {
183
+ name: 'created_at',
184
+ type: AdminForthDataTypes.DATETIME,
185
+ showIn: ['list', 'filter', 'show'],
186
+ fillOnCreate: ({ initialRecord, adminUser }) => (new Date()).toISOString(),
187
+ },
188
+ {
189
+ name: 'role',
190
+ type: AdminForthDataTypes.STRING,
191
+ enum: [
192
+ { value: 'superadmin', label: 'Super Admin' },
193
+ { value: 'user', label: 'User' },
194
+ ]
195
+ },
196
+ {
197
+ name: 'password',
198
+ virtual: true, // field will not be persisted into db
199
+ required: { create: true }, // make required only on create page
200
+ editingNote: { edit: 'Leave empty to keep password unchanged' },
201
+ type: AdminForthDataTypes.STRING,
202
+ showIn: ['create', 'edit'], // to show field only on create and edit pages
203
+ masked: true, // to show stars in input field
204
+
205
+ minLength: 8,
206
+ validation: [
207
+ // request to have at least 1 digit, 1 upper case, 1 lower case
208
+ AdminForth.Utils.PASSWORD_VALIDATORS.UP_LOW_NUM,
209
+ ],
210
+ },
211
+ {
212
+ name: 'password_hash',
213
+ type: AdminForthDataTypes.STRING,
214
+ backendOnly: true,
215
+ showIn: []
216
+ }
217
+ ],
218
+ hooks: {
219
+ create: {
220
+ beforeSave: async ({ record, adminUser, resource }) => {
221
+ record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);
222
+ return { ok: true };
223
+ }
224
+ },
225
+ edit: {
226
+ beforeSave: async ({ record, adminUser, resource }) => {
227
+ if (record.password) {
228
+ record.password_hash = await AdminForth.Utils.generatePasswordHash(record.password);
229
+ }
230
+ return { ok: true }
231
+ },
232
+ },
233
+ }
234
+ } as AdminForthResourceInput;
235
+ `;
236
+ }
237
+
238
+ /**
239
+ * Root package.json template
240
+ */
241
+ export function rootPackageJson(appName) {
242
+ // Note: you might want to keep versions in sync or fetch from a config
243
+ return `{
244
+ "name": "${appName}",
245
+ "version": "1.0.0",
246
+ "main": "index.ts",
247
+ "type": "module",
248
+ "keywords": [],
249
+ "author": "",
250
+ "license": "ISC",
251
+ "description": "",
252
+ "scripts": {
253
+ "start": "tsx watch --env-file=.env index.ts",
254
+ "migrate": "npx prisma migrate deploy",
255
+ "makemigration": "npx --yes prisma migrate deploy; npx --yes prisma migrate dev",
256
+ "test": "echo \\"Error: no test specified\\" && exit 1"
257
+ },
258
+ "engines": {
259
+ "node": ">=20"
260
+ },
261
+ "dependencies": {
262
+ "adminforth": "latest",
263
+ "express": "latest"
264
+ },
265
+ "devDependencies": {
266
+ "typescript": "5.4.5",
267
+ "tsx": "4.11.2",
268
+ "@types/express": "latest",
269
+ "@types/node": "latest"
270
+ }
271
+ }
272
+ `;
273
+ }
274
+
275
+ /**
276
+ * Root tsconfig.json template
277
+ */
278
+ export function rootTsConfig() {
279
+ return `{
280
+ "compilerOptions": {
281
+ "target": "esnext",
282
+ "module": "nodenext",
283
+ "esModuleInterop": true,
284
+ "forceConsistentCasingInFileNames": true,
285
+ "strict": true
286
+ },
287
+ "exclude": ["node_modules", "dist"]
288
+ }
289
+ `;
290
+ }
291
+
292
+ /**
293
+ * custom/package.json
294
+ */
295
+ export function customPackageJson(appName) {
296
+ return `{
297
+ "name": "custom",
298
+ "version": "1.0.0",
299
+ "main": "index.ts",
300
+ "scripts": {
301
+ "test": "echo \\"Error: no test specified\\" && exit 1"
302
+ },
303
+ "keywords": [],
304
+ "author": "",
305
+ "license": "ISC",
306
+ "description": ""
307
+ }
308
+ `;
309
+ }
310
+
311
+ /**
312
+ * custom/tsconfig.json
313
+ */
314
+ export function customTsconfig() {
315
+ return `{
316
+ "compilerOptions": {
317
+ "baseUrl": ".",
318
+ "paths": {
319
+ "@/": "../node_modules/adminforth/dist/spa/src/",
320
+ "": "../node_modules/adminforth/dist/spa/node_modules/",
321
+ "@@/*": "."
322
+ }
323
+ }
324
+ }
325
+ `;
326
+ }
@@ -0,0 +1,219 @@
1
+ import arg from 'arg';
2
+ import chalk from 'chalk';
3
+ import fs from 'fs';
4
+ import fse from 'fs-extra';
5
+ import inquirer from 'inquirer';
6
+ import path from 'path';
7
+ import { Listr } from 'listr2'
8
+ import { fileURLToPath } from 'url';
9
+ import {ConnectionString} from 'connection-string';
10
+ import {execa} from 'execa';
11
+
12
+ import * as templates from './templates.js';
13
+
14
+ export function parseArgumentsIntoOptions(rawArgs) {
15
+ const args = arg(
16
+ {
17
+ '--app-name': String,
18
+ '--db': String,
19
+ // you can add more flags here if needed
20
+ },
21
+ {
22
+ argv: rawArgs.slice(1), // skip "create-app"
23
+ }
24
+ );
25
+
26
+ return {
27
+ appName: args['--app-name'],
28
+ db: args['--db'],
29
+ };
30
+ }
31
+
32
+ export async function promptForMissingOptions(options) {
33
+ const questions = [];
34
+
35
+ if (!options.appName) {
36
+ questions.push({
37
+ type: 'input',
38
+ name: 'appName',
39
+ message: 'Please specify the name of the app >',
40
+ default: 'adminforth-app',
41
+ });
42
+ };
43
+
44
+ if (!options.db) {
45
+ questions.push({
46
+ type: 'input',
47
+ name: 'db',
48
+ message: 'Please specify the database URL to use >',
49
+ default: 'sqlite://.db.sqlite',
50
+ });
51
+ };
52
+
53
+ const answers = await inquirer.prompt(questions);
54
+ return {
55
+ ...options,
56
+ appName: options.appName || answers.appName,
57
+ db: options.db || answers.db,
58
+ };
59
+ }
60
+
61
+ function checkNodeVersion(minRequiredVersion = 20) {
62
+ const current = process.versions.node.split('.');
63
+ const major = parseInt(current[0], 10);
64
+
65
+ if (isNaN(major) || major < minRequiredVersion) {
66
+ throw new Error(
67
+ `Node.js v${minRequiredVersion}+ is required. You have ${process.versions.node}. ` +
68
+ `Please upgrade Node.js.`
69
+ );
70
+ }
71
+ }
72
+
73
+ function parseConnectionString(dbUrl) {
74
+ return new ConnectionString(dbUrl);
75
+ }
76
+
77
+ function detectDbProvider(protocol) {
78
+ if (protocol.startsWith('sqlite')) {
79
+ return 'sqlite';
80
+ } else if (protocol.startsWith('postgres')) {
81
+ return 'postgresql';
82
+ } else if (protocol.startsWith('mongodb')) {
83
+ return 'mongodb';
84
+ }
85
+
86
+ const message = `Unknown database provider for ${protocol}. Only SQLite, PostgreSQL, and MongoDB are supported now.`;
87
+ throw new Error(message);
88
+ }
89
+
90
+ function generateDbUrlForPrisma(connectionString) {
91
+ if (connectionString.protocol.startsWith('sqlite'))
92
+ return `file:${connectionString.host}`;
93
+ if (connectionString.protocol.startsWith('mongodb'))
94
+ return null;
95
+ return connectionString.toString();
96
+ }
97
+
98
+ function initialChecks() {
99
+ return [
100
+ {
101
+ title: 'šŸ‘€ Checking Node.js version...',
102
+ task: () => checkNodeVersion(20)
103
+ },
104
+ {
105
+ title: 'šŸ‘€ Validating current working directory...',
106
+ task: () => checkForExistingPackageJson()
107
+ }
108
+ ]
109
+ }
110
+
111
+ function checkForExistingPackageJson() {
112
+ if (fs.existsSync(path.join(process.cwd(), 'package.json'))) {
113
+ throw new Error(
114
+ `A package.json already exists in this directory.\n` +
115
+ `Please remove it or use an empty directory.`
116
+ );
117
+ }
118
+ }
119
+
120
+ async function scaffoldProject(ctx, options, cwd) {
121
+ const connectionString = parseConnectionString(options.db);
122
+ const provider = detectDbProvider(connectionString.protocol);
123
+ const prismaDbUrl = generateDbUrlForPrisma(connectionString);
124
+ ctx.skipPrismaSetup = !prismaDbUrl;
125
+ const appName = options.appName;
126
+
127
+ const dirname = path.dirname(fileURLToPath(import.meta.url));
128
+ const sourceAssetsDir = path.join(dirname, 'assets');
129
+ const targetAssetsDir = path.join(cwd, 'custom', 'assets');
130
+
131
+ await fse.ensureDir(targetAssetsDir);
132
+ await fse.copy(sourceAssetsDir, targetAssetsDir);
133
+
134
+ writeTemplateFiles(cwd, connectionString.toString(), prismaDbUrl, appName, provider);
135
+
136
+ const resourcesDir = path.join(cwd, 'resources');
137
+ await fse.ensureDir(resourcesDir);
138
+ fs.writeFileSync(path.join(resourcesDir, 'users.ts'), templates.usersResource());
139
+
140
+ const customDir = path.join(cwd, 'custom');
141
+ await fse.ensureDir(customDir);
142
+ ctx.customDir = customDir;
143
+ fs.writeFileSync(path.join(customDir, 'package.json'), templates.customPackageJson(appName));
144
+ fs.writeFileSync(path.join(customDir, 'tsconfig.json'), templates.customTsconfig());
145
+ }
146
+
147
+ function writeTemplateFiles(cwd, dbUrl, prismaDbUrl, appName, provider) {
148
+ fs.writeFileSync(path.join(cwd, '.gitignore'), templates.gitignore());
149
+ fs.writeFileSync(path.join(cwd, '.env'), templates.env(dbUrl, prismaDbUrl));
150
+ fs.writeFileSync(path.join(cwd, '.env.sample'), templates.envSample(dbUrl, prismaDbUrl));
151
+ fs.writeFileSync(path.join(cwd, 'index.ts'), templates.indexTs(appName));
152
+ if (prismaDbUrl)
153
+ fs.writeFileSync(path.join(cwd, 'schema.prisma'), templates.schemaPrisma(provider, prismaDbUrl));
154
+ fs.writeFileSync(path.join(cwd, 'package.json'), templates.rootPackageJson(appName));
155
+ fs.writeFileSync(path.join(cwd, 'tsconfig.json'), templates.rootTsConfig());
156
+ }
157
+
158
+ async function installDependencies(ctx, cwd) {
159
+ const customDir = ctx.customDir;
160
+
161
+ await Promise.all([
162
+ await execa('npm', ['install', '--no-package-lock'], { cwd }),
163
+ await execa('npm', ['install'], { cwd: customDir }),
164
+ ]);
165
+ }
166
+
167
+ function generateFinalInstructions(skipPrismaSetup) {
168
+ let instruction = 'ā­ļø Run the following commands to get started:\n';
169
+ if (!skipPrismaSetup)
170
+ instruction += `
171
+ ${chalk.dim('// runs "npx prisma migrate dev --name init" to generate and apply initial migration')}`;
172
+ ${chalk.cyan('$ npm run makemigration -- --name init')}
173
+ instruction += `
174
+ ${chalk.dim('\n// starts dev server with tsx watch for hot-reloading')}\n
175
+ ${chalk.cyan('$ npm start')}
176
+ `;
177
+
178
+ instruction += 'šŸ˜‰ Happy coding!';
179
+
180
+ return instruction;
181
+ }
182
+
183
+ export function prepareWorkflow(options) {
184
+ const cwd = process.cwd();
185
+ const tasks = new Listr([
186
+ {
187
+ title: 'šŸ” Initial checks...',
188
+ task: (_, task) =>
189
+ task.newListr(
190
+ initialChecks(),
191
+ { concurrent: true },
192
+ )
193
+ },
194
+ {
195
+ title: 'šŸš€ Scaffolding your project...',
196
+ task: async (ctx) => scaffoldProject(ctx, options, cwd)
197
+ },
198
+ {
199
+ title: 'šŸ“¦ Installing dependencies...',
200
+ task: async (ctx) => installDependencies(ctx, cwd)
201
+ },
202
+ {
203
+ title: 'šŸ“ Preparing final instructions...',
204
+ task: (ctx) => {
205
+ console.log(chalk.green(`āœ… Successfully created your new Adminforth project!\n`));
206
+ console.log(generateFinalInstructions(ctx.skipPrismaSetup));
207
+ console.log('\n\n');
208
+ }
209
+ }],
210
+ {
211
+ rendererOptions: {collapseSubtasks: false},
212
+ concurrent: false,
213
+ exitOnError: true,
214
+ collectErrors: true,
215
+ }
216
+ );
217
+
218
+ return tasks;
219
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.5.9-next.12",
3
+ "version": "1.5.9-next.14",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -40,14 +40,21 @@
40
40
  "@clickhouse/client": "^1.4.0",
41
41
  "@faker-js/faker": "^9.0.3",
42
42
  "@types/express": "^5.0.0",
43
+ "arg": "^5.0.2",
43
44
  "better-sqlite3": "^11.5.0",
45
+ "chalk": "^5.4.1",
46
+ "connection-string": "^4.4.0",
44
47
  "dayjs": "^1.11.11",
45
48
  "dotenv": "^16.4.5",
49
+ "esm": "^3.2.25",
50
+ "execa": "^9.5.2",
46
51
  "express": "^4.21.0",
47
52
  "filewatcher": "^3.0.1",
48
53
  "fs-extra": "^11.2.0",
49
54
  "fuse.js": "^7.0.0",
55
+ "inquirer": "^12.3.0",
50
56
  "jsonwebtoken": "^9.0.2",
57
+ "listr2": "^8.2.5",
51
58
  "mongodb": "6.6",
52
59
  "node-fetch": "^3.3.2",
53
60
  "pg": "^8.11.5",