@effectify/prisma 0.1.1 → 0.1.2
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 +14 -11
- package/prisma/dev.db +0 -0
- package/prisma/generated/edge.js +7 -7
- package/prisma/generated/effect/index.ts +2 -7
- package/prisma/generated/effect/models/Todo.ts +6 -0
- package/prisma/generated/effect/prisma-repository.ts +18 -18
- package/prisma/generated/effect/schemas/enums.ts +1 -1
- package/prisma/generated/effect/schemas/types.ts +1 -1
- package/prisma/generated/index-browser.js +4 -4
- package/prisma/generated/index.d.ts +25 -9
- package/prisma/generated/index.js +7 -7
- package/prisma/generated/package.json +3 -3
- package/prisma/generated/schema.prisma +1 -1
- package/prisma/schema.prisma +1 -1
- package/src/cli.ts +22 -0
- package/src/commands/init.ts +0 -2
- package/src/commands/prisma.ts +50 -0
- package/src/generators/sql-schema-generator.ts +0 -9
- package/src/services/generator-context.ts +4 -0
- package/src/services/generator-service.ts +178 -0
- package/src/services/render-service.ts +32 -0
- package/src/templates/index-custom-error.eta +190 -0
- package/src/templates/index-default.eta +363 -0
- package/src/templates/model.eta +6 -0
- package/src/templates/prisma-raw-sql.eta +31 -0
- package/src/{effect-prisma.ts → templates/prisma-repository.eta} +18 -890
- package/src/templates/prisma-schema.eta +94 -0
- package/vitest.config.ts +1 -0
- package/src/cli.tsx +0 -23
- package/src/commands/generate-effect.ts +0 -109
- package/src/commands/generate-sql-schema.ts +0 -109
- package/src/generators/prisma-effect-generator.ts +0 -496
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Cause from 'effect/Cause'
|
|
5
|
+
import * as Effect from 'effect/Effect'
|
|
6
|
+
import type * as Option from 'effect/Option'
|
|
7
|
+
import type { ParseError } from 'effect/ParseResult'
|
|
8
|
+
import * as Schema from 'effect/Schema'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Run a sql query with a request schema and a result schema.
|
|
12
|
+
*
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
* @category constructor
|
|
15
|
+
*/
|
|
16
|
+
export const findAll = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
17
|
+
readonly Request: Schema.Schema<IA, II, IR>
|
|
18
|
+
readonly Result: Schema.Schema<A, AI, AR>
|
|
19
|
+
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
20
|
+
}) => {
|
|
21
|
+
const encodeRequest = Schema.encode(options.Request)
|
|
22
|
+
const decode = Schema.decodeUnknown(Schema.Array(options.Result))
|
|
23
|
+
return (request: IA): Effect.Effect<ReadonlyArray<A>, E | ParseError, R | IR | AR> =>
|
|
24
|
+
Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), decode)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const void_ = <IR, II, IA, R, E>(options: {
|
|
28
|
+
readonly Request: Schema.Schema<IA, II, IR>
|
|
29
|
+
readonly execute: (request: II) => Effect.Effect<unknown, E, R>
|
|
30
|
+
}) => {
|
|
31
|
+
const encode = Schema.encode(options.Request)
|
|
32
|
+
return (request: IA): Effect.Effect<void, E | ParseError, R | IR> =>
|
|
33
|
+
Effect.asVoid(Effect.flatMap(encode(request), options.execute))
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
/**
|
|
37
|
+
* Run a sql query with a request schema and discard the result.
|
|
38
|
+
*
|
|
39
|
+
* @since 1.0.0
|
|
40
|
+
* @category constructor
|
|
41
|
+
*/
|
|
42
|
+
void_ as void,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Run a sql query with a request schema and a result schema and return the first result.
|
|
47
|
+
*
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
* @category constructor
|
|
50
|
+
*/
|
|
51
|
+
export const findOne = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
52
|
+
readonly Request: Schema.Schema<IA, II, IR>
|
|
53
|
+
readonly Result: Schema.Schema<A, AI, AR>
|
|
54
|
+
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
55
|
+
}) => {
|
|
56
|
+
const encodeRequest = Schema.encode(options.Request)
|
|
57
|
+
const decode = Schema.decodeUnknown(options.Result)
|
|
58
|
+
return (request: IA): Effect.Effect<Option.Option<A>, E | ParseError, R | IR | AR> =>
|
|
59
|
+
Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), (arr) =>
|
|
60
|
+
Array.isArray(arr) && arr.length > 0 ? Effect.asSome(decode(arr[0])) : Effect.succeedNone,
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Run a sql query with a request schema and a result schema and return the first result.
|
|
66
|
+
*
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
* @category constructor
|
|
69
|
+
*/
|
|
70
|
+
export const single = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
71
|
+
readonly Request: Schema.Schema<IA, II, IR>
|
|
72
|
+
readonly Result: Schema.Schema<A, AI, AR>
|
|
73
|
+
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
74
|
+
}) => {
|
|
75
|
+
const encodeRequest = Schema.encode(options.Request)
|
|
76
|
+
const decode = Schema.decodeUnknown(options.Result)
|
|
77
|
+
return (request: IA): Effect.Effect<A, E | ParseError | Cause.NoSuchElementException, R | IR | AR> =>
|
|
78
|
+
Effect.flatMap(
|
|
79
|
+
Effect.flatMap(encodeRequest(request), options.execute),
|
|
80
|
+
(arr): Effect.Effect<A, ParseError | Cause.NoSuchElementException, AR> =>
|
|
81
|
+
Array.isArray(arr) && arr.length > 0 ? decode(arr[0]) : Effect.fail(new Cause.NoSuchElementException()),
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const many = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
86
|
+
readonly Request: Schema.Schema<IA, II, IR>
|
|
87
|
+
readonly Result: Schema.Schema<A, AI, AR>
|
|
88
|
+
readonly execute: (request: II) => Effect.Effect<Array<unknown>, E, R>
|
|
89
|
+
}) => {
|
|
90
|
+
const encodeRequest = Schema.encode(options.Request)
|
|
91
|
+
const decode = Schema.decodeUnknown(Schema.Array(options.Result))
|
|
92
|
+
return (request: IA): Effect.Effect<Array<A>, E | ParseError, R | IR | AR> =>
|
|
93
|
+
Effect.map(Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), decode), (arr) => [...arr])
|
|
94
|
+
}
|
package/vitest.config.ts
CHANGED
package/src/cli.tsx
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import * as Command from '@effect/cli/Command'
|
|
4
|
-
import * as NodeContext from '@effect/platform-node/NodeContext'
|
|
5
|
-
import * as NodeRuntime from '@effect/platform-node/NodeRuntime'
|
|
6
|
-
import * as Console from 'effect/Console'
|
|
7
|
-
import * as Effect from 'effect/Effect'
|
|
8
|
-
import { generateEffectCommand } from './commands/generate-effect.js'
|
|
9
|
-
import { generateSqlSchemaCommand } from './commands/generate-sql-schema.js'
|
|
10
|
-
import { initCommand } from './commands/init.js'
|
|
11
|
-
|
|
12
|
-
// Main CLI command
|
|
13
|
-
const prisma = Command.make('prisma', {}, () =>
|
|
14
|
-
Console.log('🚀 prisma CLI - Use --help to see available commands'),
|
|
15
|
-
).pipe(Command.withSubcommands([initCommand, generateEffectCommand, generateSqlSchemaCommand]))
|
|
16
|
-
|
|
17
|
-
// Run the CLI
|
|
18
|
-
const cli = Command.run(prisma, {
|
|
19
|
-
name: '@effectify/prisma CLI',
|
|
20
|
-
version: '0.1.0',
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
cli(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain)
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as Command from '@effect/cli/Command'
|
|
2
|
-
import * as FileSystem from '@effect/platform/FileSystem'
|
|
3
|
-
import * as NodeFileSystem from '@effect/platform-node/NodeFileSystem'
|
|
4
|
-
import * as NodePath from '@effect/platform-node/NodePath'
|
|
5
|
-
import * as Console from 'effect/Console'
|
|
6
|
-
import * as Effect from 'effect/Effect'
|
|
7
|
-
import * as Match from 'effect/Match'
|
|
8
|
-
|
|
9
|
-
// import { generateEffectPrisma } from '../generators/prisma-effect-generator.js'
|
|
10
|
-
|
|
11
|
-
// Check if file exists
|
|
12
|
-
const fileExists = (path: string) =>
|
|
13
|
-
Effect.gen(function* () {
|
|
14
|
-
const fs = yield* FileSystem.FileSystem
|
|
15
|
-
return yield* fs.exists(path)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
// Detect package manager using pattern matching
|
|
19
|
-
const detectPackageManager = () =>
|
|
20
|
-
Effect.gen(function* () {
|
|
21
|
-
const pnpmExists = yield* fileExists('pnpm-lock.yaml')
|
|
22
|
-
const bunExists = yield* fileExists('bun.lockb')
|
|
23
|
-
const npmExists = yield* fileExists('package-lock.json')
|
|
24
|
-
|
|
25
|
-
// Create a tuple to match against
|
|
26
|
-
const lockFiles = [pnpmExists, bunExists, npmExists] as const
|
|
27
|
-
|
|
28
|
-
return Match.value(lockFiles).pipe(
|
|
29
|
-
Match.when([true, false, false], () => 'pnpm' as const),
|
|
30
|
-
Match.when([false, true, false], () => 'bun' as const),
|
|
31
|
-
Match.when([false, false, true], () => 'npm' as const),
|
|
32
|
-
Match.orElse(() => 'npm' as const), // default fallback
|
|
33
|
-
)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// Check if Prisma schema exists
|
|
37
|
-
const checkPrismaSchema = () =>
|
|
38
|
-
Effect.gen(function* () {
|
|
39
|
-
const schemaExists = yield* fileExists('prisma/schema.prisma')
|
|
40
|
-
|
|
41
|
-
if (!schemaExists) {
|
|
42
|
-
yield* Console.log('❌ Prisma schema not found.')
|
|
43
|
-
yield* Console.log('')
|
|
44
|
-
yield* Console.log('Please run the following command first:')
|
|
45
|
-
|
|
46
|
-
const packageManager = yield* detectPackageManager()
|
|
47
|
-
|
|
48
|
-
const initCommand = Match.value(packageManager).pipe(
|
|
49
|
-
Match.when('pnpm', () => 'pnpm dlx prisma init'),
|
|
50
|
-
Match.when('bun', () => 'bunx prisma init'),
|
|
51
|
-
Match.when('npm', () => 'npx prisma init'),
|
|
52
|
-
Match.exhaustive,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
yield* Console.log(` ${initCommand}`)
|
|
56
|
-
yield* Effect.fail(new Error('Prisma schema not found'))
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// Execute the Effect generator
|
|
61
|
-
const generateEffectServices = () =>
|
|
62
|
-
Effect.gen(function* () {
|
|
63
|
-
// Check if we're being called by Prisma (no interactive output)
|
|
64
|
-
const isCalledByPrisma =
|
|
65
|
-
process.env.PRISMA_GENERATOR_INVOCATION === 'true' ||
|
|
66
|
-
process.argv.includes('--generator') ||
|
|
67
|
-
!process.stdout.isTTY
|
|
68
|
-
|
|
69
|
-
if (!isCalledByPrisma) {
|
|
70
|
-
yield* Console.log('🔧 Running Effect generator...')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check if Prisma schema exists
|
|
74
|
-
yield* checkPrismaSchema()
|
|
75
|
-
|
|
76
|
-
// Note: We don't need to check for local generator files
|
|
77
|
-
// since we're importing from our own package
|
|
78
|
-
|
|
79
|
-
if (!isCalledByPrisma) {
|
|
80
|
-
yield* Console.log('🚀 Executing Effect generator...')
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Execute the generator function
|
|
84
|
-
yield* Effect.tryPromise({
|
|
85
|
-
try: () => {
|
|
86
|
-
// Create mock options for the generator
|
|
87
|
-
// const mockOptions = {
|
|
88
|
-
// dmmf: { datamodel: { models: [] } }, // Empty models for now
|
|
89
|
-
// generator: { output: { value: 'src/generated/effect-prisma' } },
|
|
90
|
-
// }
|
|
91
|
-
return Promise.resolve()
|
|
92
|
-
// return generateEffectPrisma(mockOptions)
|
|
93
|
-
},
|
|
94
|
-
catch: (error) => new Error(`Generator execution failed: ${error}`),
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
if (!isCalledByPrisma) {
|
|
98
|
-
yield* Console.log('✅ Effect generator executed successfully!')
|
|
99
|
-
yield* Console.log('💡 Generated files are available in the configured output directory')
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Ensure the effect completes and exits
|
|
103
|
-
yield* Effect.sync(() => process.exit(0))
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// Export the generate-effect command
|
|
107
|
-
export const generateEffectCommand = Command.make('generate-effect', {}, () =>
|
|
108
|
-
generateEffectServices().pipe(Effect.provide(NodeFileSystem.layer), Effect.provide(NodePath.layer)),
|
|
109
|
-
)
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as Command from '@effect/cli/Command'
|
|
2
|
-
import * as FileSystem from '@effect/platform/FileSystem'
|
|
3
|
-
import * as NodeFileSystem from '@effect/platform-node/NodeFileSystem'
|
|
4
|
-
import * as NodePath from '@effect/platform-node/NodePath'
|
|
5
|
-
import * as Console from 'effect/Console'
|
|
6
|
-
import * as Effect from 'effect/Effect'
|
|
7
|
-
import * as Match from 'effect/Match'
|
|
8
|
-
|
|
9
|
-
// import { generateSqlSchema } from '../generators/sql-schema-generator.js'
|
|
10
|
-
|
|
11
|
-
// Check if file exists
|
|
12
|
-
const fileExists = (path: string) =>
|
|
13
|
-
Effect.gen(function* () {
|
|
14
|
-
const fs = yield* FileSystem.FileSystem
|
|
15
|
-
return yield* fs.exists(path)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
// Detect package manager using pattern matching
|
|
19
|
-
const detectPackageManager = () =>
|
|
20
|
-
Effect.gen(function* () {
|
|
21
|
-
const pnpmExists = yield* fileExists('pnpm-lock.yaml')
|
|
22
|
-
const bunExists = yield* fileExists('bun.lockb')
|
|
23
|
-
const npmExists = yield* fileExists('package-lock.json')
|
|
24
|
-
|
|
25
|
-
// Create a tuple to match against
|
|
26
|
-
const lockFiles = [pnpmExists, bunExists, npmExists] as const
|
|
27
|
-
|
|
28
|
-
return Match.value(lockFiles).pipe(
|
|
29
|
-
Match.when([true, false, false], () => 'pnpm' as const),
|
|
30
|
-
Match.when([false, true, false], () => 'bun' as const),
|
|
31
|
-
Match.when([false, false, true], () => 'npm' as const),
|
|
32
|
-
Match.orElse(() => 'npm' as const), // default fallback
|
|
33
|
-
)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// Check if Prisma schema exists
|
|
37
|
-
const checkPrismaSchema = () =>
|
|
38
|
-
Effect.gen(function* () {
|
|
39
|
-
const schemaExists = yield* fileExists('prisma/schema.prisma')
|
|
40
|
-
|
|
41
|
-
if (!schemaExists) {
|
|
42
|
-
yield* Console.log('❌ Prisma schema not found.')
|
|
43
|
-
yield* Console.log('')
|
|
44
|
-
yield* Console.log('Please run the following command first:')
|
|
45
|
-
|
|
46
|
-
const packageManager = yield* detectPackageManager()
|
|
47
|
-
|
|
48
|
-
const initCommand = Match.value(packageManager).pipe(
|
|
49
|
-
Match.when('pnpm', () => 'pnpm dlx prisma init'),
|
|
50
|
-
Match.when('bun', () => 'bunx prisma init'),
|
|
51
|
-
Match.when('npm', () => 'npx prisma init'),
|
|
52
|
-
Match.exhaustive,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
yield* Console.log(` ${initCommand}`)
|
|
56
|
-
yield* Effect.fail(new Error('Prisma schema not found'))
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// Execute the SQL schema generator
|
|
61
|
-
const generateSqlSchemaServices = () =>
|
|
62
|
-
Effect.gen(function* () {
|
|
63
|
-
// Check if we're being called by Prisma (no interactive output)
|
|
64
|
-
const isCalledByPrisma =
|
|
65
|
-
process.env.PRISMA_GENERATOR_INVOCATION === 'true' ||
|
|
66
|
-
process.argv.includes('--generator') ||
|
|
67
|
-
!process.stdout.isTTY
|
|
68
|
-
|
|
69
|
-
if (!isCalledByPrisma) {
|
|
70
|
-
yield* Console.log('🔧 Running SQL schema generator...')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check if Prisma schema exists
|
|
74
|
-
yield* checkPrismaSchema()
|
|
75
|
-
|
|
76
|
-
// Note: We don't need to check for local generator files
|
|
77
|
-
// since we're importing from our own package
|
|
78
|
-
|
|
79
|
-
if (!isCalledByPrisma) {
|
|
80
|
-
yield* Console.log('🚀 Executing SQL schema generator...')
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Execute the generator function
|
|
84
|
-
yield* Effect.tryPromise({
|
|
85
|
-
try: () => {
|
|
86
|
-
// Create mock options for the generator
|
|
87
|
-
// const mockOptions = {
|
|
88
|
-
// generator: { output: { value: 'src/generated' } },
|
|
89
|
-
// }
|
|
90
|
-
|
|
91
|
-
// return generateSqlSchema(mockOptions)
|
|
92
|
-
return Promise.resolve()
|
|
93
|
-
},
|
|
94
|
-
catch: (error) => new Error(`Generator execution failed: ${error}`),
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
if (!isCalledByPrisma) {
|
|
98
|
-
yield* Console.log('✅ SQL schema generator executed successfully!')
|
|
99
|
-
yield* Console.log('💡 Generated files are available in the configured output directory')
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Ensure the effect completes and exits
|
|
103
|
-
yield* Effect.sync(() => process.exit(0))
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// Export the generate-sql-schema command
|
|
107
|
-
export const generateSqlSchemaCommand = Command.make('generate-sql-schema', {}, () =>
|
|
108
|
-
generateSqlSchemaServices().pipe(Effect.provide(NodeFileSystem.layer), Effect.provide(NodePath.layer)),
|
|
109
|
-
)
|