@pasosdejesus/m 0.16.1 → 0.17.1
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/dist/m.js +43 -0
- package/dist/plugin.d.ts +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -0
- package/dist/tasks/db.d.ts.map +1 -1
- package/dist/tasks/db.js +15 -0
- package/dist/test-utils/kysely-mocks.d.ts +174 -6
- package/dist/test-utils/kysely-mocks.d.ts.map +1 -1
- package/dist/test-utils/kysely-mocks.js +14 -3
- package/dist/util/extensions.d.ts +15 -0
- package/dist/util/extensions.d.ts.map +1 -0
- package/dist/util/extensions.js +59 -0
- package/dist/util/hooks.d.ts +28 -0
- package/dist/util/hooks.d.ts.map +1 -0
- package/dist/util/hooks.js +53 -0
- package/package.json +1 -1
package/dist/m.js
CHANGED
|
@@ -28,6 +28,7 @@ import { cliTranslations } from './i18n/locales/cli.js';
|
|
|
28
28
|
import { problem, success } from './util/colors.js';
|
|
29
29
|
import { parseFlags } from './util/cli-parser.js';
|
|
30
30
|
import { getPluginCommands } from './plugin.js';
|
|
31
|
+
import { loadExtensions } from './util/extensions.js';
|
|
31
32
|
// Custom .env loading
|
|
32
33
|
const CWD = process.cwd();
|
|
33
34
|
const searchPaths = [
|
|
@@ -39,10 +40,52 @@ for (const p of searchPaths) {
|
|
|
39
40
|
if (fs.existsSync(p))
|
|
40
41
|
dotenv.config({ path: p, override: true, quiet: true });
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Auto-discover plugins from package.json.
|
|
45
|
+
* Looks for dependencies matching @pasosdejesus/m-* pattern
|
|
46
|
+
* and imports them (each plugin self-registers via registerCommands).
|
|
47
|
+
*/
|
|
48
|
+
async function loadPlugins() {
|
|
49
|
+
const pkgPaths = [
|
|
50
|
+
path.join(CWD, 'package.json'),
|
|
51
|
+
path.join(CWD, '..', 'package.json'),
|
|
52
|
+
path.join(CWD, '..', '..', 'package.json'),
|
|
53
|
+
];
|
|
54
|
+
let pkg = null;
|
|
55
|
+
for (const p of pkgPaths) {
|
|
56
|
+
if (fs.existsSync(p)) {
|
|
57
|
+
try {
|
|
58
|
+
pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
catch { }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!pkg)
|
|
65
|
+
return;
|
|
66
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
67
|
+
for (const [name] of Object.entries(deps)) {
|
|
68
|
+
// Match @pasosdejesus/m-* plugins (e.g., @pasosdejesus/mpdj)
|
|
69
|
+
if (name.startsWith('@pasosdejesus/m') && name !== '@pasosdejesus/m') {
|
|
70
|
+
try {
|
|
71
|
+
await import(name);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Plugin not installed or not a valid module — skip silently
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Also support packages with mEngine: true metadata
|
|
78
|
+
// This requires resolving the package.json of the dependency
|
|
79
|
+
}
|
|
80
|
+
}
|
|
42
81
|
async function main() {
|
|
43
82
|
const locale = detectLocale();
|
|
44
83
|
setLocale(locale);
|
|
45
84
|
const cliT = createTranslator(locale, cliTranslations, commonCli);
|
|
85
|
+
// Auto-discover plugins from package.json
|
|
86
|
+
await loadPlugins();
|
|
87
|
+
// Load m-extensions/ (project-specific hooks)
|
|
88
|
+
await loadExtensions();
|
|
46
89
|
const commands = {
|
|
47
90
|
'db:create': { handler: runDbCreate, description: cliT('cmd.db_create_description') },
|
|
48
91
|
'db:drop': { handler: runDbDrop, description: cliT('cmd.db_drop_description') },
|
package/dist/plugin.d.ts
CHANGED
|
@@ -7,4 +7,5 @@ export interface CommandDef {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function registerCommands(commands: Record<string, CommandDef>): void;
|
|
9
9
|
export declare function getPluginCommands(): Record<string, CommandDef>;
|
|
10
|
+
export { registerHook, runHooks } from './util/hooks.js';
|
|
10
11
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI,CAE3E;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAE9D"}
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,IAAI,CAE3E;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAE9D;AAGD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/plugin.js
CHANGED
package/dist/tasks/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/tasks/db.ts"],"names":[],"mappings":"AAyNA,wBAAsB,WAAW,kBAUhC;AAED,wBAAsB,SAAS,kBAU9B;AAED,wBAAsB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/tasks/db.ts"],"names":[],"mappings":"AAyNA,wBAAsB,WAAW,kBAUhC;AAED,wBAAsB,SAAS,kBAU9B;AAED,wBAAsB,oBAAoB,kBAyJzC;AAED,wBAAsB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,iBAyDhD;AAED,wBAAsB,mBAAmB,kBAkBxC;AAkBD,wBAAsB,kBAAkB,kBAyCvC;AAED,wBAAsB,kBAAkB,kBAgCvC;AAED,wBAAsB,aAAa,kBAclC;AAED,wBAAsB,YAAY,kBAwCjC;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,iBA4B9C;AAED,wBAAsB,aAAa,kBAuBlC;AAED,wBAAsB,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,iBA6B5C;AAED,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,iBAmD/C;AAED,wBAAsB,SAAS,kBAAoD;AAEnF;;GAEG;AACH,wBAAsB,UAAU,kBAsF/B"}
|
package/dist/tasks/db.js
CHANGED
|
@@ -254,6 +254,10 @@ export async function runDbSuperCreateUser() {
|
|
|
254
254
|
// No modificar la siguiente línea fruto de larga experimentación.
|
|
255
255
|
const alterCmdForOpenBSD = `psql ${psqlSuperArgs} -d postgres -c \\\"ALTER USER ${user} WITH PASSWORD '${pass}';\\\"`.trim();
|
|
256
256
|
const alterCmdForShell = `psql ${psqlConnArgs} -d postgres -c "ALTER USER \"${user}\" WITH PASSWORD '${pass}';"`;
|
|
257
|
+
// Conceder privilegios de superusuario al usuario recién creado.
|
|
258
|
+
// Usa psqlSuperArgs porque otorgar SUPERUSER requiere conexión como superusuario.
|
|
259
|
+
const superuserCmdForOpenBSD = `psql ${psqlSuperArgs} -d postgres -c \\\"ALTER USER ${user} WITH SUPERUSER;\\\"`.trim();
|
|
260
|
+
const superuserCmdForShell = `psql ${psqlSuperArgs} -d postgres -c "ALTER USER \"${user}\" WITH SUPERUSER;"`;
|
|
257
261
|
const pgSuperUser = process.env.PG_SUPERUSER;
|
|
258
262
|
const pgSuperUserPassword = process.env.PG_SUPERUSER_PASSWORD;
|
|
259
263
|
const runPriv = (mode, cmd) => {
|
|
@@ -331,6 +335,17 @@ export async function runDbSuperCreateUser() {
|
|
|
331
335
|
problem(t('db.super.password_failed_mode', mode, lastErr));
|
|
332
336
|
continue;
|
|
333
337
|
}
|
|
338
|
+
else {
|
|
339
|
+
success(t('db.super.password_success', user));
|
|
340
|
+
}
|
|
341
|
+
const superuserCmd = (mode === 'openbsd_su') ? superuserCmdForOpenBSD : superuserCmdForShell;
|
|
342
|
+
res = runPriv(mode, superuserCmd);
|
|
343
|
+
if (res.status !== 0) {
|
|
344
|
+
const stderr = (res.stderr || '').toString();
|
|
345
|
+
lastErr = stderr || `Exit code ${res.status}`;
|
|
346
|
+
problem(t('db.super.password_failed_mode', mode, lastErr));
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
334
349
|
else {
|
|
335
350
|
success(t('db.super.password_success', user));
|
|
336
351
|
opSuccess = true;
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
export declare class MockKysely {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
_executeTakeFirst: (...args: any[]) => any;
|
|
16
|
+
_execute: (...args: any[]) => any;
|
|
17
|
+
_sqlExecute: (query: any) => any;
|
|
18
18
|
constructor(options?: {
|
|
19
19
|
executeTakeFirst?: (...args: any[]) => any;
|
|
20
20
|
execute?: (...args: any[]) => any;
|
|
@@ -89,7 +89,63 @@ export declare function createMockKysely(options?: {
|
|
|
89
89
|
/** Whether to skip mocking the config module (default: false) */
|
|
90
90
|
skipConfigMock?: boolean;
|
|
91
91
|
}): {
|
|
92
|
-
MockKysely:
|
|
92
|
+
MockKysely: {
|
|
93
|
+
new (): {
|
|
94
|
+
_executeTakeFirst: (...args: any[]) => any;
|
|
95
|
+
_execute: (...args: any[]) => any;
|
|
96
|
+
_sqlExecute: (query: any) => any;
|
|
97
|
+
selectFrom(): /*elided*/ any;
|
|
98
|
+
where(): /*elided*/ any;
|
|
99
|
+
selectAll(): /*elided*/ any;
|
|
100
|
+
select(...args: any[]): /*elided*/ any;
|
|
101
|
+
orderBy(): /*elided*/ any;
|
|
102
|
+
limit(): /*elided*/ any;
|
|
103
|
+
groupBy(): /*elided*/ any;
|
|
104
|
+
having(): /*elided*/ any;
|
|
105
|
+
leftJoin(): /*elided*/ any;
|
|
106
|
+
innerJoin(): /*elided*/ any;
|
|
107
|
+
insertInto(): /*elided*/ any;
|
|
108
|
+
values(): /*elided*/ any;
|
|
109
|
+
returningAll(): /*elided*/ any;
|
|
110
|
+
updateTable(): /*elided*/ any;
|
|
111
|
+
set(): /*elided*/ any;
|
|
112
|
+
deleteFrom(): /*elided*/ any;
|
|
113
|
+
with(): /*elided*/ any;
|
|
114
|
+
transaction(): {
|
|
115
|
+
execute: (callback: any) => Promise<any>;
|
|
116
|
+
};
|
|
117
|
+
executeTakeFirst(): any;
|
|
118
|
+
executeTakeFirstOrThrow(): any;
|
|
119
|
+
execute(): any;
|
|
120
|
+
getExecutor(): {
|
|
121
|
+
executeQuery: (query: any) => any;
|
|
122
|
+
provideConnection: (callback: any) => Promise<any>;
|
|
123
|
+
releaseConnection: () => void;
|
|
124
|
+
transformQuery: (query: any, transformer: any) => any;
|
|
125
|
+
compileQuery: (query: any, ctx: any) => {
|
|
126
|
+
sql: string;
|
|
127
|
+
parameters: never[];
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
fn: {
|
|
131
|
+
countAll: import("vitest").Mock<() => {
|
|
132
|
+
as: import("vitest").Mock<() => {}>;
|
|
133
|
+
}>;
|
|
134
|
+
sum: import("vitest").Mock<() => {
|
|
135
|
+
as: import("vitest").Mock<() => {}>;
|
|
136
|
+
}>;
|
|
137
|
+
avg: import("vitest").Mock<() => {
|
|
138
|
+
as: import("vitest").Mock<() => {}>;
|
|
139
|
+
}>;
|
|
140
|
+
max: import("vitest").Mock<() => {
|
|
141
|
+
as: import("vitest").Mock<() => {}>;
|
|
142
|
+
}>;
|
|
143
|
+
min: import("vitest").Mock<() => {
|
|
144
|
+
as: import("vitest").Mock<() => {}>;
|
|
145
|
+
}>;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
};
|
|
93
149
|
mockExecuteTakeFirst: import("vitest").Mock<(...args: any[]) => any>;
|
|
94
150
|
mockExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
95
151
|
mockSqlExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
@@ -117,7 +173,63 @@ export declare function createMockKysely(options?: {
|
|
|
117
173
|
* Pre-configured mock for database operations in API routes
|
|
118
174
|
*/
|
|
119
175
|
export declare const apiDbMocks: {
|
|
120
|
-
MockKysely:
|
|
176
|
+
MockKysely: {
|
|
177
|
+
new (): {
|
|
178
|
+
_executeTakeFirst: (...args: any[]) => any;
|
|
179
|
+
_execute: (...args: any[]) => any;
|
|
180
|
+
_sqlExecute: (query: any) => any;
|
|
181
|
+
selectFrom(): /*elided*/ any;
|
|
182
|
+
where(): /*elided*/ any;
|
|
183
|
+
selectAll(): /*elided*/ any;
|
|
184
|
+
select(...args: any[]): /*elided*/ any;
|
|
185
|
+
orderBy(): /*elided*/ any;
|
|
186
|
+
limit(): /*elided*/ any;
|
|
187
|
+
groupBy(): /*elided*/ any;
|
|
188
|
+
having(): /*elided*/ any;
|
|
189
|
+
leftJoin(): /*elided*/ any;
|
|
190
|
+
innerJoin(): /*elided*/ any;
|
|
191
|
+
insertInto(): /*elided*/ any;
|
|
192
|
+
values(): /*elided*/ any;
|
|
193
|
+
returningAll(): /*elided*/ any;
|
|
194
|
+
updateTable(): /*elided*/ any;
|
|
195
|
+
set(): /*elided*/ any;
|
|
196
|
+
deleteFrom(): /*elided*/ any;
|
|
197
|
+
with(): /*elided*/ any;
|
|
198
|
+
transaction(): {
|
|
199
|
+
execute: (callback: any) => Promise<any>;
|
|
200
|
+
};
|
|
201
|
+
executeTakeFirst(): any;
|
|
202
|
+
executeTakeFirstOrThrow(): any;
|
|
203
|
+
execute(): any;
|
|
204
|
+
getExecutor(): {
|
|
205
|
+
executeQuery: (query: any) => any;
|
|
206
|
+
provideConnection: (callback: any) => Promise<any>;
|
|
207
|
+
releaseConnection: () => void;
|
|
208
|
+
transformQuery: (query: any, transformer: any) => any;
|
|
209
|
+
compileQuery: (query: any, ctx: any) => {
|
|
210
|
+
sql: string;
|
|
211
|
+
parameters: never[];
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
fn: {
|
|
215
|
+
countAll: import("vitest").Mock<() => {
|
|
216
|
+
as: import("vitest").Mock<() => {}>;
|
|
217
|
+
}>;
|
|
218
|
+
sum: import("vitest").Mock<() => {
|
|
219
|
+
as: import("vitest").Mock<() => {}>;
|
|
220
|
+
}>;
|
|
221
|
+
avg: import("vitest").Mock<() => {
|
|
222
|
+
as: import("vitest").Mock<() => {}>;
|
|
223
|
+
}>;
|
|
224
|
+
max: import("vitest").Mock<() => {
|
|
225
|
+
as: import("vitest").Mock<() => {}>;
|
|
226
|
+
}>;
|
|
227
|
+
min: import("vitest").Mock<() => {
|
|
228
|
+
as: import("vitest").Mock<() => {}>;
|
|
229
|
+
}>;
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
};
|
|
121
233
|
mockExecuteTakeFirst: import("vitest").Mock<(...args: any[]) => any>;
|
|
122
234
|
mockExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
123
235
|
mockSqlExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
@@ -145,7 +257,63 @@ export declare const apiDbMocks: {
|
|
|
145
257
|
* Pre-configured mock for database operations in lib functions
|
|
146
258
|
*/
|
|
147
259
|
export declare const libDbMocks: {
|
|
148
|
-
MockKysely:
|
|
260
|
+
MockKysely: {
|
|
261
|
+
new (): {
|
|
262
|
+
_executeTakeFirst: (...args: any[]) => any;
|
|
263
|
+
_execute: (...args: any[]) => any;
|
|
264
|
+
_sqlExecute: (query: any) => any;
|
|
265
|
+
selectFrom(): /*elided*/ any;
|
|
266
|
+
where(): /*elided*/ any;
|
|
267
|
+
selectAll(): /*elided*/ any;
|
|
268
|
+
select(...args: any[]): /*elided*/ any;
|
|
269
|
+
orderBy(): /*elided*/ any;
|
|
270
|
+
limit(): /*elided*/ any;
|
|
271
|
+
groupBy(): /*elided*/ any;
|
|
272
|
+
having(): /*elided*/ any;
|
|
273
|
+
leftJoin(): /*elided*/ any;
|
|
274
|
+
innerJoin(): /*elided*/ any;
|
|
275
|
+
insertInto(): /*elided*/ any;
|
|
276
|
+
values(): /*elided*/ any;
|
|
277
|
+
returningAll(): /*elided*/ any;
|
|
278
|
+
updateTable(): /*elided*/ any;
|
|
279
|
+
set(): /*elided*/ any;
|
|
280
|
+
deleteFrom(): /*elided*/ any;
|
|
281
|
+
with(): /*elided*/ any;
|
|
282
|
+
transaction(): {
|
|
283
|
+
execute: (callback: any) => Promise<any>;
|
|
284
|
+
};
|
|
285
|
+
executeTakeFirst(): any;
|
|
286
|
+
executeTakeFirstOrThrow(): any;
|
|
287
|
+
execute(): any;
|
|
288
|
+
getExecutor(): {
|
|
289
|
+
executeQuery: (query: any) => any;
|
|
290
|
+
provideConnection: (callback: any) => Promise<any>;
|
|
291
|
+
releaseConnection: () => void;
|
|
292
|
+
transformQuery: (query: any, transformer: any) => any;
|
|
293
|
+
compileQuery: (query: any, ctx: any) => {
|
|
294
|
+
sql: string;
|
|
295
|
+
parameters: never[];
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
fn: {
|
|
299
|
+
countAll: import("vitest").Mock<() => {
|
|
300
|
+
as: import("vitest").Mock<() => {}>;
|
|
301
|
+
}>;
|
|
302
|
+
sum: import("vitest").Mock<() => {
|
|
303
|
+
as: import("vitest").Mock<() => {}>;
|
|
304
|
+
}>;
|
|
305
|
+
avg: import("vitest").Mock<() => {
|
|
306
|
+
as: import("vitest").Mock<() => {}>;
|
|
307
|
+
}>;
|
|
308
|
+
max: import("vitest").Mock<() => {
|
|
309
|
+
as: import("vitest").Mock<() => {}>;
|
|
310
|
+
}>;
|
|
311
|
+
min: import("vitest").Mock<() => {
|
|
312
|
+
as: import("vitest").Mock<() => {}>;
|
|
313
|
+
}>;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
};
|
|
149
317
|
mockExecuteTakeFirst: import("vitest").Mock<(...args: any[]) => any>;
|
|
150
318
|
mockExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
151
319
|
mockSqlExecute: import("vitest").Mock<(...args: any[]) => any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-mocks.d.ts","sourceRoot":"","sources":["../../src/test-utils/kysely-mocks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,
|
|
1
|
+
{"version":3,"file":"kysely-mocks.d.ts","sourceRoot":"","sources":["../../src/test-utils/kysely-mocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,6 +91,17 @@ export function createMockKysely(options = {}) {
|
|
|
91
91
|
if (opts.sqlExecute !== undefined) {
|
|
92
92
|
mockSqlExecute.mockImplementation(options.sqlExecute);
|
|
93
93
|
}
|
|
94
|
+
// Wire the MockKysely class to the shared mock functions so that
|
|
95
|
+
// libDbMocks.mockExecute (etc.) reflect actual DB calls made by the code.
|
|
96
|
+
class WiredMockKysely extends MockKysely {
|
|
97
|
+
constructor() {
|
|
98
|
+
super({
|
|
99
|
+
executeTakeFirst: mockExecuteTakeFirst,
|
|
100
|
+
execute: mockExecute,
|
|
101
|
+
sqlExecute: mockSqlExecute,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
94
105
|
const mockSql = vi.fn(() => ({
|
|
95
106
|
as: vi.fn().mockReturnValue({}),
|
|
96
107
|
execute: mockSqlExecute,
|
|
@@ -98,7 +109,7 @@ export function createMockKysely(options = {}) {
|
|
|
98
109
|
}));
|
|
99
110
|
const mockPgPool = vi.fn();
|
|
100
111
|
return {
|
|
101
|
-
MockKysely,
|
|
112
|
+
MockKysely: WiredMockKysely,
|
|
102
113
|
mockExecuteTakeFirst,
|
|
103
114
|
mockExecute,
|
|
104
115
|
mockSqlExecute,
|
|
@@ -110,7 +121,7 @@ export function createMockKysely(options = {}) {
|
|
|
110
121
|
*/
|
|
111
122
|
setupMocks() {
|
|
112
123
|
vi.mock('kysely', () => ({
|
|
113
|
-
Kysely:
|
|
124
|
+
Kysely: WiredMockKysely,
|
|
114
125
|
PostgresDialect: vi.fn(),
|
|
115
126
|
sql: mockSql,
|
|
116
127
|
}));
|
|
@@ -121,7 +132,7 @@ export function createMockKysely(options = {}) {
|
|
|
121
132
|
const skipConfigMock = opts.skipConfigMock || false;
|
|
122
133
|
if (!skipConfigMock) {
|
|
123
134
|
vi.mock('@/.config/kysely.config', () => ({
|
|
124
|
-
newKyselyPostgresql: vi.fn(() => new
|
|
135
|
+
newKyselyPostgresql: vi.fn(() => new WiredMockKysely()),
|
|
125
136
|
}));
|
|
126
137
|
}
|
|
127
138
|
},
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension loader for m — auto-discovers and loads m-extensions/.
|
|
3
|
+
*
|
|
4
|
+
* Searches upward from process.cwd() for a directory named "m-extensions"
|
|
5
|
+
* and imports all .js and .ts files found within.
|
|
6
|
+
*
|
|
7
|
+
* "Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres" (Colosenses 3:23)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Load all extension files from m-extensions/ directory.
|
|
11
|
+
* Each file is dynamically imported; its side effects (registerHook calls)
|
|
12
|
+
* register hooks that will fire at the appropriate extension points.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadExtensions(): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=extensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/util/extensions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwBH;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAoBpD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension loader for m — auto-discovers and loads m-extensions/.
|
|
3
|
+
*
|
|
4
|
+
* Searches upward from process.cwd() for a directory named "m-extensions"
|
|
5
|
+
* and imports all .js and .ts files found within.
|
|
6
|
+
*
|
|
7
|
+
* "Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres" (Colosenses 3:23)
|
|
8
|
+
*/
|
|
9
|
+
import { readdir, access as fsAccess } from 'node:fs/promises';
|
|
10
|
+
import { join, dirname } from 'node:path';
|
|
11
|
+
/**
|
|
12
|
+
* Find the nearest m-extensions/ directory by searching upward from cwd.
|
|
13
|
+
*/
|
|
14
|
+
async function findExtensionsDir() {
|
|
15
|
+
let dir = process.cwd();
|
|
16
|
+
for (let i = 0; i < 10; i++) {
|
|
17
|
+
const extDir = join(dir, 'm-extensions');
|
|
18
|
+
try {
|
|
19
|
+
await fsAccess(extDir);
|
|
20
|
+
return extDir;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
const parent = dirname(dir);
|
|
24
|
+
if (parent === dir)
|
|
25
|
+
break;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Load all extension files from m-extensions/ directory.
|
|
33
|
+
* Each file is dynamically imported; its side effects (registerHook calls)
|
|
34
|
+
* register hooks that will fire at the appropriate extension points.
|
|
35
|
+
*/
|
|
36
|
+
export async function loadExtensions() {
|
|
37
|
+
const extDir = await findExtensionsDir();
|
|
38
|
+
if (!extDir)
|
|
39
|
+
return;
|
|
40
|
+
let files;
|
|
41
|
+
try {
|
|
42
|
+
files = await readdir(extDir);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
for (const file of files) {
|
|
48
|
+
if (!file.endsWith('.js') && !file.endsWith('.ts'))
|
|
49
|
+
continue;
|
|
50
|
+
if (file.endsWith('.d.ts'))
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
await import(join(extDir, file));
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.error(`[m] Failed to load extension ${file}: ${err.message || err}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook system for m extensions.
|
|
3
|
+
*
|
|
4
|
+
* Projects can register hooks to inject logic at specific extension points.
|
|
5
|
+
* Hooks are async callbacks that receive a context object.
|
|
6
|
+
*
|
|
7
|
+
* "Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres" (Colosenses 3:23)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Register a hook callback for a named extension point.
|
|
11
|
+
* Safe to call multiple times — callbacks are appended.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerHook(name: string, callback: (ctx: any) => Promise<void>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Run all registered hooks for a named extension point.
|
|
16
|
+
* Callbacks are executed in series (order of registration).
|
|
17
|
+
* Errors are caught and logged; they do not stop subsequent hooks.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runHooks(name: string, ctx: any): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Clear all registered hooks (for testing).
|
|
22
|
+
*/
|
|
23
|
+
export declare function clearHooks(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get hook names and callback counts (for debugging/testing).
|
|
26
|
+
*/
|
|
27
|
+
export declare function debugHooks(): Record<string, number>;
|
|
28
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/util/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAKtF;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpE;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMnD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook system for m extensions.
|
|
3
|
+
*
|
|
4
|
+
* Projects can register hooks to inject logic at specific extension points.
|
|
5
|
+
* Hooks are async callbacks that receive a context object.
|
|
6
|
+
*
|
|
7
|
+
* "Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres" (Colosenses 3:23)
|
|
8
|
+
*/
|
|
9
|
+
const hooks = new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Register a hook callback for a named extension point.
|
|
12
|
+
* Safe to call multiple times — callbacks are appended.
|
|
13
|
+
*/
|
|
14
|
+
export function registerHook(name, callback) {
|
|
15
|
+
if (!hooks.has(name)) {
|
|
16
|
+
hooks.set(name, []);
|
|
17
|
+
}
|
|
18
|
+
hooks.get(name).push(callback);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run all registered hooks for a named extension point.
|
|
22
|
+
* Callbacks are executed in series (order of registration).
|
|
23
|
+
* Errors are caught and logged; they do not stop subsequent hooks.
|
|
24
|
+
*/
|
|
25
|
+
export async function runHooks(name, ctx) {
|
|
26
|
+
const callbacks = hooks.get(name);
|
|
27
|
+
if (!callbacks || callbacks.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
for (const cb of callbacks) {
|
|
30
|
+
try {
|
|
31
|
+
await cb(ctx);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error(`[m] Hook "${name}" failed: ${err.message || err}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Clear all registered hooks (for testing).
|
|
40
|
+
*/
|
|
41
|
+
export function clearHooks() {
|
|
42
|
+
hooks.clear();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get hook names and callback counts (for debugging/testing).
|
|
46
|
+
*/
|
|
47
|
+
export function debugHooks() {
|
|
48
|
+
const out = {};
|
|
49
|
+
for (const [name, cbs] of hooks) {
|
|
50
|
+
out[name] = cbs.length;
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|