@maroonedog/luq 0.1.0-alpha
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 +9 -0
- package/README.md +879 -0
- package/dist/constants.d.ts +27 -0
- package/dist/core/async.experimental/async-context.d.ts +60 -0
- package/dist/core/builder/array-batch-optimizer.d.ts +66 -0
- package/dist/core/builder/context/field-context.d.ts +31 -0
- package/dist/core/builder/context/field-type-detector.d.ts +19 -0
- package/dist/core/builder/core/builder.d.ts +10 -0
- package/dist/core/builder/core/field-builder.d.ts +13 -0
- package/dist/core/builder/core/index.d.ts +17 -0
- package/dist/core/builder/index.d.ts +24 -0
- package/dist/core/builder/nested-array-processor.d.ts +52 -0
- package/dist/core/builder/plugins/composable-conditional-plugin.d.ts +32 -0
- package/dist/core/builder/plugins/composable-directly-plugin.d.ts +32 -0
- package/dist/core/builder/plugins/composable-plugin.d.ts +242 -0
- package/dist/core/builder/plugins/plugin-creator.d.ts +38 -0
- package/dist/core/builder/plugins/plugin-interfaces.d.ts +343 -0
- package/dist/core/builder/plugins/plugin-types.d.ts +441 -0
- package/dist/core/builder/raw-validator.d.ts +22 -0
- package/dist/core/builder/types/field-options.d.ts +46 -0
- package/dist/core/builder/types/types.d.ts +318 -0
- package/dist/core/builder/ultra-fast-validator.d.ts +30 -0
- package/dist/core/builder/validator-factory.d.ts +29 -0
- package/dist/core/global-config.d.ts +27 -0
- package/dist/core/index.d.ts +36 -0
- package/dist/core/optimization/array-batch-validator.d.ts +68 -0
- package/dist/core/optimization/core/field-utils.d.ts +103 -0
- package/dist/core/optimization/core/strategy-factory.d.ts +84 -0
- package/dist/core/optimization/core/validation-engine.d.ts +107 -0
- package/dist/core/optimization/execution-strategy-selector.d.ts +23 -0
- package/dist/core/optimization/unified-validator.d.ts +45 -0
- package/dist/core/plugin/__tests__/test-utils.d.ts +1 -0
- package/dist/core/plugin/arrayContains.d.ts +37 -0
- package/dist/core/plugin/arrayIncludes.d.ts +42 -0
- package/dist/core/plugin/arrayMaxLength.d.ts +43 -0
- package/dist/core/plugin/arrayMinLength.d.ts +43 -0
- package/dist/core/plugin/arrayUnique.d.ts +41 -0
- package/dist/core/plugin/booleanFalsy.d.ts +41 -0
- package/dist/core/plugin/booleanTruthy.d.ts +38 -0
- package/dist/core/plugin/compareField.d.ts +58 -0
- package/dist/core/plugin/conditionalSchema.d.ts +24 -0
- package/dist/core/plugin/custom.d.ts +60 -0
- package/dist/core/plugin/fromContext.d.ts +150 -0
- package/dist/core/plugin/index.d.ts +71 -0
- package/dist/core/plugin/jsonSchema/dsl-converter.d.ts +22 -0
- package/dist/core/plugin/jsonSchema/error-generation.d.ts +14 -0
- package/dist/core/plugin/jsonSchema/format-validators.d.ts +20 -0
- package/dist/core/plugin/jsonSchema/index.d.ts +11 -0
- package/dist/core/plugin/jsonSchema/plugin.d.ts +35 -0
- package/dist/core/plugin/jsonSchema/ref-resolver.d.ts +14 -0
- package/dist/core/plugin/jsonSchema/types.d.ts +69 -0
- package/dist/core/plugin/jsonSchema/validation-core.d.ts +29 -0
- package/dist/core/plugin/jsonSchemaFullFeature.d.ts +31 -0
- package/dist/core/plugin/literal.d.ts +40 -0
- package/dist/core/plugin/message-factories.d.ts +9 -0
- package/dist/core/plugin/nullable.d.ts +34 -0
- package/dist/core/plugin/numberFinite.d.ts +41 -0
- package/dist/core/plugin/numberInteger.d.ts +41 -0
- package/dist/core/plugin/numberMax.d.ts +49 -0
- package/dist/core/plugin/numberMin.d.ts +49 -0
- package/dist/core/plugin/numberMultipleOf.d.ts +42 -0
- package/dist/core/plugin/numberNegative.d.ts +41 -0
- package/dist/core/plugin/numberPositive.d.ts +41 -0
- package/dist/core/plugin/numberRange.d.ts +48 -0
- package/dist/core/plugin/object.d.ts +43 -0
- package/dist/core/plugin/objectAdditionalProperties.d.ts +51 -0
- package/dist/core/plugin/objectDependentRequired.d.ts +42 -0
- package/dist/core/plugin/objectDependentSchemas.d.ts +40 -0
- package/dist/core/plugin/objectMaxProperties.d.ts +42 -0
- package/dist/core/plugin/objectMinProperties.d.ts +42 -0
- package/dist/core/plugin/objectPatternProperties.d.ts +46 -0
- package/dist/core/plugin/objectPropertyNames.d.ts +36 -0
- package/dist/core/plugin/objectRecursively.d.ts +81 -0
- package/dist/core/plugin/oneOf.d.ts +44 -0
- package/dist/core/plugin/optional.d.ts +35 -0
- package/dist/core/plugin/optionalIf.d.ts +42 -0
- package/dist/core/plugin/orFail.d.ts +132 -0
- package/dist/core/plugin/readOnlyWriteOnly.d.ts +48 -0
- package/dist/core/plugin/required.d.ts +45 -0
- package/dist/core/plugin/requiredIf.d.ts +66 -0
- package/dist/core/plugin/shared-constants.d.ts +45 -0
- package/dist/core/plugin/shared.d.ts +3 -0
- package/dist/core/plugin/skip.d.ts +57 -0
- package/dist/core/plugin/stitch-typed.d.ts +15 -0
- package/dist/core/plugin/stitch.d.ts +1 -0
- package/dist/core/plugin/stitchSimple.d.ts +4 -0
- package/dist/core/plugin/stringAlphanumeric.d.ts +42 -0
- package/dist/core/plugin/stringBase64.d.ts +119 -0
- package/dist/core/plugin/stringContentEncoding.d.ts +43 -0
- package/dist/core/plugin/stringContentMediaType.d.ts +47 -0
- package/dist/core/plugin/stringDate.d.ts +48 -0
- package/dist/core/plugin/stringDatetime.d.ts +108 -0
- package/dist/core/plugin/stringDuration.d.ts +41 -0
- package/dist/core/plugin/stringEmail.d.ts +81 -0
- package/dist/core/plugin/stringEndsWith.d.ts +42 -0
- package/dist/core/plugin/stringExactLength.d.ts +46 -0
- package/dist/core/plugin/stringHostname.d.ts +104 -0
- package/dist/core/plugin/stringIpv4.d.ts +85 -0
- package/dist/core/plugin/stringIpv6.d.ts +104 -0
- package/dist/core/plugin/stringIri.d.ts +117 -0
- package/dist/core/plugin/stringIriReference.d.ts +43 -0
- package/dist/core/plugin/stringJsonPointer.d.ts +107 -0
- package/dist/core/plugin/stringMax.d.ts +43 -0
- package/dist/core/plugin/stringMin.d.ts +43 -0
- package/dist/core/plugin/stringPattern.d.ts +40 -0
- package/dist/core/plugin/stringRelativeJsonPointer.d.ts +42 -0
- package/dist/core/plugin/stringStartsWith.d.ts +42 -0
- package/dist/core/plugin/stringTime.d.ts +39 -0
- package/dist/core/plugin/stringUriTemplate.d.ts +43 -0
- package/dist/core/plugin/stringUrl.d.ts +97 -0
- package/dist/core/plugin/testUtils.d.ts +15 -0
- package/dist/core/plugin/transform-type-restrictions.d.ts +61 -0
- package/dist/core/plugin/transform.d.ts +35 -0
- package/dist/core/plugin/tupleBuilder.d.ts +66 -0
- package/dist/core/plugin/types.d.ts +143 -0
- package/dist/core/plugin/unionGuard.d.ts +50 -0
- package/dist/core/plugin/utils/field-accessor-optimized.d.ts +50 -0
- package/dist/core/plugin/utils/field-accessor.d.ts +107 -0
- package/dist/core/plugin/uuid.d.ts +95 -0
- package/dist/core/plugin/validateIf.d.ts +57 -0
- package/dist/core/registry/plugin-registry.d.ts +116 -0
- package/dist/core/registry.d.ts +6 -0
- package/dist/core/transform/index.d.ts +1 -0
- package/dist/core/transform/string/defaultValue.d.ts +6 -0
- package/dist/core/transform/string/index.d.ts +3 -0
- package/dist/core/transform/string/replace.d.ts +14 -0
- package/dist/core/transform/string/sanitize.d.ts +6 -0
- package/dist/core/utils/type-guards.d.ts +68 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +7 -0
- package/dist/plugins/arrayContains.d.ts +37 -0
- package/dist/plugins/arrayContains.js +1 -0
- package/dist/plugins/arrayContains.mjs +1 -0
- package/dist/plugins/arrayIncludes.d.ts +42 -0
- package/dist/plugins/arrayIncludes.js +1 -0
- package/dist/plugins/arrayIncludes.mjs +1 -0
- package/dist/plugins/arrayMaxLength.d.ts +43 -0
- package/dist/plugins/arrayMaxLength.js +1 -0
- package/dist/plugins/arrayMaxLength.mjs +1 -0
- package/dist/plugins/arrayMinLength.d.ts +43 -0
- package/dist/plugins/arrayMinLength.js +1 -0
- package/dist/plugins/arrayMinLength.mjs +1 -0
- package/dist/plugins/arrayUnique.d.ts +41 -0
- package/dist/plugins/arrayUnique.js +1 -0
- package/dist/plugins/arrayUnique.mjs +1 -0
- package/dist/plugins/booleanFalsy.d.ts +41 -0
- package/dist/plugins/booleanFalsy.js +1 -0
- package/dist/plugins/booleanFalsy.mjs +1 -0
- package/dist/plugins/booleanTruthy.d.ts +38 -0
- package/dist/plugins/booleanTruthy.js +1 -0
- package/dist/plugins/booleanTruthy.mjs +1 -0
- package/dist/plugins/compareField.d.ts +58 -0
- package/dist/plugins/compareField.js +1 -0
- package/dist/plugins/compareField.mjs +1 -0
- package/dist/plugins/custom.d.ts +60 -0
- package/dist/plugins/custom.js +1 -0
- package/dist/plugins/custom.mjs +1 -0
- package/dist/plugins/jsonSchema.d.ts +11 -0
- package/dist/plugins/jsonSchema.js +1 -0
- package/dist/plugins/jsonSchema.mjs +1 -0
- package/dist/plugins/jsonSchemaFullFeature.d.ts +31 -0
- package/dist/plugins/jsonSchemaFullFeature.js +1 -0
- package/dist/plugins/jsonSchemaFullFeature.mjs +1 -0
- package/dist/plugins/literal.d.ts +40 -0
- package/dist/plugins/literal.js +1 -0
- package/dist/plugins/literal.mjs +1 -0
- package/dist/plugins/nullable.d.ts +34 -0
- package/dist/plugins/nullable.js +1 -0
- package/dist/plugins/nullable.mjs +1 -0
- package/dist/plugins/numberInteger.d.ts +41 -0
- package/dist/plugins/numberInteger.js +1 -0
- package/dist/plugins/numberInteger.mjs +1 -0
- package/dist/plugins/numberMax.d.ts +49 -0
- package/dist/plugins/numberMax.js +1 -0
- package/dist/plugins/numberMax.mjs +1 -0
- package/dist/plugins/numberMin.d.ts +49 -0
- package/dist/plugins/numberMin.js +1 -0
- package/dist/plugins/numberMin.mjs +1 -0
- package/dist/plugins/numberMultipleOf.d.ts +42 -0
- package/dist/plugins/numberMultipleOf.js +1 -0
- package/dist/plugins/numberMultipleOf.mjs +1 -0
- package/dist/plugins/numberNegative.d.ts +41 -0
- package/dist/plugins/numberNegative.js +1 -0
- package/dist/plugins/numberNegative.mjs +1 -0
- package/dist/plugins/numberPositive.d.ts +41 -0
- package/dist/plugins/numberPositive.js +1 -0
- package/dist/plugins/numberPositive.mjs +1 -0
- package/dist/plugins/object.d.ts +43 -0
- package/dist/plugins/object.js +1 -0
- package/dist/plugins/object.mjs +1 -0
- package/dist/plugins/objectAdditionalProperties.d.ts +51 -0
- package/dist/plugins/objectAdditionalProperties.js +1 -0
- package/dist/plugins/objectAdditionalProperties.mjs +1 -0
- package/dist/plugins/objectDependentRequired.d.ts +42 -0
- package/dist/plugins/objectDependentRequired.js +1 -0
- package/dist/plugins/objectDependentRequired.mjs +1 -0
- package/dist/plugins/objectDependentSchemas.d.ts +40 -0
- package/dist/plugins/objectDependentSchemas.js +1 -0
- package/dist/plugins/objectDependentSchemas.mjs +1 -0
- package/dist/plugins/objectMaxProperties.d.ts +42 -0
- package/dist/plugins/objectMaxProperties.js +1 -0
- package/dist/plugins/objectMaxProperties.mjs +1 -0
- package/dist/plugins/objectMinProperties.d.ts +42 -0
- package/dist/plugins/objectMinProperties.js +1 -0
- package/dist/plugins/objectMinProperties.mjs +1 -0
- package/dist/plugins/objectPatternProperties.d.ts +46 -0
- package/dist/plugins/objectPatternProperties.js +1 -0
- package/dist/plugins/objectPatternProperties.mjs +1 -0
- package/dist/plugins/objectPropertyNames.d.ts +36 -0
- package/dist/plugins/objectPropertyNames.js +1 -0
- package/dist/plugins/objectPropertyNames.mjs +1 -0
- package/dist/plugins/oneOf.d.ts +44 -0
- package/dist/plugins/oneOf.js +1 -0
- package/dist/plugins/oneOf.mjs +1 -0
- package/dist/plugins/optional.d.ts +35 -0
- package/dist/plugins/optional.js +1 -0
- package/dist/plugins/optional.mjs +1 -0
- package/dist/plugins/readOnlyWriteOnly.d.ts +48 -0
- package/dist/plugins/readOnlyWriteOnly.js +1 -0
- package/dist/plugins/readOnlyWriteOnly.mjs +1 -0
- package/dist/plugins/required.d.ts +45 -0
- package/dist/plugins/required.js +1 -0
- package/dist/plugins/required.mjs +1 -0
- package/dist/plugins/requiredIf.d.ts +66 -0
- package/dist/plugins/requiredIf.js +1 -0
- package/dist/plugins/requiredIf.mjs +1 -0
- package/dist/plugins/skip.d.ts +57 -0
- package/dist/plugins/skip.js +1 -0
- package/dist/plugins/skip.mjs +1 -0
- package/dist/plugins/stringBase64.d.ts +119 -0
- package/dist/plugins/stringBase64.js +1 -0
- package/dist/plugins/stringBase64.mjs +1 -0
- package/dist/plugins/stringContentEncoding.d.ts +43 -0
- package/dist/plugins/stringContentEncoding.js +1 -0
- package/dist/plugins/stringContentEncoding.mjs +1 -0
- package/dist/plugins/stringContentMediaType.d.ts +47 -0
- package/dist/plugins/stringContentMediaType.js +1 -0
- package/dist/plugins/stringContentMediaType.mjs +1 -0
- package/dist/plugins/stringDate.d.ts +48 -0
- package/dist/plugins/stringDate.js +1 -0
- package/dist/plugins/stringDate.mjs +1 -0
- package/dist/plugins/stringDatetime.d.ts +108 -0
- package/dist/plugins/stringDatetime.js +1 -0
- package/dist/plugins/stringDatetime.mjs +1 -0
- package/dist/plugins/stringDuration.d.ts +41 -0
- package/dist/plugins/stringDuration.js +1 -0
- package/dist/plugins/stringDuration.mjs +1 -0
- package/dist/plugins/stringEmail.d.ts +81 -0
- package/dist/plugins/stringEmail.js +1 -0
- package/dist/plugins/stringEmail.mjs +1 -0
- package/dist/plugins/stringHostname.d.ts +104 -0
- package/dist/plugins/stringHostname.js +1 -0
- package/dist/plugins/stringHostname.mjs +1 -0
- package/dist/plugins/stringIpv4.d.ts +85 -0
- package/dist/plugins/stringIpv4.js +1 -0
- package/dist/plugins/stringIpv4.mjs +1 -0
- package/dist/plugins/stringIpv6.d.ts +104 -0
- package/dist/plugins/stringIpv6.js +1 -0
- package/dist/plugins/stringIpv6.mjs +1 -0
- package/dist/plugins/stringIri.d.ts +117 -0
- package/dist/plugins/stringIri.js +1 -0
- package/dist/plugins/stringIri.mjs +1 -0
- package/dist/plugins/stringIriReference.d.ts +43 -0
- package/dist/plugins/stringIriReference.js +1 -0
- package/dist/plugins/stringIriReference.mjs +1 -0
- package/dist/plugins/stringJsonPointer.d.ts +107 -0
- package/dist/plugins/stringJsonPointer.js +1 -0
- package/dist/plugins/stringJsonPointer.mjs +1 -0
- package/dist/plugins/stringMax.d.ts +43 -0
- package/dist/plugins/stringMax.js +1 -0
- package/dist/plugins/stringMax.mjs +1 -0
- package/dist/plugins/stringMin.d.ts +43 -0
- package/dist/plugins/stringMin.js +1 -0
- package/dist/plugins/stringMin.mjs +1 -0
- package/dist/plugins/stringPattern.d.ts +40 -0
- package/dist/plugins/stringPattern.js +1 -0
- package/dist/plugins/stringPattern.mjs +1 -0
- package/dist/plugins/stringRelativeJsonPointer.d.ts +42 -0
- package/dist/plugins/stringRelativeJsonPointer.js +1 -0
- package/dist/plugins/stringRelativeJsonPointer.mjs +1 -0
- package/dist/plugins/stringTime.d.ts +39 -0
- package/dist/plugins/stringTime.js +1 -0
- package/dist/plugins/stringTime.mjs +1 -0
- package/dist/plugins/stringUriTemplate.d.ts +43 -0
- package/dist/plugins/stringUriTemplate.js +1 -0
- package/dist/plugins/stringUriTemplate.mjs +1 -0
- package/dist/plugins/stringUrl.d.ts +97 -0
- package/dist/plugins/stringUrl.js +1 -0
- package/dist/plugins/stringUrl.mjs +1 -0
- package/dist/plugins/transform.d.ts +35 -0
- package/dist/plugins/transform.js +1 -0
- package/dist/plugins/transform.mjs +1 -0
- package/dist/plugins/tupleBuilder.d.ts +66 -0
- package/dist/plugins/tupleBuilder.js +1 -0
- package/dist/plugins/tupleBuilder.mjs +1 -0
- package/dist/plugins/uuid.d.ts +95 -0
- package/dist/plugins/uuid.js +1 -0
- package/dist/plugins/uuid.mjs +1 -0
- package/dist/plugins/validateIf.d.ts +57 -0
- package/dist/plugins/validateIf.js +1 -0
- package/dist/plugins/validateIf.mjs +1 -0
- package/dist/types/array-type-analysis.d.ts +115 -0
- package/dist/types/index.d.ts +74 -0
- package/dist/types/indexed-result.d.ts +44 -0
- package/dist/types/result.d.ts +159 -0
- package/dist/types/stitch-types.d.ts +118 -0
- package/dist/types/util.d.ts +19 -0
- package/dist/types/valitator.d.ts +10 -0
- package/package.json +353 -0
package/README.md
ADDED
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./public/img/library_image.png" alt="Luq Logo" width="300" />
|
|
3
|
+
|
|
4
|
+
# Luq - Universal Model & API Definition Platform
|
|
5
|
+
|
|
6
|
+
**Alpha Release**: Single source of truth for API, types, validation, and business logic across all languages
|
|
7
|
+
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
### The Vision: Define Once, Generate Everywhere
|
|
11
|
+
|
|
12
|
+
**Luq is not just another validation library.** It's evolving into a unified platform where you define your API contracts, data models, validation rules, and business logic once—then generate type-safe implementations for any language.
|
|
13
|
+
|
|
14
|
+
> **Note**: The roadmap and features described here represent our current vision and are subject to change. Nothing beyond the currently released TypeScript library (Phase 1) should be considered final. We'll adapt based on community feedback and technical discoveries.
|
|
15
|
+
|
|
16
|
+
### Who needs Luq?
|
|
17
|
+
|
|
18
|
+
**Today (TypeScript Library)**:
|
|
19
|
+
- Teams with existing TypeScript types who need validation
|
|
20
|
+
- Applications requiring CSP-safe dynamic validation
|
|
21
|
+
- Projects needing custom business rules as plugins
|
|
22
|
+
|
|
23
|
+
**Tomorrow (.luq Format & Multi-language - 2026)**:
|
|
24
|
+
- **Microservices** with different languages needing consistent validation
|
|
25
|
+
- **API Gateways** requiring validation at multiple layers
|
|
26
|
+
- **Mobile/Web/Backend** sharing the same business rules
|
|
27
|
+
- **Enterprise systems** needing unified validation across platforms
|
|
28
|
+
|
|
29
|
+
### Overview
|
|
30
|
+
|
|
31
|
+
**Current Release (Phase 1)**: A TypeScript validation library that serves as the foundation for something bigger:
|
|
32
|
+
- **Type-first**: Learn from your existing code patterns
|
|
33
|
+
- **Plugin Architecture**: Capture business logic as reusable components
|
|
34
|
+
- **Production-ready**: CSP-compliant, tree-shakeable (19-23KB gzipped)
|
|
35
|
+
- **JSON Schema compatible**: Bridge to existing standards
|
|
36
|
+
|
|
37
|
+
**The Journey Ahead**:
|
|
38
|
+
1. **Phase 1** (Now): TypeScript library with plugin system
|
|
39
|
+
2. **Phase 2**: `.luq` language - TypeScript-like validation DSL with IDE support
|
|
40
|
+
3. **Phase 3**: AOT compilation for optimal performance
|
|
41
|
+
4. **Phase 4**: Generate validators for Go, Python, Java, Rust, and more
|
|
42
|
+
|
|
43
|
+
## The Problem We're Solving
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
// Current reality: Everything is duplicated across languages
|
|
47
|
+
|
|
48
|
+
// Frontend API client (TypeScript)
|
|
49
|
+
interface Order { /* manually typed */ }
|
|
50
|
+
async function createOrder(order: Order) { /* manually coded */ }
|
|
51
|
+
function validateOrder(order: Order) { /* validation duplicated */ }
|
|
52
|
+
|
|
53
|
+
// Backend controller (Java)
|
|
54
|
+
@RestController
|
|
55
|
+
public class OrderController { /* manually coded */ }
|
|
56
|
+
public class Order { /* manually typed */ }
|
|
57
|
+
public ValidationResult validateOrder() { /* validation duplicated */ }
|
|
58
|
+
|
|
59
|
+
// Mobile app (Swift)
|
|
60
|
+
struct Order { /* manually typed */ }
|
|
61
|
+
func createOrder() { /* manually coded */ }
|
|
62
|
+
func validateOrder() { /* validation duplicated */ }
|
|
63
|
+
|
|
64
|
+
// API Documentation
|
|
65
|
+
openapi: 3.0.0 # manually maintained, often out of sync
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**The Luq Solution (Future - Single Source of Truth):**
|
|
69
|
+
```typescript
|
|
70
|
+
// Define everything once in order.luq
|
|
71
|
+
@endpoint("/api/orders")
|
|
72
|
+
interface OrderAPI {
|
|
73
|
+
@post("/")
|
|
74
|
+
create(body: Order): OrderResponse;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface Order {
|
|
78
|
+
@min(0) @businessRule("calculateFromItems")
|
|
79
|
+
total: number;
|
|
80
|
+
|
|
81
|
+
@minLength(1)
|
|
82
|
+
items: Product[];
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Generate everything:
|
|
87
|
+
```bash
|
|
88
|
+
luq generate order.luq --target=all
|
|
89
|
+
|
|
90
|
+
✓ Generated code for each language
|
|
91
|
+
✓ Type-safe API clients
|
|
92
|
+
✓ Models with validation
|
|
93
|
+
✓ API documentation
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Quick Start (Phase 1 - Available Now)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install @maroonedog/luq
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { Builder } from "@maroonedog/luq";
|
|
104
|
+
import { requiredPlugin, stringMinPlugin, numberMinPlugin, stringEmailPlugin } from "@maroonedog/luq/plugins";
|
|
105
|
+
|
|
106
|
+
type User = {
|
|
107
|
+
name: string;
|
|
108
|
+
age: number;
|
|
109
|
+
email: string;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const validateUser = Builder()
|
|
113
|
+
.use(requiredPlugin)
|
|
114
|
+
.use(stringMinPlugin)
|
|
115
|
+
.use(numberMinPlugin)
|
|
116
|
+
.use(stringEmailPlugin)
|
|
117
|
+
.for<User>()
|
|
118
|
+
.v("name", (b) => b.string.required().min(3))
|
|
119
|
+
.v("age", (b) => b.number.required().min(18))
|
|
120
|
+
.v("email", (b) => b.string.required().email())
|
|
121
|
+
.build();
|
|
122
|
+
|
|
123
|
+
// This TypeScript code is learning your patterns
|
|
124
|
+
// Soon, it will help generate validators for other languages
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Why Luq is Practical
|
|
128
|
+
|
|
129
|
+
### Why Not Use Existing Solutions?
|
|
130
|
+
|
|
131
|
+
**Similar tools exist, but none provide a complete solution:**
|
|
132
|
+
|
|
133
|
+
| Tool | What It Does | What's Missing |
|
|
134
|
+
|------|-------------|----------------|
|
|
135
|
+
| **TypeSpec** (Microsoft) | API-first contracts | Business logic, runtime validation, custom rules |
|
|
136
|
+
| **Smithy** (AWS) | AWS service models | General-purpose use, frontend/mobile generation |
|
|
137
|
+
| **JSON Schema** | Structure validation | API definitions, business logic, code generation |
|
|
138
|
+
| **Protobuf/gRPC** | RPC & serialization | REST APIs, complex validation, business rules |
|
|
139
|
+
| **OpenAPI** | API documentation | Implementation code, business logic, validation |
|
|
140
|
+
| **tRPC/GraphQL** | Type-safe APIs | Multi-language support, validation rules |
|
|
141
|
+
|
|
142
|
+
**Luq's Unified Approach (Progressive Abstraction Architecture):**
|
|
143
|
+
|
|
144
|
+
| Level | What You Get | Status |
|
|
145
|
+
|-------|-------------|--------|
|
|
146
|
+
| **Level 1** | TypeScript validation library | ✅ Available Now |
|
|
147
|
+
| **Level 2** | .luq format (models + validation) | 🚧 Q1-Q3 2026 |
|
|
148
|
+
| **Level 3** | Full platform (API + models + validation) | 🔮 Vision |
|
|
149
|
+
|
|
150
|
+
**Key Differentiators:**
|
|
151
|
+
- **Progressive adoption**: Start with validation, evolve to full platform
|
|
152
|
+
- **Single source of truth**: API, types, validation, and business logic together
|
|
153
|
+
- **TypeScript-like syntax**: Familiar to millions of developers
|
|
154
|
+
- **Generate everything**: Controllers, models, validators, docs, SDKs
|
|
155
|
+
|
|
156
|
+
### Luq's Practical Approach
|
|
157
|
+
|
|
158
|
+
| Challenge | Other Libraries | Luq Solution |
|
|
159
|
+
|-----------|----------------|--------------|
|
|
160
|
+
| **CSP Restrictions** | AJV fails at runtime | ✅ No eval/Function usage |
|
|
161
|
+
| **Dynamic Schemas** | AJV Standalone can't adapt | ✅ Full runtime flexibility |
|
|
162
|
+
| **Existing Types** | Rewrite as schemas | ✅ Use types as-is |
|
|
163
|
+
| **Custom Rules** | Copy-paste code | ✅ Type-safe plugins |
|
|
164
|
+
| **Bundle Size** | All-or-nothing | ✅ Import only what you need |
|
|
165
|
+
|
|
166
|
+
## Why Invest in Luq Today?
|
|
167
|
+
|
|
168
|
+
### Immediate Benefits (Phase 1 - Now)
|
|
169
|
+
| Feature | Value |
|
|
170
|
+
|---------|-------|
|
|
171
|
+
| **Type-First** | Use existing TypeScript types |
|
|
172
|
+
| **Plugin Architecture** | Capture business logic once |
|
|
173
|
+
| **Production-Ready** | CSP-safe, tree-shakeable |
|
|
174
|
+
| **JSON Schema Support** | 100% Draft-07 compliance |
|
|
175
|
+
|
|
176
|
+
### Future Benefits (Phase 2-4)
|
|
177
|
+
| Feature | Value |
|
|
178
|
+
|---------|-------|
|
|
179
|
+
| **Universal Validation** | One source of truth for all platforms |
|
|
180
|
+
| **Business Logic Preservation** | Never duplicate complex rules |
|
|
181
|
+
| **Language Agnostic** | Generate for any target language |
|
|
182
|
+
| **Performance Optimized** | AOT compilation when needed |
|
|
183
|
+
|
|
184
|
+
### The Strategic Advantage
|
|
185
|
+
|
|
186
|
+
**Start using Luq today to**:
|
|
187
|
+
1. Solve immediate TypeScript validation needs
|
|
188
|
+
2. Gradually capture your business rules as plugins
|
|
189
|
+
3. Prepare for automatic multi-language generation
|
|
190
|
+
4. Future-proof your validation strategy
|
|
191
|
+
|
|
192
|
+
## Motivation
|
|
193
|
+
|
|
194
|
+
### The Real Problem: Death by a Thousand Cuts
|
|
195
|
+
|
|
196
|
+
Every application needs input validation. It's not optional—it's fundamental. Yet despite decades of software evolution, validation remains surprisingly painful:
|
|
197
|
+
|
|
198
|
+
**The daily frustrations that sparked Luq:**
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Frontend (TypeScript)
|
|
202
|
+
function validateOrder(order: Order) {
|
|
203
|
+
// Write validation logic once...
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// BFF (Node.js)
|
|
207
|
+
function validateOrder(order) {
|
|
208
|
+
// Write it again, slightly different...
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Backend (Java/Python/Go)
|
|
212
|
+
public ValidationResult validateOrder(Order order) {
|
|
213
|
+
// Write it yet again, hope it matches...
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Three implementations. Three chances for bugs. Zero consistency.
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**The "solutions" that aren't:**
|
|
220
|
+
|
|
221
|
+
1. **JSON/YAML validation configs**: Trading code for configuration hell
|
|
222
|
+
```yaml
|
|
223
|
+
# Expressing complex business logic in YAML? No thanks.
|
|
224
|
+
rules:
|
|
225
|
+
- field: discount
|
|
226
|
+
when:
|
|
227
|
+
customer.tier:
|
|
228
|
+
not_in: [gold, platinum]
|
|
229
|
+
max: 0
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
2. **Runtime schema validators**: Losing type safety for "flexibility"
|
|
233
|
+
```javascript
|
|
234
|
+
// Types and validation drift apart over time
|
|
235
|
+
const schema = { /* 500 lines of schema */ }
|
|
236
|
+
type User = any; // "We'll fix the types later"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
3. **Code generation from specs**: One-way streets with no return
|
|
240
|
+
```bash
|
|
241
|
+
# Generate once, customize, now you can never regenerate
|
|
242
|
+
openapi-generator generate -i spec.yaml
|
|
243
|
+
# Months later: spec and code are completely out of sync
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Why Luq Exists
|
|
247
|
+
|
|
248
|
+
I searched for a solution that would let me:
|
|
249
|
+
- Write validation logic in a code-like manner (not JSON/YAML)
|
|
250
|
+
- Share the exact same rules across TypeScript, Java, Python, etc.
|
|
251
|
+
- Keep my existing TypeScript types as the source of truth
|
|
252
|
+
- Gradually evolve from simple validation to a complete platform
|
|
253
|
+
|
|
254
|
+
No existing OSS project met these needs. They all forced compromises:
|
|
255
|
+
- Use our schema format (forget your existing types)
|
|
256
|
+
- Use our configuration language (goodbye type safety)
|
|
257
|
+
- Use our specific stack (vendor lock-in)
|
|
258
|
+
- Generate once and maintain forever (technical debt from day one)
|
|
259
|
+
|
|
260
|
+
**So I built Luq with a simple philosophy:**
|
|
261
|
+
1. **Phase 1**: Solve today's validation pain in TypeScript
|
|
262
|
+
2. **Phase 2**: Define once in .luq, generate for every language
|
|
263
|
+
3. **Phase 3**: Expand to complete API/model/business logic platform
|
|
264
|
+
|
|
265
|
+
This isn't about building another validation library. It's about ending the cycle of rewriting the same validation logic in every layer of every application.
|
|
266
|
+
|
|
267
|
+
### Migration Considerations
|
|
268
|
+
|
|
269
|
+
Teams evaluating validation solutions often face practical constraints:
|
|
270
|
+
|
|
271
|
+
| Constraint | Challenge | Luq's Approach |
|
|
272
|
+
|------------|-----------|----------------|
|
|
273
|
+
| **Organizational** | Established standards and architecture | Works with existing TypeScript types |
|
|
274
|
+
| **Time** | Limited resources for refactoring | Incremental adoption possible |
|
|
275
|
+
| **Risk** | Production stability requirements | Non-breaking additive changes |
|
|
276
|
+
|
|
277
|
+
**Optional Progressive Path:**
|
|
278
|
+
|
|
279
|
+
1. Start with Builder pattern using existing types
|
|
280
|
+
2. Convert to declarative `.luq` format when beneficial
|
|
281
|
+
3. Generate optimized validators via AOT compilation
|
|
282
|
+
4. Future: Cross-language code generation
|
|
283
|
+
|
|
284
|
+
### Validation Scope Comparison
|
|
285
|
+
|
|
286
|
+
| Tool Category | Focus | Capabilities |
|
|
287
|
+
|---------------|-------|-------------|
|
|
288
|
+
| **API Specs** (OpenAPI, GraphQL) | Structure & Types | Basic constraints |
|
|
289
|
+
| **Schema Validators** | Type Safety | Type + simple rules |
|
|
290
|
+
| **Luq (.luq format)** | Complete Validation | Type + constraints + relationships + business logic |
|
|
291
|
+
|
|
292
|
+
Luq's planned `.luq` format aims to capture:
|
|
293
|
+
- Field-level constraints (min, max, patterns)
|
|
294
|
+
- Cross-field relationships
|
|
295
|
+
- Contextual validation rules
|
|
296
|
+
- Domain-specific business logic
|
|
297
|
+
|
|
298
|
+
### Choosing Between Approaches
|
|
299
|
+
|
|
300
|
+
| Factor | Schema-First | Type-First |
|
|
301
|
+
|--------|--------------|------------|
|
|
302
|
+
| **Best For** | New projects | Existing codebases |
|
|
303
|
+
| **Type Source** | Generated from schema | Already defined |
|
|
304
|
+
| **Migration Effort** | Rewrite types as schemas | Add validation to existing types |
|
|
305
|
+
| **Type Safety** | Schema drives types | Types drive validation |
|
|
306
|
+
|
|
307
|
+
Both approaches are valid. The choice depends on your project's context and constraints.
|
|
308
|
+
|
|
309
|
+
### Technical Design Decisions
|
|
310
|
+
|
|
311
|
+
**Architecture Choices:**
|
|
312
|
+
|
|
313
|
+
| Decision | Trade-off | Rationale |
|
|
314
|
+
|----------|-----------|-----------|
|
|
315
|
+
| **Plugin System** | Performance vs Extensibility | Prioritizes customization and tree-shaking |
|
|
316
|
+
| **Type-First** | Learning curve vs Migration ease | Reduces friction for existing projects |
|
|
317
|
+
| **Zero Dependencies** | Features vs Bundle size | Ensures predictable bundle size |
|
|
318
|
+
|
|
319
|
+
**Performance Considerations:**
|
|
320
|
+
- Optimized for common validation patterns (required fields, length checks, ranges)
|
|
321
|
+
- Plugin system adds ~15-20% overhead vs monolithic code
|
|
322
|
+
- AOT compilation planned to eliminate runtime overhead
|
|
323
|
+
|
|
324
|
+
**Note:** Different projects have different needs. Luq is one option among many excellent validation libraries in the ecosystem.
|
|
325
|
+
|
|
326
|
+
## Performance & Bundle Size
|
|
327
|
+
|
|
328
|
+
### Bundle Size Comparison (gzipped, measured 2025-08-14)
|
|
329
|
+
|
|
330
|
+
| Library | Simple Schema | Complex Schema | Notes |
|
|
331
|
+
|---------|---------------|----------------|-------|
|
|
332
|
+
| **AJV Standalone** | 1.03 KB | 4.63 KB | Pre-compiled validation |
|
|
333
|
+
| **Valibot** | 1.31 KB | 2.49 KB | Modular design |
|
|
334
|
+
| **Yup** | 12.80 KB | 13.40 KB | Simple API |
|
|
335
|
+
| **Luq** | 19.10 KB | 22.47 KB | Tree-shakable plugins |
|
|
336
|
+
| **Luq (JsonSchema)** | 26.06 KB | 29.07 KB | JSON Schema with individual plugins |
|
|
337
|
+
| **Luq (JsonSchema Full)** | 31.75 KB | 32.32 KB | All JSON Schema features |
|
|
338
|
+
| **AJV** | 37.78 KB | 38.33 KB | Full JSON Schema |
|
|
339
|
+
| **Joi** | 44.44 KB | 45.00 KB | Server-focused |
|
|
340
|
+
| **Zod** | 47.45 KB | 48.12 KB | Feature-rich |
|
|
341
|
+
|
|
342
|
+
### Performance Benchmarks (ops/sec)
|
|
343
|
+
|
|
344
|
+
> **Context**: Raw speed isn't everything. AJV achieves top performance using `new Function()` which fails in CSP-restricted environments. AJV Standalone requires build-time compilation, preventing dynamic schemas. Luq provides the best balance for real-world production use.
|
|
345
|
+
|
|
346
|
+
#### Simple Schema
|
|
347
|
+
| Library | Operations/sec | Relative | CSP Safe | Dynamic |
|
|
348
|
+
|---------|---------------|----------|----------|---------|
|
|
349
|
+
| **AJV Standalone** | 3,307,131 | 267.6x | ✅ | ❌ |
|
|
350
|
+
| **AJV** | 2,480,209 | 200.6x | ❌ | ✅ |
|
|
351
|
+
| **Luq (JsonSchema)** | 1,684,363 | 136.2x | ✅ | ✅ |
|
|
352
|
+
| **Luq (JsonSchema Full)** | 1,586,665 | 128.3x | ✅ | ✅ |
|
|
353
|
+
| **Luq** | 1,235,123 | 100.0x | ✅ | ✅ |
|
|
354
|
+
| **Valibot** | 902,700 | 73.0x | ✅ | ✅ |
|
|
355
|
+
| **Zod** | 486,275 | 39.3x | ✅ | ✅ |
|
|
356
|
+
| **Joi** | 175,362 | 14.2x | ✅ | ✅ |
|
|
357
|
+
| **Yup** | 130,129 | 10.5x | ✅ | ✅ |
|
|
358
|
+
|
|
359
|
+
#### Complex Schema
|
|
360
|
+
| Library | Operations/sec | Relative | CSP Safe | Dynamic |
|
|
361
|
+
|---------|---------------|----------|----------|---------|
|
|
362
|
+
| **AJV Standalone** | 239,848 | 5.51x | ✅ | ❌ |
|
|
363
|
+
| **AJV** | 232,378 | 5.34x | ❌ | ✅ |
|
|
364
|
+
| **Valibot** | 171,352 | 3.94x | ✅ | ✅ |
|
|
365
|
+
| **Zod** | 61,488 | 1.41x | ✅ | ✅ |
|
|
366
|
+
| **Luq** | 43,524 | 1.00x | ✅ | ✅ |
|
|
367
|
+
| **Luq (JsonSchema Full)** | 31,462 | 0.72x | ✅ | ✅ |
|
|
368
|
+
| **Luq (JsonSchema)** | 29,257 | 0.67x | ✅ | ✅ |
|
|
369
|
+
| **Joi** | 23,552 | 0.54x | ✅ | ✅ |
|
|
370
|
+
| **Yup** | 5,841 | 0.13x | ✅ | ✅ |
|
|
371
|
+
|
|
372
|
+
*Test Environment: AMD Ryzen 7 5825U, 5.8GB RAM, Node.js v22.12.0*
|
|
373
|
+
|
|
374
|
+
### The Practical Choice
|
|
375
|
+
|
|
376
|
+
**For production environments where you need:**
|
|
377
|
+
- ✅ Dynamic validation rules (from API/CMS)
|
|
378
|
+
- ✅ CSP compliance (no eval/Function)
|
|
379
|
+
- ✅ Type safety with existing TypeScript types
|
|
380
|
+
- ✅ Reasonable performance (faster than Yup/Joi)
|
|
381
|
+
|
|
382
|
+
**Luq is the most practical choice.**
|
|
383
|
+
|
|
384
|
+
**Note**: Performance numbers may vary with strict key validation. AJV's speed advantage comes at the cost of CSP compatibility.
|
|
385
|
+
|
|
386
|
+
## JSON Schema Support
|
|
387
|
+
|
|
388
|
+
Luq provides 100% JSON Schema Draft-07 support through a modular plugin system. You can import all necessary plugins at once or cherry-pick specific features.
|
|
389
|
+
|
|
390
|
+
### Quick Setup
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
import { Builder } from "@maroonedog/luq";
|
|
394
|
+
import { jsonSchemaFullFeaturePlugin } from "@maroonedog/luq/plugins/jsonSchemaFullFeature";
|
|
395
|
+
|
|
396
|
+
// Single plugin import for full JSON Schema support
|
|
397
|
+
const validator = Builder()
|
|
398
|
+
.use(jsonSchemaFullFeaturePlugin)
|
|
399
|
+
.fromJsonSchema({
|
|
400
|
+
type: "object",
|
|
401
|
+
properties: {
|
|
402
|
+
email: { type: "string", format: "email" },
|
|
403
|
+
age: { type: "number", minimum: 18 },
|
|
404
|
+
},
|
|
405
|
+
required: ["email"],
|
|
406
|
+
})
|
|
407
|
+
.build();
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### JSON Schema Support Summary
|
|
411
|
+
|
|
412
|
+
Luq provides **100% JSON Schema Draft-07 compliance** through modular plugins:
|
|
413
|
+
|
|
414
|
+
| Category | Coverage | Examples |
|
|
415
|
+
|----------|----------|----------|
|
|
416
|
+
| **Core Types** | ✅ Complete | string, number, boolean, null, array, object |
|
|
417
|
+
| **String Formats** | ✅ 15+ formats | email, url, uuid, date-time, ipv4/ipv6 |
|
|
418
|
+
| **Constraints** | ✅ All standard | min/max, pattern, unique, required |
|
|
419
|
+
| **Schema Composition** | ✅ Full support | allOf, anyOf, oneOf, not |
|
|
420
|
+
| **Advanced Features** | ✅ Complete | $ref, conditional validation, dependencies |
|
|
421
|
+
|
|
422
|
+
📖 **[View complete JSON Schema mapping →](https://luq.dev/json-schema)**
|
|
423
|
+
|
|
424
|
+
### Using Individual Plugins
|
|
425
|
+
|
|
426
|
+
If you prefer to import only the plugins you need:
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { Builder } from "@maroonedog/luq";
|
|
430
|
+
import { jsonSchemaPlugin } from "@maroonedog/luq/plugins/jsonSchema";
|
|
431
|
+
import { requiredPlugin } from "@maroonedog/luq/plugins/required";
|
|
432
|
+
import { stringMinPlugin } from "@maroonedog/luq/plugins/stringMin";
|
|
433
|
+
import { stringEmailPlugin } from "@maroonedog/luq/plugins/stringEmail";
|
|
434
|
+
import { numberMinPlugin } from "@maroonedog/luq/plugins/numberMin";
|
|
435
|
+
|
|
436
|
+
const validator = Builder()
|
|
437
|
+
.use(jsonSchemaPlugin)
|
|
438
|
+
.use(requiredPlugin)
|
|
439
|
+
.use(stringMinPlugin)
|
|
440
|
+
.use(stringEmailPlugin)
|
|
441
|
+
.use(numberMinPlugin)
|
|
442
|
+
.fromJsonSchema(schema)
|
|
443
|
+
.build();
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## The Journey to Universal Platform (Progressive Abstraction Architecture)
|
|
447
|
+
|
|
448
|
+
| Phase | Timeline | What We're Building | Impact |
|
|
449
|
+
|-------|----------|-------------------|---------|
|
|
450
|
+
| **Level 1** | ✅ Now | TypeScript validation library | **Foundation**: Type-first validation with plugin architecture |
|
|
451
|
+
| **Level 2** | Q1-Q3 2026 | .luq format & infrastructure | **Transformation**: Single source for models & validation |
|
|
452
|
+
| **v1.0** | Q4 2026 | Java support + production ready | **Expansion**: First multi-language release |
|
|
453
|
+
| **Level 3** | Beyond 2026 | Unified platform | **Vision**: API + models + validation + business logic |
|
|
454
|
+
|
|
455
|
+
### Roadmap Highlights
|
|
456
|
+
|
|
457
|
+
**Q4 2025**: Frontend framework integration (React hooks, etc.)
|
|
458
|
+
**Q1-Q3 2026**: .luq format specification, VSCode extension, Language Server
|
|
459
|
+
**Q4 2026**: **v1.0 Release with Java support & production toolchain**
|
|
460
|
+
**2027+**: Python, Go, C#, Rust + expanded platform features
|
|
461
|
+
|
|
462
|
+
### Current Capabilities (Phase 1)
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
// Use existing TypeScript types
|
|
466
|
+
type User = {
|
|
467
|
+
name: string;
|
|
468
|
+
email: string;
|
|
469
|
+
age: number;
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// Add validation incrementally
|
|
473
|
+
const validator = Builder()
|
|
474
|
+
.use(requiredPlugin)
|
|
475
|
+
.use(stringMinPlugin)
|
|
476
|
+
.use(stringEmailPlugin)
|
|
477
|
+
.use(numberMinPlugin)
|
|
478
|
+
.for<User>()
|
|
479
|
+
.v("name", (b) => b.string.required().min(3))
|
|
480
|
+
.v("email", (b) => b.string.required().email())
|
|
481
|
+
.v("age", (b) => b.number.required().min(18))
|
|
482
|
+
.build();
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### The .luq Format: Unified Model Definition Language (Phase 2)
|
|
486
|
+
|
|
487
|
+
**⚠️ CRITICAL DISTINCTION**: `.luq` is **NOT TypeScript**. It's a **TypeScript-like** language with its own syntax, compiler, and toolchain.
|
|
488
|
+
|
|
489
|
+
**What .luq actually is:**
|
|
490
|
+
- **Independent Language**: A domain-specific language (DSL) for API/model/validation definition
|
|
491
|
+
- **TypeScript-like Syntax**: Familiar syntax to reduce learning curve, but NOT TypeScript
|
|
492
|
+
- **Custom Compiler**: Our own parser, type checker, and code generator
|
|
493
|
+
- **No TypeScript Runtime**: Cannot import TypeScript modules or use TypeScript features directly
|
|
494
|
+
- **Purpose-Built**: Designed specifically for cross-language validation and API generation
|
|
495
|
+
|
|
496
|
+
**Why TypeScript-like (not TypeScript):**
|
|
497
|
+
```typescript
|
|
498
|
+
// ❌ This is NOT valid .luq (TypeScript features won't work)
|
|
499
|
+
interface Order {
|
|
500
|
+
items: Array<Product>; // ❌ TypeScript generics
|
|
501
|
+
total: number | null; // ❌ TypeScript union types
|
|
502
|
+
created: Date; // ❌ TypeScript Date type
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// ✅ This is valid .luq (TypeScript-like but different)
|
|
506
|
+
interface Order {
|
|
507
|
+
@array(Product)
|
|
508
|
+
items: Product[]; // .luq array syntax
|
|
509
|
+
|
|
510
|
+
@nullable
|
|
511
|
+
total: number; // .luq nullable decorator
|
|
512
|
+
|
|
513
|
+
@datetime
|
|
514
|
+
created: string; // .luq uses string with format decorators
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**What we're building:**
|
|
519
|
+
- **Custom VSCode extension**: NOT a TypeScript extension, but a completely new language support
|
|
520
|
+
- **Independent Language Server**: Our own LSP implementation, not TypeScript's
|
|
521
|
+
- **Dedicated Compiler**: .luq → multi-language code generation pipeline
|
|
522
|
+
- **Separate Type System**: Similar to TypeScript but with validation-specific semantics
|
|
523
|
+
|
|
524
|
+
**Key Language Features:**
|
|
525
|
+
- **Built-in adapters**: Standard database, cache, queue abstractions (primary approach)
|
|
526
|
+
- **Escape hatch imports**: Direct import of existing code when needed (language-specific)
|
|
527
|
+
- **Type checking**: Our own type system optimized for validation and code generation
|
|
528
|
+
- **Decorators**: First-class citizens in .luq (not experimental like TypeScript)
|
|
529
|
+
- **Validator functions**: Built into the language semantics
|
|
530
|
+
- **Cross-language semantics**: Designed to map cleanly to Java, Python, Go, etc.
|
|
531
|
+
|
|
532
|
+
**Primary Approach: Built-in Adapters (90% of use cases)**
|
|
533
|
+
```typescript
|
|
534
|
+
// order.luq - Use generated, standardized adapters
|
|
535
|
+
|
|
536
|
+
// Database adapter - generated for each target language
|
|
537
|
+
@database("postgresql")
|
|
538
|
+
adapter db {
|
|
539
|
+
orders: Order[];
|
|
540
|
+
customers: Customer[];
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Cache adapter
|
|
544
|
+
@cache("redis")
|
|
545
|
+
adapter cache {
|
|
546
|
+
ttl: 3600;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Use standardized interfaces in validation
|
|
550
|
+
@crossField
|
|
551
|
+
async function validateCustomerCredit(this: Order): Promise<ValidationResult> {
|
|
552
|
+
// db.select() is generated in every target language
|
|
553
|
+
const customer = await db.select(Customer)
|
|
554
|
+
.where("id", this.customer.id)
|
|
555
|
+
.first();
|
|
556
|
+
|
|
557
|
+
const orderTotal = await db.select(Order)
|
|
558
|
+
.where("customerId", customer.id)
|
|
559
|
+
.sum("total");
|
|
560
|
+
|
|
561
|
+
if (orderTotal + this.total > customer.creditLimit) {
|
|
562
|
+
return error("Exceeds credit limit");
|
|
563
|
+
}
|
|
564
|
+
return ok();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Generated standardized code for each language
|
|
568
|
+
// Each language uses its idiomatic patterns
|
|
569
|
+
// Users can choose their preferred framework
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**Escape Hatch: Direct Imports (10% special cases)**
|
|
573
|
+
```typescript
|
|
574
|
+
// Only when you need existing business logic that can't be standardized
|
|
575
|
+
|
|
576
|
+
// Import existing Java service (escape hatch)
|
|
577
|
+
@importJava("../legacy/ComplexBusinessLogic.java")
|
|
578
|
+
import ComplexBusinessLogic;
|
|
579
|
+
|
|
580
|
+
@validator
|
|
581
|
+
async function validateComplexRule(this: Order): Promise<ValidationResult> {
|
|
582
|
+
// Use existing complex logic that can't be easily migrated
|
|
583
|
+
return await ComplexBusinessLogic.validateWithLegacyRules(this);
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Why create a TypeScript-like language instead of using TypeScript?**
|
|
588
|
+
- **Familiar syntax**: Reduces learning curve for millions of developers
|
|
589
|
+
- **Purpose-built semantics**: Validation and API features as first-class citizens
|
|
590
|
+
- **Cross-language mapping**: Designed to generate clean code in Java, Python, Go, etc.
|
|
591
|
+
- **No JavaScript baggage**: Free from JS/TS runtime limitations and quirks
|
|
592
|
+
- **Validation-optimized**: Type system designed specifically for validation use cases
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
// order.luq - Complete API & model definition in one place
|
|
596
|
+
|
|
597
|
+
// Standard adapters (recommended approach)
|
|
598
|
+
@database("postgresql")
|
|
599
|
+
adapter db {
|
|
600
|
+
orders: Order[];
|
|
601
|
+
customers: Customer[];
|
|
602
|
+
products: Product[];
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
@cache("redis")
|
|
606
|
+
adapter cache {
|
|
607
|
+
ttl: 3600;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Import only for special cases (escape hatch)
|
|
611
|
+
import { calculateTotalFromItems } from "./business-logic"; // Legacy TypeScript
|
|
612
|
+
@importJava("../legacy/TaxCalculator.java") // Legacy Java that can't be migrated
|
|
613
|
+
import TaxCalculator;
|
|
614
|
+
|
|
615
|
+
// API endpoint definition
|
|
616
|
+
@endpoint("/api/orders")
|
|
617
|
+
@authenticated
|
|
618
|
+
interface OrderAPI {
|
|
619
|
+
@post("/")
|
|
620
|
+
@rateLimit(100)
|
|
621
|
+
create(body: CreateOrderRequest): OrderResponse;
|
|
622
|
+
|
|
623
|
+
@get("/:id")
|
|
624
|
+
@cache(300)
|
|
625
|
+
getById(id: string): Order;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Data model with validation
|
|
629
|
+
interface Order {
|
|
630
|
+
@uuid()
|
|
631
|
+
id: string;
|
|
632
|
+
|
|
633
|
+
@required() @min(0)
|
|
634
|
+
@computed(calculateTotalFromItems) // Use imported function
|
|
635
|
+
total: number;
|
|
636
|
+
|
|
637
|
+
@minLength(1) @maxLength(100)
|
|
638
|
+
items: OrderItem[];
|
|
639
|
+
|
|
640
|
+
@required()
|
|
641
|
+
customer: {
|
|
642
|
+
@required()
|
|
643
|
+
id: string;
|
|
644
|
+
|
|
645
|
+
@oneOf(["active", "suspended", "closed"])
|
|
646
|
+
@validate(isActiveCustomer) // Type-safe function reference
|
|
647
|
+
status: string;
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Cross-field validation - 'this' parameter for model context
|
|
652
|
+
@crossField
|
|
653
|
+
function validateDiscountEligibility(this: Order): ValidationResult {
|
|
654
|
+
if (this.discount > 0 && !["gold", "platinum"].includes(this.customer.tier)) {
|
|
655
|
+
return error("Discount requires gold or platinum tier");
|
|
656
|
+
}
|
|
657
|
+
return ok();
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Field-level validation with parameters
|
|
661
|
+
interface Product {
|
|
662
|
+
@min(0) @max(1000000) // Simple decorators with arguments
|
|
663
|
+
price: number;
|
|
664
|
+
|
|
665
|
+
@validate(validatePriceRange, 100, 50000) // Function with additional params
|
|
666
|
+
premiumPrice: number;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Validator function that accepts additional parameters
|
|
670
|
+
function validatePriceRange(value: number, min: number, max: number): ValidationResult {
|
|
671
|
+
if (value < min || value > max) {
|
|
672
|
+
return error(`Price must be between ${min} and ${max}`);
|
|
673
|
+
}
|
|
674
|
+
return ok();
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Cross-field with async and this context
|
|
678
|
+
@crossField
|
|
679
|
+
async function validateInventory(this: Order): Promise<ValidationResult> {
|
|
680
|
+
const available = await checkInventory(this.items);
|
|
681
|
+
return available ? ok() : error("Insufficient inventory");
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Recommended: Use standard adapter
|
|
685
|
+
@crossField
|
|
686
|
+
async function validateCustomerCredit(this: Order): Promise<ValidationResult> {
|
|
687
|
+
// Standard query interface - same in all generated languages
|
|
688
|
+
const customer = await db.select(Customer)
|
|
689
|
+
.where("id", this.customer.id)
|
|
690
|
+
.include("orders") // Eager loading
|
|
691
|
+
.first();
|
|
692
|
+
|
|
693
|
+
const totalOrders = customer.orders.reduce((sum, o) => sum + o.total, 0);
|
|
694
|
+
return totalOrders + this.total <= customer.creditLimit
|
|
695
|
+
? ok()
|
|
696
|
+
: error("Exceeds credit limit");
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Escape hatch: When you must use existing service
|
|
700
|
+
@crossField
|
|
701
|
+
async function validateTax(this: Order): Promise<ValidationResult> {
|
|
702
|
+
// Use legacy Java service that can't be standardized
|
|
703
|
+
const tax = await TaxCalculator.calculateComplexTax(this);
|
|
704
|
+
return tax > 0 ? ok() : error("Invalid tax calculation");
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Decorator Signature Patterns:**
|
|
709
|
+
```typescript
|
|
710
|
+
// Pattern 1: Simple decorators with direct values
|
|
711
|
+
@min(0) @max(100) // Built-in decorators
|
|
712
|
+
price: number;
|
|
713
|
+
|
|
714
|
+
// Pattern 2: Field validator with value as first parameter
|
|
715
|
+
@validate(isValidSKU) // (value: string) => ValidationResult
|
|
716
|
+
sku: string;
|
|
717
|
+
|
|
718
|
+
// Pattern 3: Field validator with additional parameters
|
|
719
|
+
@validate(matchesPattern, /^SKU-\d{6}$/) // (value: string, pattern: RegExp) => ValidationResult
|
|
720
|
+
productCode: string;
|
|
721
|
+
|
|
722
|
+
// Pattern 4: Cross-field validator with 'this' context
|
|
723
|
+
@crossField
|
|
724
|
+
function validateRelatedFields(this: Order): ValidationResult {
|
|
725
|
+
// Access entire model via 'this'
|
|
726
|
+
if (this.endDate <= this.startDate) {
|
|
727
|
+
return error("End date must be after start date");
|
|
728
|
+
}
|
|
729
|
+
return ok();
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Pattern 5: Computed field with 'this' context
|
|
733
|
+
@computed
|
|
734
|
+
function calculateTotal(this: Order): number {
|
|
735
|
+
return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
**What the .luq toolchain generates**:
|
|
740
|
+
- **Backend code**: Controllers, models, validators
|
|
741
|
+
- **Client SDKs**: Type-safe API clients
|
|
742
|
+
- **Documentation**: API specs in standard formats
|
|
743
|
+
- **Adapters**: Database and service integrations
|
|
744
|
+
- **Business logic**: Consistent across all platforms
|
|
745
|
+
|
|
746
|
+
## Real-World Example: Dynamic Validation
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
// Common scenario: Load validation rules from API or CMS
|
|
750
|
+
async function loadValidationRules() {
|
|
751
|
+
const rules = await fetch('/api/validation-rules').then(r => r.json());
|
|
752
|
+
|
|
753
|
+
// ❌ AJV: Fails in production with CSP
|
|
754
|
+
// const ajv = new Ajv();
|
|
755
|
+
// const validate = ajv.compile(rules); // Uses new Function() internally
|
|
756
|
+
|
|
757
|
+
// ❌ AJV Standalone: Can't handle dynamic schemas
|
|
758
|
+
// Pre-compiled at build time, can't adapt to API response
|
|
759
|
+
|
|
760
|
+
// ✅ Luq: Works everywhere, adapts at runtime
|
|
761
|
+
const validator = Builder()
|
|
762
|
+
.use(jsonSchemaFullFeaturePlugin)
|
|
763
|
+
.fromJsonSchema(rules)
|
|
764
|
+
.build();
|
|
765
|
+
|
|
766
|
+
return validator;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// Multi-tenant SaaS with per-customer rules
|
|
770
|
+
async function getCustomerValidator(customerId: string) {
|
|
771
|
+
const config = await getCustomerConfig(customerId);
|
|
772
|
+
|
|
773
|
+
// Luq can safely build validators at runtime
|
|
774
|
+
return Builder()
|
|
775
|
+
.use(requiredPlugin)
|
|
776
|
+
.use(customBusinessPlugin)
|
|
777
|
+
.for<Order>()
|
|
778
|
+
.v("total", b => b.number.min(config.minOrderValue))
|
|
779
|
+
.v("items", b => b.array.maxLength(config.maxItems))
|
|
780
|
+
.build();
|
|
781
|
+
}
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
## Technical Specifications
|
|
785
|
+
|
|
786
|
+
### Architecture Features
|
|
787
|
+
|
|
788
|
+
| Feature | Description | Impact |
|
|
789
|
+
|---------|-------------|--------|
|
|
790
|
+
| **AOT Compilation** | Pre-compile validators at build time | Eliminates runtime overhead |
|
|
791
|
+
| **Plugin System** | Modular validation rules | Tree-shaking support |
|
|
792
|
+
| **Zero Dependencies** | No external runtime dependencies | Predictable bundle size |
|
|
793
|
+
| **Type Safety** | Full TypeScript type inference | Compile-time error detection |
|
|
794
|
+
|
|
795
|
+
### Use Case Recommendations
|
|
796
|
+
|
|
797
|
+
| Scenario | Recommended Configuration | Rationale |
|
|
798
|
+
|----------|---------------------------|-----------|
|
|
799
|
+
| **CSP-restricted environments** | **Luq** | No eval/Function, full features |
|
|
800
|
+
| **Dynamic schema loading** | **Luq** | Safe runtime validation |
|
|
801
|
+
| **Existing TypeScript types** | **Luq** | No schema rewriting needed |
|
|
802
|
+
| **Custom business rules** | **Luq** | Type-safe plugin architecture |
|
|
803
|
+
| **JSON Schema migration** | Luq JsonSchema | Full compatibility, safe runtime |
|
|
804
|
+
| **Minimal bundle critical** | Valibot | 1-2KB solution |
|
|
805
|
+
| **Pre-compiled validation** | AJV Standalone | If schemas never change |
|
|
806
|
+
|
|
807
|
+
### Benchmark Methodology
|
|
808
|
+
|
|
809
|
+
- Test data: Simple (3 fields) and Complex (nested objects, arrays) schemas
|
|
810
|
+
- Iterations: 1,000,000 operations per benchmark
|
|
811
|
+
- Environment: AMD Ryzen 7 5825U, 5.8GB RAM, Node.js v22.12.0
|
|
812
|
+
- Details: See `bundle-size-comparison` directory
|
|
813
|
+
|
|
814
|
+
## Your Migration Path to Universal Platform
|
|
815
|
+
|
|
816
|
+
### Today - Level 1 (Available Now)
|
|
817
|
+
```typescript
|
|
818
|
+
// Start with validation using your existing TypeScript types
|
|
819
|
+
import { Builder } from "@maroonedog/luq";
|
|
820
|
+
const validator = Builder().for<Order>()
|
|
821
|
+
.v("total", b => b.number.min(0))
|
|
822
|
+
.build();
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
### 2026 Q1-Q3 - Level 2 (.luq Format)
|
|
826
|
+
```typescript
|
|
827
|
+
// Unified model & validation definitions
|
|
828
|
+
// order.luq
|
|
829
|
+
interface Order {
|
|
830
|
+
@min(0) @businessRule("calculateTotal")
|
|
831
|
+
total: number;
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
### 2026 Q4 - v1.0 (Java Support)
|
|
836
|
+
```bash
|
|
837
|
+
# Generate for TypeScript & Java
|
|
838
|
+
luq generate order.luq --lang=typescript --out=frontend/
|
|
839
|
+
luq generate order.luq --lang=java --out=backend/
|
|
840
|
+
|
|
841
|
+
# Generated code integrates with your existing stack
|
|
842
|
+
# No framework lock-in - use what you prefer
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### Future - Level 3 (Unified Platform)
|
|
846
|
+
```typescript
|
|
847
|
+
// Complete API & model definition
|
|
848
|
+
// api.luq
|
|
849
|
+
@endpoint("/api/orders")
|
|
850
|
+
interface OrderAPI {
|
|
851
|
+
@post("/") create(body: Order): OrderResponse;
|
|
852
|
+
@get("/:id") getById(id: string): Order;
|
|
853
|
+
}
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
```bash
|
|
857
|
+
# Generate everything
|
|
858
|
+
luq generate api.luq --target=all
|
|
859
|
+
|
|
860
|
+
✓ Backend code generation
|
|
861
|
+
✓ Client SDK generation
|
|
862
|
+
✓ API documentation
|
|
863
|
+
✓ Complete type safety across all targets
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
**Progressive Abstraction Architecture: Start simple, evolve to comprehensive.**
|
|
867
|
+
|
|
868
|
+
## Learn More
|
|
869
|
+
|
|
870
|
+
For detailed documentation, advanced examples, and roadmap:
|
|
871
|
+
|
|
872
|
+
**📖 [Documentation](https://luq.dev)** - Complete guides and API reference
|
|
873
|
+
**🚀 [Roadmap](https://luq.dev/roadmap)** - Development timeline and future plans
|
|
874
|
+
**🧩 [Plugins](https://luq.dev/plugins)** - Browse available plugins
|
|
875
|
+
**💡 [Examples](https://luq.dev/guides)** - Real-world usage patterns
|
|
876
|
+
|
|
877
|
+
## License
|
|
878
|
+
|
|
879
|
+
MIT
|