Skip to content

Commit 3e663ba

Browse files
authored
Add positional pattern support for gel generate queries (#1308)
Enables selective query generation by accepting glob patterns as positional arguments.
1 parent b15566c commit 3e663ba

File tree

7 files changed

+421
-15
lines changed

7 files changed

+421
-15
lines changed

docs/queries.rst

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,33 @@ Consider the following file tree.
4848
└── getUser.edgeql
4949
5050
51-
The following command will run the ``queries`` generator.
51+
The following command will run the ``queries`` generator on all ``.edgeql`` files in your project.
5252

5353
.. tabs::
5454

5555
.. code-tab:: bash
5656
:caption: Node.js
5757

5858
$ npx @edgedb/generate queries
59+
60+
# Or process specific files with patterns:
61+
$ npx @edgedb/generate queries "queries/*.edgeql"
5962
6063
.. code-tab:: bash
6164
:caption: Deno
6265

6366
$ deno run --allow-all --unstable https://deno.land/x/edgedb/generate.ts queries
67+
68+
# Or with patterns:
69+
$ deno run --allow-all --unstable https://deno.land/x/edgedb/generate.ts queries "queries/*.edgeql"
6470
6571
.. code-tab:: bash
6672
:caption: Bun
6773

6874
$ bunx @edgedb/generate queries
75+
76+
# Or with patterns:
77+
$ bunx @edgedb/generate queries "queries/*.edgeql"
6978
7079
.. note:: Deno users
7180

@@ -182,6 +191,45 @@ We can now use this function in our code.
182191
Generators work by connecting to the database to get information about the current state of the schema. Make sure you run the generators again any time the schema changes so that the generated code is in-sync with the current state of the schema.
183192

184193

194+
File Pattern Selection
195+
----------------------
196+
197+
By default, the generator scans your entire project for ``*.edgeql`` files. You can specify which files to process using glob patterns as positional arguments.
198+
199+
.. code-block:: bash
200+
201+
# Process specific files
202+
$ npx @edgedb/generate queries "getUser.edgeql" "admin/permissions.edgeql"
203+
204+
# Use glob patterns
205+
$ npx @edgedb/generate queries "src/**/*user*.edgeql"
206+
207+
# Process entire directories
208+
$ npx @edgedb/generate queries "queries/" "admin/"
209+
210+
**Pattern Features:**
211+
212+
- **Glob support**: Use ``*``, ``**``, and ``?`` wildcards for flexible matching
213+
- **Directory expansion**: Bare directory names automatically expand to ``directory/**/*.edgeql``
214+
- **Schema protection**: Migration and fixup files in ``dbschema/`` are automatically excluded
215+
- **Multiple patterns**: Specify multiple patterns to process files from different locations
216+
217+
**Examples:**
218+
219+
.. code-block:: bash
220+
221+
# Process only user-related queries
222+
$ npx @edgedb/generate queries "**/*user*.edgeql"
223+
224+
# Process queries from specific modules
225+
$ npx @edgedb/generate queries "src/queries/" "admin/queries/"
226+
227+
# Process a single file
228+
$ npx @edgedb/generate queries "scripts/migration-helper.edgeql"
229+
230+
Patterns are resolved relative to your current working directory and will automatically exclude schema management files to prevent accidentally processing migrations.
231+
232+
185233
Single-file mode
186234
----------------
187235

@@ -205,6 +253,9 @@ The following command will run the generator in ``--file`` mode.
205253
.. code-block:: bash
206254
207255
$ npx @edgedb/generate queries --file
256+
257+
# Or generate single file from specific patterns:
258+
$ npx @edgedb/generate queries --file "src/queries/*.edgeql" "admin/*.edgeql"
208259
209260
A single file will be generated that exports two functions, ``getUser`` and ``getMovies``. By default this file is generated into the ``dbschema`` directory.
210261

packages/generate/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@
2727
"conditional-type-checks": "^1.0.6",
2828
"esbuild": "^0.21.4",
2929
"gel": "^2.1.1",
30-
"globby": "^14.0.1",
3130
"jest": "^29.7.0",
3231
"ts-jest": "^29.1.4",
32+
"tsx": "^4.11.0",
3333
"typescript": "^5.5.2"
3434
},
3535
"dependencies": {
3636
"@iarna/toml": "^2.2.5",
37-
"debug": "^4.3.4"
37+
"debug": "^4.3.4",
38+
"globby": "^14.0.1"
3839
},
3940
"scripts": {
4041
"typecheck": "tsc --project tsconfig.build.json --noEmit",

packages/generate/src/cli.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ const run = async () => {
105105
currentDir = path.join(currentDir, "..");
106106
}
107107

108+
// Collect positional arguments (patterns) for queries generator
109+
const positionalArgs: string[] = [];
110+
if (generator === Generator.Queries) {
111+
while (args.length && !args[0]!.startsWith("-")) {
112+
positionalArgs.push(args.shift()!);
113+
}
114+
if (positionalArgs.length > 0) {
115+
options.patterns = positionalArgs;
116+
}
117+
}
118+
108119
while (args.length) {
109120
let flag = args.shift()!;
110121
let val: string | null = null;

packages/generate/src/commandutil.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface CommandOptions {
1717
updateIgnoreFile?: boolean;
1818
useHttpClient?: boolean;
1919
future?: Partial<Record<keyof typeof defaultFutureFlags, boolean>>;
20+
patterns?: string[];
2021
}
2122

2223
const { input } = systemUtils;

packages/generate/src/queries.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { type CommandOptions } from "./commandutil";
55
import { headerComment } from "./genutil";
66
import type { Target } from "./genutil";
77

8-
const { walk, readFileUtf8 } = systemUtils;
8+
const { readFileUtf8 } = systemUtils;
99

1010
// generate per-file queries
1111
// generate queries in a single file
@@ -40,9 +40,12 @@ currently supported.`);
4040
// generate one query per file
4141

4242
console.log(`Detected schema directory: ${params.schemaDir}`);
43-
const matches = await getMatches(root, params.schemaDir);
43+
const matches = await getMatches(root, params.options.patterns);
4444
if (matches.length === 0) {
45-
console.log(`No .edgeql files found outside of ${params.schemaDir}`);
45+
const patternMsg = params.options.patterns?.length
46+
? ` matching patterns: ${params.options.patterns.join(", ")}`
47+
: ` outside of ${params.schemaDir}`;
48+
console.log(`No .edgeql files found${patternMsg}`);
4649
return;
4750
}
4851

@@ -158,15 +161,23 @@ export function stringifyImports(imports: ImportMap) {
158161
.join("\n");
159162
}
160163

161-
async function getMatches(root: string, schemaDir: string) {
162-
return walk(root, {
163-
match: [/[^/]\.edgeql$/],
164-
skip: [
165-
/node_modules/,
166-
RegExp(`${schemaDir}\\${path.sep}migrations`),
167-
RegExp(`${schemaDir}\\${path.sep}fixups`),
168-
],
164+
async function getMatches(root: string, patterns?: string[]) {
165+
// Single code path using globby for both cases
166+
const { globby } = await import("globby");
167+
168+
const searchPatterns = patterns && patterns.length > 0 ? patterns : ["."];
169+
170+
const allFiles = await globby(searchPatterns, {
171+
cwd: root,
172+
absolute: true,
173+
onlyFiles: true,
174+
expandDirectories: {
175+
extensions: ["edgeql"],
176+
},
177+
ignore: ["node_modules/**", `**/migrations/**`, `**/fixups/**`],
169178
});
179+
180+
return allFiles;
170181
}
171182

172183
// const targetToExtension: {[k in Target]: string} = {

0 commit comments

Comments
 (0)