admindb 2.4.0 → 2.5.0
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/LICENSE +20 -20
- package/dist/app.js +36 -25
- package/dist/core/context.d.ts +1 -0
- package/dist/core/context.js +2 -0
- package/dist/core/errors.d.ts +1 -0
- package/dist/core/errors.js +39 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +20 -0
- package/dist/core/result.d.ts +1 -0
- package/dist/core/result.js +10 -0
- package/dist/core/router.d.ts +1 -0
- package/dist/core/router.js +37 -0
- package/dist/data/chain.js +1 -1
- package/dist/data/engine.js +1 -1
- package/dist/db/database.d.ts +1 -1
- package/dist/db/database.js +9 -31
- package/dist/db/dialects/index.d.ts +1 -0
- package/dist/db/dialects/index.js +58 -0
- package/dist/db/dialects/postgres/ddl.d.ts +1 -0
- package/dist/db/dialects/postgres/ddl.js +107 -0
- package/dist/db/dialects/postgres/dialect.d.ts +1 -0
- package/dist/db/dialects/postgres/dialect.js +28 -0
- package/dist/db/dialects/postgres/introspector.d.ts +1 -0
- package/dist/db/dialects/postgres/introspector.js +265 -0
- package/dist/db/dialects/postgres/types.d.ts +1 -0
- package/dist/db/dialects/postgres/types.js +83 -0
- package/dist/db/dialects/sqlite/ddl.d.ts +1 -0
- package/dist/db/dialects/sqlite/ddl.js +244 -0
- package/dist/db/dialects/sqlite/dialect.d.ts +1 -0
- package/dist/db/dialects/sqlite/dialect.js +25 -0
- package/dist/db/dialects/sqlite/introspector.d.ts +1 -0
- package/dist/db/dialects/sqlite/introspector.js +214 -0
- package/dist/db/dialects/sqlite/types.d.ts +1 -0
- package/dist/db/dialects/sqlite/types.js +69 -0
- package/dist/db/dialects/types.d.ts +1 -0
- package/dist/db/dialects/types.js +15 -0
- package/dist/db/export.js +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/manager.d.ts +1 -1
- package/dist/db/manager.js +101 -21
- package/dist/db/postgres.d.ts +1 -1
- package/dist/db/postgres.js +20 -284
- package/dist/db/types.d.ts +1 -1
- package/dist/db/types.js +0 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/modules/databases/databases.routes.d.ts +1 -0
- package/dist/modules/databases/databases.routes.js +150 -0
- package/dist/modules/databases/databases.service.d.ts +1 -0
- package/dist/modules/databases/databases.service.js +134 -0
- package/dist/modules/databases/index.d.ts +1 -0
- package/dist/{routes → modules/databases}/index.js +2 -3
- package/dist/modules/erd/erd.routes.d.ts +1 -0
- package/dist/modules/erd/erd.routes.js +32 -0
- package/dist/modules/erd/erd.service.d.ts +1 -0
- package/dist/modules/erd/erd.service.js +39 -0
- package/dist/modules/erd/index.d.ts +1 -0
- package/dist/modules/erd/index.js +18 -0
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +62 -0
- package/dist/modules/query/index.d.ts +1 -0
- package/dist/modules/query/index.js +18 -0
- package/dist/modules/query/query.routes.d.ts +1 -0
- package/dist/modules/query/query.routes.js +54 -0
- package/dist/modules/query/query.service.d.ts +1 -0
- package/dist/modules/query/query.service.js +95 -0
- package/dist/modules/rows/blob.helper.d.ts +1 -0
- package/dist/modules/rows/blob.helper.js +40 -0
- package/dist/modules/rows/display.helper.d.ts +1 -0
- package/dist/modules/rows/display.helper.js +73 -0
- package/dist/modules/rows/index.d.ts +1 -0
- package/dist/modules/rows/index.js +20 -0
- package/dist/modules/rows/rows.routes.d.ts +1 -0
- package/dist/modules/rows/rows.routes.js +555 -0
- package/dist/modules/rows/rows.service.d.ts +1 -0
- package/dist/modules/rows/rows.service.js +433 -0
- package/dist/modules/schema/index.d.ts +1 -0
- package/dist/modules/schema/index.js +18 -0
- package/dist/modules/schema/schema.routes.d.ts +1 -0
- package/dist/modules/schema/schema.routes.js +171 -0
- package/dist/modules/schema/schema.service.d.ts +1 -0
- package/dist/modules/schema/schema.service.js +58 -0
- package/dist/modules/seed/index.d.ts +1 -0
- package/dist/modules/seed/index.js +18 -0
- package/dist/modules/seed/seed.routes.d.ts +1 -0
- package/dist/modules/seed/seed.routes.js +212 -0
- package/dist/modules/seed/seed.service.d.ts +1 -0
- package/dist/{routes/api/helpers.js → modules/seed/seed.service.js} +86 -109
- package/dist/modules/tables/index.d.ts +1 -0
- package/dist/modules/tables/index.js +18 -0
- package/dist/modules/tables/tables.routes.d.ts +1 -0
- package/dist/modules/tables/tables.routes.js +194 -0
- package/dist/modules/tables/tables.service.d.ts +1 -0
- package/dist/modules/tables/tables.service.js +218 -0
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/types/api.d.ts +1 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +1 -3
- package/dist/utils/stream.d.ts +1 -0
- package/dist/utils/stream.js +131 -0
- package/dist/views/pages/error.hbs +10 -1
- package/dist/views/pages/home.hbs +1 -1
- package/dist/views/pages/query.hbs +1 -1
- package/dist/views/pages/seed-select.hbs +1 -252
- package/dist/views/pages/seed.hbs +1 -307
- package/dist/views/pages/table.hbs +1 -1
- package/dist/views/partials/sidebar.hbs +1 -1
- package/docs/API.md +4 -17
- package/docs/EXAMPLES.md +579 -579
- package/docs/SECURITY.md +265 -265
- package/package.json +4 -2
- package/dist/db/introspection.d.ts +0 -1
- package/dist/db/introspection.js +0 -164
- package/dist/routes/api/erd.d.ts +0 -1
- package/dist/routes/api/erd.js +0 -45
- package/dist/routes/api/helpers.d.ts +0 -1
- package/dist/routes/api/import-export.d.ts +0 -1
- package/dist/routes/api/import-export.js +0 -84
- package/dist/routes/api/index.d.ts +0 -1
- package/dist/routes/api/index.js +0 -55
- package/dist/routes/api/query.d.ts +0 -1
- package/dist/routes/api/query.js +0 -77
- package/dist/routes/api/rows.d.ts +0 -1
- package/dist/routes/api/rows.js +0 -373
- package/dist/routes/api/seed.d.ts +0 -1
- package/dist/routes/api/seed.js +0 -180
- package/dist/routes/api/tables.d.ts +0 -1
- package/dist/routes/api/tables.js +0 -230
- package/dist/routes/databases.d.ts +0 -1
- package/dist/routes/databases.js +0 -212
- package/dist/routes/index.d.ts +0 -1
- package/dist/routes/pages.d.ts +0 -1
- package/dist/routes/pages.js +0 -540
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Muhammad Bin Khalid
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Muhammad Bin Khalid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
package/dist/app.js
CHANGED
|
@@ -10,14 +10,13 @@ const express_handlebars_1 = require("express-handlebars");
|
|
|
10
10
|
const database_1 = require("./db/database");
|
|
11
11
|
const postgres_1 = require("./db/postgres");
|
|
12
12
|
const logger_1 = require("./utils/logger");
|
|
13
|
-
const
|
|
14
|
-
const index_1 = require("./routes/api/index");
|
|
15
|
-
const databases_1 = require("./routes/databases");
|
|
13
|
+
const index_1 = require("./modules/index");
|
|
16
14
|
const args_1 = require("./cli/args");
|
|
17
15
|
const common_1 = require("./utils/common");
|
|
18
16
|
const icons_1 = require("./utils/icons");
|
|
19
17
|
const serverless_1 = require("./serverless");
|
|
20
18
|
const auth_1 = require("./auth");
|
|
19
|
+
const index_2 = require("./db/dialects/index");
|
|
21
20
|
const APP_VERSION = (0, args_1.getPackageVersion)();
|
|
22
21
|
function createRouter(options = {}) {
|
|
23
22
|
const isServerless = options.serverless !== undefined ? options.serverless : (0, serverless_1.isServerlessEnvironment)();
|
|
@@ -60,10 +59,15 @@ function createRouter(options = {}) {
|
|
|
60
59
|
else {
|
|
61
60
|
singleDb = new database_1.SqliteDatabase(options.dbPath ?? 'admindb.db', logger, { readonly: globalReadonly });
|
|
62
61
|
}
|
|
63
|
-
if (!defaultDbId) {
|
|
62
|
+
if (!defaultDbId && singleDb) {
|
|
64
63
|
defaultDbId = singleDb.dialect === 'postgres' ? 'PostgreSQL' : (node_path_1.default.basename(singleDb.path) || 'SQLite');
|
|
65
64
|
}
|
|
66
65
|
}
|
|
66
|
+
let singleDialect;
|
|
67
|
+
if (singleDb) {
|
|
68
|
+
const pgSchema = singleDb.schema || 'public';
|
|
69
|
+
singleDialect = (0, index_2.getDialect)(singleDb.dialect, singleDb.dialect === 'postgres' ? pgSchema : undefined);
|
|
70
|
+
}
|
|
67
71
|
const app = (0, express_1.default)();
|
|
68
72
|
app.disable('x-powered-by');
|
|
69
73
|
app.use(express_1.default.static(node_path_1.default.join(__dirname, 'public')));
|
|
@@ -88,14 +92,28 @@ function createRouter(options = {}) {
|
|
|
88
92
|
res.locals.isDefaultPassword = authConfig.isDefaultPassword;
|
|
89
93
|
res.locals.icons = icons_1.ICONS;
|
|
90
94
|
res.locals.tables = [];
|
|
91
|
-
res.locals.internalTables = [];
|
|
92
95
|
next();
|
|
93
96
|
}
|
|
94
97
|
catch (err) {
|
|
95
98
|
next(err);
|
|
96
99
|
}
|
|
97
100
|
});
|
|
98
|
-
|
|
101
|
+
if (manager) {
|
|
102
|
+
(0, index_1.registerDatabasesRoutes)(app, {
|
|
103
|
+
manager,
|
|
104
|
+
logger,
|
|
105
|
+
basePath,
|
|
106
|
+
readonly: globalReadonly,
|
|
107
|
+
allowBrowse: isServerless ? false : options.allowBrowse,
|
|
108
|
+
browseRoot: options.browseRoot,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
app.get('/', (_req, res) => {
|
|
113
|
+
res.redirect(302, `${basePath}/home/${encodeURIComponent(defaultDbId)}`);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const getContext = (req) => {
|
|
99
117
|
if (manager) {
|
|
100
118
|
const dbId = String(req.params.db || req.params.dbId || req.params.id || '');
|
|
101
119
|
if (!manager.has(dbId)) {
|
|
@@ -111,27 +129,20 @@ function createRouter(options = {}) {
|
|
|
111
129
|
}
|
|
112
130
|
}
|
|
113
131
|
const effectiveRo = globalReadonly ? true : manager.isDbReadOnly(dbId);
|
|
114
|
-
return manager.
|
|
132
|
+
return manager.getContext(dbId, effectiveRo);
|
|
115
133
|
}
|
|
116
|
-
return
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
134
|
+
return {
|
|
135
|
+
id: defaultDbId,
|
|
136
|
+
name: defaultDbId,
|
|
137
|
+
path: singleDb.path,
|
|
138
|
+
db: singleDb,
|
|
139
|
+
dialect: singleDialect,
|
|
140
|
+
capabilities: singleDialect.capabilities,
|
|
141
|
+
isReadOnly: singleDb.isReadOnly,
|
|
121
142
|
logger,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
browseRoot: options.browseRoot,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
app.get('/', (_req, res) => {
|
|
130
|
-
res.redirect(302, `${basePath}/home/${encodeURIComponent(defaultDbId)}`);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
(0, pages_1.registerPages)(app, { getDb, logger });
|
|
134
|
-
(0, index_1.registerApi)(app, { getDb, logger });
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
(0, index_1.registerModules)(app, { getContext, logger });
|
|
135
146
|
addErrorHandlers(app, logger);
|
|
136
147
|
return app;
|
|
137
148
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import type {Logger} from '../utils/logger';import type {IDatabase} from '../db/types';import type {IDialect,DialectCapabilities} from '../db/dialects/types';export interface DatabaseContext{readonly id:string;readonly name:string;readonly path:string;readonly db:IDatabase;readonly dialect:IDialect;readonly capabilities:DialectCapabilities;readonly isReadOnly:boolean;readonly logger:Logger;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare class AppError extends Error{readonly status:number;readonly details?:Record<string,unknown>;constructor(message:string,status?:number,details?:Record<string,unknown>);}export declare class NotFoundError extends AppError{constructor(message?:string,details?:Record<string,unknown>);}export declare class BadRequestError extends AppError{constructor(message:string,details?:Record<string,unknown>);}export declare class ForbiddenError extends AppError{constructor(message?:string,details?:Record<string,unknown>);}export declare class ConflictError extends AppError{constructor(message:string,details?:Record<string,unknown>);}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConflictError = exports.ForbiddenError = exports.BadRequestError = exports.NotFoundError = exports.AppError = void 0;
|
|
4
|
+
class AppError extends Error {
|
|
5
|
+
status;
|
|
6
|
+
details;
|
|
7
|
+
constructor(message, status = 500, details) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = this.constructor.name;
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.details = details;
|
|
12
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.AppError = AppError;
|
|
16
|
+
class NotFoundError extends AppError {
|
|
17
|
+
constructor(message = 'Resource not found.', details) {
|
|
18
|
+
super(message, 404, details);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.NotFoundError = NotFoundError;
|
|
22
|
+
class BadRequestError extends AppError {
|
|
23
|
+
constructor(message, details) {
|
|
24
|
+
super(message, 400, details);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.BadRequestError = BadRequestError;
|
|
28
|
+
class ForbiddenError extends AppError {
|
|
29
|
+
constructor(message = 'Database is open in read-only mode — write operations are disabled.', details) {
|
|
30
|
+
super(message, 403, details);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.ForbiddenError = ForbiddenError;
|
|
34
|
+
class ConflictError extends AppError {
|
|
35
|
+
constructor(message, details) {
|
|
36
|
+
super(message, 409, details);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ConflictError = ConflictError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './result';export * from './errors';export * from './context';export * from './router';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./result"), exports);
|
|
18
|
+
__exportStar(require("./errors"), exports);
|
|
19
|
+
__exportStar(require("./context"), exports);
|
|
20
|
+
__exportStar(require("./router"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type SQLInputValue=null|number|bigint|string|boolean|Uint8Array|Buffer|Date;export interface Result<T=unknown>{success:boolean;data?:T;error?:string;}export interface MutationResult{changes?:number;lastInsertRowid?:number|null;}export declare function okResult<T>(data?:T):Result<T>;export declare function errResult<T=never>(error:string):Result<T>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.okResult = okResult;
|
|
4
|
+
exports.errResult = errResult;
|
|
5
|
+
function okResult(data) {
|
|
6
|
+
return { success: true, ...(data !== undefined ? { data } : {}) };
|
|
7
|
+
}
|
|
8
|
+
function errResult(error) {
|
|
9
|
+
return { success: false, error };
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import type {Request,Response,NextFunction} from 'express';import type {DatabaseContext} from './context';import type {Logger} from '../utils/logger';export interface RouteContext{getContext:(req:Request)=>DatabaseContext;logger:Logger;}export declare const ok:(res:Response,data:unknown,status?:number)=>Response;export declare const fail:(res:Response,error:string,status?:number,details?:Record<string,unknown>|null)=>Response;export declare const notFound:(res:Response,message:string)=>void;export declare const wrap:(fn:(req:Request,res:Response,next?:NextFunction)=>unknown)=>(req:Request,res:Response,next?:NextFunction)=>Promise<void>;export declare function initPageLocals(res:Response,dbOrCtx:{dialect:string|{name:string;};path:string;isReadOnly:boolean;},dbId:string,allNames:string[]):{tables:string[];};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wrap = exports.notFound = exports.fail = exports.ok = void 0;
|
|
4
|
+
exports.initPageLocals = initPageLocals;
|
|
5
|
+
const common_1 = require("../utils/common");
|
|
6
|
+
const ok = (res, data, status = 200) => res.status(status).json({ success: true, data });
|
|
7
|
+
exports.ok = ok;
|
|
8
|
+
const fail = (res, error, status = 400, details) => res.status(status).json({ success: false, error, ...(details ? { details } : {}) });
|
|
9
|
+
exports.fail = fail;
|
|
10
|
+
const notFound = (res, message) => {
|
|
11
|
+
res.status(404).render('pages/error', { title: 'Not found', status: 404, error: message });
|
|
12
|
+
};
|
|
13
|
+
exports.notFound = notFound;
|
|
14
|
+
const wrap = (fn) => async (req, res, next) => {
|
|
15
|
+
try {
|
|
16
|
+
await fn(req, res, next);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
(0, exports.fail)(res, (0, common_1.errorMessage)(err), 500);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
exports.wrap = wrap;
|
|
23
|
+
function initPageLocals(res, dbOrCtx, dbId, allNames) {
|
|
24
|
+
const dialectName = typeof dbOrCtx.dialect === 'string' ? dbOrCtx.dialect : dbOrCtx.dialect.name;
|
|
25
|
+
const isPostgres = dialectName === 'postgres';
|
|
26
|
+
const isSqlite = dialectName === 'sqlite';
|
|
27
|
+
res.locals.dbId = dbId;
|
|
28
|
+
res.locals.dbPath = dbOrCtx.path;
|
|
29
|
+
res.locals.tables = allNames;
|
|
30
|
+
res.locals.dialect = dialectName;
|
|
31
|
+
res.locals.isPostgres = isPostgres;
|
|
32
|
+
res.locals.isSqlite = isSqlite;
|
|
33
|
+
res.locals.dialectName = isPostgres ? 'PostgreSQL' : 'SQLite';
|
|
34
|
+
res.locals.readonly = dbOrCtx.isReadOnly;
|
|
35
|
+
res.locals.databasesMode = false;
|
|
36
|
+
return { tables: allNames };
|
|
37
|
+
}
|
package/dist/data/chain.js
CHANGED
|
@@ -18,7 +18,7 @@ async function getErChainConfig(db, rootTable, scope = 'chain') {
|
|
|
18
18
|
const tableListRes = await db.listTables();
|
|
19
19
|
const tableNames = (tableListRes.data ?? [])
|
|
20
20
|
.map((t) => t.name)
|
|
21
|
-
.filter((name) => !name.startsWith('sqlite_')
|
|
21
|
+
.filter((name) => !name.startsWith('sqlite_'));
|
|
22
22
|
const tables = [];
|
|
23
23
|
for (const name of tableNames) {
|
|
24
24
|
const info = await db.getTableInfo(name);
|
package/dist/data/engine.js
CHANGED
|
@@ -114,7 +114,7 @@ class SeedEngine {
|
|
|
114
114
|
const tableListRes = await db.listTables();
|
|
115
115
|
const tableNames = (tableListRes.data ?? [])
|
|
116
116
|
.map((t) => t.name)
|
|
117
|
-
.filter((name) => !name.startsWith('sqlite_')
|
|
117
|
+
.filter((name) => !name.startsWith('sqlite_'));
|
|
118
118
|
const tableInfos = new Map();
|
|
119
119
|
const allTableData = [];
|
|
120
120
|
for (const name of tableNames) {
|
package/dist/db/database.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import type {Logger} from '../utils/logger';import{type ColumnDef,type IndexDef} from '../sql/generator';import type {DatabaseDialect,DbOpenOptions,IDatabase,ReferencingTableInfo,Result,RowFilters,
|
|
1
|
+
import type {Logger} from '../utils/logger';import{type ColumnDef,type IndexDef} from '../sql/generator';import type {DatabaseDialect,DbOpenOptions,IDatabase,ReferencingTableInfo,Result,RowFilters,SchemaInfo,SQLInputValue,TableInfoData,TableListItem,WhereClause} from './types';export * from './types';export * from './filters';export declare class SqliteDatabase implements IDatabase{private db;private logger;readonly path:string;readonly isReadOnly:boolean;readonly dialect:DatabaseDialect;constructor(dbPath:string,logger:Logger,options?:DbOpenOptions);private readonlyBlocked;close():void;private tryRun;private transaction;private toBind;all<T=unknown>(sql:string,params?:SQLInputValue[]):Promise<Result<T[]>>;run(sql:string,params?:SQLInputValue[]):Promise<Result<{changes:number;lastInsertRowid:number|null;}>>;execResult(sql:string):Promise<Result<{changes?:number;}>>;hasMultipleStatements(sql:string):boolean;runWrite(sql:string):Promise<Result<{changes?:number;}>>;listTables():Promise<Result<TableListItem[]>>;getTableInfo(table:string):Promise<Result<TableInfoData>>;getRowCount(table:string,filters?:RowFilters):Promise<Result<number>>;getRows(table:string,opts?:{page?:number;limit?:number;orderBy?:string;orderDir?:'asc'|'desc';filters?:RowFilters;}):Promise<Result<Record<string,unknown>[]>>;getAllRows(table:string):Promise<Result<Record<string,unknown>[]>>;getRow(table:string,where:WhereClause[]):Promise<Result<Record<string,unknown>|null>>;insertRow(table:string,fields:WhereClause[]):Promise<Result<{changes:number;lastInsertRowid:number|null;}>>;insertRows(table:string,rows:WhereClause[][]):Promise<Result<{inserted:number;skipped:number;}>>;updateRow(table:string,fields:WhereClause[],where:WhereClause[]):Promise<Result<{changes:number;lastInsertRowid:number|null;}>>;updateRows(table:string,rows:{fields:WhereClause[];where:WhereClause[];}[]):Promise<Result<{updated:number;}>>;deleteRow(table:string,where:WhereClause[]):Promise<Result<{changes:number;lastInsertRowid:number|null;}>>;deleteRows(table:string,rows:WhereClause[][]):Promise<Result<{deleted:number;}>>;getRowsByPks(table:string,pks:WhereClause[][]):Promise<Result<Record<string,unknown>[]>>;getCreateStatement(table:string):Promise<Result<string|null>>;getSettings():Promise<Result<Record<string,string>>>;getSchema(table:string):Promise<Result<SchemaInfo>>;getReferencingTables(table:string):Promise<Result<ReferencingTableInfo[]>>;getRowsByFk(table:string,column:string,value:unknown,limit?:number):Promise<Result<{rows:Record<string,unknown>[];total:number;}>>;renameTable(oldName:string,newName:string):Promise<Result<{changes?:number;}>>;addColumn(table:string,col:ColumnDef):Promise<Result<{changes?:number;}>>;modifyColumn(table:string,oldColName:string,newColDef:ColumnDef):Promise<Result<{changes?:number;}>>;renameColumn(table:string,oldName:string,newName:string):Promise<Result<{changes?:number;}>>;dropColumn(table:string,column:string):Promise<Result<{changes?:number;}>>;dropTable(table:string):Promise<Result<{changes?:number;}>>;createIndex(table:string,index:IndexDef):Promise<Result<{changes?:number;}>>;dropIndex(indexName:string):Promise<Result<{changes?:number;}>>;private getTableInfoSync;}
|
package/dist/db/database.js
CHANGED
|
@@ -21,9 +21,8 @@ exports.SqliteDatabase = void 0;
|
|
|
21
21
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
22
22
|
const generator_1 = require("../sql/generator");
|
|
23
23
|
const common_1 = require("../utils/common");
|
|
24
|
-
const types_1 = require("./types");
|
|
25
24
|
const filters_1 = require("./filters");
|
|
26
|
-
const
|
|
25
|
+
const dialect_1 = require("./dialects/sqlite/dialect");
|
|
27
26
|
const migrations_1 = require("./migrations");
|
|
28
27
|
__exportStar(require("./types"), exports);
|
|
29
28
|
__exportStar(require("./filters"), exports);
|
|
@@ -44,7 +43,6 @@ class SqliteDatabase {
|
|
|
44
43
|
}
|
|
45
44
|
else {
|
|
46
45
|
this.db.exec('PRAGMA journal_mode = WAL;');
|
|
47
|
-
this.initSchema();
|
|
48
46
|
}
|
|
49
47
|
this.logger.info(`Opened SQLite database at ${dbPath}${this.isReadOnly ? ' (read-only)' : ''}`);
|
|
50
48
|
}
|
|
@@ -59,16 +57,6 @@ class SqliteDatabase {
|
|
|
59
57
|
this.logger.warn(`Failed to close database: ${(0, common_1.errorMessage)(err)}`);
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
|
-
initSchema() {
|
|
63
|
-
this.db.exec(`
|
|
64
|
-
CREATE TABLE IF NOT EXISTS ${(0, generator_1.quoteIdentifier)(types_1.INTERNAL_TABLES.savedQueries)} (
|
|
65
|
-
${(0, generator_1.quoteIdentifier)('id')} INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
66
|
-
${(0, generator_1.quoteIdentifier)('name')} TEXT NOT NULL UNIQUE,
|
|
67
|
-
${(0, generator_1.quoteIdentifier)('sql')} TEXT NOT NULL,
|
|
68
|
-
${(0, generator_1.quoteIdentifier)('created_at')} TEXT NOT NULL DEFAULT (datetime('now'))
|
|
69
|
-
);
|
|
70
|
-
`);
|
|
71
|
-
}
|
|
72
60
|
async tryRun(fn) {
|
|
73
61
|
try {
|
|
74
62
|
return { success: true, data: await Promise.resolve(fn()) };
|
|
@@ -162,15 +150,15 @@ class SqliteDatabase {
|
|
|
162
150
|
}
|
|
163
151
|
}
|
|
164
152
|
async listTables() {
|
|
165
|
-
return
|
|
153
|
+
return dialect_1.sqliteDialect.introspector.listTables(this.db);
|
|
166
154
|
}
|
|
167
155
|
async getTableInfo(table) {
|
|
168
|
-
return
|
|
156
|
+
return dialect_1.sqliteDialect.introspector.getTableInfo(this.db, table);
|
|
169
157
|
}
|
|
170
158
|
async getRowCount(table, filters) {
|
|
171
159
|
return this.tryRun(() => {
|
|
172
|
-
const
|
|
173
|
-
const { where, params } = (0, filters_1.buildFilterClause)(filters,
|
|
160
|
+
const cols = this.db.prepare(`PRAGMA table_info(${(0, generator_1.quoteIdentifier)(table)})`).all();
|
|
161
|
+
const { where, params } = (0, filters_1.buildFilterClause)(filters, cols.map((c) => c.name));
|
|
174
162
|
const row = this.db
|
|
175
163
|
.prepare(`SELECT COUNT(*) AS c FROM ${(0, generator_1.quoteIdentifier)(table)}${where}`)
|
|
176
164
|
.get(...params);
|
|
@@ -179,9 +167,8 @@ class SqliteDatabase {
|
|
|
179
167
|
}
|
|
180
168
|
async getRows(table, opts = {}) {
|
|
181
169
|
return this.tryRun(() => {
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
const orderCol = opts.orderBy || info?.primaryKey?.[0] || cols[0]?.name;
|
|
170
|
+
const cols = this.db.prepare(`PRAGMA table_info(${(0, generator_1.quoteIdentifier)(table)})`).all();
|
|
171
|
+
const orderCol = opts.orderBy || cols[0]?.name;
|
|
185
172
|
const orderDir = opts.orderDir === 'desc' ? 'DESC' : 'ASC';
|
|
186
173
|
const limit = opts.limit && opts.limit > 0 ? opts.limit : 200;
|
|
187
174
|
const page = opts.page && opts.page > 0 ? opts.page : 1;
|
|
@@ -288,15 +275,6 @@ class SqliteDatabase {
|
|
|
288
275
|
return row?.sql ?? null;
|
|
289
276
|
});
|
|
290
277
|
}
|
|
291
|
-
async listSavedQueries() {
|
|
292
|
-
return this.all(`SELECT id, name, sql, created_at FROM ${(0, generator_1.quoteIdentifier)(types_1.INTERNAL_TABLES.savedQueries)} ORDER BY name COLLATE NOCASE`);
|
|
293
|
-
}
|
|
294
|
-
async saveQuery(name, sql) {
|
|
295
|
-
return this.run(`INSERT INTO ${(0, generator_1.quoteIdentifier)(types_1.INTERNAL_TABLES.savedQueries)} (name, sql) VALUES (?, ?)`, [name, sql]);
|
|
296
|
-
}
|
|
297
|
-
async deleteSavedQuery(id) {
|
|
298
|
-
return this.run(`DELETE FROM ${(0, generator_1.quoteIdentifier)(types_1.INTERNAL_TABLES.savedQueries)} WHERE id = ?`, [Number(id)]);
|
|
299
|
-
}
|
|
300
278
|
async getSettings() {
|
|
301
279
|
return this.tryRun(() => {
|
|
302
280
|
const pragmas = ['journal_mode', 'synchronous', 'foreign_keys', 'page_size', 'encoding', 'auto_vacuum', 'mmap_size', 'temp_store'];
|
|
@@ -313,10 +291,10 @@ class SqliteDatabase {
|
|
|
313
291
|
});
|
|
314
292
|
}
|
|
315
293
|
async getSchema(table) {
|
|
316
|
-
return
|
|
294
|
+
return dialect_1.sqliteDialect.introspector.getSchema(this.db, table);
|
|
317
295
|
}
|
|
318
296
|
async getReferencingTables(table) {
|
|
319
|
-
return
|
|
297
|
+
return dialect_1.sqliteDialect.introspector.getReferencingTables(this.db, table);
|
|
320
298
|
}
|
|
321
299
|
async getRowsByFk(table, column, value, limit = 50) {
|
|
322
300
|
return this.tryRun(() => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';export * from './sqlite/dialect';export * from './sqlite/types';export * from './sqlite/introspector';export * from './sqlite/ddl';export * from './postgres/dialect';export * from './postgres/types';export * from './postgres/introspector';export * from './postgres/ddl';import type {IDialect} from './types';export interface DialectAdapter<D=unknown>{readonly id:string;readonly name:string;getDialect(schema?:string):IDialect<D>;}export declare class DialectRegistry{private static adapters;static register(adapter:DialectAdapter):void;static get(name:string):DialectAdapter|undefined;static list():string[];}export declare function getDialect(name:'sqlite'|'postgres'|string,schema?:string):IDialect;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DialectRegistry = void 0;
|
|
18
|
+
exports.getDialect = getDialect;
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
__exportStar(require("./sqlite/dialect"), exports);
|
|
21
|
+
__exportStar(require("./sqlite/types"), exports);
|
|
22
|
+
__exportStar(require("./sqlite/introspector"), exports);
|
|
23
|
+
__exportStar(require("./sqlite/ddl"), exports);
|
|
24
|
+
__exportStar(require("./postgres/dialect"), exports);
|
|
25
|
+
__exportStar(require("./postgres/types"), exports);
|
|
26
|
+
__exportStar(require("./postgres/introspector"), exports);
|
|
27
|
+
__exportStar(require("./postgres/ddl"), exports);
|
|
28
|
+
const dialect_1 = require("./sqlite/dialect");
|
|
29
|
+
const dialect_2 = require("./postgres/dialect");
|
|
30
|
+
class DialectRegistry {
|
|
31
|
+
static adapters = new Map();
|
|
32
|
+
static register(adapter) {
|
|
33
|
+
this.adapters.set(adapter.id.toLowerCase(), adapter);
|
|
34
|
+
}
|
|
35
|
+
static get(name) {
|
|
36
|
+
return this.adapters.get(name.toLowerCase());
|
|
37
|
+
}
|
|
38
|
+
static list() {
|
|
39
|
+
return Array.from(this.adapters.keys());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.DialectRegistry = DialectRegistry;
|
|
43
|
+
DialectRegistry.register({
|
|
44
|
+
id: 'sqlite',
|
|
45
|
+
name: 'SQLite',
|
|
46
|
+
getDialect: () => dialect_1.sqliteDialect,
|
|
47
|
+
});
|
|
48
|
+
DialectRegistry.register({
|
|
49
|
+
id: 'postgres',
|
|
50
|
+
name: 'PostgreSQL',
|
|
51
|
+
getDialect: (schema) => (schema && schema !== 'public' ? new dialect_2.PostgresDialect(schema) : dialect_2.postgresDialect),
|
|
52
|
+
});
|
|
53
|
+
function getDialect(name, schema) {
|
|
54
|
+
const adapter = DialectRegistry.get(name);
|
|
55
|
+
if (adapter)
|
|
56
|
+
return adapter.getDialect(schema);
|
|
57
|
+
return dialect_1.sqliteDialect;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{type ColumnDef,type IndexDef} from '../../../sql/generator';import type {IDdlGenerator} from '../types';import type {Result} from '../../types';export declare class PostgresDdlGenerator implements IDdlGenerator{createTable(table:string,columns:ColumnDef[]):string;renameTable(oldName:string,newName:string):string;dropTable(table:string,options?:{cascade?:boolean;ifExists?:boolean;}):string;truncateTable(table:string,options?:{cascade?:boolean;restartIdentity?:boolean;}):string;addColumn(table:string,col:ColumnDef):string;renameColumn(table:string,oldName:string,newName:string):string;dropColumn(table:string,column:string):string;createIndex(table:string,index:IndexDef):string;dropIndex(indexName:string):string;modifyColumn(driver:unknown,table:string,oldCol:string,newCol:ColumnDef):Promise<Result<{changes?:number;}>>;}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresDdlGenerator = void 0;
|
|
4
|
+
const generator_1 = require("../../../sql/generator");
|
|
5
|
+
class PostgresDdlGenerator {
|
|
6
|
+
createTable(table, columns) {
|
|
7
|
+
const colDefs = [];
|
|
8
|
+
const pks = [];
|
|
9
|
+
for (const c of columns) {
|
|
10
|
+
let def = `${(0, generator_1.quoteIdentifier)(c.name)} ${c.type}`;
|
|
11
|
+
if (c.primaryKey)
|
|
12
|
+
pks.push((0, generator_1.quoteIdentifier)(c.name));
|
|
13
|
+
if (c.notNull)
|
|
14
|
+
def += ' NOT NULL';
|
|
15
|
+
if (c.defaultValue !== undefined && c.defaultValue !== null && c.defaultValue !== '') {
|
|
16
|
+
def += ` DEFAULT ${c.defaultValue}`;
|
|
17
|
+
}
|
|
18
|
+
if (c.unique && !c.primaryKey)
|
|
19
|
+
def += ' UNIQUE';
|
|
20
|
+
if (c.foreignKey?.table && c.foreignKey.column) {
|
|
21
|
+
def += ` REFERENCES ${(0, generator_1.quoteIdentifier)(c.foreignKey.table)} (${(0, generator_1.quoteIdentifier)(c.foreignKey.column)})`;
|
|
22
|
+
}
|
|
23
|
+
colDefs.push(` ${def}`);
|
|
24
|
+
}
|
|
25
|
+
if (pks.length) {
|
|
26
|
+
colDefs.push(` PRIMARY KEY (${pks.join(', ')})`);
|
|
27
|
+
}
|
|
28
|
+
return `CREATE TABLE ${(0, generator_1.quoteIdentifier)(table)} (\n${colDefs.join(',\n')}\n);`;
|
|
29
|
+
}
|
|
30
|
+
renameTable(oldName, newName) {
|
|
31
|
+
return `ALTER TABLE ${(0, generator_1.quoteIdentifier)(oldName)} RENAME TO ${(0, generator_1.quoteIdentifier)(newName)};`;
|
|
32
|
+
}
|
|
33
|
+
dropTable(table, options) {
|
|
34
|
+
const ifExists = options?.ifExists ? 'IF EXISTS ' : '';
|
|
35
|
+
const cascade = options?.cascade ? ' CASCADE' : '';
|
|
36
|
+
return `DROP TABLE ${ifExists}${(0, generator_1.quoteIdentifier)(table)}${cascade};`;
|
|
37
|
+
}
|
|
38
|
+
truncateTable(table, options) {
|
|
39
|
+
const restartIdentity = options?.restartIdentity ? ' RESTART IDENTITY' : '';
|
|
40
|
+
const cascade = options?.cascade ? ' CASCADE' : '';
|
|
41
|
+
return `TRUNCATE ${(0, generator_1.quoteIdentifier)(table)}${restartIdentity}${cascade};`;
|
|
42
|
+
}
|
|
43
|
+
addColumn(table, col) {
|
|
44
|
+
let sql = `ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} ADD COLUMN ${(0, generator_1.quoteIdentifier)(col.name)} ${col.type}`;
|
|
45
|
+
if (col.notNull)
|
|
46
|
+
sql += ' NOT NULL';
|
|
47
|
+
if (col.defaultValue !== undefined && col.defaultValue !== null && col.defaultValue !== '') {
|
|
48
|
+
sql += ` DEFAULT ${col.defaultValue}`;
|
|
49
|
+
}
|
|
50
|
+
if (col.foreignKey) {
|
|
51
|
+
sql += ` REFERENCES ${(0, generator_1.quoteIdentifier)(col.foreignKey.table)} (${(0, generator_1.quoteIdentifier)(col.foreignKey.column)})`;
|
|
52
|
+
}
|
|
53
|
+
return sql + ';';
|
|
54
|
+
}
|
|
55
|
+
renameColumn(table, oldName, newName) {
|
|
56
|
+
return `ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} RENAME COLUMN ${(0, generator_1.quoteIdentifier)(oldName)} TO ${(0, generator_1.quoteIdentifier)(newName)};`;
|
|
57
|
+
}
|
|
58
|
+
dropColumn(table, column) {
|
|
59
|
+
return `ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} DROP COLUMN ${(0, generator_1.quoteIdentifier)(column)} CASCADE;`;
|
|
60
|
+
}
|
|
61
|
+
createIndex(table, index) {
|
|
62
|
+
const unique = index.unique ? 'UNIQUE ' : '';
|
|
63
|
+
const cols = index.columns.map(generator_1.quoteIdentifier).join(', ');
|
|
64
|
+
const name = index.name || `idx_${table}_${index.columns.join('_')}`;
|
|
65
|
+
return `CREATE ${unique}INDEX IF NOT EXISTS ${(0, generator_1.quoteIdentifier)(name)} ON ${(0, generator_1.quoteIdentifier)(table)} (${cols});`;
|
|
66
|
+
}
|
|
67
|
+
dropIndex(indexName) {
|
|
68
|
+
return `DROP INDEX IF EXISTS ${(0, generator_1.quoteIdentifier)(indexName)} CASCADE;`;
|
|
69
|
+
}
|
|
70
|
+
async modifyColumn(driver, table, oldCol, newCol) {
|
|
71
|
+
try {
|
|
72
|
+
const pool = (driver && typeof driver === 'object' && 'pool' in driver)
|
|
73
|
+
? driver.pool
|
|
74
|
+
: driver;
|
|
75
|
+
const newName = String(newCol.name || oldCol).trim();
|
|
76
|
+
if (oldCol !== newName) {
|
|
77
|
+
await pool.query(`ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} RENAME COLUMN ${(0, generator_1.quoteIdentifier)(oldCol)} TO ${(0, generator_1.quoteIdentifier)(newName)};`);
|
|
78
|
+
}
|
|
79
|
+
const colToModify = newName;
|
|
80
|
+
if (newCol.type) {
|
|
81
|
+
await pool.query(`ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} ALTER COLUMN ${(0, generator_1.quoteIdentifier)(colToModify)} TYPE ${newCol.type} USING ${(0, generator_1.quoteIdentifier)(colToModify)}::${newCol.type};`);
|
|
82
|
+
}
|
|
83
|
+
if (newCol.notNull !== undefined) {
|
|
84
|
+
const action = newCol.notNull ? 'SET NOT NULL' : 'DROP NOT NULL';
|
|
85
|
+
await pool.query(`ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} ALTER COLUMN ${(0, generator_1.quoteIdentifier)(colToModify)} ${action};`);
|
|
86
|
+
}
|
|
87
|
+
if (newCol.defaultValue !== undefined) {
|
|
88
|
+
const action = newCol.defaultValue === null || newCol.defaultValue === '' ? 'DROP DEFAULT' : `SET DEFAULT ${newCol.defaultValue}`;
|
|
89
|
+
await pool.query(`ALTER TABLE ${(0, generator_1.quoteIdentifier)(table)} ALTER COLUMN ${(0, generator_1.quoteIdentifier)(colToModify)} ${action};`);
|
|
90
|
+
}
|
|
91
|
+
if (newCol.unique !== undefined) {
|
|
92
|
+
const idxName = `idx_${table}_${colToModify}_unique`;
|
|
93
|
+
if (newCol.unique) {
|
|
94
|
+
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS ${(0, generator_1.quoteIdentifier)(idxName)} ON ${(0, generator_1.quoteIdentifier)(table)} (${(0, generator_1.quoteIdentifier)(colToModify)});`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
await pool.query(`DROP INDEX IF EXISTS ${(0, generator_1.quoteIdentifier)(idxName)};`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { success: true, data: { changes: 1 } };
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.PostgresDdlGenerator = PostgresDdlGenerator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import type {DialectCapabilities,IDialect} from '../types';import{PostgresDdlGenerator} from './ddl';import{PostgresIntrospector} from './introspector';export declare class PostgresDialect implements IDialect{readonly name:"postgres";readonly capabilities:DialectCapabilities;readonly introspector:PostgresIntrospector;readonly ddl:PostgresDdlGenerator;constructor(schema?:string);quoteIdentifier(identifier:string):string;mapType(type:string):import("./types").MappedType;getDesignerTypes():readonly string[];}export declare const postgresDialect:PostgresDialect;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.postgresDialect = exports.PostgresDialect = void 0;
|
|
4
|
+
const generator_1 = require("../../../sql/generator");
|
|
5
|
+
const types_1 = require("../types");
|
|
6
|
+
const ddl_1 = require("./ddl");
|
|
7
|
+
const introspector_1 = require("./introspector");
|
|
8
|
+
const types_2 = require("./types");
|
|
9
|
+
class PostgresDialect {
|
|
10
|
+
name = 'postgres';
|
|
11
|
+
capabilities = types_1.POSTGRES_CAPABILITIES;
|
|
12
|
+
introspector;
|
|
13
|
+
ddl = new ddl_1.PostgresDdlGenerator();
|
|
14
|
+
constructor(schema = 'public') {
|
|
15
|
+
this.introspector = new introspector_1.PostgresIntrospector(schema);
|
|
16
|
+
}
|
|
17
|
+
quoteIdentifier(identifier) {
|
|
18
|
+
return (0, generator_1.quoteIdentifier)(identifier);
|
|
19
|
+
}
|
|
20
|
+
mapType(type) {
|
|
21
|
+
return (0, types_2.mapPostgresColumnType)(type);
|
|
22
|
+
}
|
|
23
|
+
getDesignerTypes() {
|
|
24
|
+
return types_2.POSTGRES_DESIGNER_TYPES;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.PostgresDialect = PostgresDialect;
|
|
28
|
+
exports.postgresDialect = new PostgresDialect();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import type {ISchemaIntrospector} from '../types';import type {ReferencingTableInfo,Result,SchemaInfo,TableInfoData,TableListItem} from '../../types';export declare class PostgresIntrospector implements ISchemaIntrospector{private schema;constructor(schema?:string);private getPool;listTables(driver:unknown):Promise<Result<TableListItem[]>>;getColumnCountMap(driver:unknown):Promise<Result<Record<string,number>>>;getTableInfo(driver:unknown,table:string):Promise<Result<TableInfoData>>;getSchema(driver:unknown,table:string):Promise<Result<SchemaInfo>>;getReferencingTables(driver:unknown,table:string):Promise<Result<ReferencingTableInfo[]>>;getCreateStatement(driver:unknown,table:string):Promise<Result<string|null>>;}
|