sdnext 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/utils/hook.d.ts +1 -0
- package/dist/utils/hook.js +45 -6
- package/dist/utils/readSdNextSetting.d.ts +5 -0
- package/dist/utils/readSdNextSetting.js +14 -0
- package/dist/utils/writeSdNextSetting.d.ts +2 -0
- package/dist/utils/writeSdNextSetting.js +9 -0
- package/package.json +1 -1
- package/src/utils/hook.ts +55 -11
- package/src/utils/readSdNextSetting.ts +22 -0
- package/src/utils/writeSdNextSetting.ts +11 -0
package/dist/utils/hook.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
export type HookType = "get" | "query" | "mutation";
|
|
3
|
+
export type OperationType = HookType | "skip";
|
|
3
4
|
export type HookContentMap = Record<HookType, string>;
|
|
4
5
|
export interface HookData extends HookContentMap {
|
|
5
6
|
overwrite: boolean;
|
package/dist/utils/hook.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
|
|
2
2
|
import { join, parse, relative } from "path";
|
|
3
|
+
import { cwd } from "process";
|
|
3
4
|
import { checkbox as prompts_checkbox, select as prompts_select } from "@inquirer/prompts";
|
|
5
|
+
import { readSdNextSetting } from "./readSdNextSetting.js";
|
|
6
|
+
import { writeSdNextSetting } from "./writeSdNextSetting.js";
|
|
4
7
|
function getHookTypeFromName(name) {
|
|
5
8
|
if (/^get[^a-z]/.test(name)) return "get";
|
|
6
9
|
if (/^query[^a-z]/.test(name)) return "query";
|
|
7
10
|
return "mutation";
|
|
8
11
|
}
|
|
9
|
-
|
|
12
|
+
let hook_setting = {};
|
|
13
|
+
async function getSetting() {
|
|
14
|
+
hook_setting = await readSdNextSetting();
|
|
15
|
+
return hook_setting;
|
|
16
|
+
}
|
|
17
|
+
async function getHookTypeFromContent(path, content) {
|
|
18
|
+
const setting = await getSetting();
|
|
19
|
+
const type = setting.hook?.[path];
|
|
20
|
+
if (void 0 !== type && "skip" !== type) return type;
|
|
10
21
|
if (content.includes("useMutation")) return "mutation";
|
|
11
22
|
if (content.includes("IdOrParams")) return "get";
|
|
12
23
|
if (content.includes("useQuery")) return "query";
|
|
@@ -20,7 +31,9 @@ async function createHook(path, hookMap) {
|
|
|
20
31
|
const hasSchema = !!match;
|
|
21
32
|
const upName = name.replace(/^./, (char)=>char.toUpperCase());
|
|
22
33
|
const key = name.replace(/[A-Z]/g, (char)=>`-${char.toLowerCase()}`);
|
|
23
|
-
const mutationHook = `import {
|
|
34
|
+
const mutationHook = `import { useId } from "react"
|
|
35
|
+
|
|
36
|
+
import { useMutation, UseMutationOptions } from "@tanstack/react-query"
|
|
24
37
|
import { createRequestFn } from "deepsea-tools"
|
|
25
38
|
|
|
26
39
|
import { ${name}Action } from "@/actions/${join(dir, name)}"
|
|
@@ -38,15 +51,34 @@ export interface Use${upName}Params<TOnMutateResult = unknown> extends Omit<
|
|
|
38
51
|
> {}
|
|
39
52
|
|
|
40
53
|
export function use${upName}<TOnMutateResult = unknown>({ onMutate, onSuccess, onError, onSettled, ...rest }: Use${upName}Params<TOnMutateResult> = {}) {
|
|
54
|
+
const key = useId()
|
|
55
|
+
|
|
41
56
|
return useMutation({
|
|
42
57
|
mutationFn: ${name}Client,
|
|
43
58
|
onMutate(variables, context) {
|
|
59
|
+
message.open({
|
|
60
|
+
key,
|
|
61
|
+
type: "loading",
|
|
62
|
+
content: "中...",
|
|
63
|
+
duration: 0,
|
|
64
|
+
})
|
|
44
65
|
return onMutate?.(variables, context) as TOnMutateResult | Promise<TOnMutateResult>
|
|
45
66
|
},
|
|
46
67
|
onSuccess(data, variables, onMutateResult, context) {
|
|
68
|
+
context.client.invalidateQueries({ queryKey: ["query-${key.replace(/^.+-/, "")}"] })
|
|
69
|
+
context.client.invalidateQueries({ queryKey: ["get-${key.replace(/^.+-/, "")}", data.id] })
|
|
70
|
+
|
|
71
|
+
message.open({
|
|
72
|
+
key,
|
|
73
|
+
type: "success",
|
|
74
|
+
content: "成功",
|
|
75
|
+
})
|
|
76
|
+
|
|
47
77
|
return onSuccess?.(data, variables, onMutateResult, context)
|
|
48
78
|
},
|
|
49
79
|
onError(error, variables, onMutateResult, context) {
|
|
80
|
+
message.destroy(key)
|
|
81
|
+
|
|
50
82
|
return onError?.(error, variables, onMutateResult, context)
|
|
51
83
|
},
|
|
52
84
|
onSettled(data, error, variables, onMutateResult, context) {
|
|
@@ -103,13 +135,14 @@ export const use${upName} = createUseQuery({
|
|
|
103
135
|
query: queryHook,
|
|
104
136
|
mutation: mutationHook
|
|
105
137
|
};
|
|
106
|
-
const
|
|
138
|
+
const hookName = base.replace(/^./, (char)=>`use${char.toUpperCase()}`);
|
|
139
|
+
const hookPath = join("hooks", dir, hookName);
|
|
107
140
|
let hookType = getHookTypeFromName(name);
|
|
108
141
|
let overwrite = true;
|
|
109
142
|
try {
|
|
110
143
|
const current = await readFile(hookPath, "utf-8");
|
|
111
144
|
if (current.trim()) overwrite = false;
|
|
112
|
-
const contentType = getHookTypeFromContent(current);
|
|
145
|
+
const contentType = await getHookTypeFromContent(join(cwd(), hookPath), current);
|
|
113
146
|
if (contentType) hookType = contentType;
|
|
114
147
|
if (map[hookType] === current) return;
|
|
115
148
|
} catch (error) {
|
|
@@ -141,7 +174,10 @@ async function hook(options, { args }) {
|
|
|
141
174
|
if (0 === entires.length) return void console.log("All hooks are the latest.");
|
|
142
175
|
const newEntires = entires.filter(([path, { overwrite }])=>overwrite);
|
|
143
176
|
const oldEntires = entires.filter(([path, { overwrite }])=>!overwrite);
|
|
177
|
+
const root = cwd();
|
|
178
|
+
const setting = await getSetting();
|
|
144
179
|
for await (const [path, { overwrite, type, ...map }] of newEntires){
|
|
180
|
+
const resolved = join(root, "hooks", path);
|
|
145
181
|
const answer = await prompts_select({
|
|
146
182
|
message: path,
|
|
147
183
|
choices: [
|
|
@@ -150,8 +186,10 @@ async function hook(options, { args }) {
|
|
|
150
186
|
"get",
|
|
151
187
|
"skip"
|
|
152
188
|
],
|
|
153
|
-
default: type
|
|
189
|
+
default: setting.hook?.[resolved] ?? type
|
|
154
190
|
});
|
|
191
|
+
setting.hook ??= {};
|
|
192
|
+
setting.hook[resolved] = answer;
|
|
155
193
|
if ("skip" === answer) continue;
|
|
156
194
|
const { dir, base } = parse(path);
|
|
157
195
|
await mkdir(join("hooks", dir), {
|
|
@@ -159,11 +197,12 @@ async function hook(options, { args }) {
|
|
|
159
197
|
});
|
|
160
198
|
await writeFile(join("hooks", dir, base.replace(/^./, (char)=>`use${char.toUpperCase()}`)), map[answer]);
|
|
161
199
|
}
|
|
200
|
+
await writeSdNextSetting(setting);
|
|
162
201
|
const overwrites = await prompts_checkbox({
|
|
163
202
|
message: "Please check the hooks you want to overwrite",
|
|
164
203
|
choices: oldEntires.map(([key])=>key)
|
|
165
204
|
});
|
|
166
|
-
for
|
|
205
|
+
for (const [path, { overwrite, type, ...map }] of oldEntires){
|
|
167
206
|
if (!overwrites.includes(path)) continue;
|
|
168
207
|
const { dir, base } = parse(path);
|
|
169
208
|
await mkdir(join("hooks", dir), {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
async function readSdNextSetting() {
|
|
6
|
+
const userDir = homedir();
|
|
7
|
+
const settingPath = join(userDir, ".sdnext.json");
|
|
8
|
+
if (existsSync(settingPath)) {
|
|
9
|
+
const setting = JSON.parse(await readFile(settingPath, "utf-8"));
|
|
10
|
+
return setting;
|
|
11
|
+
}
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
export { readSdNextSetting };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
async function writeSdNextSetting(setting) {
|
|
5
|
+
const userDir = homedir();
|
|
6
|
+
const settingPath = join(userDir, ".sdnext.json");
|
|
7
|
+
await writeFile(settingPath, JSON.stringify(setting, void 0, 4), "utf-8");
|
|
8
|
+
}
|
|
9
|
+
export { writeSdNextSetting };
|
package/package.json
CHANGED
package/src/utils/hook.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { mkdir, readdir, readFile, stat, writeFile } from "fs/promises"
|
|
2
2
|
import { join, parse, relative } from "path"
|
|
3
|
+
import { cwd } from "process"
|
|
3
4
|
|
|
4
5
|
import { checkbox, select } from "@inquirer/prompts"
|
|
5
6
|
import { Command } from "commander"
|
|
6
7
|
|
|
8
|
+
import { readSdNextSetting, SdNextSetting } from "./readSdNextSetting"
|
|
9
|
+
import { writeSdNextSetting } from "./writeSdNextSetting"
|
|
10
|
+
|
|
7
11
|
export type HookType = "get" | "query" | "mutation"
|
|
8
12
|
|
|
13
|
+
export type OperationType = HookType | "skip"
|
|
14
|
+
|
|
9
15
|
export type HookContentMap = Record<HookType, string>
|
|
10
16
|
|
|
11
17
|
function getHookTypeFromName(name: string): HookType {
|
|
@@ -14,7 +20,17 @@ function getHookTypeFromName(name: string): HookType {
|
|
|
14
20
|
return "mutation"
|
|
15
21
|
}
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
let setting: SdNextSetting = {}
|
|
24
|
+
|
|
25
|
+
async function getSetting() {
|
|
26
|
+
setting = await readSdNextSetting()
|
|
27
|
+
return setting
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function getHookTypeFromContent(path: string, content: string): Promise<HookType | undefined> {
|
|
31
|
+
const setting = await getSetting()
|
|
32
|
+
const type = setting.hook?.[path]
|
|
33
|
+
if (type !== undefined && type !== "skip") return type
|
|
18
34
|
if (content.includes("useMutation")) return "mutation"
|
|
19
35
|
if (content.includes("IdOrParams")) return "get"
|
|
20
36
|
if (content.includes("useQuery")) return "query"
|
|
@@ -36,7 +52,9 @@ export async function createHook(path: string, hookMap: Record<string, HookData>
|
|
|
36
52
|
const upName = name.replace(/^./, char => char.toUpperCase())
|
|
37
53
|
const key = name.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`)
|
|
38
54
|
|
|
39
|
-
const mutationHook = `import {
|
|
55
|
+
const mutationHook = `import { useId } from "react"
|
|
56
|
+
|
|
57
|
+
import { useMutation, UseMutationOptions } from "@tanstack/react-query"
|
|
40
58
|
import { createRequestFn } from "deepsea-tools"
|
|
41
59
|
|
|
42
60
|
import { ${name}Action } from "@/actions/${join(dir, name)}"
|
|
@@ -62,15 +80,34 @@ export interface Use${upName}Params<TOnMutateResult = unknown> extends Omit<
|
|
|
62
80
|
> {}
|
|
63
81
|
|
|
64
82
|
export function use${upName}<TOnMutateResult = unknown>({ onMutate, onSuccess, onError, onSettled, ...rest }: Use${upName}Params<TOnMutateResult> = {}) {
|
|
83
|
+
const key = useId()
|
|
84
|
+
|
|
65
85
|
return useMutation({
|
|
66
86
|
mutationFn: ${name}Client,
|
|
67
87
|
onMutate(variables, context) {
|
|
88
|
+
message.open({
|
|
89
|
+
key,
|
|
90
|
+
type: "loading",
|
|
91
|
+
content: "中...",
|
|
92
|
+
duration: 0,
|
|
93
|
+
})
|
|
68
94
|
return onMutate?.(variables, context) as TOnMutateResult | Promise<TOnMutateResult>
|
|
69
95
|
},
|
|
70
96
|
onSuccess(data, variables, onMutateResult, context) {
|
|
97
|
+
context.client.invalidateQueries({ queryKey: ["query-${key.replace(/^.+-/, "")}"] })
|
|
98
|
+
context.client.invalidateQueries({ queryKey: ["get-${key.replace(/^.+-/, "")}", data.id] })
|
|
99
|
+
|
|
100
|
+
message.open({
|
|
101
|
+
key,
|
|
102
|
+
type: "success",
|
|
103
|
+
content: "成功",
|
|
104
|
+
})
|
|
105
|
+
|
|
71
106
|
return onSuccess?.(data, variables, onMutateResult, context)
|
|
72
107
|
},
|
|
73
108
|
onError(error, variables, onMutateResult, context) {
|
|
109
|
+
message.destroy(key)
|
|
110
|
+
|
|
74
111
|
return onError?.(error, variables, onMutateResult, context)
|
|
75
112
|
},
|
|
76
113
|
onSettled(data, error, variables, onMutateResult, context) {
|
|
@@ -147,11 +184,9 @@ export const use${upName} = createUseQuery({
|
|
|
147
184
|
mutation: mutationHook,
|
|
148
185
|
}
|
|
149
186
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
base.replace(/^./, char => `use${char.toUpperCase()}`),
|
|
154
|
-
)
|
|
187
|
+
const hookName = base.replace(/^./, char => `use${char.toUpperCase()}`)
|
|
188
|
+
|
|
189
|
+
const hookPath = join("hooks", dir, hookName)
|
|
155
190
|
|
|
156
191
|
let hookType = getHookTypeFromName(name)
|
|
157
192
|
let overwrite = true
|
|
@@ -159,7 +194,7 @@ export const use${upName} = createUseQuery({
|
|
|
159
194
|
try {
|
|
160
195
|
const current = await readFile(hookPath, "utf-8")
|
|
161
196
|
if (current.trim()) overwrite = false
|
|
162
|
-
const contentType = getHookTypeFromContent(current)
|
|
197
|
+
const contentType = await getHookTypeFromContent(join(cwd(), hookPath), current)
|
|
163
198
|
if (contentType) hookType = contentType
|
|
164
199
|
if (map[hookType] === current) return
|
|
165
200
|
} catch (error) {
|
|
@@ -207,15 +242,22 @@ export async function hook(options: Record<string, string>, { args }: Command) {
|
|
|
207
242
|
|
|
208
243
|
const oldEntires = entires.filter(([path, { overwrite }]) => !overwrite)
|
|
209
244
|
|
|
245
|
+
const root = cwd()
|
|
246
|
+
|
|
247
|
+
const setting = await getSetting()
|
|
248
|
+
|
|
210
249
|
for await (const [path, { overwrite, type, ...map }] of newEntires) {
|
|
211
|
-
|
|
250
|
+
const resolved = join(root, "hooks", path)
|
|
212
251
|
|
|
213
252
|
const answer = await select<OperationType>({
|
|
214
253
|
message: path,
|
|
215
254
|
choices: ["mutation", "query", "get", "skip"],
|
|
216
|
-
default: type,
|
|
255
|
+
default: setting.hook?.[resolved] ?? type,
|
|
217
256
|
})
|
|
218
257
|
|
|
258
|
+
setting.hook ??= {}
|
|
259
|
+
setting.hook[resolved] = answer
|
|
260
|
+
|
|
219
261
|
if (answer === "skip") continue
|
|
220
262
|
|
|
221
263
|
const { dir, base } = parse(path)
|
|
@@ -230,12 +272,14 @@ export async function hook(options: Record<string, string>, { args }: Command) {
|
|
|
230
272
|
)
|
|
231
273
|
}
|
|
232
274
|
|
|
275
|
+
await writeSdNextSetting(setting)
|
|
276
|
+
|
|
233
277
|
const overwrites = await checkbox<string>({
|
|
234
278
|
message: "Please check the hooks you want to overwrite",
|
|
235
279
|
choices: oldEntires.map(([key]) => key),
|
|
236
280
|
})
|
|
237
281
|
|
|
238
|
-
for
|
|
282
|
+
for (const [path, { overwrite, type, ...map }] of oldEntires) {
|
|
239
283
|
if (!overwrites.includes(path)) continue
|
|
240
284
|
|
|
241
285
|
const { dir, base } = parse(path)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { readFile } from "node:fs/promises"
|
|
3
|
+
import { homedir } from "node:os"
|
|
4
|
+
import { join } from "node:path"
|
|
5
|
+
|
|
6
|
+
import { OperationType } from "./hook"
|
|
7
|
+
|
|
8
|
+
export interface SdNextSetting {
|
|
9
|
+
hook?: Record<string, OperationType>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function readSdNextSetting(): Promise<SdNextSetting> {
|
|
13
|
+
const userDir = homedir()
|
|
14
|
+
const settingPath = join(userDir, ".sdnext.json")
|
|
15
|
+
|
|
16
|
+
if (existsSync(settingPath)) {
|
|
17
|
+
const setting = JSON.parse(await readFile(settingPath, "utf-8"))
|
|
18
|
+
return setting
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {}
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
import { SdNextSetting } from "./readSdNextSetting"
|
|
6
|
+
|
|
7
|
+
export async function writeSdNextSetting(setting: SdNextSetting) {
|
|
8
|
+
const userDir = homedir()
|
|
9
|
+
const settingPath = join(userDir, ".sdnext.json")
|
|
10
|
+
await writeFile(settingPath, JSON.stringify(setting, undefined, 4), "utf-8")
|
|
11
|
+
}
|