@trayio/commons 5.13.0-unstable → 5.14.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/dist/schema/JsonSchemaIntrospector.d.ts +5 -40
- package/dist/schema/JsonSchemaIntrospector.d.ts.map +1 -1
- package/dist/schema/JsonSchemaIntrospector.js +34 -100
- package/dist/schema/JsonSchemaIntrospector.unit.test.js +37 -72
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -1,53 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility for converting runtime JavaScript objects to JSON Schema
|
|
3
3
|
* Used for dynamic output schema generation in CDK connectors
|
|
4
|
+
*
|
|
5
|
+
* This implementation uses the generate-schema library to convert raw JSON
|
|
6
|
+
* responses into valid JSON Schema representations, matching the behavior
|
|
7
|
+
* of the legacy connector framework.
|
|
4
8
|
*/
|
|
5
9
|
export declare class JsonSchemaIntrospector {
|
|
6
10
|
/**
|
|
7
11
|
* Introspects a JavaScript object and generates a JSON Schema representation
|
|
8
12
|
*
|
|
9
13
|
* @param obj - The object to introspect
|
|
10
|
-
* @param options - Configuration options for introspection
|
|
11
14
|
* @returns A JSON Schema object describing the structure
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* const data = { id: 1, name: "John", active: true };
|
|
16
|
-
* const schema = JsonSchemaIntrospector.introspectToJsonSchema(data);
|
|
17
|
-
* // Returns:
|
|
18
|
-
* // {
|
|
19
|
-
* // type: 'object',
|
|
20
|
-
* // properties: {
|
|
21
|
-
* // id: { type: 'number' },
|
|
22
|
-
* // name: { type: 'string' },
|
|
23
|
-
* // active: { type: 'boolean' }
|
|
24
|
-
* // },
|
|
25
|
-
* // required: ['id', 'name', 'active']
|
|
26
|
-
* // }
|
|
27
|
-
* ```
|
|
28
15
|
*/
|
|
29
|
-
static introspectToJsonSchema(obj: any
|
|
30
|
-
private static introspectRecursive;
|
|
16
|
+
static introspectToJsonSchema(obj: any): any;
|
|
31
17
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Configuration options for JSON Schema introspection
|
|
34
|
-
*/
|
|
35
|
-
export type IntrospectionOptions = {
|
|
36
|
-
/**
|
|
37
|
-
* Maximum depth for recursive introspection
|
|
38
|
-
* @default 10
|
|
39
|
-
*/
|
|
40
|
-
maxDepth?: number;
|
|
41
|
-
/**
|
|
42
|
-
* Whether to include example values in the schema
|
|
43
|
-
* @default false
|
|
44
|
-
*/
|
|
45
|
-
includeExamples?: boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Whether to mark all present fields as required
|
|
48
|
-
* If false, only marks non-null/non-undefined fields as required
|
|
49
|
-
* @default true
|
|
50
|
-
*/
|
|
51
|
-
strictRequired?: boolean;
|
|
52
|
-
};
|
|
53
18
|
//# sourceMappingURL=JsonSchemaIntrospector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonSchemaIntrospector.d.ts","sourceRoot":"","sources":["../../src/schema/JsonSchemaIntrospector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"JsonSchemaIntrospector.d.ts","sourceRoot":"","sources":["../../src/schema/JsonSchemaIntrospector.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,qBAAa,sBAAsB;IAClC;;;;;OAKG;IACH,MAAM,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;CAS5C"}
|
|
@@ -1,118 +1,52 @@
|
|
|
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.JsonSchemaIntrospector = void 0;
|
|
27
|
+
const generateSchema = __importStar(require("generate-schema"));
|
|
4
28
|
/**
|
|
5
29
|
* Utility for converting runtime JavaScript objects to JSON Schema
|
|
6
30
|
* Used for dynamic output schema generation in CDK connectors
|
|
31
|
+
*
|
|
32
|
+
* This implementation uses the generate-schema library to convert raw JSON
|
|
33
|
+
* responses into valid JSON Schema representations, matching the behavior
|
|
34
|
+
* of the legacy connector framework.
|
|
7
35
|
*/
|
|
8
36
|
class JsonSchemaIntrospector {
|
|
9
37
|
/**
|
|
10
38
|
* Introspects a JavaScript object and generates a JSON Schema representation
|
|
11
39
|
*
|
|
12
40
|
* @param obj - The object to introspect
|
|
13
|
-
* @param options - Configuration options for introspection
|
|
14
41
|
* @returns A JSON Schema object describing the structure
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* const data = { id: 1, name: "John", active: true };
|
|
19
|
-
* const schema = JsonSchemaIntrospector.introspectToJsonSchema(data);
|
|
20
|
-
* // Returns:
|
|
21
|
-
* // {
|
|
22
|
-
* // type: 'object',
|
|
23
|
-
* // properties: {
|
|
24
|
-
* // id: { type: 'number' },
|
|
25
|
-
* // name: { type: 'string' },
|
|
26
|
-
* // active: { type: 'boolean' }
|
|
27
|
-
* // },
|
|
28
|
-
* // required: ['id', 'name', 'active']
|
|
29
|
-
* // }
|
|
30
|
-
* ```
|
|
31
42
|
*/
|
|
32
|
-
static introspectToJsonSchema(obj
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
return this.introspectRecursive(obj, 0, opts);
|
|
39
|
-
}
|
|
40
|
-
static introspectRecursive(obj, depth, options) {
|
|
41
|
-
// Prevent infinite recursion
|
|
42
|
-
if (depth >= options.maxDepth) {
|
|
43
|
-
return { type: 'object', additionalProperties: true };
|
|
44
|
-
}
|
|
45
|
-
// Handle null
|
|
46
|
-
if (obj === null) {
|
|
47
|
-
return { type: 'null' };
|
|
48
|
-
}
|
|
49
|
-
// Handle arrays
|
|
50
|
-
if (Array.isArray(obj)) {
|
|
51
|
-
if (obj.length === 0) {
|
|
52
|
-
return { type: 'array', items: {} };
|
|
53
|
-
}
|
|
54
|
-
// Generate schema from first item
|
|
55
|
-
const itemSchema = this.introspectRecursive(obj[0], depth + 1, options);
|
|
56
|
-
const schema = {
|
|
57
|
-
type: 'array',
|
|
58
|
-
items: itemSchema,
|
|
59
|
-
};
|
|
60
|
-
if (options.includeExamples) {
|
|
61
|
-
schema.examples = [obj];
|
|
62
|
-
}
|
|
63
|
-
return schema;
|
|
64
|
-
}
|
|
65
|
-
const type = typeof obj;
|
|
66
|
-
// Handle primitives
|
|
67
|
-
if (type === 'string') {
|
|
68
|
-
const schema = { type: 'string' };
|
|
69
|
-
if (options.includeExamples) {
|
|
70
|
-
schema.examples = [obj];
|
|
71
|
-
}
|
|
72
|
-
return schema;
|
|
73
|
-
}
|
|
74
|
-
if (type === 'number') {
|
|
75
|
-
const schema = { type: 'number' };
|
|
76
|
-
if (options.includeExamples) {
|
|
77
|
-
schema.examples = [obj];
|
|
78
|
-
}
|
|
79
|
-
return schema;
|
|
80
|
-
}
|
|
81
|
-
if (type === 'boolean') {
|
|
82
|
-
const schema = { type: 'boolean' };
|
|
83
|
-
if (options.includeExamples) {
|
|
84
|
-
schema.examples = [obj];
|
|
85
|
-
}
|
|
86
|
-
return schema;
|
|
87
|
-
}
|
|
88
|
-
// Handle objects
|
|
89
|
-
if (type === 'object') {
|
|
90
|
-
const properties = {};
|
|
91
|
-
const required = [];
|
|
92
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
93
|
-
properties[key] = this.introspectRecursive(value, depth + 1, options);
|
|
94
|
-
// Add to required array based on options
|
|
95
|
-
if (options.strictRequired) {
|
|
96
|
-
required.push(key);
|
|
97
|
-
}
|
|
98
|
-
else if (value !== null && value !== undefined) {
|
|
99
|
-
required.push(key);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const schema = {
|
|
103
|
-
type: 'object',
|
|
104
|
-
properties,
|
|
105
|
-
};
|
|
106
|
-
if (required.length > 0) {
|
|
107
|
-
schema.required = required;
|
|
108
|
-
}
|
|
109
|
-
if (options.includeExamples) {
|
|
110
|
-
schema.examples = [obj];
|
|
111
|
-
}
|
|
112
|
-
return schema;
|
|
43
|
+
static introspectToJsonSchema(obj) {
|
|
44
|
+
// If object already has $schema, assume it's a JSON schema and return as-is
|
|
45
|
+
// This matches the old connector framework behavior
|
|
46
|
+
if (obj && typeof obj === 'object' && obj.$schema) {
|
|
47
|
+
return obj;
|
|
113
48
|
}
|
|
114
|
-
|
|
115
|
-
return { type: 'string' };
|
|
49
|
+
return generateSchema.json('Schema', obj);
|
|
116
50
|
}
|
|
117
51
|
}
|
|
118
52
|
exports.JsonSchemaIntrospector = JsonSchemaIntrospector;
|
|
@@ -4,18 +4,18 @@ const JsonSchemaIntrospector_1 = require("./JsonSchemaIntrospector");
|
|
|
4
4
|
describe('JsonSchemaIntrospector', () => {
|
|
5
5
|
describe('introspectToJsonSchema', () => {
|
|
6
6
|
it('should handle primitive types', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
const stringSchema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema('test');
|
|
8
|
+
expect(stringSchema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
9
|
+
expect(stringSchema.type).toBeDefined();
|
|
10
|
+
const numberSchema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(42);
|
|
11
|
+
expect(numberSchema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
12
|
+
expect(numberSchema.type).toBe('number');
|
|
13
|
+
const boolSchema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(true);
|
|
14
|
+
expect(boolSchema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
15
|
+
expect(boolSchema.type).toBe('boolean');
|
|
16
|
+
const nullSchema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(null);
|
|
17
|
+
expect(nullSchema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
18
|
+
expect(nullSchema.type).toBe('null');
|
|
19
19
|
});
|
|
20
20
|
it('should handle simple objects', () => {
|
|
21
21
|
const obj = {
|
|
@@ -24,15 +24,14 @@ describe('JsonSchemaIntrospector', () => {
|
|
|
24
24
|
active: true,
|
|
25
25
|
};
|
|
26
26
|
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj);
|
|
27
|
-
expect(schema).
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
required: ['id', 'name', 'active'],
|
|
27
|
+
expect(schema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
28
|
+
expect(schema.type).toBe('object');
|
|
29
|
+
expect(schema.properties).toEqual({
|
|
30
|
+
id: { type: 'number' },
|
|
31
|
+
name: { type: 'string' },
|
|
32
|
+
active: { type: 'boolean' },
|
|
35
33
|
});
|
|
34
|
+
// Note: generate-schema doesn't add 'required' array, which is fine for path referencing
|
|
36
35
|
});
|
|
37
36
|
it('should handle nested objects', () => {
|
|
38
37
|
const obj = {
|
|
@@ -45,6 +44,7 @@ describe('JsonSchemaIntrospector', () => {
|
|
|
45
44
|
},
|
|
46
45
|
};
|
|
47
46
|
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj);
|
|
47
|
+
expect(schema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
48
48
|
expect(schema.type).toBe('object');
|
|
49
49
|
expect(schema.properties.user.type).toBe('object');
|
|
50
50
|
expect(schema.properties.user.properties.profile.type).toBe('object');
|
|
@@ -70,16 +70,11 @@ describe('JsonSchemaIntrospector', () => {
|
|
|
70
70
|
],
|
|
71
71
|
};
|
|
72
72
|
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj);
|
|
73
|
-
expect(schema.properties.users).
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
id: { type: 'number' },
|
|
79
|
-
name: { type: 'string' },
|
|
80
|
-
},
|
|
81
|
-
required: ['id', 'name'],
|
|
82
|
-
},
|
|
73
|
+
expect(schema.properties.users.type).toBe('array');
|
|
74
|
+
expect(schema.properties.users.items.type).toBe('object');
|
|
75
|
+
expect(schema.properties.users.items.properties).toEqual({
|
|
76
|
+
id: { type: 'number' },
|
|
77
|
+
name: { type: 'string' },
|
|
83
78
|
});
|
|
84
79
|
});
|
|
85
80
|
it('should handle empty arrays', () => {
|
|
@@ -90,50 +85,19 @@ describe('JsonSchemaIntrospector', () => {
|
|
|
90
85
|
items: {},
|
|
91
86
|
});
|
|
92
87
|
});
|
|
93
|
-
it('should
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
level3: {
|
|
98
|
-
level4: {
|
|
99
|
-
level5: {
|
|
100
|
-
tooDeep: 'value',
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(deepObj, {
|
|
108
|
-
maxDepth: 2,
|
|
109
|
-
});
|
|
110
|
-
// Should cut off at depth 2 (level1 -> level2 -> stop)
|
|
111
|
-
expect(schema.properties.level1.properties.level2).toEqual({
|
|
88
|
+
it('should return as-is if object already has $schema', () => {
|
|
89
|
+
// This matches the old connector framework behavior
|
|
90
|
+
const existingSchema = {
|
|
91
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
112
92
|
type: 'object',
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
it('should include examples when requested', () => {
|
|
117
|
-
const obj = { name: 'John' };
|
|
118
|
-
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj, {
|
|
119
|
-
includeExamples: true,
|
|
120
|
-
});
|
|
121
|
-
expect(schema.examples).toEqual([{ name: 'John' }]);
|
|
122
|
-
expect(schema.properties.name.examples).toEqual(['John']);
|
|
123
|
-
});
|
|
124
|
-
it('should handle strictRequired option', () => {
|
|
125
|
-
const obj = {
|
|
126
|
-
present: 'value',
|
|
127
|
-
// In real use, there might be optional fields
|
|
93
|
+
properties: {
|
|
94
|
+
custom: { type: 'string' },
|
|
95
|
+
},
|
|
128
96
|
};
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
expect(
|
|
133
|
-
const relaxedSchema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj, {
|
|
134
|
-
strictRequired: false,
|
|
135
|
-
});
|
|
136
|
-
expect(relaxedSchema.required).toEqual(['present']);
|
|
97
|
+
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(existingSchema);
|
|
98
|
+
// Should return the input unchanged
|
|
99
|
+
expect(schema).toBe(existingSchema);
|
|
100
|
+
expect(schema.$schema).toBe('http://json-schema.org/draft-07/schema#');
|
|
137
101
|
});
|
|
138
102
|
it('should handle complex real-world example', () => {
|
|
139
103
|
const obj = {
|
|
@@ -158,6 +122,7 @@ describe('JsonSchemaIntrospector', () => {
|
|
|
158
122
|
],
|
|
159
123
|
};
|
|
160
124
|
const schema = JsonSchemaIntrospector_1.JsonSchemaIntrospector.introspectToJsonSchema(obj);
|
|
125
|
+
expect(schema.$schema).toBe('http://json-schema.org/draft-04/schema#');
|
|
161
126
|
expect(schema.type).toBe('object');
|
|
162
127
|
expect(schema.properties.id.type).toBe('number');
|
|
163
128
|
expect(schema.properties.metadata.type).toBe('object');
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { JsonSchemaIntrospector
|
|
1
|
+
export { JsonSchemaIntrospector } from './JsonSchemaIntrospector';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/commons",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.14.0",
|
|
4
4
|
"description": "Extensions to the standard/core libraries and basic features",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": "./dist/*.js"
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"formidable": "3.5.1",
|
|
26
26
|
"fp-ts": "2.12.3",
|
|
27
27
|
"fs-extra": "11.1.0",
|
|
28
|
+
"generate-schema": "^2.6.0",
|
|
28
29
|
"io-ts": "2.2.20",
|
|
29
30
|
"io-ts-reporters": "2.0.1",
|
|
30
31
|
"io-ts-types": "0.5.19",
|
|
@@ -45,6 +46,5 @@
|
|
|
45
46
|
},
|
|
46
47
|
"files": [
|
|
47
48
|
"/dist"
|
|
48
|
-
]
|
|
49
|
-
"stableVersion": "0.0.0"
|
|
49
|
+
]
|
|
50
50
|
}
|