@devbro/pashmak 0.1.26 → 0.1.28

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.
Files changed (31) hide show
  1. package/dist/app/console/generate/GenerateApiDocsCommand.d.mts +9 -0
  2. package/dist/app/console/generate/GenerateApiDocsCommand.mjs +117 -0
  3. package/dist/app/console/generate/GenerateApiDocsCommand.mjs.map +1 -0
  4. package/dist/app/console/generate/index.d.mts +1 -0
  5. package/dist/app/console/generate/index.mjs +1 -0
  6. package/dist/app/console/generate/index.mjs.map +1 -1
  7. package/dist/app/console/index.d.mts +1 -0
  8. package/dist/app/console/migrate/MigrateCommand.mjs +5 -0
  9. package/dist/app/console/migrate/MigrateCommand.mjs.map +1 -1
  10. package/dist/app/console/migrate/MigrateRollbackCommand.mjs +2 -0
  11. package/dist/app/console/migrate/MigrateRollbackCommand.mjs.map +1 -1
  12. package/dist/bin/app/console/DefaultCommand.cjs +3 -0
  13. package/dist/bin/app/console/KeyGenerateCommand.cjs +3 -0
  14. package/dist/bin/app/console/StartCommand.cjs +3 -0
  15. package/dist/bin/app/console/generate/GenerateApiDocsCommand.cjs +868 -0
  16. package/dist/bin/app/console/generate/GenerateControllerCommand.cjs +3 -0
  17. package/dist/bin/app/console/generate/index.cjs +131 -14
  18. package/dist/bin/app/console/index.cjs +170 -46
  19. package/dist/bin/app/console/migrate/GenerateMigrateCommand.cjs +3 -0
  20. package/dist/bin/app/console/migrate/MigrateCommand.cjs +8 -0
  21. package/dist/bin/app/console/migrate/MigrateRollbackCommand.cjs +5 -0
  22. package/dist/bin/app/console/migrate/index.cjs +10 -0
  23. package/dist/bin/app/console/queue/GenerateQueueMigrateCommand.cjs +3 -0
  24. package/dist/bin/cache.cjs +3 -0
  25. package/dist/bin/facades.cjs +3 -0
  26. package/dist/bin/factories.cjs +3 -0
  27. package/dist/bin/index.cjs +180 -49
  28. package/dist/bin/middlewares.cjs +3 -0
  29. package/dist/bin/queue.cjs +3 -0
  30. package/dist/bin/router.cjs +3 -0
  31. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ import { Command } from 'clipanion';
2
+
3
+ declare class GenerateApiDocsCommand extends Command {
4
+ static paths: string[][];
5
+ execute(): Promise<void>;
6
+ private extractParameters;
7
+ }
8
+
9
+ export { GenerateApiDocsCommand };
@@ -0,0 +1,117 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { cli, router } from "../../../facades.mjs";
4
+ import { Command } from "clipanion";
5
+ import path from "path";
6
+ import * as fs from "fs/promises";
7
+ class GenerateApiDocsCommand extends Command {
8
+ static {
9
+ __name(this, "GenerateApiDocsCommand");
10
+ }
11
+ static paths = [
12
+ [`make`, `apidocs`],
13
+ [`generate`, `apidocs`]
14
+ ];
15
+ async execute() {
16
+ const rootDir = process.cwd();
17
+ this.context.stdout.write(`Generating OpenAPI documentation...
18
+ `);
19
+ const routes = router().routes;
20
+ const openApiSpec = {
21
+ openapi: "3.0.0",
22
+ info: {
23
+ title: "API Documentation",
24
+ version: "1.0.0",
25
+ description: "Auto-generated API documentation"
26
+ },
27
+ servers: [
28
+ {
29
+ url: "/",
30
+ description: "Local server"
31
+ }
32
+ ],
33
+ paths: {}
34
+ };
35
+ for (const route of routes) {
36
+ const routePath = route.path;
37
+ const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
38
+ if (!openApiSpec.paths[openApiPath]) {
39
+ openApiSpec.paths[openApiPath] = {};
40
+ }
41
+ for (const method of route.methods) {
42
+ const lowerMethod = method.toLowerCase();
43
+ if (lowerMethod === "head") {
44
+ continue;
45
+ }
46
+ openApiSpec.paths[openApiPath][lowerMethod] = {
47
+ summary: `${method} ${routePath}`,
48
+ description: `Endpoint for ${method} ${routePath}`,
49
+ parameters: this.extractParameters(routePath),
50
+ responses: {
51
+ "200": {
52
+ description: "Successful response",
53
+ content: {
54
+ "application/json": {
55
+ schema: {
56
+ type: "object"
57
+ }
58
+ }
59
+ }
60
+ },
61
+ "500": {
62
+ description: "Internal server error"
63
+ }
64
+ }
65
+ };
66
+ if (["post", "put", "patch"].includes(lowerMethod)) {
67
+ openApiSpec.paths[openApiPath][lowerMethod].requestBody = {
68
+ required: true,
69
+ content: {
70
+ "application/json": {
71
+ schema: {
72
+ type: "object"
73
+ }
74
+ }
75
+ }
76
+ };
77
+ }
78
+ }
79
+ }
80
+ const publicDir = path.join(rootDir, "public");
81
+ await fs.mkdir(publicDir, { recursive: true });
82
+ const outputPath = path.join(publicDir, "openapi.json");
83
+ await fs.writeFile(
84
+ outputPath,
85
+ JSON.stringify(openApiSpec, null, 2),
86
+ "utf-8"
87
+ );
88
+ this.context.stdout.write(
89
+ `OpenAPI documentation generated at: ${outputPath}
90
+ `
91
+ );
92
+ this.context.stdout.write(`Total routes documented: ${routes.length}
93
+ `);
94
+ }
95
+ extractParameters(routePath) {
96
+ const paramRegex = /:([a-zA-Z0-9_]+)/g;
97
+ const parameters = [];
98
+ let match;
99
+ while ((match = paramRegex.exec(routePath)) !== null) {
100
+ parameters.push({
101
+ name: match[1],
102
+ in: "path",
103
+ required: true,
104
+ schema: {
105
+ type: "string"
106
+ },
107
+ description: `Path parameter ${match[1]}`
108
+ });
109
+ }
110
+ return parameters;
111
+ }
112
+ }
113
+ cli().register(GenerateApiDocsCommand);
114
+ export {
115
+ GenerateApiDocsCommand
116
+ };
117
+ //# sourceMappingURL=GenerateApiDocsCommand.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app/console/generate/GenerateApiDocsCommand.mts"],"sourcesContent":["import { cli, router } from \"../../../facades.mjs\";\nimport { Command } from \"clipanion\";\nimport path from \"path\";\nimport * as fs from \"fs/promises\";\n\nexport class GenerateApiDocsCommand extends Command {\n static paths = [\n [`make`, `apidocs`],\n [`generate`, `apidocs`],\n ];\n\n async execute() {\n const rootDir = process.cwd();\n\n this.context.stdout.write(`Generating OpenAPI documentation...\\n`);\n\n // Get all routes from the router\n const routes = router().routes;\n\n // Generate OpenAPI 3.0 specification\n const openApiSpec = {\n openapi: \"3.0.0\",\n info: {\n title: \"API Documentation\",\n version: \"1.0.0\",\n description: \"Auto-generated API documentation\",\n },\n servers: [\n {\n url: \"/\",\n description: \"Local server\",\n },\n ],\n paths: {} as Record<string, any>,\n };\n\n // Process each route\n for (const route of routes) {\n const routePath = route.path;\n // Convert route path to OpenAPI format (e.g., /api/:id -> /api/{id})\n const openApiPath = routePath.replace(/:([a-zA-Z0-9_]+)/g, \"{$1}\");\n\n if (!openApiSpec.paths[openApiPath]) {\n openApiSpec.paths[openApiPath] = {};\n }\n\n // Add each HTTP method for this route\n for (const method of route.methods) {\n const lowerMethod = method.toLowerCase();\n\n // Skip HEAD as it's usually auto-generated\n if (lowerMethod === \"head\") {\n continue;\n }\n\n openApiSpec.paths[openApiPath][lowerMethod] = {\n summary: `${method} ${routePath}`,\n description: `Endpoint for ${method} ${routePath}`,\n parameters: this.extractParameters(routePath),\n responses: {\n \"200\": {\n description: \"Successful response\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n },\n },\n },\n },\n \"500\": {\n description: \"Internal server error\",\n },\n },\n };\n\n // Add request body for POST, PUT, PATCH\n if ([\"post\", \"put\", \"patch\"].includes(lowerMethod)) {\n openApiSpec.paths[openApiPath][lowerMethod].requestBody = {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n },\n },\n },\n };\n }\n }\n }\n\n // Ensure public directory exists\n const publicDir = path.join(rootDir, \"public\");\n await fs.mkdir(publicDir, { recursive: true });\n\n // Write the OpenAPI spec to public/openapi.json\n const outputPath = path.join(publicDir, \"openapi.json\");\n await fs.writeFile(\n outputPath,\n JSON.stringify(openApiSpec, null, 2),\n \"utf-8\",\n );\n\n this.context.stdout.write(\n `OpenAPI documentation generated at: ${outputPath}\\n`,\n );\n this.context.stdout.write(`Total routes documented: ${routes.length}\\n`);\n }\n\n private extractParameters(routePath: string): any[] {\n const paramRegex = /:([a-zA-Z0-9_]+)/g;\n const parameters: any[] = [];\n let match;\n\n while ((match = paramRegex.exec(routePath)) !== null) {\n parameters.push({\n name: match[1],\n in: \"path\",\n required: true,\n schema: {\n type: \"string\",\n },\n description: `Path parameter ${match[1]}`,\n });\n }\n\n return parameters;\n }\n}\n\ncli().register(GenerateApiDocsCommand);\n"],"mappings":"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","names":[]}
@@ -1,2 +1,3 @@
1
1
  export { GenerateControllerCommand } from './GenerateControllerCommand.mjs';
2
+ export { GenerateApiDocsCommand } from './GenerateApiDocsCommand.mjs';
2
3
  import 'clipanion';
@@ -1,2 +1,3 @@
1
1
  export * from "./GenerateControllerCommand.mjs";
2
+ export * from "./GenerateApiDocsCommand.mjs";
2
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app/console/generate/index.mts"],"sourcesContent":["export * from \"./GenerateControllerCommand.mjs\";\n"],"mappings":"AAAA,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app/console/generate/index.mts"],"sourcesContent":["export * from \"./GenerateControllerCommand.mjs\";\nexport * from \"./GenerateApiDocsCommand.mjs\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;","names":[]}
@@ -5,6 +5,7 @@ export { StartCommand } from './StartCommand.mjs';
5
5
  export { DefaultCommand } from './DefaultCommand.mjs';
6
6
  export { KeyGenerateCommand } from './KeyGenerateCommand.mjs';
7
7
  export { GenerateControllerCommand } from './generate/GenerateControllerCommand.mjs';
8
+ export { GenerateApiDocsCommand } from './generate/GenerateApiDocsCommand.mjs';
8
9
  export { CreateProjectCommand } from './project/CreateProjectCommand.mjs';
9
10
  export { GenerateQueueMigrateCommand } from './queue/GenerateQueueMigrateCommand.mjs';
10
11
  import 'clipanion';
@@ -28,6 +28,7 @@ class MigrateCommand extends Command {
28
28
  logger().info("reverting all migrations!!");
29
29
  const existing_migrations = await db.runQuery({
30
30
  sql: "select * from migrations order by created_at DESC",
31
+ parts: [],
31
32
  bindings: []
32
33
  });
33
34
  const migrationsDir2 = config.get("migration.path");
@@ -39,6 +40,7 @@ class MigrateCommand extends Command {
39
40
  await migrationInstance.down(db.getSchema());
40
41
  await db.runQuery({
41
42
  sql: "delete from migrations where filename = $1",
43
+ parts: [],
42
44
  bindings: [migration_record.filename]
43
45
  });
44
46
  } catch (error) {
@@ -66,12 +68,14 @@ class MigrateCommand extends Command {
66
68
  files = dirEntries.filter((entry) => entry.endsWith(".ts") || entry.endsWith(".js")).sort();
67
69
  let batch_number = await db.runQuery({
68
70
  sql: "select max(batch) as next_batch from migrations",
71
+ parts: [],
69
72
  bindings: []
70
73
  });
71
74
  batch_number = batch_number[0].next_batch || 0;
72
75
  batch_number++;
73
76
  const migrations = await db.runQuery({
74
77
  sql: "select * from migrations order by created_at ASC",
78
+ parts: [],
75
79
  bindings: []
76
80
  });
77
81
  const completed_migrations = migrations.map((r) => r.filename);
@@ -86,6 +90,7 @@ class MigrateCommand extends Command {
86
90
  await c.up(db.getSchema());
87
91
  await db.runQuery({
88
92
  sql: "insert into migrations (filename, batch) values ($1,$2)",
93
+ parts: [],
89
94
  bindings: [class_to_migrate, batch_number]
90
95
  });
91
96
  migrated_count++;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app/console/migrate/MigrateCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { Blueprint } from \"@devbro/neko-sql\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\n\nexport class MigrateCommand extends Command {\n static paths = [[`migrate`]];\n\n fresh = Option.Boolean(`--fresh`, false, {\n description: `whether to delete and recreate database`,\n });\n\n refresh = Option.Boolean(`--refresh`, false, {\n description: `whether to drop all tables before running migrations by using rollback function`,\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n if (this.fresh) {\n throw new Error(\"not implemented\");\n }\n\n if (this.refresh) {\n logger().info(\"reverting all migrations!!\");\n // read all migrations and undo them all\n const existing_migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC\",\n bindings: [],\n });\n\n const migrationsDir = config.get(\"migration.path\");\n\n for (const migration_record of existing_migrations) {\n logger().info(`rolling back ${migration_record.filename}`);\n try {\n const MigrationClass = (\n await import(path.join(migrationsDir, migration_record.filename))\n ).default;\n const migrationInstance: Migration = new MigrationClass();\n\n // Call the down method to rollback the migration\n await migrationInstance.down(db.getSchema());\n\n // Remove the migration record from the migrations table\n await db.runQuery({\n sql: \"delete from migrations where filename = $1\",\n bindings: [migration_record.filename],\n });\n } catch (error) {\n logger().error(\n `Failed to rollback migration ${migration_record.filename}: ${error}`,\n );\n throw error;\n }\n }\n\n logger().info(\n `rolled back ${existing_migrations.length} migrations successfully!`,\n );\n }\n\n //create migration table if not exists\n if (!(await schema.tableExists(\"migrations\"))) {\n await schema.createTable(\"migrations\", (blueprint: Blueprint) => {\n blueprint.id();\n blueprint.timestamps();\n blueprint.string(\"filename\");\n blueprint.integer(\"batch\");\n });\n }\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries\n .filter((entry) => entry.endsWith(\".ts\") || entry.endsWith(\".js\"))\n .sort();\n let batch_number = await db.runQuery({\n sql: \"select max(batch) as next_batch from migrations\",\n bindings: [],\n });\n batch_number = batch_number[0].next_batch || 0;\n batch_number++;\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at ASC\",\n bindings: [],\n });\n\n const completed_migrations = migrations.map((r: any) => r.filename);\n const pending_migrations = files.filter(\n (file) => !completed_migrations.includes(file),\n );\n\n let migrated_count = 0;\n for (const class_to_migrate of pending_migrations) {\n logger().info(`migrating up ${class_to_migrate}`);\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n const c: Migration = new ClassToMigrate();\n await c.up(db.getSchema());\n await db.runQuery({\n sql: \"insert into migrations (filename, batch) values ($1,$2)\",\n bindings: [class_to_migrate, batch_number],\n });\n migrated_count++;\n }\n\n if (migrated_count === 0) {\n logger().warn(\"no migrations to run!\");\n return;\n }\n\n logger().info(`migrated ${migrated_count} migrations successfully!`);\n return;\n });\n }\n}\n\ncli().register(MigrateCommand);\n"],"mappings":"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","names":["migrationsDir"]}
1
+ {"version":3,"sources":["../../../../src/app/console/migrate/MigrateCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { Blueprint } from \"@devbro/neko-sql\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\n\nexport class MigrateCommand extends Command {\n static paths = [[`migrate`]];\n\n fresh = Option.Boolean(`--fresh`, false, {\n description: `whether to delete and recreate database`,\n });\n\n refresh = Option.Boolean(`--refresh`, false, {\n description: `whether to drop all tables before running migrations by using rollback function`,\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n if (this.fresh) {\n throw new Error(\"not implemented\");\n }\n\n if (this.refresh) {\n logger().info(\"reverting all migrations!!\");\n // read all migrations and undo them all\n const existing_migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC\",\n parts: [],\n bindings: [],\n });\n\n const migrationsDir = config.get(\"migration.path\");\n\n for (const migration_record of existing_migrations) {\n logger().info(`rolling back ${migration_record.filename}`);\n try {\n const MigrationClass = (\n await import(path.join(migrationsDir, migration_record.filename))\n ).default;\n const migrationInstance: Migration = new MigrationClass();\n\n // Call the down method to rollback the migration\n await migrationInstance.down(db.getSchema());\n\n // Remove the migration record from the migrations table\n await db.runQuery({\n sql: \"delete from migrations where filename = $1\",\n parts: [],\n bindings: [migration_record.filename],\n });\n } catch (error) {\n logger().error(\n `Failed to rollback migration ${migration_record.filename}: ${error}`,\n );\n throw error;\n }\n }\n\n logger().info(\n `rolled back ${existing_migrations.length} migrations successfully!`,\n );\n }\n\n //create migration table if not exists\n if (!(await schema.tableExists(\"migrations\"))) {\n await schema.createTable(\"migrations\", (blueprint: Blueprint) => {\n blueprint.id();\n blueprint.timestamps();\n blueprint.string(\"filename\");\n blueprint.integer(\"batch\");\n });\n }\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries\n .filter((entry) => entry.endsWith(\".ts\") || entry.endsWith(\".js\"))\n .sort();\n let batch_number = await db.runQuery({\n sql: \"select max(batch) as next_batch from migrations\",\n parts: [],\n bindings: [],\n });\n batch_number = batch_number[0].next_batch || 0;\n batch_number++;\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at ASC\",\n parts: [],\n bindings: [],\n });\n\n const completed_migrations = migrations.map((r: any) => r.filename);\n const pending_migrations = files.filter(\n (file) => !completed_migrations.includes(file),\n );\n\n let migrated_count = 0;\n for (const class_to_migrate of pending_migrations) {\n logger().info(`migrating up ${class_to_migrate}`);\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n const c: Migration = new ClassToMigrate();\n await c.up(db.getSchema());\n await db.runQuery({\n sql: \"insert into migrations (filename, batch) values ($1,$2)\",\n parts: [],\n bindings: [class_to_migrate, batch_number],\n });\n migrated_count++;\n }\n\n if (migrated_count === 0) {\n logger().warn(\"no migrations to run!\");\n return;\n }\n\n logger().info(`migrated ${migrated_count} migrations successfully!`);\n return;\n });\n }\n}\n\ncli().register(MigrateCommand);\n"],"mappings":"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","names":["migrationsDir"]}
@@ -26,6 +26,7 @@ class MigrateRollbackCommand extends Command {
26
26
  files = dirEntries.filter((entry) => entry.endsWith(".ts")).sort();
27
27
  const migrations = await db.runQuery({
28
28
  sql: "select * from migrations order by created_at DESC limit $1",
29
+ parts: [],
29
30
  bindings: [this.steps]
30
31
  });
31
32
  for (const migration of migrations) {
@@ -36,6 +37,7 @@ class MigrateRollbackCommand extends Command {
36
37
  await c.down(db.getSchema());
37
38
  await db.runQuery({
38
39
  sql: "delete from migrations where id = $1",
40
+ parts: [],
39
41
  bindings: [migration.id]
40
42
  });
41
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app/console/migrate/MigrateRollbackCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\nimport * as t from \"typanion\";\n\nexport class MigrateRollbackCommand extends Command {\n static paths = [[`migrate`, \"rollback\"]];\n\n steps = Option.String(`--steps`, \"1\", {\n description: `how many migrations to rollback`,\n validator: t.isNumber(),\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries.filter((entry) => entry.endsWith(\".ts\")).sort();\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC limit $1\",\n bindings: [this.steps],\n });\n\n for (const migration of migrations) {\n const class_to_migrate = migration.filename;\n logger().info(`rolling back ${class_to_migrate}`);\n\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n\n const c: Migration = new ClassToMigrate();\n await c.down(db.getSchema());\n await db.runQuery({\n sql: \"delete from migrations where id = $1\",\n bindings: [migration.id],\n });\n }\n });\n }\n}\n\ncli().register(MigrateRollbackCommand);\n"],"mappings":";;AAAA,SAAS,KAAK,MAAM,UAAU,cAAc;AAC5C,SAAS,SAAS,cAAc;AAChC,SAAS,wBAAwB;AACjC,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,cAAc;AAEvB,YAAY,OAAO;AAEZ,MAAM,+BAA+B,QAAQ;AAAA,EATpD,OASoD;AAAA;AAAA;AAAA,EAClD,OAAO,QAAQ,CAAC,CAAC,WAAW,UAAU,CAAC;AAAA,EAEvC,QAAQ,OAAO,OAAO,WAAW,KAAK;AAAA,IACpC,aAAa;AAAA,IACb,WAAW,EAAE,SAAS;AAAA,EACxB,CAAC;AAAA,EAED,MAAM,UAAU;AACd,UAAM,iBAAiB,IAAI,YAAY;AAErC,YAAM,KAAK,SAAS;AACpB,YAAM,SAAS,GAAG,UAAU;AAE5B,YAAM,gBAAgB,OAAO,IAAI,gBAAgB;AACjD,UAAI,QAAkB,CAAC;AAEvB,YAAM,aAAa,MAAM,GAAG,QAAQ,aAAa;AACjD,cAAQ,WAAW,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,CAAC,EAAE,KAAK;AAEjE,YAAM,aAAa,MAAM,GAAG,SAAS;AAAA,QACnC,KAAK;AAAA,QACL,UAAU,CAAC,KAAK,KAAK;AAAA,MACvB,CAAC;AAED,iBAAW,aAAa,YAAY;AAClC,cAAM,mBAAmB,UAAU;AACnC,eAAO,EAAE,KAAK,gBAAgB,gBAAgB,EAAE;AAEhD,cAAM,kBACJ,MAAM,OAAO,KAAK,KAAK,eAAe,gBAAgB,IACtD;AAEF,cAAM,IAAe,IAAI,eAAe;AACxC,cAAM,EAAE,KAAK,GAAG,UAAU,CAAC;AAC3B,cAAM,GAAG,SAAS;AAAA,UAChB,KAAK;AAAA,UACL,UAAU,CAAC,UAAU,EAAE;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,IAAI,EAAE,SAAS,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app/console/migrate/MigrateRollbackCommand.mts"],"sourcesContent":["import { cli, db as database, logger } from \"../../../facades.mjs\";\nimport { Command, Option } from \"clipanion\";\nimport { context_provider } from \"@devbro/neko-context\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { config } from \"@devbro/neko-config\";\nimport { Migration } from \"@devbro/neko-sql\";\nimport * as t from \"typanion\";\n\nexport class MigrateRollbackCommand extends Command {\n static paths = [[`migrate`, \"rollback\"]];\n\n steps = Option.String(`--steps`, \"1\", {\n description: `how many migrations to rollback`,\n validator: t.isNumber(),\n });\n\n async execute() {\n await context_provider.run(async () => {\n // this.context.stdout.write(`Hello Migrate Command!\\n`);\n const db = database();\n const schema = db.getSchema();\n\n const migrationsDir = config.get(\"migration.path\");\n let files: string[] = [];\n\n const dirEntries = await fs.readdir(migrationsDir);\n files = dirEntries.filter((entry) => entry.endsWith(\".ts\")).sort();\n\n const migrations = await db.runQuery({\n sql: \"select * from migrations order by created_at DESC limit $1\",\n parts: [],\n bindings: [this.steps],\n });\n\n for (const migration of migrations) {\n const class_to_migrate = migration.filename;\n logger().info(`rolling back ${class_to_migrate}`);\n\n const ClassToMigrate = (\n await import(path.join(migrationsDir, class_to_migrate))\n ).default;\n\n const c: Migration = new ClassToMigrate();\n await c.down(db.getSchema());\n await db.runQuery({\n sql: \"delete from migrations where id = $1\",\n parts: [],\n bindings: [migration.id],\n });\n }\n });\n }\n}\n\ncli().register(MigrateRollbackCommand);\n"],"mappings":";;AAAA,SAAS,KAAK,MAAM,UAAU,cAAc;AAC5C,SAAS,SAAS,cAAc;AAChC,SAAS,wBAAwB;AACjC,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,cAAc;AAEvB,YAAY,OAAO;AAEZ,MAAM,+BAA+B,QAAQ;AAAA,EATpD,OASoD;AAAA;AAAA;AAAA,EAClD,OAAO,QAAQ,CAAC,CAAC,WAAW,UAAU,CAAC;AAAA,EAEvC,QAAQ,OAAO,OAAO,WAAW,KAAK;AAAA,IACpC,aAAa;AAAA,IACb,WAAW,EAAE,SAAS;AAAA,EACxB,CAAC;AAAA,EAED,MAAM,UAAU;AACd,UAAM,iBAAiB,IAAI,YAAY;AAErC,YAAM,KAAK,SAAS;AACpB,YAAM,SAAS,GAAG,UAAU;AAE5B,YAAM,gBAAgB,OAAO,IAAI,gBAAgB;AACjD,UAAI,QAAkB,CAAC;AAEvB,YAAM,aAAa,MAAM,GAAG,QAAQ,aAAa;AACjD,cAAQ,WAAW,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,CAAC,EAAE,KAAK;AAEjE,YAAM,aAAa,MAAM,GAAG,SAAS;AAAA,QACnC,KAAK;AAAA,QACL,OAAO,CAAC;AAAA,QACR,UAAU,CAAC,KAAK,KAAK;AAAA,MACvB,CAAC;AAED,iBAAW,aAAa,YAAY;AAClC,cAAM,mBAAmB,UAAU;AACnC,eAAO,EAAE,KAAK,gBAAgB,gBAAgB,EAAE;AAEhD,cAAM,kBACJ,MAAM,OAAO,KAAK,KAAK,eAAe,gBAAgB,IACtD;AAEF,cAAM,IAAe,IAAI,eAAe;AACxC,cAAM,EAAE,KAAK,GAAG,UAAU,CAAC;AAC3B,cAAM,GAAG,SAAS;AAAA,UAChB,KAAK;AAAA,UACL,OAAO,CAAC;AAAA,UACR,UAAU,CAAC,UAAU,EAAE;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,IAAI,EAAE,SAAS,sBAAsB;","names":[]}
@@ -115,6 +115,9 @@ var CompiledRoute = class {
115
115
  }
116
116
  prepareOutputJsonFormat(obj) {
117
117
  function traverse(value) {
118
+ if (value === void 0 || value === null) {
119
+ return null;
120
+ }
118
121
  if (!value || typeof value !== "object") {
119
122
  return value;
120
123
  }
@@ -118,6 +118,9 @@ var CompiledRoute = class {
118
118
  }
119
119
  prepareOutputJsonFormat(obj) {
120
120
  function traverse(value) {
121
+ if (value === void 0 || value === null) {
122
+ return null;
123
+ }
121
124
  if (!value || typeof value !== "object") {
122
125
  return value;
123
126
  }
@@ -116,6 +116,9 @@ var CompiledRoute = class {
116
116
  }
117
117
  prepareOutputJsonFormat(obj) {
118
118
  function traverse(value) {
119
+ if (value === void 0 || value === null) {
120
+ return null;
121
+ }
119
122
  if (!value || typeof value !== "object") {
120
123
  return value;
121
124
  }