naystack 1.2.13 → 1.2.15
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 +260 -9
- package/dist/graphql/index.cjs.js +3 -0
- package/dist/graphql/index.esm.js +3 -0
- package/dist/graphql/server.cjs.js +9 -6
- package/dist/graphql/server.esm.js +9 -6
- package/dist/graphql/utils.cjs.js +3 -0
- package/dist/graphql/utils.d.mts +11 -11
- package/dist/graphql/utils.d.ts +11 -11
- package/dist/graphql/utils.esm.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,13 +19,15 @@ yarn add naystack
|
|
|
19
19
|
|
|
20
20
|
Naystack provides the following modules, each accessible via its own import path:
|
|
21
21
|
|
|
22
|
-
| Module | Import Path
|
|
23
|
-
| ----------- |
|
|
24
|
-
| **Auth** | `naystack/auth`
|
|
25
|
-
| **
|
|
26
|
-
| **
|
|
27
|
-
| **
|
|
28
|
-
| **
|
|
22
|
+
| Module | Import Path | Description |
|
|
23
|
+
| ----------- | -------------------------- | ------------------------------------------------------------------ |
|
|
24
|
+
| **Auth** | `naystack/auth` | Email, Google, and Instagram authentication (server-side routes) |
|
|
25
|
+
| **Auth UI** | `naystack/auth/email/client` | Client-side React hooks for login / signup / logout flows |
|
|
26
|
+
| **GraphQL** | `naystack/graphql` | GraphQL server initialization with type-graphql |
|
|
27
|
+
| **GQL App** | `naystack/graphql/client` / `naystack/graphql/server` | Apollo Client helpers for Next.js App Router (client + server) |
|
|
28
|
+
| **Client** | `naystack/client` | Generic client-side hooks and utilities |
|
|
29
|
+
| **File** | `naystack/file` | File upload to AWS S3 |
|
|
30
|
+
| **Socials** | `naystack/socials` | Instagram and Threads API integration |
|
|
29
31
|
|
|
30
32
|
---
|
|
31
33
|
|
|
@@ -39,11 +41,21 @@ import {
|
|
|
39
41
|
} from "naystack/auth";
|
|
40
42
|
```
|
|
41
43
|
|
|
44
|
+
### High-level Auth Flow in a Next.js App Router project
|
|
45
|
+
|
|
46
|
+
From a real-world setup (like `veas-web`), the pieces look like this:
|
|
47
|
+
|
|
48
|
+
- **Server-side auth routes** – created with `getEmailAuthRoutes` (and optionally Google / Instagram)
|
|
49
|
+
- **Server-side GraphQL context** – uses `getUserIdFromRequest` from the email auth routes
|
|
50
|
+
- **Client-side auth hooks** – created with `getEmailAuthUtils` and used in login/signup/logout forms
|
|
51
|
+
|
|
52
|
+
The sections below show each part in more detail.
|
|
53
|
+
|
|
42
54
|
### Email Authentication
|
|
43
55
|
|
|
44
56
|
Setup email-based authentication with JWT tokens and optional Turnstile captcha verification.
|
|
45
57
|
|
|
46
|
-
**
|
|
58
|
+
**Next.js App Router Example (server routes):**
|
|
47
59
|
|
|
48
60
|
```typescript
|
|
49
61
|
const emailAuth = getEmailAuthRoutes({
|
|
@@ -61,6 +73,101 @@ const emailAuth = getEmailAuthRoutes({
|
|
|
61
73
|
export const { GET, POST, PUT, DELETE, getUserIdFromRequest } = emailAuth;
|
|
62
74
|
```
|
|
63
75
|
|
|
76
|
+
**Client-side hooks (login, signup, logout) – as used in `veas-web`:**
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// app/(auth)/utils.ts
|
|
80
|
+
import { getEmailAuthUtils } from "naystack/auth/email/client";
|
|
81
|
+
|
|
82
|
+
// The argument is the URL where your email auth API lives
|
|
83
|
+
export const { useLogin, useLogout, useSignUp } =
|
|
84
|
+
getEmailAuthUtils("/api/email");
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// app/(auth)/login/components/form.tsx
|
|
89
|
+
"use client";
|
|
90
|
+
import React, { useState } from "react";
|
|
91
|
+
import { useLogin } from "@/app/(auth)/utils";
|
|
92
|
+
import { useRouter } from "next/navigation";
|
|
93
|
+
|
|
94
|
+
export default function LoginForm() {
|
|
95
|
+
const login = useLogin();
|
|
96
|
+
const router = useRouter();
|
|
97
|
+
const [email, setEmail] = useState("");
|
|
98
|
+
const [password, setPassword] = useState("");
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<form
|
|
102
|
+
onSubmit={async (e) => {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
const ok = await login({ email, password });
|
|
105
|
+
if (ok) router.push("/dashboard");
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
{/* inputs + submit */}
|
|
109
|
+
</form>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// app/(auth)/signup/components/form.tsx
|
|
116
|
+
"use client";
|
|
117
|
+
import React, { useState } from "react";
|
|
118
|
+
import { useSignUp } from "@/app/(auth)/utils";
|
|
119
|
+
import { useRouter } from "next/navigation";
|
|
120
|
+
|
|
121
|
+
export default function SignupForm() {
|
|
122
|
+
const signUp = useSignUp();
|
|
123
|
+
const router = useRouter();
|
|
124
|
+
const [email, setEmail] = useState("");
|
|
125
|
+
const [password, setPassword] = useState("");
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<form
|
|
129
|
+
onSubmit={async (e) => {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
const ok = await signUp({ email, password });
|
|
132
|
+
if (ok) router.push("/onboard");
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
{/* inputs + submit */}
|
|
136
|
+
</form>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// app/dashboard/components/logout-button.tsx
|
|
143
|
+
"use client";
|
|
144
|
+
import React, { useState } from "react";
|
|
145
|
+
import { useLogout } from "@/app/(auth)/utils";
|
|
146
|
+
import { useRouter } from "next/navigation";
|
|
147
|
+
|
|
148
|
+
export default function LogoutButton() {
|
|
149
|
+
const logout = useLogout();
|
|
150
|
+
const [loading, setLoading] = useState(false);
|
|
151
|
+
const router = useRouter();
|
|
152
|
+
|
|
153
|
+
const handleLogout = async () => {
|
|
154
|
+
setLoading(true);
|
|
155
|
+
try {
|
|
156
|
+
await logout();
|
|
157
|
+
router.push("/login");
|
|
158
|
+
} finally {
|
|
159
|
+
setLoading(false);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<button onClick={handleLogout} disabled={loading}>
|
|
165
|
+
{loading ? "Logging out..." : "Logout"}
|
|
166
|
+
</button>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
64
171
|
**Real-World Example with Drizzle ORM:**
|
|
65
172
|
|
|
66
173
|
```typescript
|
|
@@ -302,7 +409,7 @@ import {
|
|
|
302
409
|
import type { Context, AuthorizedContext } from "naystack/graphql";
|
|
303
410
|
```
|
|
304
411
|
|
|
305
|
-
### Initialize GraphQL Server
|
|
412
|
+
### Initialize GraphQL Server (Next.js App Router)
|
|
306
413
|
|
|
307
414
|
**Basic Example:**
|
|
308
415
|
|
|
@@ -357,6 +464,17 @@ export const { GET, POST } = await initGraphQLServer({
|
|
|
357
464
|
});
|
|
358
465
|
```
|
|
359
466
|
|
|
467
|
+
### Real-world pattern from a full Next.js app (like `veas-web`)
|
|
468
|
+
|
|
469
|
+
In a typical app you will:
|
|
470
|
+
|
|
471
|
+
- Define **GraphQL resolvers** using `QueryLibrary` / `FieldLibrary`
|
|
472
|
+
- Initialize the GraphQL **API route** with `initGraphQLServer`
|
|
473
|
+
- Use **server-side helper** `getGraphQLQuery` to call GraphQL from RSC / server actions
|
|
474
|
+
- Use **client-side helper** `getApolloWrapper` and `useAuthMutation` for client components
|
|
475
|
+
|
|
476
|
+
The next sections show how these pieces fit together.
|
|
477
|
+
|
|
360
478
|
#### Options
|
|
361
479
|
|
|
362
480
|
| Option | Type | Required | Description |
|
|
@@ -483,6 +601,139 @@ const fields = {
|
|
|
483
601
|
const UserFieldResolver = FieldLibrary(User, fields);
|
|
484
602
|
```
|
|
485
603
|
|
|
604
|
+
**How this looks in a real app (`veas-web`-style):**
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
// app/api/(graphql)/User/db.ts
|
|
608
|
+
import { pgTable, serial, text, timestamp, real } from "drizzle-orm/pg-core";
|
|
609
|
+
|
|
610
|
+
export const UserTable = pgTable("users", {
|
|
611
|
+
id: serial("id").primaryKey(),
|
|
612
|
+
email: text("email").notNull(),
|
|
613
|
+
password: text("password").notNull(),
|
|
614
|
+
name: text("name"),
|
|
615
|
+
dateOfBirth: timestamp("date_of_birth"),
|
|
616
|
+
placeOfBirthLat: real("place_of_birth_lat"),
|
|
617
|
+
placeOfBirthLong: real("place_of_birth_long"),
|
|
618
|
+
timezone: real("timezone"),
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
export type UserDB = typeof UserTable.$inferSelect;
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// app/api/(graphql)/User/types.ts
|
|
626
|
+
import { Field, ObjectType } from "type-graphql";
|
|
627
|
+
|
|
628
|
+
@ObjectType("User")
|
|
629
|
+
export class User {
|
|
630
|
+
@Field()
|
|
631
|
+
id: number;
|
|
632
|
+
|
|
633
|
+
@Field()
|
|
634
|
+
email: string;
|
|
635
|
+
|
|
636
|
+
@Field(() => String, { nullable: true })
|
|
637
|
+
name: string | null;
|
|
638
|
+
|
|
639
|
+
@Field(() => Date, { nullable: true })
|
|
640
|
+
dateOfBirth: Date | null;
|
|
641
|
+
|
|
642
|
+
@Field(() => Number, { nullable: true })
|
|
643
|
+
placeOfBirthLat: number | null;
|
|
644
|
+
|
|
645
|
+
@Field(() => Number, { nullable: true })
|
|
646
|
+
placeOfBirthLong: number | null;
|
|
647
|
+
|
|
648
|
+
@Field(() => Number, { nullable: true })
|
|
649
|
+
timezone: number | null;
|
|
650
|
+
|
|
651
|
+
@Field()
|
|
652
|
+
isOnboarded: boolean;
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
// app/api/(graphql)/User/resolvers/is-onboarded.ts
|
|
658
|
+
import { field } from "naystack/graphql";
|
|
659
|
+
import type { UserDB } from "../db";
|
|
660
|
+
|
|
661
|
+
export default field(
|
|
662
|
+
async (user: UserDB) => {
|
|
663
|
+
return (
|
|
664
|
+
!!user.name &&
|
|
665
|
+
!!user.dateOfBirth &&
|
|
666
|
+
user.placeOfBirthLat !== null &&
|
|
667
|
+
user.placeOfBirthLong !== null &&
|
|
668
|
+
user.timezone !== null
|
|
669
|
+
);
|
|
670
|
+
},
|
|
671
|
+
{ output: Boolean },
|
|
672
|
+
);
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
// app/api/(graphql)/User/resolvers/get-current-user.ts
|
|
677
|
+
import { query } from "naystack/graphql";
|
|
678
|
+
import { db } from "@/app/api/lib/db";
|
|
679
|
+
import { UserTable } from "../db";
|
|
680
|
+
import { eq } from "drizzle-orm";
|
|
681
|
+
import { User } from "../types";
|
|
682
|
+
|
|
683
|
+
export default query(
|
|
684
|
+
async (ctx: { userId: number | null }) => {
|
|
685
|
+
if (!ctx.userId) return null;
|
|
686
|
+
const [user] = await db
|
|
687
|
+
.select()
|
|
688
|
+
.from(UserTable)
|
|
689
|
+
.where(eq(UserTable.id, ctx.userId));
|
|
690
|
+
return user || null;
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
output: User,
|
|
694
|
+
},
|
|
695
|
+
);
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
// app/api/(graphql)/User/graphql.ts
|
|
700
|
+
import { QueryLibrary, FieldLibrary } from "naystack/graphql";
|
|
701
|
+
import getCurrentUser from "./resolvers/get-current-user";
|
|
702
|
+
import onboardUser from "./resolvers/onboard-user";
|
|
703
|
+
import isOnboarded from "./resolvers/is-onboarded";
|
|
704
|
+
import type { UserDB } from "./db";
|
|
705
|
+
import { User } from "./types";
|
|
706
|
+
|
|
707
|
+
export const UserResolvers = QueryLibrary({
|
|
708
|
+
getCurrentUser,
|
|
709
|
+
onboardUser,
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
export const UserFieldResolvers = FieldLibrary<UserDB>(User, {
|
|
713
|
+
isOnboarded,
|
|
714
|
+
});
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
```typescript
|
|
718
|
+
// app/api/(graphql)/route.ts
|
|
719
|
+
import { initGraphQLServer } from "naystack/graphql";
|
|
720
|
+
import { UserResolvers, UserFieldResolvers } from "./User/graphql";
|
|
721
|
+
import { getUserIdFromRequest } from "@/app/api/(auth)/email";
|
|
722
|
+
|
|
723
|
+
export const { GET, POST } = await initGraphQLServer({
|
|
724
|
+
resolvers: [UserResolvers, UserFieldResolvers],
|
|
725
|
+
context: async (req) => {
|
|
726
|
+
const res = getUserIdFromRequest(req);
|
|
727
|
+
if (!res) return { userId: null };
|
|
728
|
+
return {
|
|
729
|
+
userId: res.accessUserId ?? res.refreshUserID ?? null,
|
|
730
|
+
};
|
|
731
|
+
},
|
|
732
|
+
});
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
This gives you a full GraphQL API route that uses Naystack’s auth, Drizzle models, and functional resolvers.
|
|
736
|
+
|
|
486
737
|
**Real-World Example:**
|
|
487
738
|
|
|
488
739
|
```typescript
|
|
@@ -655,6 +655,9 @@ function QueryLibrary(queries) {
|
|
|
655
655
|
descriptor
|
|
656
656
|
);
|
|
657
657
|
}
|
|
658
|
+
if (def.authorized) {
|
|
659
|
+
(0, import_type_graphql2.Authorized)()(GeneratedResolver, key);
|
|
660
|
+
}
|
|
658
661
|
(0, import_type_graphql2.Ctx)()(GeneratedResolver.prototype, key, 0);
|
|
659
662
|
if (def.input) {
|
|
660
663
|
(0, import_type_graphql2.Arg)("input", () => def.input || String, def.inputOptions)(
|
|
@@ -651,6 +651,9 @@ function QueryLibrary(queries) {
|
|
|
651
651
|
descriptor
|
|
652
652
|
);
|
|
653
653
|
}
|
|
654
|
+
if (def.authorized) {
|
|
655
|
+
Authorized()(GeneratedResolver, key);
|
|
656
|
+
}
|
|
654
657
|
Ctx()(GeneratedResolver.prototype, key, 0);
|
|
655
658
|
if (def.input) {
|
|
656
659
|
Arg("input", () => def.input || String, def.inputOptions)(
|
|
@@ -25,6 +25,7 @@ __export(server_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(server_exports);
|
|
27
27
|
var import_client = require("@apollo/client");
|
|
28
|
+
var import_client_integration_nextjs = require("@apollo/client-integration-nextjs");
|
|
28
29
|
var import_headers = require("next/headers");
|
|
29
30
|
var import_react = require("react");
|
|
30
31
|
function Injector({
|
|
@@ -43,14 +44,16 @@ async function InjectorSuspensed({
|
|
|
43
44
|
return /* @__PURE__ */ React.createElement(Component, { loading: false, ...props || {}, data });
|
|
44
45
|
}
|
|
45
46
|
var getGraphQLQuery = ({ uri }) => {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const { query } = (0, import_client_integration_nextjs.registerApolloClient)(() => {
|
|
48
|
+
return new import_client.ApolloClient({
|
|
49
|
+
cache: new import_client.InMemoryCache(),
|
|
50
|
+
link: new import_client.HttpLink({
|
|
51
|
+
uri
|
|
52
|
+
})
|
|
53
|
+
});
|
|
51
54
|
});
|
|
52
55
|
return async (_query, options) => {
|
|
53
|
-
const res = await
|
|
56
|
+
const res = await query({
|
|
54
57
|
query: _query,
|
|
55
58
|
variables: options?.variables,
|
|
56
59
|
context: {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
HttpLink,
|
|
5
5
|
InMemoryCache
|
|
6
6
|
} from "@apollo/client";
|
|
7
|
+
import { registerApolloClient } from "@apollo/client-integration-nextjs";
|
|
7
8
|
import { cookies } from "next/headers";
|
|
8
9
|
import { Suspense } from "react";
|
|
9
10
|
function Injector({
|
|
@@ -22,14 +23,16 @@ async function InjectorSuspensed({
|
|
|
22
23
|
return /* @__PURE__ */ React.createElement(Component, { loading: false, ...props || {}, data });
|
|
23
24
|
}
|
|
24
25
|
var getGraphQLQuery = ({ uri }) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const { query } = registerApolloClient(() => {
|
|
27
|
+
return new ApolloClient({
|
|
28
|
+
cache: new InMemoryCache(),
|
|
29
|
+
link: new HttpLink({
|
|
30
|
+
uri
|
|
31
|
+
})
|
|
32
|
+
});
|
|
30
33
|
});
|
|
31
34
|
return async (_query, options) => {
|
|
32
|
-
const res = await
|
|
35
|
+
const res = await query({
|
|
33
36
|
query: _query,
|
|
34
37
|
variables: options?.variables,
|
|
35
38
|
context: {
|
|
@@ -73,6 +73,9 @@ function QueryLibrary(queries) {
|
|
|
73
73
|
descriptor
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
|
+
if (def.authorized) {
|
|
77
|
+
(0, import_type_graphql.Authorized)()(GeneratedResolver, key);
|
|
78
|
+
}
|
|
76
79
|
(0, import_type_graphql.Ctx)()(GeneratedResolver.prototype, key, 0);
|
|
77
80
|
if (def.input) {
|
|
78
81
|
(0, import_type_graphql.Arg)("input", () => def.input || String, def.inputOptions)(
|
package/dist/graphql/utils.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GraphQLScalarType } from 'graphql';
|
|
2
2
|
import { ClassType, Query, Arg } from 'type-graphql';
|
|
3
|
-
import { Context } from './types.mjs';
|
|
3
|
+
import { AuthorizedContext, Context } from './types.mjs';
|
|
4
4
|
|
|
5
5
|
type ReturnOptions = Parameters<typeof Query>[1];
|
|
6
6
|
type ArgsOptions = Parameters<typeof Arg>[2];
|
|
@@ -9,26 +9,26 @@ type DeepPartial<T> = {
|
|
|
9
9
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
10
10
|
};
|
|
11
11
|
type OtherTypes<T> = GraphQLScalarType<T, T> | [GraphQLScalarType<T, T>] | NumberConstructor | [NumberConstructor] | StringConstructor | [StringConstructor] | BooleanConstructor | [BooleanConstructor];
|
|
12
|
-
interface BaseDefinition<T extends Values, U extends Values> {
|
|
12
|
+
interface BaseDefinition<T extends Values, U extends Values, IsAuth extends boolean> {
|
|
13
13
|
output: T extends object ? ClassType<DeepPartial<T>> | [ClassType<DeepPartial<T>>] : OtherTypes<T>;
|
|
14
14
|
outputOptions?: ReturnOptions;
|
|
15
15
|
input?: U extends object ? ClassType<U> | [ClassType<U>] : OtherTypes<U>;
|
|
16
16
|
inputOptions?: ArgsOptions;
|
|
17
|
-
authorized?:
|
|
17
|
+
authorized?: IsAuth;
|
|
18
18
|
}
|
|
19
|
-
interface QueryDefinition<T extends Values, U extends Values> extends BaseDefinition<T, U> {
|
|
20
|
-
fn: (ctx: Context, data: U) => Promise<T | T[]> | T | T[];
|
|
19
|
+
interface QueryDefinition<T extends Values, U extends Values, IsAuth extends boolean> extends BaseDefinition<T, U, IsAuth> {
|
|
20
|
+
fn: (ctx: IsAuth extends true ? AuthorizedContext : Context, data: U) => Promise<T | T[]> | T | T[];
|
|
21
21
|
mutation?: boolean;
|
|
22
22
|
}
|
|
23
|
-
interface FieldResolverDefinition<T extends Values, U extends Values, Root> extends BaseDefinition<T, U> {
|
|
24
|
-
fn: (root: Root, ctx: Context, data: U) => Promise<T | T[]> | T | T[];
|
|
23
|
+
interface FieldResolverDefinition<T extends Values, U extends Values, IsAuth extends boolean, Root> extends BaseDefinition<T, U, IsAuth> {
|
|
24
|
+
fn: (root: Root, ctx: IsAuth extends true ? AuthorizedContext : Context, data: U) => Promise<T | T[]> | T | T[];
|
|
25
25
|
}
|
|
26
|
-
declare function query<T extends Values, U extends Values>(fn: QueryDefinition<T, U>["fn"], options: Omit<QueryDefinition<T, U>, "fn">): QueryDefinition<T, U>;
|
|
27
|
-
declare function field<T extends Values, U extends Values, Root>(fn: FieldResolverDefinition<T, U, Root>["fn"], options: Omit<FieldResolverDefinition<T, U, Root>, "fn">): FieldResolverDefinition<T, U, Root>;
|
|
28
|
-
declare function QueryLibrary<T extends Record<string, QueryDefinition<any, any>>>(queries: T): {
|
|
26
|
+
declare function query<T extends Values, U extends Values, IsAuth extends boolean>(fn: QueryDefinition<T, U, IsAuth>["fn"], options: Omit<QueryDefinition<T, U, IsAuth>, "fn">): QueryDefinition<T, U, IsAuth>;
|
|
27
|
+
declare function field<T extends Values, U extends Values, IsAuth extends boolean, Root>(fn: FieldResolverDefinition<T, U, IsAuth, Root>["fn"], options: Omit<FieldResolverDefinition<T, U, IsAuth, Root>, "fn">): FieldResolverDefinition<T, U, IsAuth, Root>;
|
|
28
|
+
declare function QueryLibrary<T extends Record<string, QueryDefinition<any, any, any>>>(queries: T): {
|
|
29
29
|
new (): {};
|
|
30
30
|
};
|
|
31
|
-
declare function FieldLibrary<X extends object, T extends Record<string, FieldResolverDefinition<any, any, X>> = Record<string, FieldResolverDefinition<any, any, X>>>(type: ClassType, queries: T): {
|
|
31
|
+
declare function FieldLibrary<X extends object, T extends Record<string, FieldResolverDefinition<any, any, any, X>> = Record<string, FieldResolverDefinition<any, any, any, X>>>(type: ClassType, queries: T): {
|
|
32
32
|
new (): {};
|
|
33
33
|
};
|
|
34
34
|
|
package/dist/graphql/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GraphQLScalarType } from 'graphql';
|
|
2
2
|
import { ClassType, Query, Arg } from 'type-graphql';
|
|
3
|
-
import { Context } from './types.js';
|
|
3
|
+
import { AuthorizedContext, Context } from './types.js';
|
|
4
4
|
|
|
5
5
|
type ReturnOptions = Parameters<typeof Query>[1];
|
|
6
6
|
type ArgsOptions = Parameters<typeof Arg>[2];
|
|
@@ -9,26 +9,26 @@ type DeepPartial<T> = {
|
|
|
9
9
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
10
10
|
};
|
|
11
11
|
type OtherTypes<T> = GraphQLScalarType<T, T> | [GraphQLScalarType<T, T>] | NumberConstructor | [NumberConstructor] | StringConstructor | [StringConstructor] | BooleanConstructor | [BooleanConstructor];
|
|
12
|
-
interface BaseDefinition<T extends Values, U extends Values> {
|
|
12
|
+
interface BaseDefinition<T extends Values, U extends Values, IsAuth extends boolean> {
|
|
13
13
|
output: T extends object ? ClassType<DeepPartial<T>> | [ClassType<DeepPartial<T>>] : OtherTypes<T>;
|
|
14
14
|
outputOptions?: ReturnOptions;
|
|
15
15
|
input?: U extends object ? ClassType<U> | [ClassType<U>] : OtherTypes<U>;
|
|
16
16
|
inputOptions?: ArgsOptions;
|
|
17
|
-
authorized?:
|
|
17
|
+
authorized?: IsAuth;
|
|
18
18
|
}
|
|
19
|
-
interface QueryDefinition<T extends Values, U extends Values> extends BaseDefinition<T, U> {
|
|
20
|
-
fn: (ctx: Context, data: U) => Promise<T | T[]> | T | T[];
|
|
19
|
+
interface QueryDefinition<T extends Values, U extends Values, IsAuth extends boolean> extends BaseDefinition<T, U, IsAuth> {
|
|
20
|
+
fn: (ctx: IsAuth extends true ? AuthorizedContext : Context, data: U) => Promise<T | T[]> | T | T[];
|
|
21
21
|
mutation?: boolean;
|
|
22
22
|
}
|
|
23
|
-
interface FieldResolverDefinition<T extends Values, U extends Values, Root> extends BaseDefinition<T, U> {
|
|
24
|
-
fn: (root: Root, ctx: Context, data: U) => Promise<T | T[]> | T | T[];
|
|
23
|
+
interface FieldResolverDefinition<T extends Values, U extends Values, IsAuth extends boolean, Root> extends BaseDefinition<T, U, IsAuth> {
|
|
24
|
+
fn: (root: Root, ctx: IsAuth extends true ? AuthorizedContext : Context, data: U) => Promise<T | T[]> | T | T[];
|
|
25
25
|
}
|
|
26
|
-
declare function query<T extends Values, U extends Values>(fn: QueryDefinition<T, U>["fn"], options: Omit<QueryDefinition<T, U>, "fn">): QueryDefinition<T, U>;
|
|
27
|
-
declare function field<T extends Values, U extends Values, Root>(fn: FieldResolverDefinition<T, U, Root>["fn"], options: Omit<FieldResolverDefinition<T, U, Root>, "fn">): FieldResolverDefinition<T, U, Root>;
|
|
28
|
-
declare function QueryLibrary<T extends Record<string, QueryDefinition<any, any>>>(queries: T): {
|
|
26
|
+
declare function query<T extends Values, U extends Values, IsAuth extends boolean>(fn: QueryDefinition<T, U, IsAuth>["fn"], options: Omit<QueryDefinition<T, U, IsAuth>, "fn">): QueryDefinition<T, U, IsAuth>;
|
|
27
|
+
declare function field<T extends Values, U extends Values, IsAuth extends boolean, Root>(fn: FieldResolverDefinition<T, U, IsAuth, Root>["fn"], options: Omit<FieldResolverDefinition<T, U, IsAuth, Root>, "fn">): FieldResolverDefinition<T, U, IsAuth, Root>;
|
|
28
|
+
declare function QueryLibrary<T extends Record<string, QueryDefinition<any, any, any>>>(queries: T): {
|
|
29
29
|
new (): {};
|
|
30
30
|
};
|
|
31
|
-
declare function FieldLibrary<X extends object, T extends Record<string, FieldResolverDefinition<any, any, X>> = Record<string, FieldResolverDefinition<any, any, X>>>(type: ClassType, queries: T): {
|
|
31
|
+
declare function FieldLibrary<X extends object, T extends Record<string, FieldResolverDefinition<any, any, any, X>> = Record<string, FieldResolverDefinition<any, any, any, X>>>(type: ClassType, queries: T): {
|
|
32
32
|
new (): {};
|
|
33
33
|
};
|
|
34
34
|
|