on-zero 0.7.2-1784530701923 → 0.7.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/dist/cjs/asyncTasks.cjs +51 -0
- package/dist/cjs/asyncTasks.native.js +84 -0
- package/dist/cjs/asyncTasks.native.js.map +1 -0
- package/dist/cjs/createZeroDirectServer.cjs +269 -0
- package/dist/cjs/createZeroDirectServer.native.js +287 -0
- package/dist/cjs/createZeroDirectServer.native.js.map +1 -0
- package/dist/cjs/createZeroSQLiteServer.cjs +50 -0
- package/dist/cjs/createZeroSQLiteServer.native.js +58 -0
- package/dist/cjs/createZeroSQLiteServer.native.js.map +1 -0
- package/dist/cjs/createZeroSQLiteServer.test.cjs +595 -0
- package/dist/cjs/createZeroSQLiteServer.test.native.js +647 -0
- package/dist/cjs/createZeroSQLiteServer.test.native.js.map +1 -0
- package/dist/cjs/createZeroServer.cjs +82 -0
- package/dist/cjs/createZeroServer.native.js +93 -0
- package/dist/cjs/createZeroServer.native.js.map +1 -0
- package/dist/cjs/createZeroServer.test.cjs +378 -0
- package/dist/cjs/createZeroServer.test.native.js +448 -0
- package/dist/cjs/createZeroServer.test.native.js.map +1 -0
- package/dist/cjs/createZeroServerCore.cjs +211 -0
- package/dist/cjs/createZeroServerCore.native.js +355 -0
- package/dist/cjs/createZeroServerCore.native.js.map +1 -0
- package/dist/cjs/helpers/createMutators.cjs +3 -4
- package/dist/cjs/helpers/createMutators.native.js +3 -6
- package/dist/cjs/helpers/createMutators.native.js.map +1 -1
- package/dist/cjs/httpPull/auth.test.cjs +197 -0
- package/dist/cjs/httpPull/auth.test.native.js +279 -0
- package/dist/cjs/httpPull/auth.test.native.js.map +1 -0
- package/dist/cjs/httpPull/churn.test.cjs +132 -0
- package/dist/cjs/httpPull/churn.test.native.js +155 -0
- package/dist/cjs/httpPull/churn.test.native.js.map +1 -0
- package/dist/cjs/httpPull/completeAck.test.cjs +69 -0
- package/dist/cjs/httpPull/completeAck.test.native.js +76 -0
- package/dist/cjs/httpPull/completeAck.test.native.js.map +1 -0
- package/dist/cjs/httpPull/fixtureServer.cjs +340 -0
- package/dist/cjs/httpPull/fixtureServer.native.js +534 -0
- package/dist/cjs/httpPull/fixtureServer.native.js.map +1 -0
- package/dist/cjs/httpPull/integration.test.cjs +53 -0
- package/dist/cjs/httpPull/integration.test.native.js +60 -0
- package/dist/cjs/httpPull/integration.test.native.js.map +1 -0
- package/dist/cjs/httpPull/rebase.test.cjs +360 -0
- package/dist/cjs/httpPull/rebase.test.native.js +420 -0
- package/dist/cjs/httpPull/rebase.test.native.js.map +1 -0
- package/dist/cjs/httpPull/relations.test.cjs +107 -0
- package/dist/cjs/httpPull/relations.test.native.js +119 -0
- package/dist/cjs/httpPull/relations.test.native.js.map +1 -0
- package/dist/cjs/httpPull/testHarness.cjs +100 -0
- package/dist/cjs/httpPull/testHarness.native.js +112 -0
- package/dist/cjs/httpPull/testHarness.native.js.map +1 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.native.js +1 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/run.cjs +1 -1
- package/dist/cjs/run.native.js +1 -1
- package/dist/cjs/server.cjs +22 -0
- package/dist/cjs/server.native.js +4 -0
- package/dist/cjs/server.native.js.map +1 -0
- package/dist/cjs/sqliteRuntime.cjs +318 -0
- package/dist/cjs/sqliteRuntime.native.js +438 -0
- package/dist/cjs/sqliteRuntime.native.js.map +1 -0
- package/dist/cjs/state.cjs +1 -1
- package/dist/cjs/state.native.js +1 -1
- package/dist/cjs/syncHost.cjs +179 -0
- package/dist/cjs/syncHost.native.js +388 -0
- package/dist/cjs/syncHost.native.js.map +1 -0
- package/dist/cjs/syncHost.test.cjs +240 -0
- package/dist/cjs/syncHost.test.native.js +290 -0
- package/dist/cjs/syncHost.test.native.js.map +1 -0
- package/dist/cjs/zeroRunner.cjs +1 -1
- package/dist/cjs/zeroRunner.native.js +1 -1
- package/dist/esm/asyncTasks.mjs +26 -0
- package/dist/esm/asyncTasks.mjs.map +1 -0
- package/dist/esm/asyncTasks.native.js +56 -0
- package/dist/esm/asyncTasks.native.js.map +1 -0
- package/dist/esm/createZeroDirectServer.mjs +241 -0
- package/dist/esm/createZeroDirectServer.mjs.map +1 -0
- package/dist/esm/createZeroDirectServer.native.js +256 -0
- package/dist/esm/createZeroDirectServer.native.js.map +1 -0
- package/dist/esm/createZeroSQLiteServer.mjs +24 -0
- package/dist/esm/createZeroSQLiteServer.mjs.map +1 -0
- package/dist/esm/createZeroSQLiteServer.native.js +29 -0
- package/dist/esm/createZeroSQLiteServer.native.js.map +1 -0
- package/dist/esm/createZeroSQLiteServer.test.mjs +596 -0
- package/dist/esm/createZeroSQLiteServer.test.mjs.map +1 -0
- package/dist/esm/createZeroSQLiteServer.test.native.js +645 -0
- package/dist/esm/createZeroSQLiteServer.test.native.js.map +1 -0
- package/dist/esm/createZeroServer.mjs +57 -0
- package/dist/esm/createZeroServer.mjs.map +1 -0
- package/dist/esm/createZeroServer.native.js +65 -0
- package/dist/esm/createZeroServer.native.js.map +1 -0
- package/dist/esm/createZeroServer.test.mjs +379 -0
- package/dist/esm/createZeroServer.test.mjs.map +1 -0
- package/dist/esm/createZeroServer.test.native.js +446 -0
- package/dist/esm/createZeroServer.test.native.js.map +1 -0
- package/dist/esm/createZeroServerCore.mjs +186 -0
- package/dist/esm/createZeroServerCore.mjs.map +1 -0
- package/dist/esm/createZeroServerCore.native.js +327 -0
- package/dist/esm/createZeroServerCore.native.js.map +1 -0
- package/dist/esm/helpers/createMutators.mjs +3 -4
- package/dist/esm/helpers/createMutators.mjs.map +1 -1
- package/dist/esm/helpers/createMutators.native.js +3 -6
- package/dist/esm/helpers/createMutators.native.js.map +1 -1
- package/dist/esm/httpPull/auth.test.mjs +198 -0
- package/dist/esm/httpPull/auth.test.mjs.map +1 -0
- package/dist/esm/httpPull/auth.test.native.js +277 -0
- package/dist/esm/httpPull/auth.test.native.js.map +1 -0
- package/dist/esm/httpPull/churn.test.mjs +133 -0
- package/dist/esm/httpPull/churn.test.mjs.map +1 -0
- package/dist/esm/httpPull/churn.test.native.js +153 -0
- package/dist/esm/httpPull/churn.test.native.js.map +1 -0
- package/dist/esm/httpPull/completeAck.test.mjs +70 -0
- package/dist/esm/httpPull/completeAck.test.mjs.map +1 -0
- package/dist/esm/httpPull/completeAck.test.native.js +74 -0
- package/dist/esm/httpPull/completeAck.test.native.js.map +1 -0
- package/dist/esm/httpPull/fixtureServer.mjs +315 -0
- package/dist/esm/httpPull/fixtureServer.mjs.map +1 -0
- package/dist/esm/httpPull/fixtureServer.native.js +506 -0
- package/dist/esm/httpPull/fixtureServer.native.js.map +1 -0
- package/dist/esm/httpPull/integration.test.mjs +54 -0
- package/dist/esm/httpPull/integration.test.mjs.map +1 -0
- package/dist/esm/httpPull/integration.test.native.js +58 -0
- package/dist/esm/httpPull/integration.test.native.js.map +1 -0
- package/dist/esm/httpPull/rebase.test.mjs +361 -0
- package/dist/esm/httpPull/rebase.test.mjs.map +1 -0
- package/dist/esm/httpPull/rebase.test.native.js +418 -0
- package/dist/esm/httpPull/rebase.test.native.js.map +1 -0
- package/dist/esm/httpPull/relations.test.mjs +108 -0
- package/dist/esm/httpPull/relations.test.mjs.map +1 -0
- package/dist/esm/httpPull/relations.test.native.js +117 -0
- package/dist/esm/httpPull/relations.test.native.js.map +1 -0
- package/dist/esm/httpPull/testHarness.mjs +72 -0
- package/dist/esm/httpPull/testHarness.mjs.map +1 -0
- package/dist/esm/httpPull/testHarness.native.js +81 -0
- package/dist/esm/httpPull/testHarness.native.js.map +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +1 -0
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/run.mjs +1 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/run.native.js +1 -1
- package/dist/esm/server.mjs +4 -0
- package/dist/esm/server.mjs.map +1 -0
- package/dist/esm/server.native.js +2 -0
- package/dist/esm/server.native.js.map +1 -0
- package/dist/esm/sqliteRuntime.mjs +289 -0
- package/dist/esm/sqliteRuntime.mjs.map +1 -0
- package/dist/esm/sqliteRuntime.native.js +406 -0
- package/dist/esm/sqliteRuntime.native.js.map +1 -0
- package/dist/esm/state.mjs +1 -1
- package/dist/esm/state.native.js +1 -1
- package/dist/esm/syncHost.mjs +153 -0
- package/dist/esm/syncHost.mjs.map +1 -0
- package/dist/esm/syncHost.native.js +359 -0
- package/dist/esm/syncHost.native.js.map +1 -0
- package/dist/esm/syncHost.test.mjs +217 -0
- package/dist/esm/syncHost.test.mjs.map +1 -0
- package/dist/esm/syncHost.test.native.js +264 -0
- package/dist/esm/syncHost.test.native.js.map +1 -0
- package/dist/esm/zeroRunner.mjs +1 -1
- package/dist/esm/zeroRunner.mjs.map +1 -1
- package/dist/esm/zeroRunner.native.js +1 -1
- package/package.json +23 -8
- package/readme.md +65 -40
- package/src/asyncTasks.ts +36 -0
- package/src/createZeroClient.tsx +1 -1
- package/src/createZeroDirectServer.ts +411 -0
- package/src/createZeroSQLiteServer.test.ts +614 -0
- package/src/createZeroSQLiteServer.ts +56 -0
- package/src/createZeroServer.test.ts +421 -0
- package/src/createZeroServer.ts +105 -0
- package/src/createZeroServerCore.ts +296 -0
- package/src/helpers/createMutators.ts +2 -6
- package/src/httpPull/auth.test.ts +208 -0
- package/src/httpPull/churn.test.ts +147 -0
- package/src/httpPull/completeAck.test.ts +80 -0
- package/src/httpPull/fixtureServer.ts +391 -0
- package/src/httpPull/integration.test.ts +57 -0
- package/src/httpPull/rebase.test.ts +368 -0
- package/src/httpPull/relations.test.ts +135 -0
- package/src/httpPull/testHarness.ts +95 -0
- package/src/index.ts +1 -0
- package/src/run.ts +1 -1
- package/src/server.native.ts +3 -0
- package/src/server.ts +4 -0
- package/src/sqliteRuntime.ts +512 -0
- package/src/state.ts +1 -1
- package/src/syncHost.test.ts +223 -0
- package/src/syncHost.ts +294 -0
- package/src/types.ts +5 -0
- package/src/zeroRunner.ts +1 -1
- package/test-fixtures/server-return-types.ts +58 -21
- package/types/asyncTasks.d.ts +11 -0
- package/types/asyncTasks.d.ts.map +1 -0
- package/types/createZeroDirectServer.d.ts +80 -0
- package/types/createZeroDirectServer.d.ts.map +1 -0
- package/types/createZeroSQLiteServer.d.ts +12 -0
- package/types/createZeroSQLiteServer.d.ts.map +1 -0
- package/types/createZeroSQLiteServer.test.d.ts +2 -0
- package/types/createZeroSQLiteServer.test.d.ts.map +1 -0
- package/types/createZeroServer.d.ts +18 -0
- package/types/createZeroServer.d.ts.map +1 -0
- package/types/createZeroServer.test.d.ts +2 -0
- package/types/createZeroServer.test.d.ts.map +1 -0
- package/types/createZeroServerCore.d.ts +256 -0
- package/types/createZeroServerCore.d.ts.map +1 -0
- package/types/helpers/createMutators.d.ts +1 -2
- package/types/helpers/createMutators.d.ts.map +1 -1
- package/types/httpPull/auth.test.d.ts +2 -0
- package/types/httpPull/auth.test.d.ts.map +1 -0
- package/types/httpPull/churn.test.d.ts +2 -0
- package/types/httpPull/churn.test.d.ts.map +1 -0
- package/types/httpPull/completeAck.test.d.ts +2 -0
- package/types/httpPull/completeAck.test.d.ts.map +1 -0
- package/types/httpPull/fixtureSchema.d.ts +1 -1
- package/types/httpPull/fixtureServer.d.ts +14 -0
- package/types/httpPull/fixtureServer.d.ts.map +1 -0
- package/types/httpPull/integration.test.d.ts +2 -0
- package/types/httpPull/integration.test.d.ts.map +1 -0
- package/types/httpPull/rebase.test.d.ts +2 -0
- package/types/httpPull/rebase.test.d.ts.map +1 -0
- package/types/httpPull/relations.test.d.ts +2 -0
- package/types/httpPull/relations.test.d.ts.map +1 -0
- package/types/httpPull/testHarness.d.ts +32 -0
- package/types/httpPull/testHarness.d.ts.map +1 -0
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/server.d.ts +5 -0
- package/types/server.d.ts.map +1 -0
- package/types/server.native.d.ts +1 -0
- package/types/server.native.d.ts.map +1 -0
- package/types/sqliteRuntime.d.ts +71 -0
- package/types/sqliteRuntime.d.ts.map +1 -0
- package/types/syncHost.d.ts +42 -0
- package/types/syncHost.d.ts.map +1 -0
- package/types/syncHost.test.d.ts +2 -0
- package/types/syncHost.test.d.ts.map +1 -0
- package/types/types.d.ts +4 -0
- package/types/types.d.ts.map +1 -1
- package/dist/cjs/orez.cjs +0 -227
- package/dist/cjs/orez.native.js +0 -314
- package/dist/cjs/orez.native.js.map +0 -1
- package/dist/cjs/orez.test.cjs +0 -211
- package/dist/cjs/orez.test.native.js +0 -226
- package/dist/cjs/orez.test.native.js.map +0 -1
- package/dist/esm/orez.mjs +0 -202
- package/dist/esm/orez.mjs.map +0 -1
- package/dist/esm/orez.native.js +0 -286
- package/dist/esm/orez.native.js.map +0 -1
- package/dist/esm/orez.test.mjs +0 -188
- package/dist/esm/orez.test.mjs.map +0 -1
- package/dist/esm/orez.test.native.js +0 -200
- package/dist/esm/orez.test.native.js.map +0 -1
- package/src/orez.test.ts +0 -195
- package/src/orez.ts +0 -331
- package/types/orez.d.ts +0 -53
- package/types/orez.d.ts.map +0 -1
- package/types/orez.test.d.ts +0 -2
- package/types/orez.test.d.ts.map +0 -1
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { createBuilder, mustGetQuery } from '@rocicorp/zero'
|
|
2
|
+
|
|
3
|
+
import { runAsyncTaskEntries } from './asyncTasks'
|
|
4
|
+
import { createPermissions } from './createPermissions'
|
|
5
|
+
import { createMutators } from './helpers/createMutators'
|
|
6
|
+
import {
|
|
7
|
+
getScopedAuthData,
|
|
8
|
+
isInZeroMutation,
|
|
9
|
+
mutatorContext,
|
|
10
|
+
runWithAuthScope,
|
|
11
|
+
} from './helpers/mutatorContext'
|
|
12
|
+
import { runWithQueryContext } from './helpers/queryContext'
|
|
13
|
+
import { getMutationsPermissions } from './modelRegistry'
|
|
14
|
+
import { setCustomQueries } from './run'
|
|
15
|
+
import { getZQL, setEnvironment, setSchema } from './state'
|
|
16
|
+
import { setEvaluatingPermission } from './where'
|
|
17
|
+
import { setRunner } from './zeroRunner'
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
AdminRoleMode,
|
|
21
|
+
AsyncTask,
|
|
22
|
+
AsyncTaskEntry,
|
|
23
|
+
AsyncTaskOptions,
|
|
24
|
+
AuthData,
|
|
25
|
+
GenericModels,
|
|
26
|
+
MutatorContext,
|
|
27
|
+
QueryBuilder,
|
|
28
|
+
Transaction,
|
|
29
|
+
} from './types'
|
|
30
|
+
import type {
|
|
31
|
+
AnyQueryRegistry,
|
|
32
|
+
HumanReadable,
|
|
33
|
+
Query,
|
|
34
|
+
Schema as ZeroSchema,
|
|
35
|
+
} from '@rocicorp/zero'
|
|
36
|
+
import type { Database, TransactionProviderInput } from '@rocicorp/zero/server'
|
|
37
|
+
|
|
38
|
+
type MutateAuthData = Pick<AuthData, 'email' | 'id'> & Partial<AuthData>
|
|
39
|
+
|
|
40
|
+
export type MutateOptions = {
|
|
41
|
+
authData?: MutateAuthData
|
|
42
|
+
awaitEffects?: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type ServerMutate<Models extends GenericModels> = {
|
|
46
|
+
[Key in keyof Models]: {
|
|
47
|
+
[K in keyof Models[Key]['mutate']]: Models[Key]['mutate'][K] extends (
|
|
48
|
+
ctx: MutatorContext,
|
|
49
|
+
arg: infer Arg,
|
|
50
|
+
) => any
|
|
51
|
+
? (arg: Arg, options?: MutateOptions) => Promise<void>
|
|
52
|
+
: (options?: MutateOptions) => Promise<void>
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ValidateQueryArgs = {
|
|
57
|
+
authData: AuthData | null
|
|
58
|
+
queryName: string
|
|
59
|
+
params: unknown
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ValidateMutationArgs = {
|
|
63
|
+
authData: AuthData | null
|
|
64
|
+
mutatorName: string
|
|
65
|
+
tableName: string
|
|
66
|
+
args: unknown
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type ValidateQueryFn = (args: ValidateQueryArgs) => void
|
|
70
|
+
export type ValidateMutationFn = (args: ValidateMutationArgs) => void | Promise<void>
|
|
71
|
+
|
|
72
|
+
export type ServerQueryResolverOptions = {
|
|
73
|
+
authData: AuthData | null
|
|
74
|
+
name: string
|
|
75
|
+
args: unknown
|
|
76
|
+
queries: AnyQueryRegistry
|
|
77
|
+
permissions: ReturnType<typeof createPermissions>
|
|
78
|
+
validateQuery?: ValidateQueryFn
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function resolveServerQuery({
|
|
82
|
+
authData,
|
|
83
|
+
name,
|
|
84
|
+
args,
|
|
85
|
+
queries,
|
|
86
|
+
permissions,
|
|
87
|
+
validateQuery,
|
|
88
|
+
}: ServerQueryResolverOptions) {
|
|
89
|
+
if (name.startsWith('permission.')) {
|
|
90
|
+
const table = name.slice('permission.'.length)
|
|
91
|
+
const { objOrId } = args as {
|
|
92
|
+
objOrId: string | Record<string, any>
|
|
93
|
+
}
|
|
94
|
+
const permission = getMutationsPermissions(table)
|
|
95
|
+
if (!permission) {
|
|
96
|
+
throw new Error(`[permission] no permission defined for table: ${table}`)
|
|
97
|
+
}
|
|
98
|
+
setEvaluatingPermission(true)
|
|
99
|
+
try {
|
|
100
|
+
return (getZQL() as any)[table]
|
|
101
|
+
.where((eb: any) => {
|
|
102
|
+
return permissions.buildPermissionQuery(
|
|
103
|
+
authData,
|
|
104
|
+
eb,
|
|
105
|
+
permission,
|
|
106
|
+
objOrId,
|
|
107
|
+
table,
|
|
108
|
+
)
|
|
109
|
+
})
|
|
110
|
+
.one()
|
|
111
|
+
} finally {
|
|
112
|
+
setEvaluatingPermission(false)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (validateQuery) {
|
|
117
|
+
validateQuery({ authData, queryName: name, params: args })
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const query = (mustGetQuery as any)(queries, name)
|
|
121
|
+
return query.fn({ args, ctx: authData })
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type TransactionAttemptLifecycle = {
|
|
125
|
+
beginAttempt(): void
|
|
126
|
+
completeAttempt(): void
|
|
127
|
+
rollbackAttempt(): void
|
|
128
|
+
commitTransaction(): void
|
|
129
|
+
rollbackTransaction(): void
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type ZeroServerDatabase = Database<Transaction>
|
|
133
|
+
|
|
134
|
+
export type ZeroServerCommonOptions<
|
|
135
|
+
Schema extends ZeroSchema,
|
|
136
|
+
Models extends GenericModels,
|
|
137
|
+
ServerActions extends Record<string, unknown>,
|
|
138
|
+
> = {
|
|
139
|
+
schema: Schema
|
|
140
|
+
models: Models
|
|
141
|
+
createServerActions: () => ServerActions
|
|
142
|
+
queries?: AnyQueryRegistry
|
|
143
|
+
/** generated validators keyed by model and mutation name */
|
|
144
|
+
mutations?: Record<string, Record<string, any>>
|
|
145
|
+
/** synchronous query authorization hook; throw to reject */
|
|
146
|
+
validateQuery?: ValidateQueryFn
|
|
147
|
+
/** mutation authorization hook; throw to reject */
|
|
148
|
+
validateMutation?: ValidateMutationFn
|
|
149
|
+
/** controls which operations the admin role bypasses */
|
|
150
|
+
defaultAllowAdminRole?: AdminRoleMode
|
|
151
|
+
/** auth data used by direct server mutations when no scope provides it */
|
|
152
|
+
defaultMutateAuthData?: MutateAuthData
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type ZeroDirectServerOptions<
|
|
156
|
+
Schema extends ZeroSchema,
|
|
157
|
+
Models extends GenericModels,
|
|
158
|
+
ServerActions extends Record<string, unknown>,
|
|
159
|
+
> = ZeroServerCommonOptions<Schema, Models, ServerActions> & {
|
|
160
|
+
createDatabase: () => ZeroServerDatabase
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type ZeroDirectServer<Schema extends ZeroSchema, Models extends GenericModels> = {
|
|
164
|
+
transaction: <
|
|
165
|
+
CB extends (tx: Transaction) => Promise<any>,
|
|
166
|
+
Returns extends CB extends (tx: Transaction) => Promise<infer X> ? X : never,
|
|
167
|
+
>(
|
|
168
|
+
query: CB,
|
|
169
|
+
) => Promise<Returns>
|
|
170
|
+
mutate: ServerMutate<Models>
|
|
171
|
+
query: <R>(
|
|
172
|
+
cb: (q: QueryBuilder) => Query<any, Schema, R>,
|
|
173
|
+
authData?: AuthData | null,
|
|
174
|
+
) => Promise<HumanReadable<R>>
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function createAsyncTaskCollector() {
|
|
178
|
+
const committed: AsyncTaskEntry[] = []
|
|
179
|
+
let attempt: AsyncTaskEntry[] | undefined
|
|
180
|
+
let completedAttempt: AsyncTaskEntry[] | undefined
|
|
181
|
+
|
|
182
|
+
const enqueueTask = (task: AsyncTask, opts?: AsyncTaskOptions) => {
|
|
183
|
+
const entries = attempt ?? committed
|
|
184
|
+
entries.push({ task, barrier: opts?.barrier === true })
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const lifecycle: TransactionAttemptLifecycle = {
|
|
188
|
+
beginAttempt() {
|
|
189
|
+
attempt = []
|
|
190
|
+
completedAttempt = undefined
|
|
191
|
+
},
|
|
192
|
+
completeAttempt() {
|
|
193
|
+
completedAttempt = attempt
|
|
194
|
+
attempt = undefined
|
|
195
|
+
},
|
|
196
|
+
rollbackAttempt() {
|
|
197
|
+
attempt = undefined
|
|
198
|
+
completedAttempt = undefined
|
|
199
|
+
},
|
|
200
|
+
commitTransaction() {
|
|
201
|
+
if (completedAttempt) committed.push(...completedAttempt)
|
|
202
|
+
completedAttempt = undefined
|
|
203
|
+
},
|
|
204
|
+
rollbackTransaction() {
|
|
205
|
+
attempt = undefined
|
|
206
|
+
completedAttempt = undefined
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return { committed, enqueueTask, lifecycle }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function createZeroDirectServerRuntime<
|
|
214
|
+
Schema extends ZeroSchema,
|
|
215
|
+
Models extends GenericModels,
|
|
216
|
+
ServerActions extends Record<string, unknown>,
|
|
217
|
+
>({
|
|
218
|
+
createDatabase,
|
|
219
|
+
createServerActions,
|
|
220
|
+
defaultAllowAdminRole = 'all',
|
|
221
|
+
defaultMutateAuthData = {} as MutateAuthData,
|
|
222
|
+
models,
|
|
223
|
+
mutations: mutationValidators,
|
|
224
|
+
queries,
|
|
225
|
+
schema,
|
|
226
|
+
validateMutation,
|
|
227
|
+
validateQuery,
|
|
228
|
+
}: ZeroDirectServerOptions<Schema, Models, ServerActions>): {
|
|
229
|
+
permissions: ReturnType<typeof createPermissions<Schema>>
|
|
230
|
+
server: ZeroDirectServer<Schema, Models>
|
|
231
|
+
} {
|
|
232
|
+
setSchema(schema, createBuilder(schema))
|
|
233
|
+
setEnvironment('server')
|
|
234
|
+
|
|
235
|
+
const permissions = createPermissions<Schema>({
|
|
236
|
+
environment: 'server',
|
|
237
|
+
schema,
|
|
238
|
+
adminRoleMode: defaultAllowAdminRole,
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
async function runTransaction<
|
|
242
|
+
CB extends (tx: Transaction) => Promise<any>,
|
|
243
|
+
Returns extends CB extends (tx: Transaction) => Promise<infer X> ? X : never,
|
|
244
|
+
>(database: ZeroServerDatabase, query: CB): Promise<Returns> {
|
|
245
|
+
try {
|
|
246
|
+
if (isInZeroMutation()) {
|
|
247
|
+
const { tx } = mutatorContext()
|
|
248
|
+
return await query(tx)
|
|
249
|
+
}
|
|
250
|
+
return (await database.transaction(query, dummyTransactionInput)) as Returns
|
|
251
|
+
} catch (err) {
|
|
252
|
+
if ((err as any)?.name !== 'PermissionError') {
|
|
253
|
+
console.error(`Error running transaction(): ${err}`)
|
|
254
|
+
}
|
|
255
|
+
throw err
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function transaction<
|
|
260
|
+
CB extends (tx: Transaction) => Promise<any>,
|
|
261
|
+
Returns extends CB extends (tx: Transaction) => Promise<infer X> ? X : never,
|
|
262
|
+
>(query: CB): Promise<Returns> {
|
|
263
|
+
return runTransaction(createDatabase(), query)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function runMutate(
|
|
267
|
+
modelName: string,
|
|
268
|
+
mutatorName: string,
|
|
269
|
+
mutatorArg: unknown,
|
|
270
|
+
options?: MutateOptions,
|
|
271
|
+
) {
|
|
272
|
+
let authData = options?.authData
|
|
273
|
+
if (!authData) {
|
|
274
|
+
const scoped = getScopedAuthData()
|
|
275
|
+
if (scoped) authData = scoped as MutateAuthData
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const tasks = createAsyncTaskCollector()
|
|
279
|
+
const mutators = createMutators({
|
|
280
|
+
models,
|
|
281
|
+
environment: 'server',
|
|
282
|
+
enqueueTask: tasks.enqueueTask,
|
|
283
|
+
authData: {
|
|
284
|
+
...defaultMutateAuthData,
|
|
285
|
+
...authData,
|
|
286
|
+
},
|
|
287
|
+
createServerActions,
|
|
288
|
+
can: permissions.can,
|
|
289
|
+
validateMutation,
|
|
290
|
+
mutationValidators,
|
|
291
|
+
})
|
|
292
|
+
const modelMutators = mutators[modelName as keyof typeof mutators] as Record<
|
|
293
|
+
string,
|
|
294
|
+
(tx: Transaction, arg?: unknown) => Promise<void>
|
|
295
|
+
>
|
|
296
|
+
const mutator = modelMutators[mutatorName]
|
|
297
|
+
|
|
298
|
+
await runTransaction(
|
|
299
|
+
createDatabaseWithLifecycle(createDatabase(), tasks.lifecycle),
|
|
300
|
+
async (tx) => {
|
|
301
|
+
await mutator(tx, mutatorArg)
|
|
302
|
+
},
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
if (tasks.committed.length) {
|
|
306
|
+
const resolvedAuth = authData ?? null
|
|
307
|
+
const entries = tasks.committed.map((entry) => ({
|
|
308
|
+
...entry,
|
|
309
|
+
task: () => runWithAuthScope(resolvedAuth, entry.task),
|
|
310
|
+
}))
|
|
311
|
+
if (options?.awaitEffects) {
|
|
312
|
+
await Promise.all(entries.map(({ task }) => task()))
|
|
313
|
+
} else {
|
|
314
|
+
await runAsyncTaskEntries(entries, { background: () => undefined })
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const mutate = new Proxy({} as ServerMutate<Models>, {
|
|
320
|
+
get(_, modelName: string) {
|
|
321
|
+
return new Proxy(
|
|
322
|
+
{},
|
|
323
|
+
{
|
|
324
|
+
get(_, mutatorName: string) {
|
|
325
|
+
return (arg: unknown, options?: MutateOptions) =>
|
|
326
|
+
runMutate(modelName, mutatorName, arg, options)
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
)
|
|
330
|
+
},
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
function query<R>(
|
|
334
|
+
cb: (q: QueryBuilder) => Query<any, Schema, R>,
|
|
335
|
+
authData?: AuthData | null,
|
|
336
|
+
): Promise<HumanReadable<R>> {
|
|
337
|
+
const run = () =>
|
|
338
|
+
transaction(async (tx) => {
|
|
339
|
+
return tx.run(cb(getZQL()))
|
|
340
|
+
}) as any
|
|
341
|
+
|
|
342
|
+
if (authData !== undefined) {
|
|
343
|
+
return runWithQueryContext({ authData }, run)
|
|
344
|
+
}
|
|
345
|
+
return run()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (queries) {
|
|
349
|
+
setCustomQueries(queries)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
setRunner((queryObj) => {
|
|
353
|
+
return transaction(async (tx) => {
|
|
354
|
+
return tx.run(queryObj)
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
permissions,
|
|
360
|
+
server: {
|
|
361
|
+
transaction,
|
|
362
|
+
mutate,
|
|
363
|
+
query,
|
|
364
|
+
},
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function createZeroDirectServer<
|
|
369
|
+
Schema extends ZeroSchema,
|
|
370
|
+
Models extends GenericModels,
|
|
371
|
+
ServerActions extends Record<string, unknown>,
|
|
372
|
+
>(
|
|
373
|
+
options: ZeroDirectServerOptions<Schema, Models, ServerActions>,
|
|
374
|
+
): ZeroDirectServer<Schema, Models> {
|
|
375
|
+
return createZeroDirectServerRuntime(options).server
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function createDatabaseWithLifecycle(
|
|
379
|
+
database: ZeroServerDatabase,
|
|
380
|
+
lifecycle: TransactionAttemptLifecycle,
|
|
381
|
+
): ZeroServerDatabase {
|
|
382
|
+
return {
|
|
383
|
+
async transaction(callback, input) {
|
|
384
|
+
try {
|
|
385
|
+
const value = await database.transaction(async (tx, hooks) => {
|
|
386
|
+
lifecycle.beginAttempt()
|
|
387
|
+
try {
|
|
388
|
+
const result = await callback(tx, hooks)
|
|
389
|
+
lifecycle.completeAttempt()
|
|
390
|
+
return result
|
|
391
|
+
} catch (error) {
|
|
392
|
+
lifecycle.rollbackAttempt()
|
|
393
|
+
throw error
|
|
394
|
+
}
|
|
395
|
+
}, input)
|
|
396
|
+
lifecycle.commitTransaction()
|
|
397
|
+
return value
|
|
398
|
+
} catch (error) {
|
|
399
|
+
lifecycle.rollbackTransaction()
|
|
400
|
+
throw error
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const dummyTransactionInput: TransactionProviderInput = {
|
|
407
|
+
clientGroupID: 'unused',
|
|
408
|
+
clientID: 'unused',
|
|
409
|
+
mutationID: 42,
|
|
410
|
+
upstreamSchema: 'unused',
|
|
411
|
+
}
|