aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authornetop://ウィビ <paul@webb.page>2026-04-24 12:38:19 -0700
committernetop://ウィビ <paul@webb.page>2026-04-24 12:38:19 -0700
commit5edb72ac0dfa94dc6184cc694e63c35fb373f317 (patch)
tree5674ce17896569e5c2a60dc6bd5197d74d7ac9b2 /source
parent51b4f405d5080bffcd17b00c6b75d3320f9736bd (diff)
downloadgq-5edb72ac0dfa94dc6184cc694e63c35fb373f317.tar.gz
gq-5edb72ac0dfa94dc6184cc694e63c35fb373f317.zip
fixes dynamic imports
Diffstat (limited to '')
-rw-r--r--source/import.ts78
1 files changed, 38 insertions, 40 deletions
diff --git a/source/import.ts b/source/import.ts
index a9692bf..41786b9 100644
--- a/source/import.ts
+++ b/source/import.ts
@@ -3,14 +3,15 @@
/*** IMPORT ------------------------------------------- ***/
-import { dirname, join } from "@std/path";
+import { dirname, resolve } from "@std/path";
/*** UTILITY ------------------------------------------ ***/
-const { cwd, readFileSync } = Deno;
+const { readFileSync } = Deno;
+const DYNAMIC_IMPORT_MARKER = "# DYNAMIC_IMPORTS";
const DYNAMIC_IMPORT_REGEX = /^#\s(DYNAMIC_IMPORTS)/gm;
const ENCODING = "utf-8";
-const FILE_REGEX = /\w*(.graphql)/g;
+const IMPORT_PATH_REGEX = /"([^"]+\.graphql)"/;
const IMPORT_REGEX = /^#\s(import)\s.*(.graphql")/gm;
/*** EXPORT ------------------------------------------- ***/
@@ -24,68 +25,65 @@ const IMPORT_REGEX = /^#\s(import)\s.*(.graphql")/gm;
* inline with the contents of the referenced file, resolved relative to the
* entry file.
* 2. **Dynamic imports** — if the file contains `# DYNAMIC_IMPORTS`, every
- * `.graphql` file found one level below `<cwd>/schema/` is inlined at that
- * marker. Useful for feature-folder layouts.
+ * `.graphql` file found one level below the entry file’s directory is
+ * inlined at that marker. Useful for feature-folder layouts.
*
- * Errors are logged and an empty string is returned so boot doesn't crash.
+ * All paths are resolved relative to the entry file itself, so consumers are
+ * free to place their schema wherever they like.
*
- * @param path - Path to the entry `.graphql` file, relative to `Deno.cwd()`.
+ * Errors are logged and an empty string is returned so boot doesn’t crash.
+ *
+ * @param path - Path to the entry `.graphql` file. Absolute paths are used
+ * as-is; relative paths are resolved against `Deno.cwd()`.
* @returns The fully-expanded schema string.
*/
export async function importQL(path: string): Promise<string> {
- const SCHEMA_DIRECTORY = join(cwd(), "schema");
-
try {
const decoder = new TextDecoder(ENCODING);
- const file = readFileSync(join(cwd(), String(path)));
- const imports = decoder.decode(file).match(IMPORT_REGEX) || [];
- const shouldTryDynamicallyImporting = decoder.decode(file).match(DYNAMIC_IMPORT_REGEX) ? true : false;
- let parsedFile = decoder.decode(file);
+ const entryPath = resolve(String(path));
+ const entryDir = dirname(entryPath);
+ const mainContent = decoder.decode(readFileSync(entryPath));
+ const imports = mainContent.match(IMPORT_REGEX) || [];
+ const shouldTryDynamicallyImporting = DYNAMIC_IMPORT_REGEX.test(mainContent);
+ let parsedFile = mainContent;
/*** `import` statements in the supplied schema file
are parsed to dynamically bring in linked files. ***/
- imports.map((imp: string) => {
- const matchedFilename: null | Array<string> = imp.match(FILE_REGEX);
+ for (const imp of imports) {
+ const matched = imp.match(IMPORT_PATH_REGEX);
- if (!matchedFilename || !matchedFilename.length || matchedFilename.length < 1)
- return;
+ if (!matched || !matched[1])
+ continue;
- const filename = matchedFilename[0];
- const importedFileDecoder = new TextDecoder(ENCODING);
- const importedFile = Deno.readFileSync(join(dirname(String(path)), filename));
- const decodedFile = importedFileDecoder.decode(importedFile);
+ const importedFile = readFileSync(resolve(entryDir, matched[1]));
+ const decodedFile = decoder.decode(importedFile);
parsedFile = parsedFile.replace(imp, decodedFile);
- });
+ }
- /*** With dynamic importing, we just look inside the `program`
- directory to find `.graphql` files and automatically bring
- them in, if `# DYNAMIC_IMPORTS` exists in `schema.graphql`. ***/
+ /*** With dynamic importing, we look one level below the entry
+ file’s directory to find `.graphql` files and automatically
+ bring them in, if `# DYNAMIC_IMPORTS` exists in the entry. ***/
if (shouldTryDynamicallyImporting) {
- const graphqlFiles = [];
-
- for await (const dirEntry of Deno.readDir(SCHEMA_DIRECTORY)) {
- const { isDirectory } = dirEntry;
+ const graphqlFiles: string[] = [];
- if (isDirectory) {
- const DIR = join(SCHEMA_DIRECTORY, dirEntry.name);
+ for await (const dirEntry of Deno.readDir(entryDir)) {
+ if (!dirEntry.isDirectory)
+ continue;
- for await (const dirEntry of Deno.readDir(DIR)) {
- const { isFile } = dirEntry;
+ const subDir = resolve(entryDir, dirEntry.name);
- if (isFile && dirEntry.name.match(FILE_REGEX))
- graphqlFiles.push(join(DIR, dirEntry.name));
- }
+ for await (const sub of Deno.readDir(subDir)) {
+ if (sub.isFile && sub.name.endsWith(".graphql"))
+ graphqlFiles.push(resolve(subDir, sub.name));
}
}
for (const file of graphqlFiles) {
- const importedFileDecoder = new TextDecoder(ENCODING);
- const importedFile = Deno.readFileSync(file);
- const decodedFile = importedFileDecoder.decode(importedFile);
- const insertPosition = parsedFile.indexOf("# DYNAMIC_IMPORTS");
+ const decodedFile = decoder.decode(readFileSync(file));
+ const insertPosition = parsedFile.indexOf(DYNAMIC_IMPORT_MARKER);
if (insertPosition !== -1) {
parsedFile =