forj 0.1.7 → 0.1.9
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/package.json +9 -16
- package/src/d1/model.ts +1 -1
- package/src/dynamodb/repository.ts +2 -2
- package/src/dynamodb/schema.ts +8 -8
- package/src/migrations/builder.ts +8 -2
- package/src/migrations/migrator.ts +8 -7
- package/src/migrations/schema.ts +11 -3
- package/src/types.ts +35 -6
- package/src/utils.ts +8 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forj",
|
|
3
3
|
"description": "SQLite ORM and Query Builder whitout dependencies",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.9",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"files": ["src"],
|
|
@@ -13,38 +13,31 @@
|
|
|
13
13
|
"./dynamodb/types": "./src/dynamodb/types.ts",
|
|
14
14
|
"./migrate": "./src/migrations/index.ts"
|
|
15
15
|
},
|
|
16
|
-
"-exports": {
|
|
17
|
-
".": {
|
|
18
|
-
"import": "./dist/index.js",
|
|
19
|
-
"types": "./dist/index.d.ts"
|
|
20
|
-
},
|
|
21
|
-
"./d1": {
|
|
22
|
-
"import": "./dist/d1.js",
|
|
23
|
-
"types": "./dist/d1.d.ts"
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
16
|
"scripts": {
|
|
27
17
|
"bench": "tsx tests/benchmark/*.bench.ts",
|
|
28
18
|
"build": "tsup",
|
|
29
19
|
"-prepublishOnly": "bun run build"
|
|
30
20
|
},
|
|
31
21
|
"dependencies": {
|
|
32
|
-
"@aws-sdk/client-dynamodb": "3.
|
|
33
|
-
"@aws-sdk/lib-dynamodb": "3.
|
|
22
|
+
"@aws-sdk/client-dynamodb": "^3.1003.0",
|
|
23
|
+
"@aws-sdk/lib-dynamodb": "^3.1003.0",
|
|
24
|
+
"pathe": "^2.0",
|
|
34
25
|
"pluralize": "^8.0",
|
|
35
|
-
"t0n": "^0.1",
|
|
26
|
+
"t0n": "^0.1.12",
|
|
36
27
|
"zod": "^4.3.6"
|
|
37
28
|
},
|
|
38
29
|
"devDependencies": {
|
|
30
|
+
"@types/node": "^25.1.0",
|
|
39
31
|
"@types/pluralize": "^0.0.33",
|
|
40
32
|
"@cloudflare/workers-types": "^4.20260113.0",
|
|
41
33
|
"bun-types": "^1.3.8",
|
|
42
34
|
"terser": "^5.46.0",
|
|
43
35
|
"tiny-glob": "^0.2",
|
|
44
|
-
"tsup": "^8.5.
|
|
36
|
+
"tsup": "^8.5.0",
|
|
45
37
|
"tsx": "^4.19.4",
|
|
46
38
|
"typescript": "^5.9.3"
|
|
47
39
|
},
|
|
40
|
+
"packageManager": "bun@1.3.10",
|
|
48
41
|
"engines": {
|
|
49
42
|
"node": ">=18.0.0"
|
|
50
43
|
},
|
|
@@ -89,4 +82,4 @@
|
|
|
89
82
|
"bun",
|
|
90
83
|
"nodejs"
|
|
91
84
|
]
|
|
92
|
-
}
|
|
85
|
+
}
|
package/src/d1/model.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type * as z from 'zod'
|
|
2
2
|
import { Dynamodb } from './client'
|
|
3
3
|
import { Schema } from './schema'
|
|
4
4
|
import { _model } from './decorators'
|
|
5
5
|
import type { ModelOpts } from './types'
|
|
6
6
|
|
|
7
7
|
export function Repository<
|
|
8
|
-
S extends ZodTypeAny,
|
|
8
|
+
S extends z.ZodTypeAny,
|
|
9
9
|
B extends new (...args: any[]) => any
|
|
10
10
|
>(
|
|
11
11
|
schema: S,
|
package/src/dynamodb/schema.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod'
|
|
2
2
|
import type { SchemaStructure } from './types'
|
|
3
3
|
|
|
4
4
|
const m = Symbol('a')
|
|
@@ -12,17 +12,17 @@ export function arraySchema(v: any): any {
|
|
|
12
12
|
return v
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function getArrayItem(schema: z.ZodArray<any>): ZodTypeAny {
|
|
15
|
+
function getArrayItem(schema: z.ZodArray<any>): z.ZodTypeAny {
|
|
16
16
|
const def: any = schema._def
|
|
17
|
-
return (def.element ?? def.type ?? def.innerType) as ZodTypeAny
|
|
17
|
+
return (def.element ?? def.type ?? def.innerType) as z.ZodTypeAny
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function extractZodKeys(schema: ZodTypeAny): SchemaStructure {
|
|
20
|
+
export function extractZodKeys(schema: z.ZodTypeAny): SchemaStructure {
|
|
21
21
|
if (schema instanceof z.ZodObject) {
|
|
22
22
|
const shape = schema.shape
|
|
23
23
|
|
|
24
24
|
return Object.entries(shape).map(([key, value]) => {
|
|
25
|
-
const inner = unwrap(value as ZodTypeAny)
|
|
25
|
+
const inner = unwrap(value as z.ZodTypeAny)
|
|
26
26
|
|
|
27
27
|
if (inner instanceof z.ZodObject)
|
|
28
28
|
return notEmpty(key, extractZodKeys(inner))
|
|
@@ -50,7 +50,7 @@ export function extractZodKeys(schema: ZodTypeAny): SchemaStructure {
|
|
|
50
50
|
return []
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export function unwrap(schema: ZodTypeAny): ZodTypeAny {
|
|
53
|
+
export function unwrap(schema: z.ZodTypeAny): z.ZodTypeAny {
|
|
54
54
|
while (true) {
|
|
55
55
|
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {
|
|
56
56
|
schema = (schema._def as any).innerType
|
|
@@ -63,7 +63,7 @@ export function unwrap(schema: ZodTypeAny): ZodTypeAny {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (schema instanceof z.ZodUnion) {
|
|
66
|
-
const options = (schema._def as any).options as ZodTypeAny[]
|
|
66
|
+
const options = (schema._def as any).options as z.ZodTypeAny[]
|
|
67
67
|
const nonEmpty = options.find(
|
|
68
68
|
opt => !(opt instanceof z.ZodUndefined) && !(opt instanceof z.ZodNull)
|
|
69
69
|
)
|
|
@@ -95,7 +95,7 @@ function notEmpty(key: string, schema: SchemaStructure): string | Record<string,
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
export function Schema<
|
|
98
|
-
T extends ZodTypeAny,
|
|
98
|
+
T extends z.ZodTypeAny,
|
|
99
99
|
B extends object
|
|
100
100
|
>(
|
|
101
101
|
schema: T,
|
|
@@ -3,7 +3,11 @@ import { sqlName, tableSlug } from '../utils'
|
|
|
3
3
|
import type { ColumnDefinition, IndexDefinition, ForeignKeyDefinition } from './types'
|
|
4
4
|
|
|
5
5
|
export default class SchemaBuilder {
|
|
6
|
-
static create(
|
|
6
|
+
static create(
|
|
7
|
+
blueprint: Blueprint,
|
|
8
|
+
exist: boolean = false,
|
|
9
|
+
rowId: boolean = true
|
|
10
|
+
): string {
|
|
7
11
|
const table = sqlName(blueprint.table)
|
|
8
12
|
const columns = blueprint.columns
|
|
9
13
|
const indexes = blueprint.indexes
|
|
@@ -19,7 +23,9 @@ export default class SchemaBuilder {
|
|
|
19
23
|
...foreignKeyDefinitions
|
|
20
24
|
].filter(Boolean)
|
|
21
25
|
|
|
22
|
-
return `CREATE TABLE ${exist ? 'IF NOT EXISTS ' : ''}${table} (\n ${allDefinitions.join(',\n ')}\n)
|
|
26
|
+
return `CREATE TABLE ${exist ? 'IF NOT EXISTS ' : ''}${table} (\n ${allDefinitions.join(',\n ')}\n)${
|
|
27
|
+
rowId ? '' : ' WITHOUT ROWID'
|
|
28
|
+
};`
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
static alter(blueprint: Blueprint): string[] {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import glob from 'tiny-glob'
|
|
2
2
|
import { mkdirSync, existsSync, writeFileSync } from 'node:fs'
|
|
3
|
-
import { dirname, join
|
|
4
|
-
import { Datte, IMPORT } from 't0n'
|
|
3
|
+
import { dirname, join } from 'pathe'
|
|
4
|
+
import { Datte, Envir, IMPORT } from 't0n'
|
|
5
5
|
import { Schema } from './schema'
|
|
6
6
|
import { MigrationInfo, MigrationClass, Queue } from './types'
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
export const _forj = join(dirname(new URL(import.meta.url).pathname), '..')
|
|
9
|
+
export const _root = Envir.get('npm_config_local_prefix') || Envir.get('PWD') || join(_forj, '../../../')
|
|
9
10
|
|
|
10
11
|
export class Migrator {
|
|
11
12
|
static #input: string
|
|
@@ -24,17 +25,17 @@ export class Migrator {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
static dir(dir?: string) {
|
|
27
|
-
this.#input = join(
|
|
28
|
+
this.#input = join(_root, 'migrations', dir || '')
|
|
28
29
|
this.#output = join(this.#input, 'sql')
|
|
29
30
|
return this
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
static inputDir(dir: string) {
|
|
33
|
-
this.#input = join(
|
|
34
|
+
this.#input = join(_root, dir)
|
|
34
35
|
return this
|
|
35
36
|
}
|
|
36
37
|
static outputDir(dir: string) {
|
|
37
|
-
this.#output = join(
|
|
38
|
+
this.#output = join(_root, dir)
|
|
38
39
|
return this
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -88,7 +89,7 @@ export class Migrator {
|
|
|
88
89
|
if (!match) return null
|
|
89
90
|
const [, year, month, day, hour, minute, second, slugName] = match
|
|
90
91
|
|
|
91
|
-
const input = join(
|
|
92
|
+
const input = join(_root, fileName)
|
|
92
93
|
const output = join(this.#output, name +'.sql')
|
|
93
94
|
const mod = await IMPORT(input)
|
|
94
95
|
const handler = mod.default as MigrationClass
|
package/src/migrations/schema.ts
CHANGED
|
@@ -47,8 +47,8 @@ export class Schema {
|
|
|
47
47
|
return blueprint
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
static create(table: string, fn: BlueprintFn, exist: boolean = false) {
|
|
51
|
-
this.#addStatement(Builder.create(this.#blueprint(table, fn), exist))
|
|
50
|
+
static create(table: string, fn: BlueprintFn, exist: boolean = false, rowId: boolean = true) {
|
|
51
|
+
this.#addStatement(Builder.create(this.#blueprint(table, fn), exist, rowId))
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
static createIfNotExists(table: string, fn: BlueprintFn) {
|
|
@@ -66,7 +66,15 @@ export class Schema {
|
|
|
66
66
|
this.#addStatement(Builder.create(this.#blueprint(table, fn as BlueprintFn, (table: Blueprint) => {
|
|
67
67
|
columns.forEach(column => table.foreignId(column))
|
|
68
68
|
table.primary(table.columns.map(c => c.name))
|
|
69
|
-
})
|
|
69
|
+
}), false, false))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static createWithoutRowId(table: string, fn: BlueprintFn, exist: boolean = false) {
|
|
73
|
+
this.create(table, fn, false, false)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static createIfNotExistsWithoutRowId(table: string, fn: BlueprintFn) {
|
|
77
|
+
this.create(table, fn, true, false)
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
static table(table: string, fn: BlueprintFn) {
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import z from 'zod'
|
|
2
|
-
import
|
|
1
|
+
import type * as z from 'zod'
|
|
2
|
+
import type zm from 'zod/mini'
|
|
3
|
+
import type QueryBuilder from './query-builder'
|
|
3
4
|
import { types } from './utils'
|
|
4
5
|
|
|
5
6
|
export type text = string
|
|
@@ -28,17 +29,45 @@ export type OrderDirection = 'ASC' | 'DESC' | 'asc' | 'desc'
|
|
|
28
29
|
|
|
29
30
|
export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'CROSS'
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
// type ZodRawShapeCompat = Record<string, z.ZodTypeAny>
|
|
32
33
|
|
|
33
|
-
export type
|
|
34
|
+
// export type DBSchema = z.ZodObject<ZodRawShapeCompat>
|
|
35
|
+
|
|
36
|
+
// export type SchemaObject = ZodRawShapeCompat
|
|
37
|
+
|
|
38
|
+
// export type SchemaKeys<TSchema extends DBSchema | SchemaObject> =
|
|
39
|
+
// TSchema extends z.ZodObject<infer TShape extends ZodRawShapeCompat>
|
|
40
|
+
// ? keyof TShape
|
|
41
|
+
// : TSchema extends ZodRawShapeCompat
|
|
42
|
+
// ? keyof TSchema
|
|
43
|
+
// : never
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
export type DBSchema = z.ZodTypeAny | zm.ZodMiniObject
|
|
47
|
+
|
|
48
|
+
export type SchemaObject = Record<string, z.ZodTypeAny>
|
|
34
49
|
|
|
35
50
|
export type SchemaKeys<TSchema extends DBSchema | SchemaObject> =
|
|
36
|
-
TSchema extends
|
|
51
|
+
TSchema extends { shape: infer TShape }
|
|
37
52
|
? keyof TShape
|
|
38
|
-
: TSchema extends
|
|
53
|
+
: TSchema extends SchemaObject
|
|
39
54
|
? keyof TSchema
|
|
40
55
|
: never
|
|
41
56
|
|
|
57
|
+
|
|
58
|
+
//////////////////////////
|
|
59
|
+
// funcionando no zod/v4
|
|
60
|
+
// export type DBSchema = z.ZodObject<z.ZodRawShape>
|
|
61
|
+
|
|
62
|
+
// export type SchemaObject = z.ZodRawShape
|
|
63
|
+
|
|
64
|
+
// export type SchemaKeys<TSchema extends DBSchema | SchemaObject> =
|
|
65
|
+
// TSchema extends z.ZodObject<infer TShape extends z.ZodRawShape>
|
|
66
|
+
// ? keyof TShape
|
|
67
|
+
// : TSchema extends z.ZodRawShape
|
|
68
|
+
// ? keyof TSchema
|
|
69
|
+
// : never
|
|
70
|
+
|
|
42
71
|
// TODO: transform QueryBuilder<S, T, C> into a interface
|
|
43
72
|
export type RunFn<S, T, C extends keyof T = keyof T> = (qb: QueryBuilder<S, T, C>) => Promise<Result<T, C>>
|
|
44
73
|
// export type RunBatchFn<S, T, C extends keyof T = keyof T> = (qb: QueryBuilder<S, T, C>[]) => Promise<Result<T, C>>[]
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pluralize from 'pluralize'
|
|
2
|
-
import type
|
|
2
|
+
import type * as z from 'zod'
|
|
3
3
|
import type { DBSchema } from './types'
|
|
4
4
|
|
|
5
5
|
export const types = {
|
|
@@ -70,9 +70,9 @@ const zodTypeMap: Record<string, string> = {
|
|
|
70
70
|
ZodFunction: 'function',
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export const isZod = (obj: any): obj is ZodTypeAny => obj && typeof obj == 'object' && '_def' in obj
|
|
73
|
+
export const isZod = (obj: any): obj is z.ZodTypeAny => obj && typeof obj == 'object' && '_def' in obj
|
|
74
74
|
|
|
75
|
-
const getDef = (schema: any) => schema?._def ?? {}
|
|
75
|
+
const getDef = (schema: any) => schema?._def ?? schema?.def ?? {}
|
|
76
76
|
|
|
77
77
|
const getTypeName = (def: any): string => {
|
|
78
78
|
if (!def) return ''
|
|
@@ -95,8 +95,8 @@ const unwrap = (schema: any): any => {
|
|
|
95
95
|
let allowNull = false
|
|
96
96
|
let allowUndefined = false
|
|
97
97
|
|
|
98
|
-
while (current?._def) {
|
|
99
|
-
const def = current._def
|
|
98
|
+
while (current?._def || current?.def) {
|
|
99
|
+
const def = current._def || current?.def
|
|
100
100
|
const type = getTypeName(def)
|
|
101
101
|
|
|
102
102
|
if (type == 'ZodNullable')
|
|
@@ -146,7 +146,7 @@ export const zHas = (key: string, schema?: any): boolean => {
|
|
|
146
146
|
return true
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
export const zGet = (key: string, schema?: any): [string, ZodTypeAny] | false => {
|
|
149
|
+
export const zGet = (key: string, schema?: any): [string, z.ZodTypeAny] | false => {
|
|
150
150
|
const keys = key.split('.')
|
|
151
151
|
|
|
152
152
|
for (const k of keys) {
|
|
@@ -194,9 +194,9 @@ export const zSame = (key: string, val: any, schema?: any, deep: boolean = false
|
|
|
194
194
|
if (val === undefined) return _schema.allowUndefined
|
|
195
195
|
if (val === null) return _schema.allowNull
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
const def = getDef(_schema.schema)
|
|
198
|
+
if (!def) return false
|
|
198
199
|
|
|
199
|
-
const def = _schema.schema._def
|
|
200
200
|
const type = getTypeName(def)
|
|
201
201
|
|
|
202
202
|
if (!type) return false
|