c12 1.4.1 → 1.5.0

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/README.md CHANGED
@@ -75,9 +75,9 @@ Resolve configuration from this working directory. The default is `process.cwd()
75
75
 
76
76
  Configuration base name. The default is `config`.
77
77
 
78
- ### `configName`
78
+ ### `configFile`
79
79
 
80
- Configuration file name without extension. Default is generated from `name` (name=foo => `foo.config`).
80
+ Configuration file name without extension. Default is generated from `name` (f.e., if `name` is `foo`, the config file will be => `foo.config`).
81
81
 
82
82
  Set to `false` to avoid loading the config file.
83
83
 
package/dist/index.cjs CHANGED
@@ -8,10 +8,10 @@ const node_os = require('node:os');
8
8
  const createJiti = require('jiti');
9
9
  const rc9 = require('rc9');
10
10
  const defu = require('defu');
11
+ const ohash = require('ohash');
11
12
  const pkgTypes = require('pkg-types');
12
13
  const chokidar = require('chokidar');
13
14
  const perfectDebounce = require('perfect-debounce');
14
- const ohash = require('ohash');
15
15
 
16
16
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
17
17
 
@@ -64,7 +64,7 @@ async function loadDotenv(options) {
64
64
  }
65
65
  function interpolate(target, source = {}, parse = (v) => v) {
66
66
  function getValue(key) {
67
- return source[key] !== void 0 ? source[key] : target[key];
67
+ return source[key] === void 0 ? target[key] : source[key];
68
68
  }
69
69
  function interpolate2(value, parents = []) {
70
70
  if (typeof value !== "string") {
@@ -94,7 +94,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
94
94
  value2 = getValue(key);
95
95
  value2 = interpolate2(value2, [...parents, key]);
96
96
  }
97
- return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
97
+ return value2 === void 0 ? newValue : newValue.replace(replacePart, value2);
98
98
  }, value)
99
99
  );
100
100
  }
@@ -107,7 +107,7 @@ async function loadConfig(options) {
107
107
  options.cwd = pathe.resolve(process.cwd(), options.cwd || ".");
108
108
  options.name = options.name || "config";
109
109
  options.envName = options.envName ?? process.env.NODE_ENV;
110
- options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
110
+ options.configFile = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
111
111
  options.rcFile = options.rcFile ?? `.${options.name}rc`;
112
112
  if (options.extend !== false) {
113
113
  options.extend = {
@@ -249,7 +249,7 @@ async function extendConfig(config, options) {
249
249
  }
250
250
  }
251
251
  }
252
- const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"];
252
+ const GIT_PREFIXES = ["gh:", "github:", "gitlab:", "bitbucket:", "https://"];
253
253
  const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
254
254
  async function resolveConfig(source, options, sourceOptions = {}) {
255
255
  if (options.resolve) {
@@ -260,14 +260,18 @@ async function resolveConfig(source, options, sourceOptions = {}) {
260
260
  }
261
261
  if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
262
262
  const { downloadTemplate } = await import('giget');
263
- const url = new URL(source);
264
- const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/");
265
- const name = gitRepo.replace(/[#/:@\\]/g, "_");
266
- const tmpDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", name) : pathe.resolve(node_os.homedir(), ".cache/c12", name);
267
- if (node_fs.existsSync(tmpDir)) {
268
- await promises.rm(tmpDir, { recursive: true });
263
+ const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + ohash.hash(source);
264
+ let cloneDir;
265
+ const localNodeModules = pathe.resolve(options.cwd, "node_modules");
266
+ if (node_fs.existsSync(localNodeModules)) {
267
+ cloneDir = pathe.join(localNodeModules, ".c12", cloneName);
268
+ } else {
269
+ cloneDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : pathe.resolve(node_os.homedir(), ".cache/c12", cloneName);
269
270
  }
270
- const cloned = await downloadTemplate(source, { dir: tmpDir });
271
+ if (node_fs.existsSync(cloneDir)) {
272
+ await promises.rm(cloneDir, { recursive: true });
273
+ }
274
+ const cloned = await downloadTemplate(source, { dir: cloneDir });
271
275
  source = cloned.dir;
272
276
  }
273
277
  if (NPM_PACKAGE_RE.test(source)) {
@@ -276,7 +280,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
276
280
  } catch {
277
281
  }
278
282
  }
279
- const isDir = !pathe.extname(source);
283
+ const ext = pathe.extname(source);
284
+ const isDir = !ext || ext === pathe.basename(source);
280
285
  const cwd = pathe.resolve(options.cwd, isDir ? source : pathe.dirname(source));
281
286
  if (isDir) {
282
287
  source = options.configFile;
@@ -329,7 +334,7 @@ const eventMap = {
329
334
  async function watchConfig(options) {
330
335
  let config = await loadConfig(options);
331
336
  const configName = options.name || "config";
332
- const configFileName = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
337
+ const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
333
338
  const watchingFiles = [
334
339
  ...new Set(
335
340
  (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
@@ -379,10 +384,10 @@ async function watchConfig(options) {
379
384
  await options.onUpdate(changeCtx);
380
385
  }
381
386
  };
382
- if (options.debounce !== false) {
383
- _fswatcher.on("all", perfectDebounce.debounce(onChange, options.debounce ?? 100));
384
- } else {
387
+ if (options.debounce === false) {
385
388
  _fswatcher.on("all", onChange);
389
+ } else {
390
+ _fswatcher.on("all", perfectDebounce.debounce(onChange, options.debounce ?? 100));
386
391
  }
387
392
  const utils = {
388
393
  watchingFiles,
@@ -0,0 +1,120 @@
1
+ import { JITI } from 'jiti';
2
+ import { JITIOptions } from 'jiti/dist/types';
3
+ import { WatchOptions } from 'chokidar';
4
+ import { diff } from 'ohash';
5
+
6
+ interface DotenvOptions {
7
+ /**
8
+ * The project root directory (either absolute or relative to the current working directory).
9
+ */
10
+ cwd: string;
11
+ /**
12
+ * What file to look in for environment variables (either absolute or relative
13
+ * to the current working directory). For example, `.env`.
14
+ */
15
+ fileName?: string;
16
+ /**
17
+ * Whether to interpolate variables within .env.
18
+ *
19
+ * @example
20
+ * ```env
21
+ * BASE_DIR="/test"
22
+ * # resolves to "/test/further"
23
+ * ANOTHER_DIR="${BASE_DIR}/further"
24
+ * ```
25
+ */
26
+ interpolate?: boolean;
27
+ /**
28
+ * An object describing environment variables (key, value pairs).
29
+ */
30
+ env?: NodeJS.ProcessEnv;
31
+ }
32
+ type Env = typeof process.env;
33
+ /**
34
+ * Load and interpolate environment variables into `process.env`.
35
+ * If you need more control (or access to the values), consider using `loadDotenv` instead
36
+ *
37
+ */
38
+ declare function setupDotenv(options: DotenvOptions): Promise<Env>;
39
+ /** Load environment variables into an object. */
40
+ declare function loadDotenv(options: DotenvOptions): Promise<Env>;
41
+
42
+ interface ConfigLayerMeta {
43
+ name?: string;
44
+ [key: string]: any;
45
+ }
46
+ type UserInputConfig = Record<string, any>;
47
+ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
48
+ $test?: T;
49
+ $development?: T;
50
+ $production?: T;
51
+ $env?: Record<string, T>;
52
+ $meta?: MT;
53
+ }
54
+ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
55
+ interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
56
+ meta?: MT;
57
+ overrides?: T;
58
+ [key: string]: any;
59
+ }
60
+ interface ConfigLayer<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
61
+ config: T | null;
62
+ source?: string;
63
+ sourceOptions?: SourceOptions<T, MT>;
64
+ meta?: MT;
65
+ cwd?: string;
66
+ configFile?: string;
67
+ }
68
+ interface ResolvedConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends ConfigLayer<T, MT> {
69
+ layers?: ConfigLayer<T, MT>[];
70
+ cwd?: string;
71
+ }
72
+ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
73
+ name?: string;
74
+ cwd?: string;
75
+ configFile?: string;
76
+ rcFile?: false | string;
77
+ globalRc?: boolean;
78
+ dotenv?: boolean | DotenvOptions;
79
+ envName?: string | false;
80
+ packageJson?: boolean | string | string[];
81
+ defaults?: T;
82
+ defaultConfig?: T;
83
+ overrides?: T;
84
+ resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
85
+ jiti?: JITI;
86
+ jitiOptions?: JITIOptions;
87
+ extend?: false | {
88
+ extendKey?: string | string[];
89
+ };
90
+ }
91
+ type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
92
+ declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
93
+
94
+ declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
95
+
96
+ type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
97
+ watchingFiles: string[];
98
+ unwatch: () => Promise<void>;
99
+ };
100
+ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends LoadConfigOptions<T, MT> {
101
+ chokidarOptions?: WatchOptions;
102
+ debounce?: false | number;
103
+ onWatch?: (event: {
104
+ type: "created" | "updated" | "removed";
105
+ path: string;
106
+ }) => void | Promise<void>;
107
+ acceptHMR?: (context: {
108
+ getDiff: () => ReturnType<typeof diff>;
109
+ newConfig: ResolvedConfig<T, MT>;
110
+ oldConfig: ResolvedConfig<T, MT>;
111
+ }) => void | boolean | Promise<void | boolean>;
112
+ onUpdate?: (context: {
113
+ getDiff: () => ReturnType<typeof diff>;
114
+ newConfig: ResolvedConfig<T, MT>;
115
+ oldConfig: ResolvedConfig<T, MT>;
116
+ }) => void | Promise<void>;
117
+ }
118
+ declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
119
+
120
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
@@ -0,0 +1,120 @@
1
+ import { JITI } from 'jiti';
2
+ import { JITIOptions } from 'jiti/dist/types';
3
+ import { WatchOptions } from 'chokidar';
4
+ import { diff } from 'ohash';
5
+
6
+ interface DotenvOptions {
7
+ /**
8
+ * The project root directory (either absolute or relative to the current working directory).
9
+ */
10
+ cwd: string;
11
+ /**
12
+ * What file to look in for environment variables (either absolute or relative
13
+ * to the current working directory). For example, `.env`.
14
+ */
15
+ fileName?: string;
16
+ /**
17
+ * Whether to interpolate variables within .env.
18
+ *
19
+ * @example
20
+ * ```env
21
+ * BASE_DIR="/test"
22
+ * # resolves to "/test/further"
23
+ * ANOTHER_DIR="${BASE_DIR}/further"
24
+ * ```
25
+ */
26
+ interpolate?: boolean;
27
+ /**
28
+ * An object describing environment variables (key, value pairs).
29
+ */
30
+ env?: NodeJS.ProcessEnv;
31
+ }
32
+ type Env = typeof process.env;
33
+ /**
34
+ * Load and interpolate environment variables into `process.env`.
35
+ * If you need more control (or access to the values), consider using `loadDotenv` instead
36
+ *
37
+ */
38
+ declare function setupDotenv(options: DotenvOptions): Promise<Env>;
39
+ /** Load environment variables into an object. */
40
+ declare function loadDotenv(options: DotenvOptions): Promise<Env>;
41
+
42
+ interface ConfigLayerMeta {
43
+ name?: string;
44
+ [key: string]: any;
45
+ }
46
+ type UserInputConfig = Record<string, any>;
47
+ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
48
+ $test?: T;
49
+ $development?: T;
50
+ $production?: T;
51
+ $env?: Record<string, T>;
52
+ $meta?: MT;
53
+ }
54
+ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
55
+ interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
56
+ meta?: MT;
57
+ overrides?: T;
58
+ [key: string]: any;
59
+ }
60
+ interface ConfigLayer<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
61
+ config: T | null;
62
+ source?: string;
63
+ sourceOptions?: SourceOptions<T, MT>;
64
+ meta?: MT;
65
+ cwd?: string;
66
+ configFile?: string;
67
+ }
68
+ interface ResolvedConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends ConfigLayer<T, MT> {
69
+ layers?: ConfigLayer<T, MT>[];
70
+ cwd?: string;
71
+ }
72
+ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
73
+ name?: string;
74
+ cwd?: string;
75
+ configFile?: string;
76
+ rcFile?: false | string;
77
+ globalRc?: boolean;
78
+ dotenv?: boolean | DotenvOptions;
79
+ envName?: string | false;
80
+ packageJson?: boolean | string | string[];
81
+ defaults?: T;
82
+ defaultConfig?: T;
83
+ overrides?: T;
84
+ resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
85
+ jiti?: JITI;
86
+ jitiOptions?: JITIOptions;
87
+ extend?: false | {
88
+ extendKey?: string | string[];
89
+ };
90
+ }
91
+ type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
92
+ declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
93
+
94
+ declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
95
+
96
+ type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
97
+ watchingFiles: string[];
98
+ unwatch: () => Promise<void>;
99
+ };
100
+ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends LoadConfigOptions<T, MT> {
101
+ chokidarOptions?: WatchOptions;
102
+ debounce?: false | number;
103
+ onWatch?: (event: {
104
+ type: "created" | "updated" | "removed";
105
+ path: string;
106
+ }) => void | Promise<void>;
107
+ acceptHMR?: (context: {
108
+ getDiff: () => ReturnType<typeof diff>;
109
+ newConfig: ResolvedConfig<T, MT>;
110
+ oldConfig: ResolvedConfig<T, MT>;
111
+ }) => void | boolean | Promise<void | boolean>;
112
+ onUpdate?: (context: {
113
+ getDiff: () => ReturnType<typeof diff>;
114
+ newConfig: ResolvedConfig<T, MT>;
115
+ oldConfig: ResolvedConfig<T, MT>;
116
+ }) => void | Promise<void>;
117
+ }
118
+ declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
119
+
120
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.d.ts CHANGED
@@ -117,4 +117,4 @@ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT ext
117
117
  }
118
118
  declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
119
119
 
120
- export { C12InputConfig, ConfigLayer, ConfigLayerMeta, ConfigWatcher, DefineConfig, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolvedConfig, SourceOptions, UserInputConfig, WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
120
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  import { existsSync, promises } from 'node:fs';
2
- import { resolve, extname, dirname } from 'pathe';
2
+ import { resolve, join, extname, basename, dirname } from 'pathe';
3
3
  import * as dotenv from 'dotenv';
4
4
  import { rm } from 'node:fs/promises';
5
5
  import { homedir } from 'node:os';
6
6
  import createJiti from 'jiti';
7
7
  import * as rc9 from 'rc9';
8
8
  import { defu } from 'defu';
9
+ import { hash, diff } from 'ohash';
9
10
  import { findWorkspaceDir, readPackageJSON } from 'pkg-types';
10
11
  import { watch } from 'chokidar';
11
12
  import { debounce } from 'perfect-debounce';
12
- import { diff } from 'ohash';
13
13
 
14
14
  async function setupDotenv(options) {
15
15
  const targetEnvironment = options.env ?? process.env;
@@ -44,7 +44,7 @@ async function loadDotenv(options) {
44
44
  }
45
45
  function interpolate(target, source = {}, parse = (v) => v) {
46
46
  function getValue(key) {
47
- return source[key] !== void 0 ? source[key] : target[key];
47
+ return source[key] === void 0 ? target[key] : source[key];
48
48
  }
49
49
  function interpolate2(value, parents = []) {
50
50
  if (typeof value !== "string") {
@@ -74,7 +74,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
74
74
  value2 = getValue(key);
75
75
  value2 = interpolate2(value2, [...parents, key]);
76
76
  }
77
- return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
77
+ return value2 === void 0 ? newValue : newValue.replace(replacePart, value2);
78
78
  }, value)
79
79
  );
80
80
  }
@@ -87,7 +87,7 @@ async function loadConfig(options) {
87
87
  options.cwd = resolve(process.cwd(), options.cwd || ".");
88
88
  options.name = options.name || "config";
89
89
  options.envName = options.envName ?? process.env.NODE_ENV;
90
- options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
90
+ options.configFile = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
91
91
  options.rcFile = options.rcFile ?? `.${options.name}rc`;
92
92
  if (options.extend !== false) {
93
93
  options.extend = {
@@ -229,7 +229,7 @@ async function extendConfig(config, options) {
229
229
  }
230
230
  }
231
231
  }
232
- const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"];
232
+ const GIT_PREFIXES = ["gh:", "github:", "gitlab:", "bitbucket:", "https://"];
233
233
  const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
234
234
  async function resolveConfig(source, options, sourceOptions = {}) {
235
235
  if (options.resolve) {
@@ -240,14 +240,18 @@ async function resolveConfig(source, options, sourceOptions = {}) {
240
240
  }
241
241
  if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
242
242
  const { downloadTemplate } = await import('giget');
243
- const url = new URL(source);
244
- const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/");
245
- const name = gitRepo.replace(/[#/:@\\]/g, "_");
246
- const tmpDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", name) : resolve(homedir(), ".cache/c12", name);
247
- if (existsSync(tmpDir)) {
248
- await rm(tmpDir, { recursive: true });
243
+ const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + hash(source);
244
+ let cloneDir;
245
+ const localNodeModules = resolve(options.cwd, "node_modules");
246
+ if (existsSync(localNodeModules)) {
247
+ cloneDir = join(localNodeModules, ".c12", cloneName);
248
+ } else {
249
+ cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : resolve(homedir(), ".cache/c12", cloneName);
249
250
  }
250
- const cloned = await downloadTemplate(source, { dir: tmpDir });
251
+ if (existsSync(cloneDir)) {
252
+ await rm(cloneDir, { recursive: true });
253
+ }
254
+ const cloned = await downloadTemplate(source, { dir: cloneDir });
251
255
  source = cloned.dir;
252
256
  }
253
257
  if (NPM_PACKAGE_RE.test(source)) {
@@ -256,7 +260,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
256
260
  } catch {
257
261
  }
258
262
  }
259
- const isDir = !extname(source);
263
+ const ext = extname(source);
264
+ const isDir = !ext || ext === basename(source);
260
265
  const cwd = resolve(options.cwd, isDir ? source : dirname(source));
261
266
  if (isDir) {
262
267
  source = options.configFile;
@@ -309,7 +314,7 @@ const eventMap = {
309
314
  async function watchConfig(options) {
310
315
  let config = await loadConfig(options);
311
316
  const configName = options.name || "config";
312
- const configFileName = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
317
+ const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
313
318
  const watchingFiles = [
314
319
  ...new Set(
315
320
  (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
@@ -359,10 +364,10 @@ async function watchConfig(options) {
359
364
  await options.onUpdate(changeCtx);
360
365
  }
361
366
  };
362
- if (options.debounce !== false) {
363
- _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
364
- } else {
367
+ if (options.debounce === false) {
365
368
  _fswatcher.on("all", onChange);
369
+ } else {
370
+ _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
366
371
  }
367
372
  const utils = {
368
373
  watchingFiles,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Smart Config Loader",
5
5
  "repository": "unjs/c12",
6
6
  "license": "MIT",
@@ -26,32 +26,32 @@
26
26
  "lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
27
27
  "prepack": "unbuild",
28
28
  "release": "changelogen --release && npm publish && git push --follow-tags",
29
- "test": "vitest run --coverage && pnpm test:types",
29
+ "test": "pnpm lint && vitest run --coverage && pnpm test:types",
30
30
  "test:types": "tsc --noEmit"
31
31
  },
32
32
  "dependencies": {
33
33
  "chokidar": "^3.5.3",
34
34
  "defu": "^6.1.2",
35
- "dotenv": "^16.0.3",
36
- "giget": "^1.1.2",
37
- "jiti": "^1.18.2",
38
- "mlly": "^1.2.0",
39
- "ohash": "^1.1.1",
40
- "pathe": "^1.1.0",
41
- "perfect-debounce": "^0.1.3",
42
- "pkg-types": "^1.0.2",
43
- "rc9": "^2.1.0"
35
+ "dotenv": "^16.3.1",
36
+ "giget": "^1.1.3",
37
+ "jiti": "^1.20.0",
38
+ "mlly": "^1.4.2",
39
+ "ohash": "^1.1.3",
40
+ "pathe": "^1.1.1",
41
+ "perfect-debounce": "^1.0.0",
42
+ "pkg-types": "^1.0.3",
43
+ "rc9": "^2.1.1"
44
44
  },
45
45
  "devDependencies": {
46
- "@vitest/coverage-c8": "^0.30.1",
47
- "changelogen": "^0.5.3",
48
- "eslint": "^8.38.0",
49
- "eslint-config-unjs": "^0.1.0",
50
- "expect-type": "^0.15.0",
51
- "prettier": "^2.8.7",
52
- "typescript": "^5.0.4",
53
- "unbuild": "^1.2.1",
54
- "vitest": "^0.30.1"
46
+ "@vitest/coverage-v8": "^0.34.6",
47
+ "changelogen": "^0.5.5",
48
+ "eslint": "^8.51.0",
49
+ "eslint-config-unjs": "^0.2.1",
50
+ "expect-type": "^0.17.3",
51
+ "prettier": "^3.0.3",
52
+ "typescript": "^5.2.2",
53
+ "unbuild": "^2.0.0",
54
+ "vitest": "^0.34.6"
55
55
  },
56
- "packageManager": "pnpm@8.3.0"
56
+ "packageManager": "pnpm@8.8.0"
57
57
  }