|
| 1 | +import { mkdir, writeFile } from "node:fs/promises"; |
1 | 2 | import type { AstroConfig, AstroIntegration } from "astro"; |
| 3 | +import { cyan } from "kleur/colors"; |
2 | 4 | import vitePluginSimpleScope from "vite-plugin-simple-scope"; |
3 | 5 |
|
4 | 6 | import "../ambient.d.ts"; |
| 7 | +import { existsSync } from "node:fs"; |
5 | 8 |
|
6 | 9 | type VitePlugin = Required<AstroConfig["vite"]>["plugins"][number]; |
7 | 10 |
|
8 | | -export default function simpleStackQueryIntegration(): AstroIntegration { |
| 11 | +type Options = { |
| 12 | + bypassSnippetsPrompt?: boolean; |
| 13 | +}; |
| 14 | + |
| 15 | +export default function simpleStackQueryIntegration( |
| 16 | + opts?: Options, |
| 17 | +): AstroIntegration { |
| 18 | + let root: URL; |
| 19 | + let command: "dev" | "build" | "preview"; |
9 | 20 | return { |
10 | 21 | name: "simple-stack-query", |
11 | 22 | hooks: { |
12 | | - "astro:config:setup"({ updateConfig }) { |
13 | | - updateConfig({ |
| 23 | + "astro:server:start": async () => { |
| 24 | + if (command === "dev" && !opts?.bypassSnippetsPrompt) { |
| 25 | + setTimeout(() => { |
| 26 | + addSnippets({ root }); |
| 27 | + }, 100); |
| 28 | + } |
| 29 | + }, |
| 30 | + async "astro:config:setup"(params) { |
| 31 | + root = params.config.root; |
| 32 | + command = params.command; |
| 33 | + |
| 34 | + params.updateConfig({ |
14 | 35 | vite: { |
15 | 36 | plugins: [vitePlugin(), vitePluginSimpleScope()], |
16 | 37 | }, |
@@ -46,3 +67,53 @@ function vitePlugin(): VitePlugin { |
46 | 67 | }, |
47 | 68 | }; |
48 | 69 | } |
| 70 | + |
| 71 | +async function addSnippets({ root }: { root: URL }) { |
| 72 | + const dotAstroDir = new URL(".astro/", root); |
| 73 | + const snippetsResponseFile = new URL( |
| 74 | + "simple-query-snippets-response", |
| 75 | + dotAstroDir, |
| 76 | + ); |
| 77 | + if (existsSync(snippetsResponseFile)) return; |
| 78 | + |
| 79 | + const { confirm, isCancel, outro } = await import("@clack/prompts"); |
| 80 | + const shouldAddSnippets = await confirm({ |
| 81 | + message: |
| 82 | + "Simple query offers snippets for VS Code. Would you like to add them?", |
| 83 | + }); |
| 84 | + |
| 85 | + if (isCancel(shouldAddSnippets)) process.exit(0); |
| 86 | + |
| 87 | + await mkdir(dotAstroDir, { recursive: true }); |
| 88 | + await writeFile(snippetsResponseFile, shouldAddSnippets ? "true" : "false"); |
| 89 | + |
| 90 | + if (!shouldAddSnippets) { |
| 91 | + outro(`No problem! Won't ask again. ${cyan("Dev server running.")}`); |
| 92 | + return; |
| 93 | + } |
| 94 | + |
| 95 | + const vsCodeDir = new URL(".vscode/", root); |
| 96 | + const vsCodeSnippetsFile = new URL("simple-query.code-snippets", vsCodeDir); |
| 97 | + |
| 98 | + await mkdir(vsCodeDir, { recursive: true }); |
| 99 | + await writeFile( |
| 100 | + vsCodeSnippetsFile, |
| 101 | + JSON.stringify( |
| 102 | + { |
| 103 | + "query target": { |
| 104 | + scope: "typescriptreact,javascriptreact", |
| 105 | + prefix: "$:target", |
| 106 | + body: ["data-target={$('$1')}"], |
| 107 | + }, |
| 108 | + "query ready block": { |
| 109 | + scope: "typescript,javascript", |
| 110 | + prefix: "$:ready", |
| 111 | + body: ["$.ready(async () => {", " $1", "});"], |
| 112 | + }, |
| 113 | + }, |
| 114 | + null, |
| 115 | + 2, |
| 116 | + ), |
| 117 | + ); |
| 118 | + outro(`Snippets added ✔️\n ${cyan("Dev server running.")}`); |
| 119 | +} |
0 commit comments