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.
@@ -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;
@@ -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
- function getHookTypeFromContent(content) {
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 { useMutation, UseMutationOptions } from "@tanstack/react-query"
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 hookPath = join("hooks", dir, base.replace(/^./, (char)=>`use${char.toUpperCase()}`));
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 await (const [path, { overwrite, type, ...map }] of oldEntires){
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,5 @@
1
+ import { OperationType } from "./hook";
2
+ export interface SdNextSetting {
3
+ hook?: Record<string, OperationType>;
4
+ }
5
+ export declare function readSdNextSetting(): Promise<SdNextSetting>;
@@ -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,2 @@
1
+ import { SdNextSetting } from "./readSdNextSetting";
2
+ export declare function writeSdNextSetting(setting: SdNextSetting): Promise<void>;
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdnext",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "exports": {
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
- function getHookTypeFromContent(content: string): HookType | undefined {
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 { useMutation, UseMutationOptions } from "@tanstack/react-query"
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 hookPath = join(
151
- "hooks",
152
- dir,
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
- type OperationType = HookType | "skip"
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 await (const [path, { overwrite, type, ...map }] of oldEntires) {
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
+ }