@graphql-codegen/cli 3.3.0-rc-20230402134456-aa606b215 → 3.3.1-alpha-20230404030315-638d98dae

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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createWatcher = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const promises_1 = require("node:fs/promises");
5
6
  const path_1 = require("path");
6
7
  const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
7
8
  const utils_1 = require("@graphql-tools/utils");
@@ -18,8 +19,8 @@ function log(msg) {
18
19
  // double spaces to inline the message with Listr
19
20
  (0, logger_js_1.getLogger)().info(` ${msg}`);
20
21
  }
21
- function emitWatching() {
22
- log(`${log_symbols_1.default.info} Watching for changes...`);
22
+ function emitWatching(watchDir) {
23
+ log(`${log_symbols_1.default.info} Watching for changes in ${watchDir}...`);
23
24
  }
24
25
  const createWatcher = (initalContext, onNext) => {
25
26
  (0, debugging_js_1.debugLog)(`[Watcher] Starting watcher...`);
@@ -55,6 +56,7 @@ const createWatcher = (initalContext, onNext) => {
55
56
  let watcherSubscription;
56
57
  const runWatcher = async () => {
57
58
  var _a;
59
+ const watchDirectory = await findHighestCommonDirectory(files);
58
60
  const parcelWatcher = await Promise.resolve().then(() => tslib_1.__importStar(require('@parcel/watcher')));
59
61
  (0, debugging_js_1.debugLog)(`[Watcher] Parcel watcher loaded...`);
60
62
  let isShutdown = false;
@@ -62,10 +64,10 @@ const createWatcher = (initalContext, onNext) => {
62
64
  if (!isShutdown) {
63
65
  (0, codegen_js_1.executeCodegen)(initalContext)
64
66
  .then(onNext, () => Promise.resolve())
65
- .then(() => emitWatching());
67
+ .then(() => emitWatching(watchDirectory));
66
68
  }
67
69
  }, 100);
68
- emitWatching();
70
+ emitWatching(watchDirectory);
69
71
  const ignored = [];
70
72
  for (const entry of Object.keys(config.generates).map(filename => ({
71
73
  filename,
@@ -81,7 +83,7 @@ const createWatcher = (initalContext, onNext) => {
81
83
  ignored.push(entry.filename);
82
84
  }
83
85
  }
84
- watcherSubscription = await parcelWatcher.subscribe(process.cwd(), async (_, events) => {
86
+ watcherSubscription = await parcelWatcher.subscribe(watchDirectory, async (_, events) => {
85
87
  // it doesn't matter what has changed, need to run whole process anyway
86
88
  await Promise.all(events.map(async ({ type: eventName, path }) => {
87
89
  /**
@@ -92,7 +94,7 @@ const createWatcher = (initalContext, onNext) => {
92
94
  return;
93
95
  (0, hooks_js_1.lifecycleHooks)(config.hooks).onWatchTriggered(eventName, path);
94
96
  (0, debugging_js_1.debugLog)(`[Watcher] triggered due to a file ${eventName} event: ${path}`);
95
- const fullPath = (0, path_1.join)(process.cwd(), path);
97
+ const fullPath = (0, path_1.join)(watchDirectory, path);
96
98
  // In ESM require is not defined
97
99
  try {
98
100
  delete require.cache[fullPath];
@@ -135,3 +137,56 @@ const createWatcher = (initalContext, onNext) => {
135
137
  });
136
138
  };
137
139
  exports.createWatcher = createWatcher;
140
+ /**
141
+ * Given a list of file paths (each of which may be absolute, or relative to
142
+ * `process.cwd()`), find absolute path of the "highest" common directory,
143
+ * i.e. the directory that contains all the files in the list.
144
+ *
145
+ * @param files List of relative and/or absolute file paths (or micromatch patterns)
146
+ */
147
+ const findHighestCommonDirectory = async (files) => {
148
+ // Map files to a list of basePaths, where "base" is the result of mm.scan(pathOrPattern)
149
+ // e.g. mm.scan("/**/foo/bar").base -> "/" ; mm.scan("/foo/bar/**/fizz/*.graphql") -> /foo/bar
150
+ const dirPaths = files
151
+ .map(filePath => ((0, path_1.isAbsolute)(filePath) ? filePath : (0, path_1.resolve)(filePath)))
152
+ .map(patterned => micromatch_1.default.scan(patterned).base);
153
+ // Return longest common prefix if it's accessible, otherwise process.cwd()
154
+ return (async (maybeValidPath) => {
155
+ (0, debugging_js_1.debugLog)(`[Watcher] Longest common prefix of all files: ${maybeValidPath}...`);
156
+ try {
157
+ await (0, promises_1.access)(maybeValidPath);
158
+ return maybeValidPath;
159
+ }
160
+ catch (_a) {
161
+ log(`[Watcher] Longest common prefix (${maybeValidPath}) is not accessible`);
162
+ log(`[Watcher] Watching current working directory (${process.cwd()}) instead`);
163
+ return process.cwd();
164
+ }
165
+ })(longestCommonPrefix(dirPaths.map(path => path.split(path_1.sep))).join(path_1.sep));
166
+ };
167
+ /**
168
+ * Find the longest common prefix of an array of paths, where each item in
169
+ * the array an array of path segments which comprise an absolute path when
170
+ * joined together by a path separator
171
+ *
172
+ * Adapted from:
173
+ * https://duncan-mcardle.medium.com/leetcode-problem-14-longest-common-prefix-javascript-3bc6a2f777c4
174
+ *
175
+ * @param splitPaths An array of arrays, where each item is a path split by its separator
176
+ * @returns An array of path segments representing the longest common prefix of splitPaths
177
+ */
178
+ const longestCommonPrefix = (splitPaths) => {
179
+ // Return early on empty input
180
+ if (!splitPaths.length) {
181
+ return [];
182
+ }
183
+ // Loop through the segments of the first path
184
+ for (let i = 0; i <= splitPaths[0].length; i++) {
185
+ // Check if this path segment is present in the same position of every path
186
+ if (!splitPaths.every(string => string[i] === splitPaths[0][i])) {
187
+ // If not, return the path segments up to and including the previous segment
188
+ return splitPaths[0].slice(0, i);
189
+ }
190
+ }
191
+ return splitPaths[0];
192
+ };
@@ -1,4 +1,5 @@
1
- import { join } from 'path';
1
+ import { access } from 'node:fs/promises';
2
+ import { join, isAbsolute, resolve, sep } from 'path';
2
3
  import { normalizeInstanceOrArray, normalizeOutputParam } from '@graphql-codegen/plugin-helpers';
3
4
  import { isValidPath } from '@graphql-tools/utils';
4
5
  import debounce from 'debounce';
@@ -14,8 +15,8 @@ function log(msg) {
14
15
  // double spaces to inline the message with Listr
15
16
  getLogger().info(` ${msg}`);
16
17
  }
17
- function emitWatching() {
18
- log(`${logSymbols.info} Watching for changes...`);
18
+ function emitWatching(watchDir) {
19
+ log(`${logSymbols.info} Watching for changes in ${watchDir}...`);
19
20
  }
20
21
  export const createWatcher = (initalContext, onNext) => {
21
22
  debugLog(`[Watcher] Starting watcher...`);
@@ -51,6 +52,7 @@ export const createWatcher = (initalContext, onNext) => {
51
52
  let watcherSubscription;
52
53
  const runWatcher = async () => {
53
54
  var _a;
55
+ const watchDirectory = await findHighestCommonDirectory(files);
54
56
  const parcelWatcher = await import('@parcel/watcher');
55
57
  debugLog(`[Watcher] Parcel watcher loaded...`);
56
58
  let isShutdown = false;
@@ -58,10 +60,10 @@ export const createWatcher = (initalContext, onNext) => {
58
60
  if (!isShutdown) {
59
61
  executeCodegen(initalContext)
60
62
  .then(onNext, () => Promise.resolve())
61
- .then(() => emitWatching());
63
+ .then(() => emitWatching(watchDirectory));
62
64
  }
63
65
  }, 100);
64
- emitWatching();
66
+ emitWatching(watchDirectory);
65
67
  const ignored = [];
66
68
  for (const entry of Object.keys(config.generates).map(filename => ({
67
69
  filename,
@@ -77,7 +79,7 @@ export const createWatcher = (initalContext, onNext) => {
77
79
  ignored.push(entry.filename);
78
80
  }
79
81
  }
80
- watcherSubscription = await parcelWatcher.subscribe(process.cwd(), async (_, events) => {
82
+ watcherSubscription = await parcelWatcher.subscribe(watchDirectory, async (_, events) => {
81
83
  // it doesn't matter what has changed, need to run whole process anyway
82
84
  await Promise.all(events.map(async ({ type: eventName, path }) => {
83
85
  /**
@@ -88,7 +90,7 @@ export const createWatcher = (initalContext, onNext) => {
88
90
  return;
89
91
  lifecycleHooks(config.hooks).onWatchTriggered(eventName, path);
90
92
  debugLog(`[Watcher] triggered due to a file ${eventName} event: ${path}`);
91
- const fullPath = join(process.cwd(), path);
93
+ const fullPath = join(watchDirectory, path);
92
94
  // In ESM require is not defined
93
95
  try {
94
96
  delete require.cache[fullPath];
@@ -130,3 +132,56 @@ export const createWatcher = (initalContext, onNext) => {
130
132
  });
131
133
  });
132
134
  };
135
+ /**
136
+ * Given a list of file paths (each of which may be absolute, or relative to
137
+ * `process.cwd()`), find absolute path of the "highest" common directory,
138
+ * i.e. the directory that contains all the files in the list.
139
+ *
140
+ * @param files List of relative and/or absolute file paths (or micromatch patterns)
141
+ */
142
+ const findHighestCommonDirectory = async (files) => {
143
+ // Map files to a list of basePaths, where "base" is the result of mm.scan(pathOrPattern)
144
+ // e.g. mm.scan("/**/foo/bar").base -> "/" ; mm.scan("/foo/bar/**/fizz/*.graphql") -> /foo/bar
145
+ const dirPaths = files
146
+ .map(filePath => (isAbsolute(filePath) ? filePath : resolve(filePath)))
147
+ .map(patterned => mm.scan(patterned).base);
148
+ // Return longest common prefix if it's accessible, otherwise process.cwd()
149
+ return (async (maybeValidPath) => {
150
+ debugLog(`[Watcher] Longest common prefix of all files: ${maybeValidPath}...`);
151
+ try {
152
+ await access(maybeValidPath);
153
+ return maybeValidPath;
154
+ }
155
+ catch (_a) {
156
+ log(`[Watcher] Longest common prefix (${maybeValidPath}) is not accessible`);
157
+ log(`[Watcher] Watching current working directory (${process.cwd()}) instead`);
158
+ return process.cwd();
159
+ }
160
+ })(longestCommonPrefix(dirPaths.map(path => path.split(sep))).join(sep));
161
+ };
162
+ /**
163
+ * Find the longest common prefix of an array of paths, where each item in
164
+ * the array an array of path segments which comprise an absolute path when
165
+ * joined together by a path separator
166
+ *
167
+ * Adapted from:
168
+ * https://duncan-mcardle.medium.com/leetcode-problem-14-longest-common-prefix-javascript-3bc6a2f777c4
169
+ *
170
+ * @param splitPaths An array of arrays, where each item is a path split by its separator
171
+ * @returns An array of path segments representing the longest common prefix of splitPaths
172
+ */
173
+ const longestCommonPrefix = (splitPaths) => {
174
+ // Return early on empty input
175
+ if (!splitPaths.length) {
176
+ return [];
177
+ }
178
+ // Loop through the segments of the first path
179
+ for (let i = 0; i <= splitPaths[0].length; i++) {
180
+ // Check if this path segment is present in the same position of every path
181
+ if (!splitPaths.every(string => string[i] === splitPaths[0][i])) {
182
+ // If not, return the path segments up to and including the previous segment
183
+ return splitPaths[0].slice(0, i);
184
+ }
185
+ }
186
+ return splitPaths[0];
187
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-codegen/cli",
3
- "version": "3.3.0-rc-20230402134456-aa606b215",
3
+ "version": "3.3.1-alpha-20230404030315-638d98dae",
4
4
  "peerDependencies": {
5
5
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
6
6
  },
@@ -9,7 +9,7 @@
9
9
  "@babel/template": "^7.18.10",
10
10
  "@babel/types": "^7.18.13",
11
11
  "@graphql-codegen/core": "^3.1.0",
12
- "@graphql-codegen/plugin-helpers": "4.2.0-rc-20230402134456-aa606b215",
12
+ "@graphql-codegen/plugin-helpers": "^4.2.0",
13
13
  "@graphql-tools/apollo-engine-loader": "^7.3.6",
14
14
  "@graphql-tools/code-file-loader": "^7.3.17",
15
15
  "@graphql-tools/git-loader": "^7.2.13",