@promakeai/orm 1.0.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/README.md +154 -0
- package/dist/ORM.d.ts +190 -0
- package/dist/adapters/IDataAdapter.d.ts +134 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +1054 -0
- package/dist/schema/defineSchema.d.ts +50 -0
- package/dist/schema/fieldBuilder.d.ts +152 -0
- package/dist/schema/helpers.d.ts +54 -0
- package/dist/schema/index.d.ts +9 -0
- package/dist/schema/schemaHelpers.d.ts +55 -0
- package/dist/schema/validator.d.ts +45 -0
- package/dist/types.d.ts +192 -0
- package/dist/utils/jsonConverter.d.ts +29 -0
- package/dist/utils/populateResolver.d.ts +57 -0
- package/dist/utils/translationQuery.d.ts +50 -0
- package/dist/utils/whereBuilder.d.ts +38 -0
- package/package.json +48 -0
- package/src/ORM.ts +398 -0
- package/src/adapters/IDataAdapter.ts +196 -0
- package/src/index.ts +148 -0
- package/src/schema/defineSchema.ts +164 -0
- package/src/schema/fieldBuilder.ts +244 -0
- package/src/schema/helpers.ts +171 -0
- package/src/schema/index.ts +47 -0
- package/src/schema/schemaHelpers.ts +123 -0
- package/src/schema/validator.ts +189 -0
- package/src/types.ts +243 -0
- package/src/utils/jsonConverter.ts +94 -0
- package/src/utils/populateResolver.ts +322 -0
- package/src/utils/translationQuery.ts +306 -0
- package/src/utils/whereBuilder.ts +154 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Definition API
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for defining database schemas.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { defineSchema, f } from '@promakeai/orm';
|
|
9
|
+
*
|
|
10
|
+
* export default defineSchema({
|
|
11
|
+
* languages: ['en', 'tr', 'de'],
|
|
12
|
+
* tables: {
|
|
13
|
+
* products: {
|
|
14
|
+
* id: f.id(),
|
|
15
|
+
* price: f.decimal().required(),
|
|
16
|
+
* name: f.string().translatable().required(),
|
|
17
|
+
* category_id: f.int().ref('categories'),
|
|
18
|
+
* },
|
|
19
|
+
* categories: {
|
|
20
|
+
* id: f.id(),
|
|
21
|
+
* slug: f.string().required().unique(),
|
|
22
|
+
* name: f.string().translatable().required(),
|
|
23
|
+
* },
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { SchemaDefinition, SchemaInput } from "../types";
|
|
29
|
+
export { f } from "./fieldBuilder";
|
|
30
|
+
/**
|
|
31
|
+
* Define a database schema with type-safe DSL
|
|
32
|
+
*
|
|
33
|
+
* @param input - Schema definition with languages and tables
|
|
34
|
+
* @returns Validated SchemaDefinition
|
|
35
|
+
* @throws Error if schema is invalid
|
|
36
|
+
*/
|
|
37
|
+
export declare function defineSchema(input: SchemaInput): SchemaDefinition;
|
|
38
|
+
/**
|
|
39
|
+
* Create schema without validation (for testing/internal use)
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export declare function createSchemaUnsafe(input: SchemaInput): SchemaDefinition;
|
|
43
|
+
/**
|
|
44
|
+
* Merge multiple schemas into one
|
|
45
|
+
*
|
|
46
|
+
* @param schemas - Array of schema definitions to merge
|
|
47
|
+
* @returns Merged schema definition
|
|
48
|
+
* @throws Error if table names conflict
|
|
49
|
+
*/
|
|
50
|
+
export declare function mergeSchemas(schemas: SchemaDefinition[]): SchemaDefinition;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field Builder DSL
|
|
3
|
+
*
|
|
4
|
+
* Type-safe fluent API for field definitions.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { f } from '@promakeai/orm';
|
|
9
|
+
*
|
|
10
|
+
* const schema = defineSchema({
|
|
11
|
+
* tables: {
|
|
12
|
+
* products: {
|
|
13
|
+
* id: f.id(),
|
|
14
|
+
* price: f.decimal().required().min(0),
|
|
15
|
+
* name: f.string().translatable().required().trim(),
|
|
16
|
+
* email: f.string().lowercase().trim().unique(),
|
|
17
|
+
* categoryId: f.int().ref('categories'),
|
|
18
|
+
* brandId: f.int().ref({ table: 'brands', onDelete: 'SET_NULL' }),
|
|
19
|
+
* },
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import type { FieldDefinition, FieldType } from "../types";
|
|
25
|
+
/**
|
|
26
|
+
* Fluent builder for field definitions
|
|
27
|
+
*/
|
|
28
|
+
export declare class FieldBuilder {
|
|
29
|
+
protected definition: FieldDefinition;
|
|
30
|
+
constructor(type: FieldType);
|
|
31
|
+
/**
|
|
32
|
+
* Mark field as NOT NULL
|
|
33
|
+
*/
|
|
34
|
+
required(): this;
|
|
35
|
+
/**
|
|
36
|
+
* Mark field as nullable (default)
|
|
37
|
+
*/
|
|
38
|
+
nullable(): this;
|
|
39
|
+
/**
|
|
40
|
+
* Mark field as UNIQUE
|
|
41
|
+
*/
|
|
42
|
+
unique(): this;
|
|
43
|
+
/**
|
|
44
|
+
* Set default value
|
|
45
|
+
*/
|
|
46
|
+
default(value: unknown): this;
|
|
47
|
+
/**
|
|
48
|
+
* Mark field as translatable (stored in translation table)
|
|
49
|
+
* Only valid for string/text fields
|
|
50
|
+
*/
|
|
51
|
+
translatable(): this;
|
|
52
|
+
/**
|
|
53
|
+
* Add reference to another table (MongoDB-style)
|
|
54
|
+
* @param tableOrOptions - Table name or options object
|
|
55
|
+
*/
|
|
56
|
+
ref(tableOrOptions: string | {
|
|
57
|
+
table: string;
|
|
58
|
+
field?: string;
|
|
59
|
+
onDelete?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
60
|
+
onUpdate?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
61
|
+
}): this;
|
|
62
|
+
/**
|
|
63
|
+
* Trim whitespace from string values
|
|
64
|
+
*/
|
|
65
|
+
trim(): this;
|
|
66
|
+
/**
|
|
67
|
+
* Convert string to lowercase
|
|
68
|
+
*/
|
|
69
|
+
lowercase(): this;
|
|
70
|
+
/**
|
|
71
|
+
* Convert string to uppercase
|
|
72
|
+
*/
|
|
73
|
+
uppercase(): this;
|
|
74
|
+
/**
|
|
75
|
+
* Minimum string length
|
|
76
|
+
*/
|
|
77
|
+
minLength(value: number): this;
|
|
78
|
+
/**
|
|
79
|
+
* Maximum string length
|
|
80
|
+
*/
|
|
81
|
+
maxLength(value: number): this;
|
|
82
|
+
/**
|
|
83
|
+
* Minimum numeric value
|
|
84
|
+
*/
|
|
85
|
+
min(value: number): this;
|
|
86
|
+
/**
|
|
87
|
+
* Maximum numeric value
|
|
88
|
+
*/
|
|
89
|
+
max(value: number): this;
|
|
90
|
+
/**
|
|
91
|
+
* Enum values (allowed values)
|
|
92
|
+
*/
|
|
93
|
+
enum(values: string[]): this;
|
|
94
|
+
/**
|
|
95
|
+
* RegExp pattern to match
|
|
96
|
+
*/
|
|
97
|
+
match(pattern: string): this;
|
|
98
|
+
/**
|
|
99
|
+
* Build the final field definition
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
build(): FieldDefinition;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Factory object for creating field builders
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* f.id() // Primary key
|
|
110
|
+
* f.string().required().trim() // NOT NULL trimmed string
|
|
111
|
+
* f.int().default(0).min(0) // Non-negative integer
|
|
112
|
+
* f.string().unique().lowercase() // Unique lowercase string
|
|
113
|
+
* f.string().translatable().required() // Translatable NOT NULL
|
|
114
|
+
* f.int().ref('users') // Foreign key to users
|
|
115
|
+
* f.int().ref({ table: 'users', onDelete: 'CASCADE' }) // With constraint
|
|
116
|
+
* f.json().ref('categories') // Array of category IDs
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare const f: {
|
|
120
|
+
/**
|
|
121
|
+
* Primary key field (INTEGER PRIMARY KEY AUTOINCREMENT)
|
|
122
|
+
*/
|
|
123
|
+
id: () => FieldBuilder;
|
|
124
|
+
/**
|
|
125
|
+
* String field (VARCHAR/TEXT)
|
|
126
|
+
*/
|
|
127
|
+
string: () => FieldBuilder;
|
|
128
|
+
/**
|
|
129
|
+
* Text field (TEXT/LONGTEXT)
|
|
130
|
+
*/
|
|
131
|
+
text: () => FieldBuilder;
|
|
132
|
+
/**
|
|
133
|
+
* Integer field (INTEGER)
|
|
134
|
+
*/
|
|
135
|
+
int: () => FieldBuilder;
|
|
136
|
+
/**
|
|
137
|
+
* Decimal field (REAL/DECIMAL)
|
|
138
|
+
*/
|
|
139
|
+
decimal: () => FieldBuilder;
|
|
140
|
+
/**
|
|
141
|
+
* Boolean field (INTEGER 0/1 in SQLite)
|
|
142
|
+
*/
|
|
143
|
+
bool: () => FieldBuilder;
|
|
144
|
+
/**
|
|
145
|
+
* Timestamp field (TEXT in ISO format)
|
|
146
|
+
*/
|
|
147
|
+
timestamp: () => FieldBuilder;
|
|
148
|
+
/**
|
|
149
|
+
* JSON field (TEXT with JSON serialization)
|
|
150
|
+
*/
|
|
151
|
+
json: () => FieldBuilder;
|
|
152
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Utilities for transforming table/field names.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Convert plural word to singular
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* singularize('products') // 'product'
|
|
12
|
+
* singularize('categories') // 'category'
|
|
13
|
+
* singularize('users') // 'user'
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function singularize(word: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Convert string to PascalCase
|
|
19
|
+
*/
|
|
20
|
+
export declare function toPascalCase(str: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Convert string to camelCase
|
|
23
|
+
*/
|
|
24
|
+
export declare function toCamelCase(str: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Convert string to snake_case
|
|
27
|
+
*/
|
|
28
|
+
export declare function toSnakeCase(str: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Get singular PascalCase name for interface
|
|
31
|
+
*/
|
|
32
|
+
export declare function toInterfaceName(tableName: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get Db-prefixed interface name
|
|
35
|
+
* @example toDbInterfaceName('products') // 'DbProduct'
|
|
36
|
+
*/
|
|
37
|
+
export declare function toDbInterfaceName(tableName: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Pluralize a word (basic implementation)
|
|
40
|
+
*/
|
|
41
|
+
export declare function pluralize(word: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Get PascalCase plural form
|
|
44
|
+
* @example toPascalCasePlural('products') // 'Products'
|
|
45
|
+
*/
|
|
46
|
+
export declare function toPascalCasePlural(tableName: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Get translation table name
|
|
49
|
+
*/
|
|
50
|
+
export declare function toTranslationTableName(tableName: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Get foreign key column name for translation table
|
|
53
|
+
*/
|
|
54
|
+
export declare function toTranslationFKName(tableName: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Module Exports
|
|
3
|
+
*/
|
|
4
|
+
export { defineSchema, f, mergeSchemas, createSchemaUnsafe } from "./defineSchema";
|
|
5
|
+
export type { FieldBuilder } from "./fieldBuilder";
|
|
6
|
+
export { validateSchema, assertValidSchema, isValidSchema, validateTable, ValidationErrorCode, } from "./validator";
|
|
7
|
+
export type { ValidationError } from "./validator";
|
|
8
|
+
export { singularize, pluralize, toPascalCase, toCamelCase, toSnakeCase, toInterfaceName, toDbInterfaceName, toPascalCasePlural, toTranslationTableName, toTranslationFKName, } from "./helpers";
|
|
9
|
+
export { getTranslatableFields, getNonTranslatableFields, getInsertableFields, hasTranslatableFields, getPrimaryKeyField, getReferenceFields, getMainTableFields, getTranslationTableFields, isRequiredField, getRequiredFields, getRefTarget, getRefTargetFull, } from "./schemaHelpers";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Utilities for working with schema definitions.
|
|
5
|
+
*/
|
|
6
|
+
import type { TableDefinition, FieldDefinition, FieldReference } from "../types";
|
|
7
|
+
/**
|
|
8
|
+
* Get names of translatable fields in a table
|
|
9
|
+
*/
|
|
10
|
+
export declare function getTranslatableFields(table: TableDefinition): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Get names of non-translatable fields in a table (excluding primary key)
|
|
13
|
+
*/
|
|
14
|
+
export declare function getNonTranslatableFields(table: TableDefinition): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Get all non-primary key fields (for INSERT statements)
|
|
17
|
+
*/
|
|
18
|
+
export declare function getInsertableFields(table: TableDefinition): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Check if table has any translatable fields
|
|
21
|
+
*/
|
|
22
|
+
export declare function hasTranslatableFields(table: TableDefinition): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get the primary key field name
|
|
25
|
+
*/
|
|
26
|
+
export declare function getPrimaryKeyField(table: TableDefinition): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Get fields with foreign key references (using ref)
|
|
29
|
+
*/
|
|
30
|
+
export declare function getReferenceFields(table: TableDefinition): [string, FieldReference][];
|
|
31
|
+
/**
|
|
32
|
+
* Get fields for main table (excluding translatable)
|
|
33
|
+
*/
|
|
34
|
+
export declare function getMainTableFields(table: TableDefinition): [string, FieldDefinition][];
|
|
35
|
+
/**
|
|
36
|
+
* Get fields for translation table
|
|
37
|
+
*/
|
|
38
|
+
export declare function getTranslationTableFields(table: TableDefinition): [string, FieldDefinition][];
|
|
39
|
+
/**
|
|
40
|
+
* Check if a field is required (NOT NULL without default)
|
|
41
|
+
*/
|
|
42
|
+
export declare function isRequiredField(field: FieldDefinition): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Get required fields for input validation
|
|
45
|
+
*/
|
|
46
|
+
export declare function getRequiredFields(table: TableDefinition): string[];
|
|
47
|
+
/**
|
|
48
|
+
* Get reference target table name from field
|
|
49
|
+
*/
|
|
50
|
+
export declare function getRefTarget(field: FieldDefinition): string | null;
|
|
51
|
+
/**
|
|
52
|
+
* Get full reference target (table and field) from field
|
|
53
|
+
* Returns { table, field } object
|
|
54
|
+
*/
|
|
55
|
+
export declare function getRefTargetFull(field: FieldDefinition): FieldReference | null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates schema definitions for correctness.
|
|
5
|
+
*/
|
|
6
|
+
import type { SchemaDefinition, TableDefinition } from "../types";
|
|
7
|
+
/**
|
|
8
|
+
* Validation error with context
|
|
9
|
+
*/
|
|
10
|
+
export interface ValidationError {
|
|
11
|
+
table: string;
|
|
12
|
+
field?: string;
|
|
13
|
+
message: string;
|
|
14
|
+
code: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Error codes for validation
|
|
18
|
+
*/
|
|
19
|
+
export declare const ValidationErrorCode: {
|
|
20
|
+
readonly MISSING_PRIMARY_KEY: "MISSING_PRIMARY_KEY";
|
|
21
|
+
readonly INVALID_REFERENCE: "INVALID_REFERENCE";
|
|
22
|
+
readonly INVALID_TRANSLATABLE_TYPE: "INVALID_TRANSLATABLE_TYPE";
|
|
23
|
+
readonly NO_LANGUAGES: "NO_LANGUAGES";
|
|
24
|
+
readonly DUPLICATE_TABLE: "DUPLICATE_TABLE";
|
|
25
|
+
readonly RESERVED_FIELD_NAME: "RESERVED_FIELD_NAME";
|
|
26
|
+
readonly SELF_REFERENCE_ON_REQUIRED: "SELF_REFERENCE_ON_REQUIRED";
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Validate a schema definition
|
|
30
|
+
*
|
|
31
|
+
* @returns Array of validation errors (empty if valid)
|
|
32
|
+
*/
|
|
33
|
+
export declare function validateSchema(schema: SchemaDefinition): ValidationError[];
|
|
34
|
+
/**
|
|
35
|
+
* Validate schema and throw if invalid
|
|
36
|
+
*/
|
|
37
|
+
export declare function assertValidSchema(schema: SchemaDefinition): void;
|
|
38
|
+
/**
|
|
39
|
+
* Check if schema is valid (returns boolean)
|
|
40
|
+
*/
|
|
41
|
+
export declare function isValidSchema(schema: SchemaDefinition): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Validate a single table definition
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateTable(tableName: string, table: TableDefinition, allTableNames: string[]): ValidationError[];
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @promakeai/orm Core Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Database-agnostic types that work in browser and Node.js
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Supported field types
|
|
8
|
+
*/
|
|
9
|
+
export type FieldType = "id" | "string" | "text" | "int" | "decimal" | "bool" | "timestamp" | "json";
|
|
10
|
+
/**
|
|
11
|
+
* Foreign key reference definition (MongoDB-style)
|
|
12
|
+
*/
|
|
13
|
+
export interface FieldReference {
|
|
14
|
+
table: string;
|
|
15
|
+
field?: string;
|
|
16
|
+
onDelete?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
17
|
+
onUpdate?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Complete field definition after DSL processing
|
|
21
|
+
*/
|
|
22
|
+
export interface FieldDefinition {
|
|
23
|
+
type: FieldType;
|
|
24
|
+
nullable: boolean;
|
|
25
|
+
unique: boolean;
|
|
26
|
+
primary: boolean;
|
|
27
|
+
default?: unknown;
|
|
28
|
+
translatable: boolean;
|
|
29
|
+
ref?: string | FieldReference;
|
|
30
|
+
required?: boolean;
|
|
31
|
+
trim?: boolean;
|
|
32
|
+
lowercase?: boolean;
|
|
33
|
+
uppercase?: boolean;
|
|
34
|
+
minLength?: number;
|
|
35
|
+
maxLength?: number;
|
|
36
|
+
min?: number;
|
|
37
|
+
max?: number;
|
|
38
|
+
enum?: string[];
|
|
39
|
+
match?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Table definition with all fields
|
|
43
|
+
*/
|
|
44
|
+
export interface TableDefinition {
|
|
45
|
+
name: string;
|
|
46
|
+
fields: Record<string, FieldDefinition>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Language configuration
|
|
50
|
+
*/
|
|
51
|
+
export interface LanguageConfig {
|
|
52
|
+
default: string;
|
|
53
|
+
supported: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Complete schema definition
|
|
57
|
+
*/
|
|
58
|
+
export interface SchemaDefinition {
|
|
59
|
+
name?: string;
|
|
60
|
+
languages: LanguageConfig;
|
|
61
|
+
tables: Record<string, TableDefinition>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Interface for FieldBuilder-like objects (for type checking)
|
|
65
|
+
*/
|
|
66
|
+
export interface FieldBuilderLike {
|
|
67
|
+
build(): FieldDefinition;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Raw schema input before processing (from user DSL)
|
|
71
|
+
*/
|
|
72
|
+
export interface SchemaInput {
|
|
73
|
+
name?: string;
|
|
74
|
+
languages: string[] | LanguageConfig;
|
|
75
|
+
tables: Record<string, Record<string, FieldBuilderLike>>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* JSON Schema Field Definition
|
|
79
|
+
*/
|
|
80
|
+
export interface JSONFieldDefinition {
|
|
81
|
+
type: FieldType;
|
|
82
|
+
translatable?: boolean;
|
|
83
|
+
required?: boolean;
|
|
84
|
+
unique?: boolean;
|
|
85
|
+
primary?: boolean;
|
|
86
|
+
nullable?: boolean;
|
|
87
|
+
default?: unknown;
|
|
88
|
+
precision?: number;
|
|
89
|
+
scale?: number;
|
|
90
|
+
min?: number;
|
|
91
|
+
max?: number;
|
|
92
|
+
trim?: boolean;
|
|
93
|
+
lowercase?: boolean;
|
|
94
|
+
uppercase?: boolean;
|
|
95
|
+
minLength?: number;
|
|
96
|
+
maxLength?: number;
|
|
97
|
+
enum?: string[];
|
|
98
|
+
match?: string;
|
|
99
|
+
ref?: string | {
|
|
100
|
+
table: string;
|
|
101
|
+
field?: string;
|
|
102
|
+
onDelete?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
103
|
+
onUpdate?: "CASCADE" | "SET_NULL" | "RESTRICT" | "NO_ACTION";
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* JSON Schema Table Definition
|
|
108
|
+
*/
|
|
109
|
+
export interface JSONTableDefinition {
|
|
110
|
+
[fieldName: string]: JSONFieldDefinition;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Complete JSON Schema Definition
|
|
114
|
+
*/
|
|
115
|
+
export interface JSONSchemaDefinition {
|
|
116
|
+
name?: string;
|
|
117
|
+
languages: string[];
|
|
118
|
+
defaultLanguage?: string;
|
|
119
|
+
tables: {
|
|
120
|
+
[tableName: string]: JSONTableDefinition;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* MongoDB-style WHERE operators
|
|
125
|
+
*/
|
|
126
|
+
export interface WhereCondition {
|
|
127
|
+
$eq?: unknown;
|
|
128
|
+
$ne?: unknown;
|
|
129
|
+
$gt?: number;
|
|
130
|
+
$gte?: number;
|
|
131
|
+
$lt?: number;
|
|
132
|
+
$lte?: number;
|
|
133
|
+
$in?: unknown[];
|
|
134
|
+
$nin?: unknown[];
|
|
135
|
+
$like?: string;
|
|
136
|
+
$notLike?: string;
|
|
137
|
+
$between?: [unknown, unknown];
|
|
138
|
+
$isNull?: boolean;
|
|
139
|
+
$not?: WhereCondition;
|
|
140
|
+
$and?: WhereCondition[];
|
|
141
|
+
$or?: WhereCondition[];
|
|
142
|
+
$nor?: WhereCondition[];
|
|
143
|
+
[key: string]: unknown;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Order by option
|
|
147
|
+
*/
|
|
148
|
+
export interface OrderByOption {
|
|
149
|
+
field: string;
|
|
150
|
+
direction: "ASC" | "DESC";
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Populate option for resolving references (MongoDB-style)
|
|
154
|
+
*/
|
|
155
|
+
export interface PopulateNested {
|
|
156
|
+
populate?: PopulateOption;
|
|
157
|
+
where?: Record<string, unknown>;
|
|
158
|
+
limit?: number;
|
|
159
|
+
orderBy?: OrderByOption[];
|
|
160
|
+
}
|
|
161
|
+
export type PopulateOption = string | string[] | Record<string, boolean | PopulateNested>;
|
|
162
|
+
/**
|
|
163
|
+
* Query options
|
|
164
|
+
*/
|
|
165
|
+
export interface QueryOptions {
|
|
166
|
+
where?: Record<string, unknown>;
|
|
167
|
+
populate?: PopulateOption;
|
|
168
|
+
orderBy?: OrderByOption[];
|
|
169
|
+
limit?: number;
|
|
170
|
+
offset?: number;
|
|
171
|
+
lang?: string;
|
|
172
|
+
fallbackLang?: string;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Paginated result
|
|
176
|
+
*/
|
|
177
|
+
export interface PaginatedResult<T> {
|
|
178
|
+
data: T[];
|
|
179
|
+
page: number;
|
|
180
|
+
limit: number;
|
|
181
|
+
total: number;
|
|
182
|
+
totalPages: number;
|
|
183
|
+
hasMore: boolean;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* ORM Configuration
|
|
187
|
+
*/
|
|
188
|
+
export interface ORMConfig {
|
|
189
|
+
schema?: SchemaDefinition;
|
|
190
|
+
defaultLang?: string;
|
|
191
|
+
fallbackLang?: string;
|
|
192
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema Converter
|
|
3
|
+
*
|
|
4
|
+
* Bidirectional conversion between JSON schema format and internal SchemaDefinition.
|
|
5
|
+
* Enables AI agents to work with JSON while maintaining type-safe internal representation.
|
|
6
|
+
*/
|
|
7
|
+
import type { JSONSchemaDefinition, SchemaDefinition } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Convert JSON schema to internal SchemaDefinition
|
|
10
|
+
*
|
|
11
|
+
* @param json - JSON schema from AI agent or file
|
|
12
|
+
* @returns Internal SchemaDefinition for processing
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const jsonSchema = {
|
|
17
|
+
* name: "products",
|
|
18
|
+
* languages: ["en", "tr"],
|
|
19
|
+
* tables: {
|
|
20
|
+
* products: {
|
|
21
|
+
* id: { type: "id", primary: true },
|
|
22
|
+
* name: { type: "string", translatable: true, required: true }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* };
|
|
26
|
+
* const schema = parseJSONSchema(jsonSchema);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseJSONSchema(json: JSONSchemaDefinition): SchemaDefinition;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Populate Resolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves references (foreign keys) in query results using batch fetching
|
|
5
|
+
* to avoid N+1 query problems.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const products = await orm.list('products', {
|
|
10
|
+
* populate: ['categoryId', 'brandId']
|
|
11
|
+
* });
|
|
12
|
+
* // Each product now has .category and .brand objects
|
|
13
|
+
*
|
|
14
|
+
* // Nested populate with options
|
|
15
|
+
* const orders = await orm.list('orders', {
|
|
16
|
+
* populate: {
|
|
17
|
+
* userId: true,
|
|
18
|
+
* items: {
|
|
19
|
+
* populate: { productId: true },
|
|
20
|
+
* limit: 10
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import type { SchemaDefinition, TableDefinition, PopulateOption } from "../types";
|
|
27
|
+
/**
|
|
28
|
+
* Adapter interface for fetching records
|
|
29
|
+
* Minimal interface needed by populate resolver
|
|
30
|
+
*/
|
|
31
|
+
export interface PopulateAdapter {
|
|
32
|
+
findMany<T = unknown>(table: string, options?: {
|
|
33
|
+
where?: Record<string, unknown>;
|
|
34
|
+
}): Promise<T[]>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve populated references for query results
|
|
38
|
+
*
|
|
39
|
+
* @param records - Query results to populate
|
|
40
|
+
* @param table - Table name of the records
|
|
41
|
+
* @param populate - Fields to populate
|
|
42
|
+
* @param schema - Schema definition
|
|
43
|
+
* @param adapter - Data adapter for fetching
|
|
44
|
+
* @returns Records with populated references
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolvePopulate<T>(records: T[], table: string, populate: PopulateOption | undefined, schema: SchemaDefinition, adapter: PopulateAdapter): Promise<T[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Get all populatable fields from a table
|
|
49
|
+
*/
|
|
50
|
+
export declare function getPopulatableFields(tableDef: TableDefinition): string[];
|
|
51
|
+
/**
|
|
52
|
+
* Validate populate options against schema
|
|
53
|
+
*/
|
|
54
|
+
export declare function validatePopulate(populate: PopulateOption | undefined, table: string, schema: SchemaDefinition): {
|
|
55
|
+
valid: boolean;
|
|
56
|
+
errors: string[];
|
|
57
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation Query Builder
|
|
3
|
+
*
|
|
4
|
+
* Build SQL queries with automatic translation table joins
|
|
5
|
+
* and COALESCE for language fallback.
|
|
6
|
+
*/
|
|
7
|
+
import type { SchemaDefinition, TableDefinition, OrderByOption } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Options for translation queries
|
|
10
|
+
*/
|
|
11
|
+
export interface TranslationQueryOptions {
|
|
12
|
+
table: string;
|
|
13
|
+
schema: SchemaDefinition;
|
|
14
|
+
lang: string;
|
|
15
|
+
fallbackLang?: string;
|
|
16
|
+
where?: Record<string, unknown>;
|
|
17
|
+
orderBy?: OrderByOption[];
|
|
18
|
+
limit?: number;
|
|
19
|
+
offset?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Query result with SQL and parameters
|
|
23
|
+
*/
|
|
24
|
+
export interface TranslationQueryResult {
|
|
25
|
+
sql: string;
|
|
26
|
+
params: unknown[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build SELECT query with translation joins
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildTranslationQuery(options: TranslationQueryOptions): TranslationQueryResult;
|
|
32
|
+
/**
|
|
33
|
+
* Build query for single record by ID with translations
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildTranslationQueryById(table: string, schema: SchemaDefinition, id: number | string, lang: string, fallbackLang?: string): TranslationQueryResult;
|
|
36
|
+
/**
|
|
37
|
+
* Build INSERT statement for translation
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildTranslationInsert(table: string, schema: SchemaDefinition, recordId: number | string, lang: string, data: Record<string, unknown>): TranslationQueryResult;
|
|
40
|
+
/**
|
|
41
|
+
* Build UPSERT statement for translation (INSERT OR REPLACE)
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildTranslationUpsert(table: string, schema: SchemaDefinition, recordId: number | string, lang: string, data: Record<string, unknown>): TranslationQueryResult;
|
|
44
|
+
/**
|
|
45
|
+
* Extract translatable fields from data object
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractTranslatableData(data: Record<string, unknown>, tableSchema: TableDefinition): {
|
|
48
|
+
mainData: Record<string, unknown>;
|
|
49
|
+
translatableData: Record<string, unknown>;
|
|
50
|
+
};
|