@gesslar/toolkit 0.4.0 → 0.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.
@@ -0,0 +1,162 @@
1
+ // Implementation: ../lib/Contract.js
2
+
3
+ import type { ValidateFunction } from 'ajv'
4
+
5
+ /**
6
+ * Debug function type for Contract operations
7
+ */
8
+ export type DebugFunction = (message: string, level?: number, ...args: unknown[]) => void
9
+
10
+ /**
11
+ * Contract represents a successful negotiation between Terms.
12
+ * It handles validation and compatibility checking between what
13
+ * one action provides and what another accepts.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Two-party contract between provider and consumer
18
+ * const provider = new Terms(providerDefinition)
19
+ * const consumer = new Terms(consumerDefinition)
20
+ * const contract = new Contract(provider, consumer, { debug: console.log })
21
+ *
22
+ * // Validate data against the contract
23
+ * const isValid = contract.validate(someData)
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Single-party contract from terms definition
29
+ * const contract = Contract.fromTerms("parser", {
30
+ * provides: {
31
+ * type: "object",
32
+ * properties: {
33
+ * name: { type: "string" },
34
+ * age: { type: "number" }
35
+ * }
36
+ * }
37
+ * })
38
+ *
39
+ * contract.validate({ name: "John", age: 30 }) // true
40
+ * ```
41
+ */
42
+ declare class Contract {
43
+ /**
44
+ * Creates a contract by negotiating between provider and consumer terms
45
+ *
46
+ * @param providerTerms - What the provider offers
47
+ * @param consumerTerms - What the consumer expects
48
+ * @param options - Configuration options
49
+ * @param options.debug - Debug function for logging negotiation details
50
+ *
51
+ * @throws {Sass} If contract negotiation fails due to incompatible terms
52
+ */
53
+ constructor(
54
+ providerTerms: import('./Terms.js').default | null,
55
+ consumerTerms: import('./Terms.js').default | null,
56
+ options?: { debug?: DebugFunction }
57
+ )
58
+
59
+ /**
60
+ * Creates a contract from terms with schema validation
61
+ *
62
+ * @param name - Contract identifier for error reporting
63
+ * @param termsDefinition - The terms definition object
64
+ * @param validator - Optional AJV schema validator function with .errors property
65
+ * @param debug - Debug function for logging validation details
66
+ * @returns New contract instance ready for data validation
67
+ *
68
+ * @throws {Sass} If terms definition is invalid according to the validator
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const contract = Contract.fromTerms("user-parser", {
73
+ * provides: {
74
+ * type: "object",
75
+ * properties: {
76
+ * id: { type: "string" },
77
+ * name: { type: "string" }
78
+ * },
79
+ * required: ["id", "name"]
80
+ * }
81
+ * })
82
+ * ```
83
+ */
84
+ static fromTerms(
85
+ name: string,
86
+ termsDefinition: object,
87
+ validator?: ValidateFunction | null,
88
+ debug?: DebugFunction
89
+ ): Contract
90
+
91
+ /**
92
+ * Validates data against this contract's schema
93
+ *
94
+ * @param data - Data object to validate against the contract
95
+ * @returns True if validation passes
96
+ *
97
+ * @throws {Sass} If validation fails with detailed error messages
98
+ * @throws {Sass} If contract has not been successfully negotiated
99
+ * @throws {Sass} If no validator is available for this contract
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * try {
104
+ * contract.validate({ id: "123", name: "John" })
105
+ * console.log("Data is valid!")
106
+ * } catch (error) {
107
+ * console.error("Validation failed:", error.message)
108
+ * }
109
+ * ```
110
+ */
111
+ validate(data: object): boolean
112
+
113
+ /**
114
+ * Check if contract negotiation was successful
115
+ *
116
+ * @returns True if the contract has been successfully negotiated
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * if (contract.isNegotiated) {
121
+ * contract.validate(data)
122
+ * } else {
123
+ * console.error("Contract negotiation failed")
124
+ * }
125
+ * ```
126
+ */
127
+ get isNegotiated(): boolean
128
+
129
+ /**
130
+ * Get the provider terms (if any)
131
+ *
132
+ * @returns Provider terms or null for single-party contracts
133
+ */
134
+ get providerTerms(): import('./Terms.js').default | null
135
+
136
+ /**
137
+ * Get the consumer terms (if any)
138
+ *
139
+ * @returns Consumer terms or null for single-party contracts
140
+ */
141
+ get consumerTerms(): import('./Terms.js').default | null
142
+
143
+ /**
144
+ * Get the contract validator function
145
+ *
146
+ * @returns The AJV validator function used by this contract, or null if none available
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * const validator = contract.validator
151
+ * if (validator) {
152
+ * const isValid = validator(someData)
153
+ * if (!isValid) {
154
+ * console.log("Validation errors:", validator.errors)
155
+ * }
156
+ * }
157
+ * ```
158
+ */
159
+ get validator(): ((data: object) => boolean) | null
160
+ }
161
+
162
+ export default Contract
@@ -0,0 +1,179 @@
1
+ // Implementation: ../lib/Schemer.js
2
+
3
+ import type { ValidateFunction, ErrorObject } from 'ajv'
4
+
5
+ /**
6
+ * Schemer provides utilities for compiling and validating JSON schemas using AJV.
7
+ *
8
+ * This class serves as a convenient wrapper around AJV (Another JSON Schema Validator)
9
+ * with toolkit-specific enhancements for error reporting and schema compilation.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Create validator from schema object
14
+ * const validator = await Schemer.from({
15
+ * type: "object",
16
+ * properties: {
17
+ * name: { type: "string" },
18
+ * age: { type: "number", minimum: 0 }
19
+ * },
20
+ * required: ["name"]
21
+ * })
22
+ *
23
+ * // Validate data
24
+ * const isValid = validator({ name: "John", age: 30 })
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Create validator from file
30
+ * const file = new FileObject("schema.json")
31
+ * const validator = await Schemer.fromFile(file)
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Get raw AJV validator and format errors
37
+ * const validate = Schemer.getValidator(schema)
38
+ * const isValid = validate(data)
39
+ * if (!isValid) {
40
+ * const errorReport = Schemer.reportValidationErrors(validate.errors)
41
+ * console.error("Validation failed:", errorReport)
42
+ * }
43
+ * ```
44
+ */
45
+ declare class Schemer {
46
+ /**
47
+ * Creates an AJV validator function from a schema file
48
+ *
49
+ * @param file - FileObject pointing to a JSON/YAML schema file
50
+ * @param options - AJV configuration options
51
+ * @returns Promise resolving to AJV validator function
52
+ *
53
+ * @throws {Sass} If file cannot be loaded or schema is invalid
54
+ * @throws {Sass} If file is not a FileObject or options are invalid
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const file = new FileObject("user-schema.json")
59
+ * const validator = await Schemer.fromFile(file, {
60
+ * allErrors: true,
61
+ * verbose: true
62
+ * })
63
+ *
64
+ * const isValid = validator({ name: "John", age: 30 })
65
+ * if (!isValid) {
66
+ * console.log("Errors:", validator.errors)
67
+ * }
68
+ * ```
69
+ */
70
+ static fromFile(
71
+ file: import('./FileObject.js').default,
72
+ options?: object
73
+ ): Promise<ValidateFunction>
74
+
75
+ /**
76
+ * Creates an AJV validator function from a schema object
77
+ *
78
+ * @param schemaData - JSON schema object to compile
79
+ * @param options - AJV configuration options
80
+ * @returns Promise resolving to AJV validator function
81
+ *
82
+ * @throws {Sass} If schema data or options are not plain objects
83
+ * @throws {Sass} If schema compilation fails
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const validator = await Schemer.from({
88
+ * type: "object",
89
+ * properties: {
90
+ * id: { type: "string", format: "uuid" },
91
+ * email: { type: "string", format: "email" }
92
+ * },
93
+ * required: ["id", "email"]
94
+ * }, {
95
+ * formats: true,
96
+ * allErrors: true
97
+ * })
98
+ *
99
+ * const isValid = validator({ id: "123", email: "test@example.com" })
100
+ * if (!isValid) {
101
+ * console.log("Errors:", validator.errors)
102
+ * }
103
+ * ```
104
+ */
105
+ static from(schemaData?: object, options?: object): Promise<ValidateFunction>
106
+
107
+ /**
108
+ * Creates a raw AJV validator function from a schema object
109
+ *
110
+ * @param schema - The JSON schema to compile
111
+ * @param options - AJV configuration options (defaults to {allErrors: true, verbose: true})
112
+ * @returns AJV validator function with .errors property when validation fails
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const validate = Schemer.getValidator({
117
+ * type: "string",
118
+ * minLength: 1,
119
+ * maxLength: 100
120
+ * })
121
+ *
122
+ * const isValid = validate("Hello World")
123
+ * if (!isValid) {
124
+ * console.log("Errors:", validate.errors)
125
+ * }
126
+ * ```
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * // Custom AJV options
131
+ * const validate = Schemer.getValidator(schema, {
132
+ * allErrors: false,
133
+ * verbose: false,
134
+ * strict: true
135
+ * })
136
+ * ```
137
+ */
138
+ static getValidator(
139
+ schema: object,
140
+ options?: { allErrors?: boolean; verbose?: boolean; [key: string]: unknown }
141
+ ): ValidateFunction
142
+
143
+ /**
144
+ * Formats AJV validation errors into a human-readable report
145
+ *
146
+ * @param errors - Array of AJV error objects from failed validation
147
+ * @returns Formatted error message with helpful details and suggestions
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const validate = Schemer.getValidator(schema)
152
+ * const isValid = validate(data)
153
+ *
154
+ * if (!isValid) {
155
+ * const report = Schemer.reportValidationErrors(validate.errors)
156
+ * console.error("Validation failed:")
157
+ * console.error(report)
158
+ * // Output:
159
+ * // - "(root)" must be object
160
+ * // ➜ Expected type: object
161
+ * // ➜ Received value: "string"
162
+ * }
163
+ * ```
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * // The error report includes helpful details:
168
+ * // - Property paths and error descriptions
169
+ * // - Expected vs actual types
170
+ * // - Missing required fields
171
+ * // - Pattern matching failures
172
+ * // - Closest matches for enum values
173
+ * // - Unexpected additional properties
174
+ * ```
175
+ */
176
+ static reportValidationErrors(errors: ErrorObject[] | null | undefined): string
177
+ }
178
+
179
+ export default Schemer
@@ -0,0 +1,145 @@
1
+ // Implementation: ../lib/Terms.js
2
+
3
+ /**
4
+ * Terms represents an interface definition - what an action promises to provide or accept.
5
+ * It's just the specification, not the negotiation. Contract handles the negotiation.
6
+ *
7
+ * Terms can be created from objects, strings (YAML/JSON), or file references.
8
+ * File references use the format "ref://path/to/file" for loading external definitions.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Create terms from object definition
13
+ * const terms = new Terms({
14
+ * provides: {
15
+ * type: "object",
16
+ * properties: {
17
+ * userId: { type: "string" },
18
+ * userName: { type: "string" }
19
+ * },
20
+ * required: ["userId"]
21
+ * }
22
+ * })
23
+ * ```
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Parse terms from YAML string
28
+ * const yamlData = `
29
+ * accepts:
30
+ * type: object
31
+ * properties:
32
+ * input:
33
+ * type: string
34
+ * minLength: 1
35
+ * `
36
+ * const parsedTerms = await Terms.parse(yamlData)
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Parse terms from file reference
42
+ * const directory = new DirectoryObject("/path/to/schemas")
43
+ * const parsedTerms = await Terms.parse("ref://user-schema.json", directory)
44
+ * ```
45
+ */
46
+ declare class Terms {
47
+ /**
48
+ * Creates a new Terms instance with the given definition
49
+ *
50
+ * @param definition - The terms definition object describing what is provided or accepted
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const terms = new Terms({
55
+ * provides: {
56
+ * type: "object",
57
+ * properties: {
58
+ * data: { type: "array", items: { type: "string" } },
59
+ * metadata: {
60
+ * type: "object",
61
+ * properties: {
62
+ * timestamp: { type: "string", format: "date-time" }
63
+ * }
64
+ * }
65
+ * }
66
+ * }
67
+ * })
68
+ * ```
69
+ */
70
+ constructor(definition: object)
71
+
72
+ /**
73
+ * Parses terms data from various sources, handling file references
74
+ *
75
+ * @param termsData - Terms data as string (YAML/JSON/file reference) or object
76
+ * @param directoryObject - Directory context for resolving file references (required for ref:// URLs)
77
+ * @returns Promise resolving to parsed terms data object
78
+ *
79
+ * @throws {Sass} If termsData is not a string or object
80
+ * @throws {Sass} If string data cannot be parsed as YAML or JSON
81
+ * @throws {Sass} If file reference cannot be loaded (missing directory or file not found)
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // Parse from YAML string
86
+ * const yamlTerms = await Terms.parse(`
87
+ * provides:
88
+ * type: string
89
+ * pattern: "^[A-Z][a-z]+"
90
+ * `)
91
+ * ```
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Parse from JSON string
96
+ * const jsonTerms = await Terms.parse(`{
97
+ * "accepts": {
98
+ * "type": "number",
99
+ * "minimum": 0,
100
+ * "maximum": 100
101
+ * }
102
+ * }`)
103
+ * ```
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * // Parse from file reference
108
+ * const directory = new DirectoryObject("./schemas")
109
+ * const fileTerms = await Terms.parse("ref://api-contract.yaml", directory)
110
+ * ```
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * // Parse from object (returns as-is)
115
+ * const objectTerms = await Terms.parse({
116
+ * provides: { type: "boolean" }
117
+ * })
118
+ * ```
119
+ */
120
+ static parse(
121
+ termsData: string | object,
122
+ directoryObject?: import('./DirectoryObject.js').default
123
+ ): Promise<object>
124
+
125
+ /**
126
+ * Get the terms definition object
127
+ *
128
+ * @returns The complete terms definition as provided to the constructor
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const terms = new Terms({
133
+ * accepts: { type: "string" },
134
+ * provides: { type: "number" }
135
+ * })
136
+ *
137
+ * const definition = terms.definition
138
+ * console.log(definition.accepts) // { type: "string" }
139
+ * console.log(definition.provides) // { type: "number" }
140
+ * ```
141
+ */
142
+ get definition(): object
143
+ }
144
+
145
+ export default Terms
@@ -7,11 +7,14 @@ export { default as FS } from './FS.js'
7
7
  // Utility classes
8
8
  export { default as Cache } from './Cache.js'
9
9
  export { default as Collection } from './Collection.js'
10
+ export { default as Contract } from './Contract.js'
10
11
  export { default as Data } from './Data.js'
11
12
  export { default as Glog } from './Glog.js'
12
13
  export { default as Sass } from './Sass.js'
14
+ export { default as Schemer } from './Schemer.js'
13
15
  export { default as Tantrum } from './Tantrum.js'
14
16
  export { default as Term } from './Term.js'
17
+ export { default as Terms } from './Terms.js'
15
18
  export { default as Type } from './Type.js'
16
19
  export { default as Util } from './Util.js'
17
20
  export { default as Valid } from './Valid.js'