@nixxie-cms/core 1.0.3 → 2.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/CHANGELOG.md +36 -0
- package/CHANGES-1.1.md +134 -0
- package/context/dist/nixxie-cms-core-context.cjs.js +4 -3
- package/context/dist/nixxie-cms-core-context.esm.js +3 -2
- package/dist/declarations/src/access.d.ts +2 -2
- package/dist/declarations/src/access.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts +2 -2
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/context.d.ts +6 -6
- package/dist/declarations/src/admin-ui/context.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/Fields.d.ts +3 -3
- package/dist/declarations/src/admin-ui/utils/Fields.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/filters.d.ts +5 -5
- package/dist/declarations/src/admin-ui/utils/filters.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts +3 -3
- package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/utils.d.ts +2 -2
- package/dist/declarations/src/admin-ui/utils/utils.d.ts.map +1 -1
- package/dist/declarations/src/context.d.ts +1 -1
- package/dist/declarations/src/context.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bigInt/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/bigInt/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bytes/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/bytes/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/calendarDay/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/calendarDay/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/checkbox/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/checkbox/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/decimal/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/decimal/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/file/index.d.ts +4 -4
- package/dist/declarations/src/fields/types/file/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/float/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/float/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/image/index.d.ts +4 -4
- package/dist/declarations/src/fields/types/image/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/integer/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/integer/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/json/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/json/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/multiselect/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/multiselect/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/multiselect/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/password/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/password/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/index.d.ts +8 -8
- package/dist/declarations/src/fields/types/relationship/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/types.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/types.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/select/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/select/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/text/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/text/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/timestamp/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/timestamp/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/virtual/index.d.ts +7 -7
- package/dist/declarations/src/fields/types/virtual/index.d.ts.map +1 -1
- package/dist/declarations/src/helpers.d.ts +249 -13
- package/dist/declarations/src/helpers.d.ts.map +1 -1
- package/dist/declarations/src/index.d.ts +9 -4
- package/dist/declarations/src/index.d.ts.map +1 -1
- package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -1
- package/dist/declarations/src/lib/admin-meta.d.ts +11 -11
- package/dist/declarations/src/lib/admin-meta.d.ts.map +1 -1
- package/dist/declarations/src/lib/core/access-control.d.ts +18 -18
- package/dist/declarations/src/lib/core/access-control.d.ts.map +1 -1
- package/dist/declarations/src/lib/core/cascade.d.ts +47 -0
- package/dist/declarations/src/lib/core/cascade.d.ts.map +1 -0
- package/dist/declarations/src/lib/core/initialise-lists.d.ts +27 -24
- package/dist/declarations/src/lib/core/initialise-lists.d.ts.map +1 -1
- package/dist/declarations/src/lib/env.d.ts +9 -0
- package/dist/declarations/src/lib/env.d.ts.map +1 -0
- package/dist/declarations/src/lib/system.d.ts +1 -1
- package/dist/declarations/src/lib/system.d.ts.map +1 -1
- package/dist/declarations/src/list-features.d.ts +162 -0
- package/dist/declarations/src/list-features.d.ts.map +1 -0
- package/dist/declarations/src/schema.d.ts +24 -23
- package/dist/declarations/src/schema.d.ts.map +1 -1
- package/dist/declarations/src/session.d.ts +75 -0
- package/dist/declarations/src/session.d.ts.map +1 -1
- package/dist/declarations/src/types/admin-meta.d.ts +11 -11
- package/dist/declarations/src/types/admin-meta.d.ts.map +1 -1
- package/dist/declarations/src/types/config/access-control.d.ts +42 -42
- package/dist/declarations/src/types/config/access-control.d.ts.map +1 -1
- package/dist/declarations/src/types/config/fields.d.ts +19 -19
- package/dist/declarations/src/types/config/fields.d.ts.map +1 -1
- package/dist/declarations/src/types/config/hooks.d.ts +131 -131
- package/dist/declarations/src/types/config/hooks.d.ts.map +1 -1
- package/dist/declarations/src/types/config/index.d.ts +190 -8
- package/dist/declarations/src/types/config/index.d.ts.map +1 -1
- package/dist/declarations/src/types/config/lists.d.ts +146 -108
- package/dist/declarations/src/types/config/lists.d.ts.map +1 -1
- package/dist/declarations/src/types/context.d.ts +507 -47
- package/dist/declarations/src/types/context.d.ts.map +1 -1
- package/dist/declarations/src/types/next-fields.d.ts +28 -28
- package/dist/declarations/src/types/next-fields.d.ts.map +1 -1
- package/dist/declarations/src/types/type-info.d.ts +3 -3
- package/dist/declarations/src/types/type-info.d.ts.map +1 -1
- package/dist/{express-455ae20c.cjs.js → express-84d534c2.cjs.js} +6 -6
- package/dist/{express-7559ca2d.esm.js → express-d0a4ce99.esm.js} +6 -6
- package/dist/{index-15c8f81e.esm.js → index-5d8b0b4e.esm.js} +363 -183
- package/dist/index-6055753b.cjs.js +393 -0
- package/dist/{index-42045902.cjs.js → index-ac29f382.cjs.js} +363 -185
- package/dist/index-f1703b7b.esm.js +386 -0
- package/dist/nixxie-cms-core.cjs.js +1388 -30
- package/dist/nixxie-cms-core.esm.js +1362 -24
- package/dist/{non-null-graphql-add6bb3d.cjs.js → non-null-graphql-4a44c122.cjs.js} +1 -1
- package/dist/{non-null-graphql-a84ed64d.esm.js → non-null-graphql-8c5feaae.esm.js} +1 -1
- package/dist/{resolve-hooks-165a9ce2.cjs.js → resolve-hooks-10a5f84c.cjs.js} +240 -6
- package/dist/{resolve-hooks-6813a045.esm.js → resolve-hooks-9e676794.esm.js} +238 -7
- package/dist/{system-a321642d.cjs.js → system-6b37a5f8.cjs.js} +33 -7
- package/dist/{system-03e49e4f.esm.js → system-e591d821.esm.js} +33 -7
- package/fields/dist/nixxie-cms-core-fields.cjs.js +29 -576
- package/fields/dist/nixxie-cms-core-fields.esm.js +18 -565
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +4 -2
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +4 -2
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.cjs.js +1 -6
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.esm.js +1 -6
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +4 -2
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +4 -2
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +4 -3
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +4 -3
- package/package.json +4 -4
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +4 -3
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +4 -3
- package/scripts/dist/nixxie-cms-core-scripts.cjs.js +4 -3
- package/scripts/dist/nixxie-cms-core-scripts.esm.js +4 -3
- package/session/dist/nixxie-cms-core-session.cjs.js +286 -0
- package/session/dist/nixxie-cms-core-session.esm.js +279 -1
- package/src/access.ts +25 -25
- package/src/admin-ui/admin-meta-graphql.ts +5 -5
- package/src/admin-ui/components/CreateButtonLink.tsx +46 -46
- package/src/admin-ui/components/Navigation.tsx +3 -3
- package/src/admin-ui/context.tsx +6 -6
- package/src/admin-ui/utils/Fields.tsx +241 -241
- package/src/admin-ui/utils/actionData.ts +36 -36
- package/src/admin-ui/utils/filters.ts +148 -148
- package/src/admin-ui/utils/useCreateItem.ts +171 -171
- package/src/admin-ui/utils/utils.tsx +127 -127
- package/src/context.ts +1 -1
- package/src/fields/non-null-graphql.ts +115 -115
- package/src/fields/types/bigInt/index.ts +6 -6
- package/src/fields/types/bytes/index.ts +6 -6
- package/src/fields/types/calendarDay/index.ts +18 -19
- package/src/fields/types/checkbox/index.ts +6 -6
- package/src/fields/types/decimal/index.ts +6 -6
- package/src/fields/types/file/index.ts +8 -8
- package/src/fields/types/float/index.ts +6 -6
- package/src/fields/types/image/index.ts +8 -8
- package/src/fields/types/integer/index.ts +6 -6
- package/src/fields/types/json/index.ts +5 -5
- package/src/fields/types/multiselect/index.ts +7 -7
- package/src/fields/types/multiselect/views/index.tsx +149 -151
- package/src/fields/types/password/index.ts +6 -6
- package/src/fields/types/relationship/index.ts +13 -13
- package/src/fields/types/relationship/views/ComboboxMany.tsx +110 -110
- package/src/fields/types/relationship/views/ComboboxSingle.tsx +115 -115
- package/src/fields/types/relationship/views/ContextualActions.tsx +139 -139
- package/src/fields/types/relationship/views/index.tsx +492 -492
- package/src/fields/types/relationship/views/types.ts +46 -46
- package/src/fields/types/relationship/views/useApolloQuery.ts +185 -185
- package/src/fields/types/relationship/views/useFilter.tsx +109 -109
- package/src/fields/types/select/index.ts +6 -6
- package/src/fields/types/text/index.ts +6 -6
- package/src/fields/types/timestamp/index.ts +23 -21
- package/src/fields/types/virtual/index.ts +11 -11
- package/src/helpers.ts +773 -42
- package/src/index.ts +66 -24
- package/src/internal-unstable/admin-ui/pages/ItemPage/common.tsx +4 -4
- package/src/internal-unstable/admin-ui/pages/ItemPage/index.tsx +5 -5
- package/src/internal-unstable/admin-ui/pages/ListPage/index.tsx +8 -8
- package/src/lib/admin-meta.ts +369 -369
- package/src/lib/context/createContext.ts +6 -0
- package/src/lib/core/access-control.ts +434 -434
- package/src/lib/core/cascade.ts +236 -0
- package/src/lib/core/initialise-lists.ts +49 -33
- package/src/lib/core/mutations/index.ts +7 -0
- package/src/lib/core/mutations/nested-mutation-many-input-resolvers.ts +145 -145
- package/src/lib/core/mutations/nested-mutation-one-input-resolvers.ts +71 -71
- package/src/lib/core/queries/output-field.ts +178 -178
- package/src/lib/env.ts +50 -0
- package/src/lib/id-field.ts +2 -2
- package/src/lib/system.ts +221 -207
- package/src/lib/typescript-schema-printer.ts +227 -227
- package/src/list-features.ts +476 -0
- package/src/schema.ts +92 -22
- package/src/session.ts +225 -0
- package/src/types/admin-meta.ts +218 -218
- package/src/types/config/access-control.ts +186 -186
- package/src/types/config/fields.ts +96 -96
- package/src/types/config/hooks.ts +529 -529
- package/src/types/config/index.ts +206 -7
- package/src/types/config/lists.ts +606 -565
- package/src/types/context.ts +592 -55
- package/src/types/next-fields.ts +31 -31
- package/src/types/type-info.ts +38 -38
- package/src/types/type-tests.ts +21 -21
package/src/lib/system.ts
CHANGED
|
@@ -1,207 +1,221 @@
|
|
|
1
|
-
import { randomBytes } from 'node:crypto'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import type { BaseNixxieTypeInfo, NixxieConfig, NixxieContext } from '../types'
|
|
5
|
-
import { createAdminMeta } from './admin-meta'
|
|
6
|
-
import { createContext } from './context/createContext'
|
|
7
|
-
import { initialiseLists, type InitialisedList } from './core/initialise-lists'
|
|
8
|
-
import { createGraphQLSchema } from './graphql'
|
|
9
|
-
|
|
10
|
-
// TODO: this cannot be changed for now, circular dependency with getSystemPaths, getEsbuildConfig
|
|
11
|
-
export function getBuiltNixxieConfigurationPath(cwd: string) {
|
|
12
|
-
return path.join(cwd, '.nixxie/config.js')
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function posixify(s: string) {
|
|
16
|
-
return s.split(path.sep).join('/')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function getSystemPaths(cwd: string, config: NixxieConfig) {
|
|
20
|
-
const prismaClientPath =
|
|
21
|
-
config.db.prismaClientPath === '@prisma/client'
|
|
22
|
-
? null
|
|
23
|
-
: config.db.prismaClientPath
|
|
24
|
-
? path.join(cwd, config.db.prismaClientPath)
|
|
25
|
-
: null
|
|
26
|
-
|
|
27
|
-
const builtTypesPath = config.types?.path
|
|
28
|
-
? path.join(cwd, config.types.path) // TODO: enforce initConfig before getSystemPaths
|
|
29
|
-
: path.join(cwd, 'node_modules/.nixxie/types.ts')
|
|
30
|
-
|
|
31
|
-
const builtPrismaPath = config.db?.prismaSchemaPath
|
|
32
|
-
? path.join(cwd, config.db.prismaSchemaPath) // TODO: enforce initConfig before getSystemPaths
|
|
33
|
-
: path.join(cwd, 'schema.prisma')
|
|
34
|
-
|
|
35
|
-
const relativePrismaPath = prismaClientPath
|
|
36
|
-
? `./${posixify(path.relative(path.dirname(builtTypesPath), prismaClientPath))}`
|
|
37
|
-
: '@prisma/client'
|
|
38
|
-
|
|
39
|
-
const builtGraphqlPath = config.graphql?.schemaPath
|
|
40
|
-
? path.join(cwd, config.graphql.schemaPath) // TODO: enforce initConfig before getSystemPaths
|
|
41
|
-
: path.join(cwd, 'schema.graphql')
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
config: getBuiltNixxieConfigurationPath(cwd),
|
|
45
|
-
admin: path.join(cwd, '.nixxie/admin'),
|
|
46
|
-
prisma: prismaClientPath ?? '@prisma/client',
|
|
47
|
-
types: {
|
|
48
|
-
relativePrismaPath,
|
|
49
|
-
},
|
|
50
|
-
schema: {
|
|
51
|
-
types: builtTypesPath,
|
|
52
|
-
prisma: builtPrismaPath,
|
|
53
|
-
graphql: builtGraphqlPath,
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function getInternalGraphQLSchema(config: NixxieConfig) {
|
|
59
|
-
// omit `graphql.omit`
|
|
60
|
-
const withoutOmit: NixxieConfig = {
|
|
61
|
-
...config,
|
|
62
|
-
lists: Object.fromEntries(
|
|
63
|
-
Object.entries(config.lists).map(([listKey, list]) => {
|
|
64
|
-
return [
|
|
65
|
-
listKey,
|
|
66
|
-
{
|
|
67
|
-
...list,
|
|
68
|
-
graphql: { ...(list.graphql || {}), omit: false },
|
|
69
|
-
fields: Object.fromEntries(
|
|
70
|
-
Object.entries(list.fields).map(([fieldKey, field]) => {
|
|
71
|
-
if (fieldKey.startsWith('__group')) return [fieldKey, field]
|
|
72
|
-
return [
|
|
73
|
-
fieldKey,
|
|
74
|
-
data => {
|
|
75
|
-
const f = field(data)
|
|
76
|
-
return {
|
|
77
|
-
...f,
|
|
78
|
-
graphql: { ...(f.graphql || {}), omit: false },
|
|
79
|
-
|
|
80
|
-
// WARNING: this bypasses access control checks for filtering and ordering on the internal schema
|
|
81
|
-
isFilterable: true, // TODO: remove when moved to .access.filter and .omit.filter
|
|
82
|
-
isOrderable: true, // TODO: remove when moved to .access.filter and .omit.filter
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
]
|
|
86
|
-
})
|
|
87
|
-
),
|
|
88
|
-
},
|
|
89
|
-
]
|
|
90
|
-
})
|
|
91
|
-
),
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const lists = initialiseLists(withoutOmit)
|
|
95
|
-
const adminMeta = createAdminMeta(withoutOmit, lists)
|
|
96
|
-
return createGraphQLSchema(withoutOmit, lists, adminMeta, true)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function injectNewDefaults(prismaClient: unknown, lists: Record<string, InitialisedList>) {
|
|
100
|
-
for (const listKey in lists) {
|
|
101
|
-
const list = lists[listKey]
|
|
102
|
-
|
|
103
|
-
// TODO: other fields might use 'random' too
|
|
104
|
-
const { dbField } = list.fields.id
|
|
105
|
-
|
|
106
|
-
if ('default' in dbField && dbField.default?.kind === 'random') {
|
|
107
|
-
const { bytes, encoding } = dbField.default
|
|
108
|
-
|
|
109
|
-
prismaClient = (prismaClient as any).$extends({
|
|
110
|
-
query: {
|
|
111
|
-
[list.prisma.listKey]: {
|
|
112
|
-
async create({ args, query }: any) {
|
|
113
|
-
return query({
|
|
114
|
-
...args,
|
|
115
|
-
data: {
|
|
116
|
-
...args.data,
|
|
117
|
-
id: args.data.id ?? randomBytes(bytes).toString(encoding),
|
|
118
|
-
},
|
|
119
|
-
})
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return prismaClient
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function formatUrl(provider: NixxieConfig['db']['provider'], url: string) {
|
|
131
|
-
if (url.startsWith('file:')) {
|
|
132
|
-
const parsed = new URL(url)
|
|
133
|
-
if (provider === 'sqlite' && !parsed.searchParams.get('connection_limit')) {
|
|
134
|
-
// https://github.com/prisma/prisma/issues/9562
|
|
135
|
-
// https://github.com/prisma/prisma/issues/10403
|
|
136
|
-
// https://github.com/prisma/prisma/issues/11789
|
|
137
|
-
parsed.searchParams.set('connection_limit', '1')
|
|
138
|
-
|
|
139
|
-
const [uri] = url.split('?')
|
|
140
|
-
return `${uri}?${parsed.search}`
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return url
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export function createSystem(config: NixxieConfig) {
|
|
148
|
-
const lists = initialiseLists(config)
|
|
149
|
-
const adminMeta = createAdminMeta(config, lists)
|
|
150
|
-
const graphQLSchemas = {
|
|
151
|
-
public: createGraphQLSchema(config, lists, adminMeta, false),
|
|
152
|
-
internal: getInternalGraphQLSchema(config),
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
config,
|
|
157
|
-
graphql: {
|
|
158
|
-
schemas: graphQLSchemas,
|
|
159
|
-
},
|
|
160
|
-
adminMeta,
|
|
161
|
-
lists,
|
|
162
|
-
getPaths: (cwd: string) => getSystemPaths(cwd, config),
|
|
163
|
-
|
|
164
|
-
getNixxie: (PM: any) => {
|
|
165
|
-
const prePrismaClient = new PM.PrismaClient({
|
|
166
|
-
datasourceUrl: formatUrl(config.db.provider, config.db.url),
|
|
167
|
-
log: config.db.enableLogging,
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
const prismaClient = config.db.extendPrismaClient(injectNewDefaults(prePrismaClient, lists))
|
|
171
|
-
const context = createContext({
|
|
172
|
-
config,
|
|
173
|
-
lists,
|
|
174
|
-
graphQLSchemas,
|
|
175
|
-
prismaClient,
|
|
176
|
-
prismaTypes: {
|
|
177
|
-
DbNull: PM.Prisma.DbNull,
|
|
178
|
-
JsonNull: PM.Prisma.JsonNull,
|
|
179
|
-
},
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
// TODO: replace with server.onStart, remove in breaking change
|
|
184
|
-
async connect() {
|
|
185
|
-
await (prismaClient as any).$connect()
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
1
|
+
import { randomBytes } from 'node:crypto'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import type { BaseNixxieTypeInfo, NixxieConfig, NixxieContext } from '../types'
|
|
5
|
+
import { createAdminMeta } from './admin-meta'
|
|
6
|
+
import { createContext } from './context/createContext'
|
|
7
|
+
import { initialiseLists, type InitialisedList } from './core/initialise-lists'
|
|
8
|
+
import { createGraphQLSchema } from './graphql'
|
|
9
|
+
|
|
10
|
+
// TODO: this cannot be changed for now, circular dependency with getSystemPaths, getEsbuildConfig
|
|
11
|
+
export function getBuiltNixxieConfigurationPath(cwd: string) {
|
|
12
|
+
return path.join(cwd, '.nixxie/config.js')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function posixify(s: string) {
|
|
16
|
+
return s.split(path.sep).join('/')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getSystemPaths(cwd: string, config: NixxieConfig) {
|
|
20
|
+
const prismaClientPath =
|
|
21
|
+
config.db.prismaClientPath === '@prisma/client'
|
|
22
|
+
? null
|
|
23
|
+
: config.db.prismaClientPath
|
|
24
|
+
? path.join(cwd, config.db.prismaClientPath)
|
|
25
|
+
: null
|
|
26
|
+
|
|
27
|
+
const builtTypesPath = config.types?.path
|
|
28
|
+
? path.join(cwd, config.types.path) // TODO: enforce initConfig before getSystemPaths
|
|
29
|
+
: path.join(cwd, 'node_modules/.nixxie/types.ts')
|
|
30
|
+
|
|
31
|
+
const builtPrismaPath = config.db?.prismaSchemaPath
|
|
32
|
+
? path.join(cwd, config.db.prismaSchemaPath) // TODO: enforce initConfig before getSystemPaths
|
|
33
|
+
: path.join(cwd, 'schema.prisma')
|
|
34
|
+
|
|
35
|
+
const relativePrismaPath = prismaClientPath
|
|
36
|
+
? `./${posixify(path.relative(path.dirname(builtTypesPath), prismaClientPath))}`
|
|
37
|
+
: '@prisma/client'
|
|
38
|
+
|
|
39
|
+
const builtGraphqlPath = config.graphql?.schemaPath
|
|
40
|
+
? path.join(cwd, config.graphql.schemaPath) // TODO: enforce initConfig before getSystemPaths
|
|
41
|
+
: path.join(cwd, 'schema.graphql')
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
config: getBuiltNixxieConfigurationPath(cwd),
|
|
45
|
+
admin: path.join(cwd, '.nixxie/admin'),
|
|
46
|
+
prisma: prismaClientPath ?? '@prisma/client',
|
|
47
|
+
types: {
|
|
48
|
+
relativePrismaPath,
|
|
49
|
+
},
|
|
50
|
+
schema: {
|
|
51
|
+
types: builtTypesPath,
|
|
52
|
+
prisma: builtPrismaPath,
|
|
53
|
+
graphql: builtGraphqlPath,
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getInternalGraphQLSchema(config: NixxieConfig) {
|
|
59
|
+
// omit `graphql.omit`
|
|
60
|
+
const withoutOmit: NixxieConfig = {
|
|
61
|
+
...config,
|
|
62
|
+
lists: Object.fromEntries(
|
|
63
|
+
Object.entries(config.lists).map(([listKey, list]) => {
|
|
64
|
+
return [
|
|
65
|
+
listKey,
|
|
66
|
+
{
|
|
67
|
+
...list,
|
|
68
|
+
graphql: { ...(list.graphql || {}), omit: false },
|
|
69
|
+
fields: Object.fromEntries(
|
|
70
|
+
Object.entries(list.fields).map(([fieldKey, field]) => {
|
|
71
|
+
if (fieldKey.startsWith('__group')) return [fieldKey, field]
|
|
72
|
+
return [
|
|
73
|
+
fieldKey,
|
|
74
|
+
data => {
|
|
75
|
+
const f = field(data)
|
|
76
|
+
return {
|
|
77
|
+
...f,
|
|
78
|
+
graphql: { ...(f.graphql || {}), omit: false },
|
|
79
|
+
|
|
80
|
+
// WARNING: this bypasses access control checks for filtering and ordering on the internal schema
|
|
81
|
+
isFilterable: true, // TODO: remove when moved to .access.filter and .omit.filter
|
|
82
|
+
isOrderable: true, // TODO: remove when moved to .access.filter and .omit.filter
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
]
|
|
86
|
+
})
|
|
87
|
+
),
|
|
88
|
+
},
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
),
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const lists = initialiseLists(withoutOmit)
|
|
95
|
+
const adminMeta = createAdminMeta(withoutOmit, lists)
|
|
96
|
+
return createGraphQLSchema(withoutOmit, lists, adminMeta, true)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function injectNewDefaults(prismaClient: unknown, lists: Record<string, InitialisedList>) {
|
|
100
|
+
for (const listKey in lists) {
|
|
101
|
+
const list = lists[listKey]
|
|
102
|
+
|
|
103
|
+
// TODO: other fields might use 'random' too
|
|
104
|
+
const { dbField } = list.fields.id
|
|
105
|
+
|
|
106
|
+
if ('default' in dbField && dbField.default?.kind === 'random') {
|
|
107
|
+
const { bytes, encoding } = dbField.default
|
|
108
|
+
|
|
109
|
+
prismaClient = (prismaClient as any).$extends({
|
|
110
|
+
query: {
|
|
111
|
+
[list.prisma.listKey]: {
|
|
112
|
+
async create({ args, query }: any) {
|
|
113
|
+
return query({
|
|
114
|
+
...args,
|
|
115
|
+
data: {
|
|
116
|
+
...args.data,
|
|
117
|
+
id: args.data.id ?? randomBytes(bytes).toString(encoding),
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return prismaClient
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function formatUrl(provider: NixxieConfig['db']['provider'], url: string) {
|
|
131
|
+
if (url.startsWith('file:')) {
|
|
132
|
+
const parsed = new URL(url)
|
|
133
|
+
if (provider === 'sqlite' && !parsed.searchParams.get('connection_limit')) {
|
|
134
|
+
// https://github.com/prisma/prisma/issues/9562
|
|
135
|
+
// https://github.com/prisma/prisma/issues/10403
|
|
136
|
+
// https://github.com/prisma/prisma/issues/11789
|
|
137
|
+
parsed.searchParams.set('connection_limit', '1')
|
|
138
|
+
|
|
139
|
+
const [uri] = url.split('?')
|
|
140
|
+
return `${uri}?${parsed.search}`
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return url
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function createSystem(config: NixxieConfig) {
|
|
148
|
+
const lists = initialiseLists(config)
|
|
149
|
+
const adminMeta = createAdminMeta(config, lists)
|
|
150
|
+
const graphQLSchemas = {
|
|
151
|
+
public: createGraphQLSchema(config, lists, adminMeta, false),
|
|
152
|
+
internal: getInternalGraphQLSchema(config),
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
config,
|
|
157
|
+
graphql: {
|
|
158
|
+
schemas: graphQLSchemas,
|
|
159
|
+
},
|
|
160
|
+
adminMeta,
|
|
161
|
+
lists,
|
|
162
|
+
getPaths: (cwd: string) => getSystemPaths(cwd, config),
|
|
163
|
+
|
|
164
|
+
getNixxie: (PM: any) => {
|
|
165
|
+
const prePrismaClient = new PM.PrismaClient({
|
|
166
|
+
datasourceUrl: formatUrl(config.db.provider, config.db.url),
|
|
167
|
+
log: config.db.enableLogging,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
const prismaClient = config.db.extendPrismaClient(injectNewDefaults(prePrismaClient, lists))
|
|
171
|
+
const context = createContext({
|
|
172
|
+
config,
|
|
173
|
+
lists,
|
|
174
|
+
graphQLSchemas,
|
|
175
|
+
prismaClient,
|
|
176
|
+
prismaTypes: {
|
|
177
|
+
DbNull: PM.Prisma.DbNull,
|
|
178
|
+
JsonNull: PM.Prisma.JsonNull,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
// TODO: replace with server.onStart, remove in breaking change
|
|
184
|
+
async connect() {
|
|
185
|
+
await (prismaClient as any).$connect()
|
|
186
|
+
// Give database-backed service stores access to the context before anything
|
|
187
|
+
// else runs (see NixxieInitableService).
|
|
188
|
+
const sudoContext = context.sudo()
|
|
189
|
+
for (const [name, service] of Object.entries(context.services)) {
|
|
190
|
+
if (!service || typeof (service as any).init !== 'function') continue
|
|
191
|
+
try {
|
|
192
|
+
await (service as any).init(sudoContext)
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Failed to initialise the "${name}" service: ${err instanceof Error ? err.message : err}`,
|
|
196
|
+
{ cause: err }
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
await config.db.onConnect?.(context)
|
|
201
|
+
},
|
|
202
|
+
// TODO: only used by tests, remove in breaking change
|
|
203
|
+
async disconnect() {
|
|
204
|
+
await (prismaClient as any).$disconnect()
|
|
205
|
+
},
|
|
206
|
+
context,
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type System = ReturnType<typeof createSystem>
|
|
213
|
+
|
|
214
|
+
export function createNixxieContext<TypeInfo extends BaseNixxieTypeInfo>(
|
|
215
|
+
config: NixxieConfig<TypeInfo>,
|
|
216
|
+
PrismaModule: unknown
|
|
217
|
+
): NixxieContext<TypeInfo> {
|
|
218
|
+
const system = createSystem(config)
|
|
219
|
+
const { context } = system.getNixxie(PrismaModule)
|
|
220
|
+
return context
|
|
221
|
+
}
|