@sanity-labs/groq-content-mapper 0.0.0 → 0.1.1

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/next.js ADDED
@@ -0,0 +1,122 @@
1
+ import { dirname, join, resolve } from "node:path";
2
+ import { spawn } from "node:child_process";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { createRequire } from "node:module";
5
+ const WEBPACK_TEST = /\.groq$/;
6
+ /**
7
+ * Sets a Next.js app up for `import query from './posts.groq' with {type: 'text'}`:
8
+ *
9
+ * ```ts
10
+ * // next.config.ts
11
+ * import {withGroqFiles} from '@sanity-labs/groq-content-mapper/next'
12
+ *
13
+ * export default withGroqFiles(nextConfig)
14
+ * ```
15
+ *
16
+ * Turbopack handles the attribute itself (Next.js 16.3 and later). The webpack Next bundles,
17
+ * 5.98, predates webpack's built-in rule for it, so the wrapper adds one: the file as its
18
+ * source, through webpack's own `asset/source`, after the project's rules.
19
+ *
20
+ * It also takes over the type check `next build` runs. Next runs the project's `tsc` for that
21
+ * check, but without `--runExternalCode`, which TypeScript takes from the command line only, so
22
+ * that check cannot start the content mapper and fails on every `.groq` import. The wrapper
23
+ * turns Next's check off and runs the same check with the flag in
24
+ * `compiler.runAfterProductionCompile`, which Next runs after the compile under either bundler,
25
+ * after the project's own hook and before the prerender; on a first build it runs `next typegen`
26
+ * first, since Next writes `next-env.d.ts` only later. A project that set
27
+ * `typescript.ignoreBuildErrors` itself gets no check.
28
+ * @beta
29
+ */
30
+ function withGroqFiles(config = {}) {
31
+ let { compiler, typescript, webpack } = config, check = !typescript?.ignoreBuildErrors;
32
+ return {
33
+ ...config,
34
+ webpack(webpackConfig, context) {
35
+ let out = webpack ? webpack(webpackConfig, context) : webpackConfig;
36
+ return out.module.rules.push({
37
+ test: WEBPACK_TEST,
38
+ type: "asset/source"
39
+ }), out;
40
+ },
41
+ ...check && {
42
+ compiler: {
43
+ ...compiler,
44
+ async runAfterProductionCompile(metadata) {
45
+ await compiler?.runAfterProductionCompile?.(metadata);
46
+ let tsconfig = resolve(metadata.projectDir, typescript?.tsconfigPath ?? "tsconfig.json");
47
+ await typeCheck(metadata.projectDir, tsconfig);
48
+ }
49
+ },
50
+ typescript: {
51
+ ...typescript,
52
+ ignoreBuildErrors: !0
53
+ }
54
+ }
55
+ };
56
+ }
57
+ /**
58
+ * Next's own check, `next/dist/lib/typescript/runTypeCheckCli`, with `--runExternalCode`: the
59
+ * project's TypeScript, run with this process's Node from the project directory.
60
+ */
61
+ async function typeCheck(dir, tsconfig) {
62
+ let require = createRequire(join(dir, "package.json")), manifest;
63
+ try {
64
+ manifest = require.resolve("typescript/package.json");
65
+ } catch {
66
+ throw stackless("The .groq type check needs TypeScript 7.1 or later, whose content mappers type the imports, and the project has no TypeScript.");
67
+ }
68
+ let { version } = JSON.parse(readFileSync(manifest, "utf8")), [major = 0, minor = 0] = version.split(".").map(Number);
69
+ if (major < 7 || major === 7 && minor < 1) throw stackless(`The .groq type check needs TypeScript 7.1 or later, whose content mappers type the imports; the project has TypeScript ${version}.`);
70
+ if (!existsSync(join(dir, "next-env.d.ts"))) {
71
+ let next = require.resolve("next/package.json"), { bin } = JSON.parse(readFileSync(next, "utf8")), typegen = await run([
72
+ join(dirname(next), bin.next),
73
+ "typegen",
74
+ dir
75
+ ], dir);
76
+ if (typegen.code !== 0) throw stackless(`next typegen failed:\n${typegen.output}`);
77
+ }
78
+ let { code, output } = await run([
79
+ join(dirname(manifest), "lib", "tsc.js"),
80
+ "--project",
81
+ tsconfig,
82
+ "--noEmit",
83
+ "--declarationMap",
84
+ "false",
85
+ "--emitDeclarationOnly",
86
+ "false",
87
+ "--runExternalCode"
88
+ ], dir);
89
+ if (output.trim() && console.log(output.trimEnd()), code !== 0) throw stackless("Failed to type check (tsc --runExternalCode).");
90
+ }
91
+ /** A child Node process's exit code and output, stdout and stderr in the order they came. */
92
+ function run(args, cwd) {
93
+ return new Promise((done, fail) => {
94
+ let child = spawn(process.execPath, args, {
95
+ cwd,
96
+ env: {
97
+ ...process.env,
98
+ ...process.stdout.isTTY && { FORCE_COLOR: "1" }
99
+ },
100
+ stdio: [
101
+ "ignore",
102
+ "pipe",
103
+ "pipe"
104
+ ]
105
+ }), output = "";
106
+ child.stdout.setEncoding("utf8").on("data", (chunk) => output += chunk), child.stderr.setEncoding("utf8").on("data", (chunk) => output += chunk), child.on("error", fail), child.on("close", (code) => done({
107
+ code: code ?? 1,
108
+ output
109
+ }));
110
+ });
111
+ }
112
+ /**
113
+ * `next build` prints a failed hook's error whole: a stack would point into this package rather
114
+ * than at the errors tsc has printed above it.
115
+ */
116
+ function stackless(message) {
117
+ let error = Error(message);
118
+ return error.stack = message, error;
119
+ }
120
+ export { withGroqFiles };
121
+
122
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","names":[],"sources":["../src/next.ts"],"sourcesContent":["import {spawn} from 'node:child_process'\nimport {existsSync, readFileSync} from 'node:fs'\nimport {createRequire} from 'node:module'\nimport {dirname, join, resolve} from 'node:path'\n\nconst WEBPACK_TEST = /\\.groq$/\n\ntype AfterProductionCompile = (metadata: {distDir: string; projectDir: string}) => Promise<void>\n\n/**\n * The part of a Next.js config `withGroqFiles` reads or sets, so this entry does not depend on\n * `next`. Each field admits Next's own type, and the rest of the config passes through as it is.\n * @beta\n */\nexport interface GroqFilesNextConfig {\n compiler?: {runAfterProductionCompile?: AfterProductionCompile}\n typescript?: {ignoreBuildErrors?: boolean; tsconfigPath?: string}\n webpack?: ((config: any, context: any) => any) | null\n}\n\n/**\n * Sets a Next.js app up for `import query from './posts.groq' with {type: 'text'}`:\n *\n * ```ts\n * // next.config.ts\n * import {withGroqFiles} from '@sanity-labs/groq-content-mapper/next'\n *\n * export default withGroqFiles(nextConfig)\n * ```\n *\n * Turbopack handles the attribute itself (Next.js 16.3 and later). The webpack Next bundles,\n * 5.98, predates webpack's built-in rule for it, so the wrapper adds one: the file as its\n * source, through webpack's own `asset/source`, after the project's rules.\n *\n * It also takes over the type check `next build` runs. Next runs the project's `tsc` for that\n * check, but without `--runExternalCode`, which TypeScript takes from the command line only, so\n * that check cannot start the content mapper and fails on every `.groq` import. The wrapper\n * turns Next's check off and runs the same check with the flag in\n * `compiler.runAfterProductionCompile`, which Next runs after the compile under either bundler,\n * after the project's own hook and before the prerender; on a first build it runs `next typegen`\n * first, since Next writes `next-env.d.ts` only later. A project that set\n * `typescript.ignoreBuildErrors` itself gets no check.\n * @beta\n */\nexport function withGroqFiles<Config extends GroqFilesNextConfig>(\n config: Config = {} as Config,\n): Config {\n const {compiler, typescript, webpack} = config\n const check = !typescript?.ignoreBuildErrors\n return {\n ...config,\n webpack(webpackConfig: any, context: any) {\n const out = webpack ? webpack(webpackConfig, context) : webpackConfig\n out.module.rules.push({test: WEBPACK_TEST, type: 'asset/source'})\n return out\n },\n ...(check && {\n compiler: {\n ...compiler,\n async runAfterProductionCompile(metadata: {distDir: string; projectDir: string}) {\n await compiler?.runAfterProductionCompile?.(metadata)\n const tsconfig = resolve(metadata.projectDir, typescript?.tsconfigPath ?? 'tsconfig.json')\n await typeCheck(metadata.projectDir, tsconfig)\n },\n },\n typescript: {...typescript, ignoreBuildErrors: true},\n }),\n }\n}\n\n/**\n * Next's own check, `next/dist/lib/typescript/runTypeCheckCli`, with `--runExternalCode`: the\n * project's TypeScript, run with this process's Node from the project directory.\n */\nasync function typeCheck(dir: string, tsconfig: string): Promise<void> {\n const require = createRequire(join(dir, 'package.json'))\n let manifest: string\n try {\n manifest = require.resolve('typescript/package.json')\n } catch {\n throw stackless(\n 'The .groq type check needs TypeScript 7.1 or later, whose content mappers type the imports, and the project has no TypeScript.',\n )\n }\n const {version} = JSON.parse(readFileSync(manifest, 'utf8')) as {version: string}\n const [major = 0, minor = 0] = version.split('.').map(Number)\n if (major < 7 || (major === 7 && minor < 1)) {\n throw stackless(\n `The .groq type check needs TypeScript 7.1 or later, whose content mappers type the imports; the project has TypeScript ${version}.`,\n )\n }\n\n // Next writes next-env.d.ts after this hook; `next typegen` writes it on a first build.\n if (!existsSync(join(dir, 'next-env.d.ts'))) {\n const next = require.resolve('next/package.json')\n const {bin} = JSON.parse(readFileSync(next, 'utf8')) as {bin: {next: string}}\n const typegen = await run([join(dirname(next), bin.next), 'typegen', dir], dir)\n if (typegen.code !== 0) throw stackless(`next typegen failed:\\n${typegen.output}`)\n }\n\n const tsc = join(dirname(manifest), 'lib', 'tsc.js')\n const args = [\n '--project',\n tsconfig,\n '--noEmit',\n '--declarationMap',\n 'false',\n '--emitDeclarationOnly',\n 'false',\n '--runExternalCode',\n ]\n const {code, output} = await run([tsc, ...args], dir)\n // Next's spinner pauses for console output, and not for a write to stdout.\n // eslint-disable-next-line no-console -- the type check's own output, as Next prints its own\n if (output.trim()) console.log(output.trimEnd())\n if (code !== 0) throw stackless('Failed to type check (tsc --runExternalCode).')\n}\n\n/** A child Node process's exit code and output, stdout and stderr in the order they came. */\nfunction run(args: string[], cwd: string): Promise<{code: number; output: string}> {\n return new Promise((done, fail) => {\n const child = spawn(process.execPath, args, {\n cwd,\n // A piped tsc prints no colors unless asked, which Next does for its own check too.\n env: {...process.env, ...(process.stdout.isTTY && {FORCE_COLOR: '1'})},\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n let output = ''\n child.stdout.setEncoding('utf8').on('data', (chunk: string) => (output += chunk))\n child.stderr.setEncoding('utf8').on('data', (chunk: string) => (output += chunk))\n child.on('error', fail)\n child.on('close', (code) => done({code: code ?? 1, output}))\n })\n}\n\n/**\n * `next build` prints a failed hook's error whole: a stack would point into this package rather\n * than at the errors tsc has printed above it.\n */\nfunction stackless(message: string): Error {\n const error = new Error(message)\n error.stack = message\n return error\n}\n"],"mappings":";;;;AAKA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;AAuCrB,SAAgB,cACd,SAAiB,CAAC,GACV;CACR,IAAM,EAAC,UAAU,YAAY,YAAW,QAClC,QAAQ,CAAC,YAAY;CAC3B,OAAO;EACL,GAAG;EACH,QAAQ,eAAoB,SAAc;GACxC,IAAM,MAAM,UAAU,QAAQ,eAAe,OAAO,IAAI;GAExD,OADA,IAAI,OAAO,MAAM,KAAK;IAAC,MAAM;IAAc,MAAM;GAAc,CAAC,GACzD;EACT;EACA,GAAI,SAAS;GACX,UAAU;IACR,GAAG;IACH,MAAM,0BAA0B,UAAiD;KAC/E,MAAM,UAAU,4BAA4B,QAAQ;KACpD,IAAM,WAAW,QAAQ,SAAS,YAAY,YAAY,gBAAgB,eAAe;KACzF,MAAM,UAAU,SAAS,YAAY,QAAQ;IAC/C;GACF;GACA,YAAY;IAAC,GAAG;IAAY,mBAAmB;GAAI;EACrD;CACF;AACF;;;;;AAMA,eAAe,UAAU,KAAa,UAAiC;CACrE,IAAM,UAAU,cAAc,KAAK,KAAK,cAAc,CAAC,GACnD;CACJ,IAAI;EACF,WAAW,QAAQ,QAAQ,yBAAyB;CACtD,QAAQ;EACN,MAAM,UACJ,gIACF;CACF;CACA,IAAM,EAAC,YAAW,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC,GACrD,CAAC,QAAQ,GAAG,QAAQ,KAAK,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CAC5D,IAAI,QAAQ,KAAM,UAAU,KAAK,QAAQ,GACvC,MAAM,UACJ,0HAA0H,QAAQ,EACpI;CAIF,IAAI,CAAC,WAAW,KAAK,KAAK,eAAe,CAAC,GAAG;EAC3C,IAAM,OAAO,QAAQ,QAAQ,mBAAmB,GAC1C,EAAC,QAAO,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC,GAC7C,UAAU,MAAM,IAAI;GAAC,KAAK,QAAQ,IAAI,GAAG,IAAI,IAAI;GAAG;GAAW;EAAG,GAAG,GAAG;EAC9E,IAAI,QAAQ,SAAS,GAAG,MAAM,UAAU,yBAAyB,QAAQ,QAAQ;CACnF;CAaA,IAAM,EAAC,MAAM,WAAU,MAAM,IAAI;EAXrB,KAAK,QAAQ,QAAQ,GAAG,OAAO,QAWP;EATlC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAE4C,GAAG,GAAG;CAIpD,IADI,OAAO,KAAK,KAAG,QAAQ,IAAI,OAAO,QAAQ,CAAC,GAC3C,SAAS,GAAG,MAAM,UAAU,+CAA+C;AACjF;;AAGA,SAAS,IAAI,MAAgB,KAAsD;CACjF,OAAO,IAAI,SAAS,MAAM,SAAS;EACjC,IAAM,QAAQ,MAAM,QAAQ,UAAU,MAAM;GAC1C;GAEA,KAAK;IAAC,GAAG,QAAQ;IAAK,GAAI,QAAQ,OAAO,SAAS,EAAC,aAAa,IAAG;GAAE;GACrE,OAAO;IAAC;IAAU;IAAQ;GAAM;EAClC,CAAC,GACG,SAAS;EAIb,AAHA,MAAM,OAAO,YAAY,MAAM,CAAC,CAAC,GAAG,SAAS,UAAmB,UAAU,KAAM,GAChF,MAAM,OAAO,YAAY,MAAM,CAAC,CAAC,GAAG,SAAS,UAAmB,UAAU,KAAM,GAChF,MAAM,GAAG,SAAS,IAAI,GACtB,MAAM,GAAG,UAAU,SAAS,KAAK;GAAC,MAAM,QAAQ;GAAG;EAAM,CAAC,CAAC;CAC7D,CAAC;AACH;;;;;AAMA,SAAS,UAAU,SAAwB;CACzC,IAAM,QAAY,MAAM,OAAO;CAE/B,OADA,MAAM,QAAQ,SACP;AACT"}
@@ -0,0 +1,21 @@
1
+ import { r as isGroqFile, t as groqModuleSource } from "./runtime-DNC5x51t.js";
2
+ import { readFileSync } from "node:fs";
3
+ import "node:module";
4
+ import { fileURLToPath } from "node:url";
5
+ /**
6
+ * Node's `load` hook for `.groq` files. Synchronous, as `module.registerHooks` requires, and so
7
+ * also what `module.register` accepts for the off-thread hooks of Node before 22.15. A URL that
8
+ * is not a plain `.groq` file goes on to the next hook.
9
+ */
10
+ const load = (url, context, nextLoad) => {
11
+ if (!url.startsWith("file:")) return nextLoad(url, context);
12
+ let { hash, search } = new URL(url), path = fileURLToPath(url.replace(/[?#].*$/, ""));
13
+ return search || hash || !isGroqFile(path) ? nextLoad(url, context) : {
14
+ format: "module",
15
+ shortCircuit: !0,
16
+ source: groqModuleSource(readFileSync(path, "utf8"))
17
+ };
18
+ };
19
+ export { load as t };
20
+
21
+ //# sourceMappingURL=nodeHooks-CRMKGlwf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeHooks-CRMKGlwf.js","names":[],"sources":["../src/nodeHooks.ts"],"sourcesContent":["import {readFileSync} from 'node:fs'\nimport {type LoadHookSync} from 'node:module'\nimport {fileURLToPath} from 'node:url'\n\nimport {groqModuleSource, isGroqFile} from './runtime.js'\n\n/**\n * Node's `load` hook for `.groq` files. Synchronous, as `module.registerHooks` requires, and so\n * also what `module.register` accepts for the off-thread hooks of Node before 22.15. A URL that\n * is not a plain `.groq` file goes on to the next hook.\n */\nexport const load: LoadHookSync = (url, context, nextLoad) => {\n if (!url.startsWith('file:')) return nextLoad(url, context)\n const {hash, search} = new URL(url)\n const path = fileURLToPath(url.replace(/[?#].*$/, ''))\n if (search || hash || !isGroqFile(path)) return nextLoad(url, context)\n return {\n format: 'module',\n shortCircuit: true,\n source: groqModuleSource(readFileSync(path, 'utf8')),\n }\n}\n"],"mappings":";;;;;;;;;AAWA,MAAa,QAAsB,KAAK,SAAS,aAAa;CAC5D,IAAI,CAAC,IAAI,WAAW,OAAO,GAAG,OAAO,SAAS,KAAK,OAAO;CAC1D,IAAM,EAAC,MAAM,WAAU,IAAI,IAAI,GAAG,GAC5B,OAAO,cAAc,IAAI,QAAQ,WAAW,EAAE,CAAC;CAErD,OADI,UAAU,QAAQ,CAAC,WAAW,IAAI,IAAU,SAAS,KAAK,OAAO,IAC9D;EACL,QAAQ;EACR,cAAc;EACd,QAAQ,iBAAiB,aAAa,MAAM,MAAM,CAAC;CACrD;AACF"}
@@ -0,0 +1,8 @@
1
+ import { LoadHookSync } from "node:module";
2
+ /**
3
+ * Node's `load` hook for `.groq` files. Synchronous, as `module.registerHooks` requires, and so
4
+ * also what `module.register` accepts for the off-thread hooks of Node before 22.15. A URL that
5
+ * is not a plain `.groq` file goes on to the next hook.
6
+ */
7
+ export declare const load: LoadHookSync;
8
+ //# sourceMappingURL=nodeHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeHooks.d.ts","names":[],"sources":["../src/nodeHooks.ts"],"mappings":";;;;;;qBAWa,MAAM"}
@@ -0,0 +1 @@
1
+ export { t as load } from "./nodeHooks-CRMKGlwf.js";
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,6 @@
1
+ import { t as load } from "./nodeHooks-CRMKGlwf.js";
2
+ import * as nodeModule from "node:module";
3
+ const { register, registerHooks } = nodeModule;
4
+ registerHooks ? registerHooks({ load }) : register("./nodeHooks.js", import.meta.url);
5
+
6
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","names":[],"sources":["../src/register.ts"],"sourcesContent":["// The preload that lets `import query from './posts.groq' with {type: 'text'}` run on Node:\n//\n// node --import @sanity-labs/groq-content-mapper/register main.ts\n//\n// Node 26.5 and later can do it alone with `--experimental-import-text`; Bun and Deno need no\n// preload at all. Types come from the content mapper, not from here.\nimport * as nodeModule from 'node:module'\n\nimport {load} from './nodeHooks.js'\n\n// `registerHooks` runs in-thread, and reaches `require()` too; Node before 22.15 has only the\n// hooks that run on their own thread.\n// oxlint-disable-next-line typescript/no-deprecated -- `register` is only the fallback for Node before 22.15\nconst {register, registerHooks} = nodeModule as Partial<typeof nodeModule>\nif (registerHooks) {\n registerHooks({load})\n} else {\n register!('./nodeHooks.js', import.meta.url)\n}\n"],"mappings":";;AAaA,MAAM,EAAC,UAAU,kBAAiB;AAC9B,gBACF,cAAc,EAAC,KAAI,CAAC,IAEpB,SAAU,kBAAkB,YAAY,GAAG"}
@@ -0,0 +1,23 @@
1
+ /** The module source for a `.groq` file's content. */
2
+ function groqModuleSource(content) {
3
+ return `export default ${JSON.stringify(content)}\n`;
4
+ }
5
+ /**
6
+ * Whether an id names a `.groq` file outright. An id with a query or a hash, as in
7
+ * `./posts.groq?raw`, asks another plugin for something this one does not make, so it is left
8
+ * alone, as is a virtual id.
9
+ */
10
+ function isGroqFile(id) {
11
+ return !id.startsWith("\0") && !/[?#]/.test(id) && id.endsWith(".groq");
12
+ }
13
+ /**
14
+ * The same module as CommonJS, for Jest when it loads the file that way. The default export is
15
+ * a JSON string, so nothing in it can be mistaken for code, and `__esModule` lets a default
16
+ * import compiled by Babel or TypeScript read `exports.default`.
17
+ */
18
+ function groqModuleSourceCommonJs(content) {
19
+ return `Object.defineProperty(exports, "__esModule", {value: true});\nexports.default = ${JSON.stringify(content)};\n`;
20
+ }
21
+ export { groqModuleSourceCommonJs as n, isGroqFile as r, groqModuleSource as t };
22
+
23
+ //# sourceMappingURL=runtime-DNC5x51t.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-DNC5x51t.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["// What the Node preload, the Vite plugin and the Jest transformer share: a `.groq` file is a\n// module whose default export is the file's text, and nothing else. The text is the file as it\n// is, which is what `import query from './posts.groq' with {type: 'text'}` evaluates to where a\n// runtime or bundler handles the attribute itself, and what the content mapper types.\n\n/** The module source for a `.groq` file's content. */\nexport function groqModuleSource(content: string): string {\n return `export default ${JSON.stringify(content)}\\n`\n}\n\n/**\n * Whether an id names a `.groq` file outright. An id with a query or a hash, as in\n * `./posts.groq?raw`, asks another plugin for something this one does not make, so it is left\n * alone, as is a virtual id.\n */\nexport function isGroqFile(id: string): boolean {\n return !id.startsWith('\\0') && !/[?#]/.test(id) && id.endsWith('.groq')\n}\n\n/**\n * The same module as CommonJS, for Jest when it loads the file that way. The default export is\n * a JSON string, so nothing in it can be mistaken for code, and `__esModule` lets a default\n * import compiled by Babel or TypeScript read `exports.default`.\n */\nexport function groqModuleSourceCommonJs(content: string): string {\n return `Object.defineProperty(exports, \"__esModule\", {value: true});\\nexports.default = ${JSON.stringify(content)};\\n`\n}\n"],"mappings":";AAMA,SAAgB,iBAAiB,SAAyB;CACxD,OAAO,kBAAkB,KAAK,UAAU,OAAO,EAAE;AACnD;;;;;;AAOA,SAAgB,WAAW,IAAqB;CAC9C,OAAO,CAAC,GAAG,WAAW,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,KAAK,GAAG,SAAS,OAAO;AACxE;;;;;;AAOA,SAAgB,yBAAyB,SAAyB;CAChE,OAAO,mFAAmF,KAAK,UAAU,OAAO,EAAE;AACpH"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The plugin `groqFiles()` returns. Typed structurally rather than as Vite's `Plugin`, so this
3
+ * declaration does not depend on Vite's types; Vite, Vitest, Rollup and Rolldown accept it as is.
4
+ * @beta
5
+ */
6
+ export interface GroqFilesVitePlugin {
7
+ enforce: 'pre';
8
+ load: (id: string) => {
9
+ code: string;
10
+ map: null;
11
+ moduleType: 'js';
12
+ } | null;
13
+ name: string;
14
+ }
15
+ /**
16
+ * The plugin for Vite, Vitest, Rollup and Rolldown: a `.groq` import evaluates to the file's
17
+ * text. Types come from the content mapper, not from here.
18
+ *
19
+ * ```ts
20
+ * import groqFiles from '@sanity-labs/groq-content-mapper/vite'
21
+ *
22
+ * export default defineConfig({plugins: [groqFiles()]})
23
+ * ```
24
+ *
25
+ * A Sanity Studio or App SDK app takes the same plugin in `vite.plugins` of `sanity.cli.ts`.
26
+ *
27
+ * `enforce: 'pre'` runs the hook before Vite's own handling of unknown files, and `moduleType`
28
+ * tells Rolldown, which reads a module's type from its extension, that the code is JavaScript.
29
+ * @beta
30
+ */
31
+ export default function groqFiles(): GroqFilesVitePlugin;
32
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","names":[],"sources":["../src/vite.ts"],"mappings":"AASA;;;;;iBAAiB;EACf;EACA,OAAO;IAAgB;IAAc;IAAW;;EAChD;;;;;;;;;;;;;;;;;;wBAmBsB,aAAa"}
package/dist/vite.js ADDED
@@ -0,0 +1,34 @@
1
+ import { r as isGroqFile, t as groqModuleSource } from "./runtime-DNC5x51t.js";
2
+ import { readFileSync } from "node:fs";
3
+ /**
4
+ * The plugin for Vite, Vitest, Rollup and Rolldown: a `.groq` import evaluates to the file's
5
+ * text. Types come from the content mapper, not from here.
6
+ *
7
+ * ```ts
8
+ * import groqFiles from '@sanity-labs/groq-content-mapper/vite'
9
+ *
10
+ * export default defineConfig({plugins: [groqFiles()]})
11
+ * ```
12
+ *
13
+ * A Sanity Studio or App SDK app takes the same plugin in `vite.plugins` of `sanity.cli.ts`.
14
+ *
15
+ * `enforce: 'pre'` runs the hook before Vite's own handling of unknown files, and `moduleType`
16
+ * tells Rolldown, which reads a module's type from its extension, that the code is JavaScript.
17
+ * @beta
18
+ */
19
+ function groqFiles() {
20
+ return {
21
+ enforce: "pre",
22
+ load(id) {
23
+ return isGroqFile(id) ? {
24
+ code: groqModuleSource(readFileSync(id, "utf8")),
25
+ map: null,
26
+ moduleType: "js"
27
+ } : null;
28
+ },
29
+ name: "@sanity-labs/groq-content-mapper"
30
+ };
31
+ }
32
+ export { groqFiles as default };
33
+
34
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","names":[],"sources":["../src/vite.ts"],"sourcesContent":["import {readFileSync} from 'node:fs'\n\nimport {groqModuleSource, isGroqFile} from './runtime.js'\n\n/**\n * The plugin `groqFiles()` returns. Typed structurally rather than as Vite's `Plugin`, so this\n * declaration does not depend on Vite's types; Vite, Vitest, Rollup and Rolldown accept it as is.\n * @beta\n */\nexport interface GroqFilesVitePlugin {\n enforce: 'pre'\n load: (id: string) => {code: string; map: null; moduleType: 'js'} | null\n name: string\n}\n\n/**\n * The plugin for Vite, Vitest, Rollup and Rolldown: a `.groq` import evaluates to the file's\n * text. Types come from the content mapper, not from here.\n *\n * ```ts\n * import groqFiles from '@sanity-labs/groq-content-mapper/vite'\n *\n * export default defineConfig({plugins: [groqFiles()]})\n * ```\n *\n * A Sanity Studio or App SDK app takes the same plugin in `vite.plugins` of `sanity.cli.ts`.\n *\n * `enforce: 'pre'` runs the hook before Vite's own handling of unknown files, and `moduleType`\n * tells Rolldown, which reads a module's type from its extension, that the code is JavaScript.\n * @beta\n */\nexport default function groqFiles(): GroqFilesVitePlugin {\n return {\n enforce: 'pre',\n load(id) {\n if (!isGroqFile(id)) return null\n return {code: groqModuleSource(readFileSync(id, 'utf8')), map: null, moduleType: 'js'}\n },\n name: '@sanity-labs/groq-content-mapper',\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+BA,SAAwB,YAAiC;CACvD,OAAO;EACL,SAAS;EACT,KAAK,IAAI;GAEP,OADK,WAAW,EAAE,IACX;IAAC,MAAM,iBAAiB,aAAa,IAAI,MAAM,CAAC;IAAG,KAAK;IAAM,YAAY;GAAI,IADzD;EAE9B;EACA,MAAM;CACR;AACF"}
package/package.json CHANGED
@@ -1,12 +1,81 @@
1
1
  {
2
2
  "name": "@sanity-labs/groq-content-mapper",
3
- "version": "0.0.0",
3
+ "version": "0.1.1",
4
+ "description": "Typed .groq file imports for TypeScript 7.1, from your Sanity schema",
5
+ "keywords": [
6
+ "content-mapper",
7
+ "groq",
8
+ "sanity",
9
+ "typegen",
10
+ "typescript"
11
+ ],
12
+ "homepage": "https://github.com/sanity-labs/groq-content-mapper#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/sanity-labs/groq-content-mapper/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": "Sanity.io <hello@sanity.io>",
4
18
  "repository": {
5
19
  "type": "git",
6
- "url": "git+https://github.com/sanity-labs/groq-content-mapper.git"
20
+ "url": "git+https://github.com/sanity-labs/groq-content-mapper.git",
21
+ "directory": "packages/groq-content-mapper"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "type": "module",
27
+ "sideEffects": [
28
+ "./dist/register.js"
29
+ ],
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": "./dist/index.js",
33
+ "./jest": "./dist/jest.js",
34
+ "./next": "./dist/next.js",
35
+ "./register": "./dist/register.js",
36
+ "./vite": "./dist/vite.js",
37
+ "./package.json": "./package.json"
7
38
  },
8
- "license": "MIT",
9
39
  "publishConfig": {
10
40
  "access": "public"
41
+ },
42
+ "dependencies": {
43
+ "@babel/generator": "^7.29.7",
44
+ "@babel/types": "^7.29.7",
45
+ "@sanity/codegen": "8.2.0",
46
+ "groq-js": "^2.0.0",
47
+ "valibot": "^1.4.2"
48
+ },
49
+ "devDependencies": {
50
+ "@sanity/tsconfig": "^2.2.1",
51
+ "@sanity/tsdown-config": "^0.31.2",
52
+ "@types/babel__generator": "^7.27.0",
53
+ "@types/node": "^24.19.2",
54
+ "esbuild": "^0.28.2",
55
+ "publint": "^0.3.25",
56
+ "tsdown": "^0.23.1",
57
+ "typescript": "7.0.2",
58
+ "typescript-7.1": "npm:typescript@7.1.0-beta",
59
+ "vite": "^8.3.5",
60
+ "vitest": "^5.0.5",
61
+ "webpack": "^5.112.0"
62
+ },
63
+ "typescript": {
64
+ "contentMapper": {
65
+ "dynamicConfig": true,
66
+ "exec": [
67
+ "node",
68
+ "dist/bin/contentMapper.js"
69
+ ]
70
+ }
71
+ },
72
+ "engines": {
73
+ "node": ">=22.12"
74
+ },
75
+ "scripts": {
76
+ "build": "tsdown",
77
+ "pretest": "pnpm build",
78
+ "test": "vitest run",
79
+ "watch": "tsdown --watch"
11
80
  }
12
- }
81
+ }