@objectstack/core 0.8.2 → 0.9.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/API_REGISTRY.md +392 -0
- package/CHANGELOG.md +8 -0
- package/README.md +36 -0
- package/dist/api-registry-plugin.d.ts +54 -0
- package/dist/api-registry-plugin.d.ts.map +1 -0
- package/dist/api-registry-plugin.js +53 -0
- package/dist/api-registry-plugin.test.d.ts +2 -0
- package/dist/api-registry-plugin.test.d.ts.map +1 -0
- package/dist/api-registry-plugin.test.js +332 -0
- package/dist/api-registry.d.ts +259 -0
- package/dist/api-registry.d.ts.map +1 -0
- package/dist/api-registry.js +599 -0
- package/dist/api-registry.test.d.ts +2 -0
- package/dist/api-registry.test.d.ts.map +1 -0
- package/dist/api-registry.test.js +957 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +35 -11
- package/dist/plugin-loader.d.ts +3 -2
- package/dist/plugin-loader.d.ts.map +1 -1
- package/dist/plugin-loader.js +13 -11
- package/dist/qa/adapter.d.ts +14 -0
- package/dist/qa/adapter.d.ts.map +1 -0
- package/dist/qa/adapter.js +1 -0
- package/dist/qa/http-adapter.d.ts +16 -0
- package/dist/qa/http-adapter.d.ts.map +1 -0
- package/dist/qa/http-adapter.js +107 -0
- package/dist/qa/index.d.ts +4 -0
- package/dist/qa/index.d.ts.map +1 -0
- package/dist/qa/index.js +3 -0
- package/dist/qa/runner.d.ts +27 -0
- package/dist/qa/runner.d.ts.map +1 -0
- package/dist/qa/runner.js +157 -0
- package/dist/security/index.d.ts +14 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +13 -0
- package/dist/security/plugin-config-validator.d.ts +79 -0
- package/dist/security/plugin-config-validator.d.ts.map +1 -0
- package/dist/security/plugin-config-validator.js +166 -0
- package/dist/security/plugin-config-validator.test.d.ts +2 -0
- package/dist/security/plugin-config-validator.test.d.ts.map +1 -0
- package/dist/security/plugin-config-validator.test.js +223 -0
- package/dist/security/plugin-permission-enforcer.d.ts +154 -0
- package/dist/security/plugin-permission-enforcer.d.ts.map +1 -0
- package/dist/security/plugin-permission-enforcer.js +323 -0
- package/dist/security/plugin-permission-enforcer.test.d.ts +2 -0
- package/dist/security/plugin-permission-enforcer.test.d.ts.map +1 -0
- package/dist/security/plugin-permission-enforcer.test.js +205 -0
- package/dist/security/plugin-signature-verifier.d.ts +96 -0
- package/dist/security/plugin-signature-verifier.d.ts.map +1 -0
- package/dist/security/plugin-signature-verifier.js +250 -0
- package/examples/api-registry-example.ts +557 -0
- package/package.json +2 -2
- package/src/api-registry-plugin.test.ts +391 -0
- package/src/api-registry-plugin.ts +86 -0
- package/src/api-registry.test.ts +1089 -0
- package/src/api-registry.ts +736 -0
- package/src/index.ts +6 -0
- package/src/logger.ts +36 -11
- package/src/plugin-loader.ts +17 -13
- package/src/qa/adapter.ts +14 -0
- package/src/qa/http-adapter.ts +114 -0
- package/src/qa/index.ts +3 -0
- package/src/qa/runner.ts +179 -0
- package/src/security/index.ts +29 -0
- package/src/security/plugin-config-validator.test.ts +276 -0
- package/src/security/plugin-config-validator.ts +191 -0
- package/src/security/plugin-permission-enforcer.test.ts +251 -0
- package/src/security/plugin-permission-enforcer.ts +408 -0
- package/src/security/plugin-signature-verifier.ts +359 -0
package/dist/index.d.ts
CHANGED
|
@@ -10,5 +10,9 @@ export * from './types.js';
|
|
|
10
10
|
export * from './logger.js';
|
|
11
11
|
export * from './plugin-loader.js';
|
|
12
12
|
export * from './enhanced-kernel.js';
|
|
13
|
+
export * from './api-registry.js';
|
|
14
|
+
export * from './api-registry-plugin.js';
|
|
15
|
+
export * as QA from './qa/index.js';
|
|
16
|
+
export * from './security/index.js';
|
|
13
17
|
export type { Logger, IHttpServer, IHttpRequest, IHttpResponse, RouteHandler, Middleware, IDataEngine, DriverInterface } from '@objectstack/spec/contracts';
|
|
14
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAC;AAGpC,cAAc,qBAAqB,CAAC;AAGpC,YAAY,EACR,MAAM,EACN,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EAClB,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,3 +10,8 @@ export * from './types.js';
|
|
|
10
10
|
export * from './logger.js';
|
|
11
11
|
export * from './plugin-loader.js';
|
|
12
12
|
export * from './enhanced-kernel.js';
|
|
13
|
+
export * from './api-registry.js';
|
|
14
|
+
export * from './api-registry-plugin.js';
|
|
15
|
+
export * as QA from './qa/index.js';
|
|
16
|
+
// Export security utilities
|
|
17
|
+
export * from './security/index.js';
|
package/dist/logger.d.ts
CHANGED
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAM;gBAEV,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAuGtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
|
package/dist/logger.js
CHANGED
|
@@ -42,8 +42,12 @@ export class ObjectLogger {
|
|
|
42
42
|
if (!this.isNode)
|
|
43
43
|
return;
|
|
44
44
|
try {
|
|
45
|
-
//
|
|
46
|
-
|
|
45
|
+
// Create require function dynamically for Node.js (avoids bundling issues in browser)
|
|
46
|
+
// @ts-ignore - dynamic import of Node.js module
|
|
47
|
+
const { createRequire } = eval('require("module")');
|
|
48
|
+
this.require = createRequire(import.meta.url);
|
|
49
|
+
// Synchronous import for Pino using createRequire (works in ESM)
|
|
50
|
+
const pino = this.require('pino');
|
|
47
51
|
// Build Pino options
|
|
48
52
|
const pinoOptions = {
|
|
49
53
|
level: this.config.level,
|
|
@@ -60,15 +64,35 @@ export class ObjectLogger {
|
|
|
60
64
|
const targets = [];
|
|
61
65
|
// Console transport
|
|
62
66
|
if (this.config.format === 'pretty') {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
67
|
+
// Check if pino-pretty is available
|
|
68
|
+
let hasPretty = false;
|
|
69
|
+
try {
|
|
70
|
+
this.require.resolve('pino-pretty');
|
|
71
|
+
hasPretty = true;
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
// ignore
|
|
75
|
+
}
|
|
76
|
+
if (hasPretty) {
|
|
77
|
+
targets.push({
|
|
78
|
+
target: 'pino-pretty',
|
|
79
|
+
options: {
|
|
80
|
+
colorize: true,
|
|
81
|
+
translateTime: 'SYS:standard',
|
|
82
|
+
ignore: 'pid,hostname'
|
|
83
|
+
},
|
|
84
|
+
level: this.config.level
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.warn('[Logger] pino-pretty not found. Install it for pretty logging: pnpm add -D pino-pretty');
|
|
89
|
+
// Fallback to text/simple
|
|
90
|
+
targets.push({
|
|
91
|
+
target: 'pino/file',
|
|
92
|
+
options: { destination: 1 },
|
|
93
|
+
level: this.config.level
|
|
94
|
+
});
|
|
95
|
+
}
|
|
72
96
|
}
|
|
73
97
|
else if (this.config.format === 'json') {
|
|
74
98
|
// JSON to stdout
|
package/dist/plugin-loader.d.ts
CHANGED
|
@@ -28,10 +28,11 @@ export interface ServiceRegistration {
|
|
|
28
28
|
dependencies?: string[];
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Plugin Configuration Validator
|
|
31
|
+
* Plugin Configuration Validator Interface
|
|
32
32
|
* Uses Zod for runtime validation of plugin configurations
|
|
33
|
+
* @deprecated Use the PluginConfigValidator class from security module instead
|
|
33
34
|
*/
|
|
34
|
-
export interface
|
|
35
|
+
export interface IPluginConfigValidator {
|
|
35
36
|
schema: z.ZodSchema;
|
|
36
37
|
validate(config: any): any;
|
|
37
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,oBAAY,gBAAgB;IACxB,iDAAiD;IACjD,SAAS,cAAc;IACvB,4CAA4C;IAC5C,SAAS,cAAc;IACvB,sDAAsD;IACtD,MAAM,WAAW;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED
|
|
1
|
+
{"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin-loader.js
CHANGED
|
@@ -230,25 +230,27 @@ export class PluginLoader {
|
|
|
230
230
|
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/;
|
|
231
231
|
return semverRegex.test(version);
|
|
232
232
|
}
|
|
233
|
-
validatePluginConfig(plugin) {
|
|
233
|
+
validatePluginConfig(plugin, config) {
|
|
234
234
|
if (!plugin.configSchema) {
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
if (!config) {
|
|
238
|
+
this.logger.debug(`Plugin ${plugin.name} has configuration schema but no config provided`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Configuration validation is now implemented in PluginConfigValidator
|
|
242
|
+
// This is a placeholder that logs the validation would happen
|
|
243
|
+
// The actual validation should be done by the caller when config is available
|
|
244
|
+
this.logger.debug(`Plugin ${plugin.name} has configuration schema (use PluginConfigValidator for validation)`);
|
|
241
245
|
}
|
|
242
246
|
async verifyPluginSignature(plugin) {
|
|
243
247
|
if (!plugin.signature) {
|
|
244
248
|
return;
|
|
245
249
|
}
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
// 3. Throw error if verification fails
|
|
251
|
-
this.logger.debug(`Plugin ${plugin.name} signature verification (not yet implemented)`);
|
|
250
|
+
// Plugin signature verification is now implemented in PluginSignatureVerifier
|
|
251
|
+
// This is a placeholder that logs the verification would happen
|
|
252
|
+
// The actual verification should be done by the caller with proper security config
|
|
253
|
+
this.logger.debug(`Plugin ${plugin.name} has signature (use PluginSignatureVerifier for verification)`);
|
|
252
254
|
}
|
|
253
255
|
async getSingletonService(registration) {
|
|
254
256
|
let instance = this.serviceInstances.get(registration.name);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QA } from '@objectstack/spec';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for executing test actions against a target system.
|
|
4
|
+
* The target could be a local Kernel instance or a remote API.
|
|
5
|
+
*/
|
|
6
|
+
export interface TestExecutionAdapter {
|
|
7
|
+
/**
|
|
8
|
+
* Execute a single test action.
|
|
9
|
+
* @param action The action to perform (create_record, api_call, etc.)
|
|
10
|
+
* @returns The result of the action (e.g. created record, API response)
|
|
11
|
+
*/
|
|
12
|
+
execute(action: QA.TestAction, context: Record<string, unknown>): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/qa/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QA } from '@objectstack/spec';
|
|
2
|
+
import { TestExecutionAdapter } from './adapter.js';
|
|
3
|
+
export declare class HttpTestAdapter implements TestExecutionAdapter {
|
|
4
|
+
private baseUrl;
|
|
5
|
+
private authToken?;
|
|
6
|
+
constructor(baseUrl: string, authToken?: string | undefined);
|
|
7
|
+
execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown>;
|
|
8
|
+
private createRecord;
|
|
9
|
+
private updateRecord;
|
|
10
|
+
private deleteRecord;
|
|
11
|
+
private readRecord;
|
|
12
|
+
private queryRecords;
|
|
13
|
+
private rawApiCall;
|
|
14
|
+
private handleResponse;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=http-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-adapter.d.ts","sourceRoot":"","sources":["../../src/qa/http-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,qBAAa,eAAgB,YAAW,oBAAoB;IAC9C,OAAO,CAAC,OAAO;IAAU,OAAO,CAAC,SAAS,CAAC;gBAAnC,OAAO,EAAE,MAAM,EAAU,SAAS,CAAC,EAAE,MAAM,YAAA;IAEzD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;YAiC3E,YAAY;YASZ,YAAY;YAWZ,YAAY;YAUZ,UAAU;YAUV,YAAY;YAUZ,UAAU;YAaV,cAAc;CAW7B"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export class HttpTestAdapter {
|
|
2
|
+
constructor(baseUrl, authToken) {
|
|
3
|
+
this.baseUrl = baseUrl;
|
|
4
|
+
this.authToken = authToken;
|
|
5
|
+
}
|
|
6
|
+
async execute(action, _context) {
|
|
7
|
+
const headers = {
|
|
8
|
+
'Content-Type': 'application/json',
|
|
9
|
+
};
|
|
10
|
+
if (this.authToken) {
|
|
11
|
+
headers['Authorization'] = `Bearer ${this.authToken}`;
|
|
12
|
+
}
|
|
13
|
+
// If action.user is specified, maybe add a specific header for impersonation if supported?
|
|
14
|
+
if (action.user) {
|
|
15
|
+
headers['X-Run-As'] = action.user;
|
|
16
|
+
}
|
|
17
|
+
switch (action.type) {
|
|
18
|
+
case 'create_record':
|
|
19
|
+
return this.createRecord(action.target, action.payload || {}, headers);
|
|
20
|
+
case 'update_record':
|
|
21
|
+
return this.updateRecord(action.target, action.payload || {}, headers);
|
|
22
|
+
case 'delete_record':
|
|
23
|
+
return this.deleteRecord(action.target, action.payload || {}, headers);
|
|
24
|
+
case 'read_record':
|
|
25
|
+
return this.readRecord(action.target, action.payload || {}, headers);
|
|
26
|
+
case 'query_records':
|
|
27
|
+
return this.queryRecords(action.target, action.payload || {}, headers);
|
|
28
|
+
case 'api_call':
|
|
29
|
+
return this.rawApiCall(action.target, action.payload || {}, headers);
|
|
30
|
+
case 'wait':
|
|
31
|
+
const ms = Number(action.payload?.duration || 1000);
|
|
32
|
+
return new Promise(resolve => setTimeout(() => resolve({ waited: ms }), ms));
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Unsupported action type in HttpAdapter: ${action.type}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async createRecord(objectName, data, headers) {
|
|
38
|
+
const response = await fetch(`${this.baseUrl}/api/data/${objectName}`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers,
|
|
41
|
+
body: JSON.stringify(data)
|
|
42
|
+
});
|
|
43
|
+
return this.handleResponse(response);
|
|
44
|
+
}
|
|
45
|
+
async updateRecord(objectName, data, headers) {
|
|
46
|
+
const id = data._id || data.id;
|
|
47
|
+
if (!id)
|
|
48
|
+
throw new Error('Update record requires _id or id in payload');
|
|
49
|
+
const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
|
|
50
|
+
method: 'PUT',
|
|
51
|
+
headers,
|
|
52
|
+
body: JSON.stringify(data)
|
|
53
|
+
});
|
|
54
|
+
return this.handleResponse(response);
|
|
55
|
+
}
|
|
56
|
+
async deleteRecord(objectName, data, headers) {
|
|
57
|
+
const id = data._id || data.id;
|
|
58
|
+
if (!id)
|
|
59
|
+
throw new Error('Delete record requires _id or id in payload');
|
|
60
|
+
const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
|
|
61
|
+
method: 'DELETE',
|
|
62
|
+
headers
|
|
63
|
+
});
|
|
64
|
+
return this.handleResponse(response);
|
|
65
|
+
}
|
|
66
|
+
async readRecord(objectName, data, headers) {
|
|
67
|
+
const id = data._id || data.id;
|
|
68
|
+
if (!id)
|
|
69
|
+
throw new Error('Read record requires _id or id in payload');
|
|
70
|
+
const response = await fetch(`${this.baseUrl}/api/data/${objectName}/${id}`, {
|
|
71
|
+
method: 'GET',
|
|
72
|
+
headers
|
|
73
|
+
});
|
|
74
|
+
return this.handleResponse(response);
|
|
75
|
+
}
|
|
76
|
+
async queryRecords(objectName, data, headers) {
|
|
77
|
+
// Assuming query via POST or GraphQL-like endpoint
|
|
78
|
+
const response = await fetch(`${this.baseUrl}/api/data/${objectName}/query`, {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers,
|
|
81
|
+
body: JSON.stringify(data)
|
|
82
|
+
});
|
|
83
|
+
return this.handleResponse(response);
|
|
84
|
+
}
|
|
85
|
+
async rawApiCall(endpoint, data, headers) {
|
|
86
|
+
const method = data.method || 'GET';
|
|
87
|
+
const body = data.body ? JSON.stringify(data.body) : undefined;
|
|
88
|
+
const url = endpoint.startsWith('http') ? endpoint : `${this.baseUrl}${endpoint}`;
|
|
89
|
+
const response = await fetch(url, {
|
|
90
|
+
method,
|
|
91
|
+
headers,
|
|
92
|
+
body
|
|
93
|
+
});
|
|
94
|
+
return this.handleResponse(response);
|
|
95
|
+
}
|
|
96
|
+
async handleResponse(response) {
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
const text = await response.text();
|
|
99
|
+
throw new Error(`HTTP Error ${response.status}: ${text}`);
|
|
100
|
+
}
|
|
101
|
+
const contentType = response.headers.get('content-type');
|
|
102
|
+
if (contentType && contentType.includes('application/json')) {
|
|
103
|
+
return response.json();
|
|
104
|
+
}
|
|
105
|
+
return response.text();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC"}
|
package/dist/qa/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { QA } from '@objectstack/spec';
|
|
2
|
+
import { TestExecutionAdapter } from './adapter.js';
|
|
3
|
+
export interface TestResult {
|
|
4
|
+
scenarioId: string;
|
|
5
|
+
passed: boolean;
|
|
6
|
+
steps: StepResult[];
|
|
7
|
+
error?: unknown;
|
|
8
|
+
duration: number;
|
|
9
|
+
}
|
|
10
|
+
export interface StepResult {
|
|
11
|
+
stepName: string;
|
|
12
|
+
passed: boolean;
|
|
13
|
+
error?: unknown;
|
|
14
|
+
output?: unknown;
|
|
15
|
+
duration: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class TestRunner {
|
|
18
|
+
private adapter;
|
|
19
|
+
constructor(adapter: TestExecutionAdapter);
|
|
20
|
+
runSuite(suite: QA.TestSuite): Promise<TestResult[]>;
|
|
21
|
+
runScenario(scenario: QA.TestScenario): Promise<TestResult>;
|
|
22
|
+
private runStep;
|
|
23
|
+
private resolveVariables;
|
|
24
|
+
private getValueByPath;
|
|
25
|
+
private assert;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/qa/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,oBAAoB;IAE3C,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQpD,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;YA4EnD,OAAO;IAyBrB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,MAAM;CA8Bf"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export class TestRunner {
|
|
2
|
+
constructor(adapter) {
|
|
3
|
+
this.adapter = adapter;
|
|
4
|
+
}
|
|
5
|
+
async runSuite(suite) {
|
|
6
|
+
const results = [];
|
|
7
|
+
for (const scenario of suite.scenarios) {
|
|
8
|
+
results.push(await this.runScenario(scenario));
|
|
9
|
+
}
|
|
10
|
+
return results;
|
|
11
|
+
}
|
|
12
|
+
async runScenario(scenario) {
|
|
13
|
+
const startTime = Date.now();
|
|
14
|
+
const context = {}; // Variable context
|
|
15
|
+
// Initialize context from initial payload if needed? Currently schema doesn't have initial context prop on Scenario
|
|
16
|
+
// But we defined TestContextSchema separately.
|
|
17
|
+
// Setup
|
|
18
|
+
if (scenario.setup) {
|
|
19
|
+
for (const step of scenario.setup) {
|
|
20
|
+
try {
|
|
21
|
+
await this.runStep(step, context);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
return {
|
|
25
|
+
scenarioId: scenario.id,
|
|
26
|
+
passed: false,
|
|
27
|
+
steps: [],
|
|
28
|
+
error: `Setup failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
29
|
+
duration: Date.now() - startTime
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const stepResults = [];
|
|
35
|
+
let scenarioPassed = true;
|
|
36
|
+
let scenarioError = undefined;
|
|
37
|
+
// Main Steps
|
|
38
|
+
for (const step of scenario.steps) {
|
|
39
|
+
const stepStartTime = Date.now();
|
|
40
|
+
try {
|
|
41
|
+
const output = await this.runStep(step, context);
|
|
42
|
+
stepResults.push({
|
|
43
|
+
stepName: step.name,
|
|
44
|
+
passed: true,
|
|
45
|
+
output,
|
|
46
|
+
duration: Date.now() - stepStartTime
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
scenarioPassed = false;
|
|
51
|
+
scenarioError = e;
|
|
52
|
+
stepResults.push({
|
|
53
|
+
stepName: step.name,
|
|
54
|
+
passed: false,
|
|
55
|
+
error: e,
|
|
56
|
+
duration: Date.now() - stepStartTime
|
|
57
|
+
});
|
|
58
|
+
break; // Stop on first failure
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Teardown (run even if failed)
|
|
62
|
+
if (scenario.teardown) {
|
|
63
|
+
for (const step of scenario.teardown) {
|
|
64
|
+
try {
|
|
65
|
+
await this.runStep(step, context);
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
// Log teardown failure but don't override main failure if it exists
|
|
69
|
+
if (scenarioPassed) {
|
|
70
|
+
scenarioPassed = false;
|
|
71
|
+
scenarioError = `Teardown failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
scenarioId: scenario.id,
|
|
78
|
+
passed: scenarioPassed,
|
|
79
|
+
steps: stepResults,
|
|
80
|
+
error: scenarioError,
|
|
81
|
+
duration: Date.now() - startTime
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async runStep(step, context) {
|
|
85
|
+
// 1. Resolve Variables with Context (Simple interpolation or just pass context?)
|
|
86
|
+
// For now, assume adpater handles context resolution or we do basic replacement
|
|
87
|
+
const resolvedAction = this.resolveVariables(step.action, context);
|
|
88
|
+
// 2. Execute Action
|
|
89
|
+
const result = await this.adapter.execute(resolvedAction, context);
|
|
90
|
+
// 3. Capture Outputs
|
|
91
|
+
if (step.capture) {
|
|
92
|
+
for (const [varName, path] of Object.entries(step.capture)) {
|
|
93
|
+
context[varName] = this.getValueByPath(result, path);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 4. Run Assertions
|
|
97
|
+
if (step.assertions) {
|
|
98
|
+
for (const assertion of step.assertions) {
|
|
99
|
+
this.assert(result, assertion, context);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
resolveVariables(action, _context) {
|
|
105
|
+
// TODO: Implement JSON path variable substitution stringify/parse
|
|
106
|
+
// For now returning as is
|
|
107
|
+
return action;
|
|
108
|
+
}
|
|
109
|
+
getValueByPath(obj, path) {
|
|
110
|
+
if (!path)
|
|
111
|
+
return obj;
|
|
112
|
+
const parts = path.split('.');
|
|
113
|
+
let current = obj;
|
|
114
|
+
for (const part of parts) {
|
|
115
|
+
if (current === null || current === undefined)
|
|
116
|
+
return undefined;
|
|
117
|
+
current = current[part];
|
|
118
|
+
}
|
|
119
|
+
return current;
|
|
120
|
+
}
|
|
121
|
+
assert(result, assertion, _context) {
|
|
122
|
+
const actual = this.getValueByPath(result, assertion.field);
|
|
123
|
+
// Resolve expected value if it's a variable ref?
|
|
124
|
+
const expected = assertion.expectedValue; // Simplify for now
|
|
125
|
+
switch (assertion.operator) {
|
|
126
|
+
case 'equals':
|
|
127
|
+
if (actual !== expected)
|
|
128
|
+
throw new Error(`Assertion failed: ${assertion.field} expected ${expected}, got ${actual}`);
|
|
129
|
+
break;
|
|
130
|
+
case 'not_equals':
|
|
131
|
+
if (actual === expected)
|
|
132
|
+
throw new Error(`Assertion failed: ${assertion.field} expected not ${expected}, got ${actual}`);
|
|
133
|
+
break;
|
|
134
|
+
case 'contains':
|
|
135
|
+
if (Array.isArray(actual)) {
|
|
136
|
+
if (!actual.includes(expected))
|
|
137
|
+
throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);
|
|
138
|
+
}
|
|
139
|
+
else if (typeof actual === 'string') {
|
|
140
|
+
if (!actual.includes(String(expected)))
|
|
141
|
+
throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
case 'not_null':
|
|
145
|
+
if (actual === null || actual === undefined)
|
|
146
|
+
throw new Error(`Assertion failed: ${assertion.field} is null`);
|
|
147
|
+
break;
|
|
148
|
+
case 'is_null':
|
|
149
|
+
if (actual !== null && actual !== undefined)
|
|
150
|
+
throw new Error(`Assertion failed: ${assertion.field} is not null`);
|
|
151
|
+
break;
|
|
152
|
+
// ... Add other operators
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`Unknown assertion operator: ${assertion.operator}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Module
|
|
3
|
+
*
|
|
4
|
+
* Provides security features for the ObjectStack microkernel:
|
|
5
|
+
* - Plugin signature verification
|
|
6
|
+
* - Plugin configuration validation
|
|
7
|
+
* - Permission and capability enforcement
|
|
8
|
+
*
|
|
9
|
+
* @module @objectstack/core/security
|
|
10
|
+
*/
|
|
11
|
+
export { PluginSignatureVerifier, type PluginSignatureConfig, type SignatureVerificationResult, } from './plugin-signature-verifier.js';
|
|
12
|
+
export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
|
|
13
|
+
export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, type PluginPermissions, type PermissionCheckResult, } from './plugin-permission-enforcer.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,8BAA8B,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Module
|
|
3
|
+
*
|
|
4
|
+
* Provides security features for the ObjectStack microkernel:
|
|
5
|
+
* - Plugin signature verification
|
|
6
|
+
* - Plugin configuration validation
|
|
7
|
+
* - Permission and capability enforcement
|
|
8
|
+
*
|
|
9
|
+
* @module @objectstack/core/security
|
|
10
|
+
*/
|
|
11
|
+
export { PluginSignatureVerifier, } from './plugin-signature-verifier.js';
|
|
12
|
+
export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
|
|
13
|
+
export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, } from './plugin-permission-enforcer.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Logger } from '@objectstack/spec/contracts';
|
|
2
|
+
import type { PluginMetadata } from '../plugin-loader.js';
|
|
3
|
+
/**
|
|
4
|
+
* Plugin Configuration Validator
|
|
5
|
+
*
|
|
6
|
+
* Validates plugin configurations against Zod schemas to ensure:
|
|
7
|
+
* 1. Type safety - all config values have correct types
|
|
8
|
+
* 2. Business rules - values meet constraints (min/max, regex, etc.)
|
|
9
|
+
* 3. Required fields - all mandatory configuration is provided
|
|
10
|
+
* 4. Default values - missing optional fields get defaults
|
|
11
|
+
*
|
|
12
|
+
* Architecture:
|
|
13
|
+
* - Uses Zod for runtime validation
|
|
14
|
+
* - Provides detailed error messages with field paths
|
|
15
|
+
* - Supports nested configuration objects
|
|
16
|
+
* - Allows partial validation for incremental updates
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const validator = new PluginConfigValidator(logger);
|
|
21
|
+
* const validConfig = validator.validatePluginConfig(plugin, userConfig);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class PluginConfigValidator {
|
|
25
|
+
private logger;
|
|
26
|
+
constructor(logger: Logger);
|
|
27
|
+
/**
|
|
28
|
+
* Validate plugin configuration against its Zod schema
|
|
29
|
+
*
|
|
30
|
+
* @param plugin - Plugin metadata with configSchema
|
|
31
|
+
* @param config - User-provided configuration
|
|
32
|
+
* @returns Validated and typed configuration
|
|
33
|
+
* @throws Error with detailed validation errors
|
|
34
|
+
*/
|
|
35
|
+
validatePluginConfig<T = any>(plugin: PluginMetadata, config: any): T;
|
|
36
|
+
/**
|
|
37
|
+
* Validate partial configuration (for incremental updates)
|
|
38
|
+
*
|
|
39
|
+
* @param plugin - Plugin metadata
|
|
40
|
+
* @param partialConfig - Partial configuration to validate
|
|
41
|
+
* @returns Validated partial configuration
|
|
42
|
+
*/
|
|
43
|
+
validatePartialConfig<T = any>(plugin: PluginMetadata, partialConfig: any): Partial<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Get default configuration from schema
|
|
46
|
+
*
|
|
47
|
+
* @param plugin - Plugin metadata
|
|
48
|
+
* @returns Default configuration object
|
|
49
|
+
*/
|
|
50
|
+
getDefaultConfig<T = any>(plugin: PluginMetadata): T | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Check if configuration is valid without throwing
|
|
53
|
+
*
|
|
54
|
+
* @param plugin - Plugin metadata
|
|
55
|
+
* @param config - Configuration to check
|
|
56
|
+
* @returns True if valid, false otherwise
|
|
57
|
+
*/
|
|
58
|
+
isConfigValid(plugin: PluginMetadata, config: any): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Get configuration errors without throwing
|
|
61
|
+
*
|
|
62
|
+
* @param plugin - Plugin metadata
|
|
63
|
+
* @param config - Configuration to check
|
|
64
|
+
* @returns Array of validation errors, or empty array if valid
|
|
65
|
+
*/
|
|
66
|
+
getConfigErrors(plugin: PluginMetadata, config: any): Array<{
|
|
67
|
+
path: string;
|
|
68
|
+
message: string;
|
|
69
|
+
}>;
|
|
70
|
+
private formatZodErrors;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a plugin config validator
|
|
74
|
+
*
|
|
75
|
+
* @param logger - Logger instance
|
|
76
|
+
* @returns Plugin config validator
|
|
77
|
+
*/
|
|
78
|
+
export declare function createPluginConfigValidator(logger: Logger): PluginConfigValidator;
|
|
79
|
+
//# sourceMappingURL=plugin-config-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-config-validator.d.ts","sourceRoot":"","sources":["../../src/security/plugin-config-validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B;;;;;;;OAOG;IACH,oBAAoB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAqCrE;;;;;;OAMG;IACH,qBAAqB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IA4BtF;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,GAAG,CAAC,GAAG,SAAS;IAiBhE;;;;;;OAMG;IACH,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO;IAS3D;;;;;;OAMG;IACH,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAgB5F,OAAO,CAAC,eAAe;CAMxB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAEjF"}
|