c12 3.3.1 → 3.3.2

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/index.mjs CHANGED
@@ -1,112 +1,419 @@
1
- import { l as loadConfig, S as SUPPORTED_EXTENSIONS } from './shared/c12.8GPsgFQh.mjs';
2
- export { a as loadDotenv, s as setupDotenv } from './shared/c12.8GPsgFQh.mjs';
3
- import { debounce } from 'perfect-debounce';
4
- import { resolve } from 'pathe';
5
- import 'node:fs';
6
- import 'node:fs/promises';
7
- import 'node:url';
8
- import 'node:os';
9
- import 'exsolve';
10
- import 'jiti';
11
- import 'rc9';
12
- import 'defu';
13
- import 'pkg-types';
14
- import 'dotenv';
1
+ import { existsSync, promises, statSync } from "node:fs";
2
+ import { basename, dirname, extname, join, normalize, resolve } from "pathe";
3
+ import * as dotenv from "dotenv";
4
+ import { readFile, rm } from "node:fs/promises";
5
+ import { pathToFileURL } from "node:url";
6
+ import { homedir } from "node:os";
7
+ import { resolveModulePath } from "exsolve";
8
+ import { createJiti } from "jiti";
9
+ import * as rc9 from "rc9";
10
+ import { defu } from "defu";
11
+ import { findWorkspaceDir, readPackageJSON } from "pkg-types";
12
+ import { debounce } from "perfect-debounce";
15
13
 
14
+ //#region src/dotenv.ts
15
+ /**
16
+ * Load and interpolate environment variables into `process.env`.
17
+ * If you need more control (or access to the values), consider using `loadDotenv` instead
18
+ *
19
+ */
20
+ async function setupDotenv(options) {
21
+ const targetEnvironment = options.env ?? process.env;
22
+ const environment = await loadDotenv({
23
+ cwd: options.cwd,
24
+ fileName: options.fileName ?? ".env",
25
+ env: targetEnvironment,
26
+ interpolate: options.interpolate ?? true
27
+ });
28
+ const dotenvVars = getDotEnvVars(targetEnvironment);
29
+ for (const key in environment) {
30
+ if (key.startsWith("_")) continue;
31
+ if (targetEnvironment[key] === void 0 || dotenvVars.has(key)) targetEnvironment[key] = environment[key];
32
+ }
33
+ return environment;
34
+ }
35
+ /** Load environment variables into an object. */
36
+ async function loadDotenv(options) {
37
+ const environment = Object.create(null);
38
+ const cwd = resolve(options.cwd || ".");
39
+ const _fileName = options.fileName || ".env";
40
+ const dotenvFiles = typeof _fileName === "string" ? [_fileName] : _fileName;
41
+ const dotenvVars = getDotEnvVars(options.env || {});
42
+ Object.assign(environment, options.env);
43
+ for (const file of dotenvFiles) {
44
+ const dotenvFile = resolve(cwd, file);
45
+ if (!statSync(dotenvFile, { throwIfNoEntry: false })?.isFile()) continue;
46
+ const parsed = dotenv.parse(await promises.readFile(dotenvFile, "utf8"));
47
+ for (const key in parsed) {
48
+ if (key in environment && !dotenvVars.has(key)) continue;
49
+ environment[key] = parsed[key];
50
+ dotenvVars.add(key);
51
+ }
52
+ }
53
+ if (options.interpolate) interpolate(environment);
54
+ return environment;
55
+ }
56
+ function interpolate(target, source = {}, parse = (v) => v) {
57
+ function getValue(key) {
58
+ return source[key] === void 0 ? target[key] : source[key];
59
+ }
60
+ function interpolate$1(value, parents = []) {
61
+ if (typeof value !== "string") return value;
62
+ return parse((value.match(/(.?\${?(?:[\w:]+)?}?)/g) || []).reduce((newValue, match) => {
63
+ const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || [];
64
+ const prefix = parts[1];
65
+ let value$1, replacePart;
66
+ if (prefix === "\\") {
67
+ replacePart = parts[0] || "";
68
+ value$1 = replacePart.replace(String.raw`\$`, "$");
69
+ } else {
70
+ const key = parts[2];
71
+ replacePart = (parts[0] || "").slice(prefix.length);
72
+ if (parents.includes(key)) {
73
+ console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`);
74
+ return "";
75
+ }
76
+ value$1 = getValue(key);
77
+ value$1 = interpolate$1(value$1, [...parents, key]);
78
+ }
79
+ return value$1 === void 0 ? newValue : newValue.replace(replacePart, value$1);
80
+ }, value));
81
+ }
82
+ for (const key in target) target[key] = interpolate$1(getValue(key));
83
+ }
84
+ function getDotEnvVars(targetEnvironment) {
85
+ const globalRegistry = globalThis.__c12_dotenv_vars__ ||= /* @__PURE__ */ new Map();
86
+ if (!globalRegistry.has(targetEnvironment)) globalRegistry.set(targetEnvironment, /* @__PURE__ */ new Set());
87
+ return globalRegistry.get(targetEnvironment);
88
+ }
89
+
90
+ //#endregion
91
+ //#region src/loader.ts
92
+ const _normalize = (p) => p?.replace(/\\/g, "/");
93
+ const ASYNC_LOADERS = {
94
+ ".yaml": () => import("confbox/yaml").then((r) => r.parseYAML),
95
+ ".yml": () => import("confbox/yaml").then((r) => r.parseYAML),
96
+ ".jsonc": () => import("confbox/jsonc").then((r) => r.parseJSONC),
97
+ ".json5": () => import("confbox/json5").then((r) => r.parseJSON5),
98
+ ".toml": () => import("confbox/toml").then((r) => r.parseTOML)
99
+ };
100
+ const SUPPORTED_EXTENSIONS = Object.freeze([
101
+ ".js",
102
+ ".ts",
103
+ ".mjs",
104
+ ".cjs",
105
+ ".mts",
106
+ ".cts",
107
+ ".json",
108
+ ".jsonc",
109
+ ".json5",
110
+ ".yaml",
111
+ ".yml",
112
+ ".toml"
113
+ ]);
114
+ async function loadConfig(options) {
115
+ options.cwd = resolve(process.cwd(), options.cwd || ".");
116
+ options.name = options.name || "config";
117
+ options.envName = options.envName ?? process.env.NODE_ENV;
118
+ options.configFile = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
119
+ options.rcFile = options.rcFile ?? `.${options.name}rc`;
120
+ if (options.extend !== false) options.extend = {
121
+ extendKey: "extends",
122
+ ...options.extend
123
+ };
124
+ const _merger = options.merger || defu;
125
+ options.jiti = options.jiti || createJiti(join(options.cwd, options.configFile), {
126
+ interopDefault: true,
127
+ moduleCache: false,
128
+ extensions: [...SUPPORTED_EXTENSIONS],
129
+ ...options.jitiOptions
130
+ });
131
+ const r = {
132
+ config: {},
133
+ cwd: options.cwd,
134
+ configFile: resolve(options.cwd, options.configFile),
135
+ layers: [],
136
+ _configFile: void 0
137
+ };
138
+ const rawConfigs = {
139
+ overrides: options.overrides,
140
+ main: void 0,
141
+ rc: void 0,
142
+ packageJson: void 0,
143
+ defaultConfig: options.defaultConfig
144
+ };
145
+ if (options.dotenv) await setupDotenv({
146
+ cwd: options.cwd,
147
+ ...options.dotenv === true ? {} : options.dotenv
148
+ });
149
+ const _mainConfig = await resolveConfig(".", options);
150
+ if (_mainConfig.configFile) {
151
+ rawConfigs.main = _mainConfig.config;
152
+ r.configFile = _mainConfig.configFile;
153
+ r._configFile = _mainConfig._configFile;
154
+ }
155
+ if (_mainConfig.meta) r.meta = _mainConfig.meta;
156
+ if (options.rcFile) {
157
+ const rcSources = [];
158
+ rcSources.push(rc9.read({
159
+ name: options.rcFile,
160
+ dir: options.cwd
161
+ }));
162
+ if (options.globalRc) {
163
+ const workspaceDir = await findWorkspaceDir(options.cwd).catch(() => {});
164
+ if (workspaceDir) rcSources.push(rc9.read({
165
+ name: options.rcFile,
166
+ dir: workspaceDir
167
+ }));
168
+ rcSources.push(rc9.readUser({
169
+ name: options.rcFile,
170
+ dir: options.cwd
171
+ }));
172
+ }
173
+ rawConfigs.rc = _merger({}, ...rcSources);
174
+ }
175
+ if (options.packageJson) {
176
+ const keys = (Array.isArray(options.packageJson) ? options.packageJson : [typeof options.packageJson === "string" ? options.packageJson : options.name]).filter((t) => t && typeof t === "string");
177
+ const pkgJsonFile = await readPackageJSON(options.cwd).catch(() => {});
178
+ rawConfigs.packageJson = _merger({}, ...keys.map((key) => pkgJsonFile?.[key]));
179
+ }
180
+ const configs = {};
181
+ for (const key in rawConfigs) {
182
+ const value = rawConfigs[key];
183
+ configs[key] = await (typeof value === "function" ? value({
184
+ configs,
185
+ rawConfigs
186
+ }) : value);
187
+ }
188
+ if (Array.isArray(configs.main)) r.config = configs.main;
189
+ else {
190
+ r.config = _merger(configs.overrides, configs.main, configs.rc, configs.packageJson, configs.defaultConfig);
191
+ if (options.extend) {
192
+ await extendConfig(r.config, options);
193
+ r.layers = r.config._layers;
194
+ delete r.config._layers;
195
+ r.config = _merger(r.config, ...r.layers.map((e) => e.config));
196
+ }
197
+ }
198
+ r.layers = [...[
199
+ configs.overrides && {
200
+ config: configs.overrides,
201
+ configFile: void 0,
202
+ cwd: void 0
203
+ },
204
+ {
205
+ config: configs.main,
206
+ configFile: options.configFile,
207
+ cwd: options.cwd
208
+ },
209
+ configs.rc && {
210
+ config: configs.rc,
211
+ configFile: options.rcFile
212
+ },
213
+ configs.packageJson && {
214
+ config: configs.packageJson,
215
+ configFile: "package.json"
216
+ }
217
+ ].filter((l) => l && l.config), ...r.layers];
218
+ if (options.defaults) r.config = _merger(r.config, options.defaults);
219
+ if (options.omit$Keys) {
220
+ for (const key in r.config) if (key.startsWith("$")) delete r.config[key];
221
+ }
222
+ if (options.configFileRequired && !r._configFile) throw new Error(`Required config (${r.configFile}) cannot be resolved.`);
223
+ return r;
224
+ }
225
+ async function extendConfig(config, options) {
226
+ config._layers = config._layers || [];
227
+ if (!options.extend) return;
228
+ let keys = options.extend.extendKey;
229
+ if (typeof keys === "string") keys = [keys];
230
+ const extendSources = [];
231
+ for (const key of keys) {
232
+ extendSources.push(...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(Boolean));
233
+ delete config[key];
234
+ }
235
+ for (let extendSource of extendSources) {
236
+ const originalExtendSource = extendSource;
237
+ let sourceOptions = {};
238
+ if (extendSource.source) {
239
+ sourceOptions = extendSource.options || {};
240
+ extendSource = extendSource.source;
241
+ }
242
+ if (Array.isArray(extendSource)) {
243
+ sourceOptions = extendSource[1] || {};
244
+ extendSource = extendSource[0];
245
+ }
246
+ if (typeof extendSource !== "string") {
247
+ console.warn(`Cannot extend config from \`${JSON.stringify(originalExtendSource)}\` in ${options.cwd}`);
248
+ continue;
249
+ }
250
+ const _config = await resolveConfig(extendSource, options, sourceOptions);
251
+ if (!_config.config) {
252
+ console.warn(`Cannot extend config from \`${extendSource}\` in ${options.cwd}`);
253
+ continue;
254
+ }
255
+ await extendConfig(_config.config, {
256
+ ...options,
257
+ cwd: _config.cwd
258
+ });
259
+ config._layers.push(_config);
260
+ if (_config.config._layers) {
261
+ config._layers.push(..._config.config._layers);
262
+ delete _config.config._layers;
263
+ }
264
+ }
265
+ }
266
+ const GIGET_PREFIXES = [
267
+ "gh:",
268
+ "github:",
269
+ "gitlab:",
270
+ "bitbucket:",
271
+ "https://",
272
+ "http://"
273
+ ];
274
+ const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
275
+ async function resolveConfig(source, options, sourceOptions = {}) {
276
+ if (options.resolve) {
277
+ const res$1 = await options.resolve(source, options);
278
+ if (res$1) return res$1;
279
+ }
280
+ const _merger = options.merger || defu;
281
+ const customProviderKeys = Object.keys(sourceOptions.giget?.providers || {}).map((key) => `${key}:`);
282
+ const gigetPrefixes = customProviderKeys.length > 0 ? [...new Set([...customProviderKeys, ...GIGET_PREFIXES])] : GIGET_PREFIXES;
283
+ if (options.giget !== false && gigetPrefixes.some((prefix) => source.startsWith(prefix))) {
284
+ const { downloadTemplate } = await import("giget");
285
+ const { digest } = await import("ohash");
286
+ const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + digest(source).slice(0, 10).replace(/[-_]/g, "");
287
+ let cloneDir;
288
+ const localNodeModules = resolve(options.cwd, "node_modules");
289
+ const parentDir = dirname(options.cwd);
290
+ if (basename(parentDir) === ".c12") cloneDir = join(parentDir, cloneName);
291
+ else if (existsSync(localNodeModules)) cloneDir = join(localNodeModules, ".c12", cloneName);
292
+ else cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : resolve(homedir(), ".cache/c12", cloneName);
293
+ if (existsSync(cloneDir) && !sourceOptions.install) await rm(cloneDir, { recursive: true });
294
+ source = (await downloadTemplate(source, {
295
+ dir: cloneDir,
296
+ install: sourceOptions.install,
297
+ force: sourceOptions.install,
298
+ auth: sourceOptions.auth,
299
+ ...options.giget,
300
+ ...sourceOptions.giget
301
+ })).dir;
302
+ }
303
+ if (NPM_PACKAGE_RE.test(source)) source = tryResolve(source, options) || source;
304
+ const ext = extname(source);
305
+ const isDir = !ext || ext === basename(source);
306
+ const cwd = resolve(options.cwd, isDir ? source : dirname(source));
307
+ if (isDir) source = options.configFile;
308
+ const res = {
309
+ config: void 0,
310
+ configFile: void 0,
311
+ cwd,
312
+ source,
313
+ sourceOptions
314
+ };
315
+ res.configFile = tryResolve(resolve(cwd, source), options) || tryResolve(resolve(cwd, ".config", source.replace(/\.config$/, "")), options) || tryResolve(resolve(cwd, ".config", source), options) || source;
316
+ if (!existsSync(res.configFile)) return res;
317
+ res._configFile = res.configFile;
318
+ const configFileExt = extname(res.configFile) || "";
319
+ if (configFileExt in ASYNC_LOADERS) res.config = (await ASYNC_LOADERS[configFileExt]())(await readFile(res.configFile, "utf8"));
320
+ else res.config = await options.jiti.import(res.configFile, { default: true });
321
+ if (typeof res.config === "function") res.config = await res.config(options.context);
322
+ if (options.envName) {
323
+ const envConfig = {
324
+ ...res.config["$" + options.envName],
325
+ ...res.config.$env?.[options.envName]
326
+ };
327
+ if (Object.keys(envConfig).length > 0) res.config = _merger(envConfig, res.config);
328
+ }
329
+ res.meta = defu(res.sourceOptions.meta, res.config.$meta);
330
+ delete res.config.$meta;
331
+ if (res.sourceOptions.overrides) res.config = _merger(res.sourceOptions.overrides, res.config);
332
+ res.configFile = _normalize(res.configFile);
333
+ res.source = _normalize(res.source);
334
+ return res;
335
+ }
336
+ function tryResolve(id, options) {
337
+ const res = resolveModulePath(id, {
338
+ try: true,
339
+ from: pathToFileURL(join(options.cwd || ".", options.configFile || "/")),
340
+ suffixes: ["", "/index"],
341
+ extensions: SUPPORTED_EXTENSIONS,
342
+ cache: false
343
+ });
344
+ return res ? normalize(res) : void 0;
345
+ }
346
+
347
+ //#endregion
348
+ //#region src/types.ts
16
349
  function createDefineConfig() {
17
- return (input) => input;
350
+ return (input) => input;
18
351
  }
19
352
 
353
+ //#endregion
354
+ //#region src/watch.ts
20
355
  const eventMap = {
21
- add: "created",
22
- change: "updated",
23
- unlink: "removed"
356
+ add: "created",
357
+ change: "updated",
358
+ unlink: "removed"
24
359
  };
25
360
  async function watchConfig(options) {
26
- let config = await loadConfig(options);
27
- const configName = options.name || "config";
28
- const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
29
- const watchingFiles = [
30
- ...new Set(
31
- (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
32
- ...SUPPORTED_EXTENSIONS.flatMap((ext) => [
33
- resolve(l.cwd, configFileName + ext),
34
- resolve(l.cwd, ".config", configFileName + ext),
35
- resolve(
36
- l.cwd,
37
- ".config",
38
- configFileName.replace(/\.config$/, "") + ext
39
- )
40
- ]),
41
- l.source && resolve(l.cwd, l.source),
42
- // TODO: Support watching rc from home and workspace
43
- options.rcFile && resolve(
44
- l.cwd,
45
- typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`
46
- ),
47
- options.packageJson && resolve(l.cwd, "package.json")
48
- ]).filter(Boolean)
49
- )
50
- ];
51
- const watch = await import('chokidar').then((r) => r.watch || r.default || r);
52
- const { diff } = await import('ohash/utils');
53
- const _fswatcher = watch(watchingFiles, {
54
- ignoreInitial: true,
55
- ...options.chokidarOptions
56
- });
57
- const onChange = async (event, path) => {
58
- const type = eventMap[event];
59
- if (!type) {
60
- return;
61
- }
62
- if (options.onWatch) {
63
- await options.onWatch({
64
- type,
65
- path
66
- });
67
- }
68
- const oldConfig = config;
69
- try {
70
- config = await loadConfig(options);
71
- } catch (error) {
72
- console.warn(`Failed to load config ${path}
73
- ${error}`);
74
- return;
75
- }
76
- const changeCtx = {
77
- newConfig: config,
78
- oldConfig,
79
- getDiff: () => diff(oldConfig.config, config.config)
80
- };
81
- if (options.acceptHMR) {
82
- const changeHandled = await options.acceptHMR(changeCtx);
83
- if (changeHandled) {
84
- return;
85
- }
86
- }
87
- if (options.onUpdate) {
88
- await options.onUpdate(changeCtx);
89
- }
90
- };
91
- if (options.debounce === false) {
92
- _fswatcher.on("all", onChange);
93
- } else {
94
- _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
95
- }
96
- const utils = {
97
- watchingFiles,
98
- unwatch: async () => {
99
- await _fswatcher.close();
100
- }
101
- };
102
- return new Proxy(utils, {
103
- get(_, prop) {
104
- if (prop in utils) {
105
- return utils[prop];
106
- }
107
- return config[prop];
108
- }
109
- });
361
+ let config = await loadConfig(options);
362
+ const configName = options.name || "config";
363
+ const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
364
+ const watchingFiles = [...new Set((config.layers || []).filter((l) => l.cwd).flatMap((l) => [
365
+ ...SUPPORTED_EXTENSIONS.flatMap((ext) => [
366
+ resolve(l.cwd, configFileName + ext),
367
+ resolve(l.cwd, ".config", configFileName + ext),
368
+ resolve(l.cwd, ".config", configFileName.replace(/\.config$/, "") + ext)
369
+ ]),
370
+ l.source && resolve(l.cwd, l.source),
371
+ options.rcFile && resolve(l.cwd, typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`),
372
+ options.packageJson && resolve(l.cwd, "package.json")
373
+ ]).filter(Boolean))];
374
+ const watch = await import("chokidar").then((r) => r.watch || r.default || r);
375
+ const { diff } = await import("ohash/utils");
376
+ const _fswatcher = watch(watchingFiles, {
377
+ ignoreInitial: true,
378
+ ...options.chokidarOptions
379
+ });
380
+ const onChange = async (event, path) => {
381
+ const type = eventMap[event];
382
+ if (!type) return;
383
+ if (options.onWatch) await options.onWatch({
384
+ type,
385
+ path
386
+ });
387
+ const oldConfig = config;
388
+ try {
389
+ config = await loadConfig(options);
390
+ } catch (error) {
391
+ console.warn(`Failed to load config ${path}\n${error}`);
392
+ return;
393
+ }
394
+ const changeCtx = {
395
+ newConfig: config,
396
+ oldConfig,
397
+ getDiff: () => diff(oldConfig.config, config.config)
398
+ };
399
+ if (options.acceptHMR) {
400
+ if (await options.acceptHMR(changeCtx)) return;
401
+ }
402
+ if (options.onUpdate) await options.onUpdate(changeCtx);
403
+ };
404
+ if (options.debounce === false) _fswatcher.on("all", onChange);
405
+ else _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
406
+ const utils = {
407
+ watchingFiles,
408
+ unwatch: async () => {
409
+ await _fswatcher.close();
410
+ }
411
+ };
412
+ return new Proxy(utils, { get(_, prop) {
413
+ if (prop in utils) return utils[prop];
414
+ return config[prop];
415
+ } });
110
416
  }
111
417
 
112
- export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, watchConfig };
418
+ //#endregion
419
+ export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/update.d.mts CHANGED
@@ -1,53 +1,53 @@
1
- import * as magicast from 'magicast';
1
+ import * as magicast0 from "magicast";
2
2
 
3
+ //#region src/update.d.ts
3
4
  /**
4
5
  * @experimental Update a config file or create a new one.
5
6
  */
6
7
  declare function updateConfig(opts: UpdateConfigOptions): Promise<UpdateConfigResult>;
7
8
  interface UpdateConfigResult {
8
- configFile?: string;
9
- created?: boolean;
9
+ configFile?: string;
10
+ created?: boolean;
10
11
  }
11
12
  type MaybePromise<T> = T | Promise<T>;
12
- type MagicAstOptions = Exclude<Parameters<(typeof magicast)["parseModule"]>[1], undefined>;
13
+ type MagicAstOptions = Exclude<Parameters<(typeof magicast0)["parseModule"]>[1], undefined>;
13
14
  interface UpdateConfigOptions {
14
- /**
15
- * Current working directory
16
- */
17
- cwd: string;
18
- /**
19
- * Config file name
20
- */
15
+ /**
16
+ * Current working directory
17
+ */
18
+ cwd: string;
19
+ /**
20
+ * Config file name
21
+ */
22
+ configFile: string;
23
+ /**
24
+ * Extension used for new config file.
25
+ */
26
+ createExtension?: string;
27
+ /**
28
+ * Magicast options
29
+ */
30
+ magicast?: MagicAstOptions;
31
+ /**
32
+ * Update function.
33
+ */
34
+ onUpdate?: (config: any) => MaybePromise<void>;
35
+ /**
36
+ * Handle default config creation.
37
+ *
38
+ * Tip: you can use this option as a hook to prompt users about config creation.
39
+ *
40
+ * Context object:
41
+ * - path: determined full path to the config file
42
+ *
43
+ * Returns types:
44
+ * - string: custom config template
45
+ * - true: write the template
46
+ * - false: abort the operation
47
+ */
48
+ onCreate?: (ctx: {
21
49
  configFile: string;
22
- /**
23
- * Extension used for new config file.
24
- */
25
- createExtension?: string;
26
- /**
27
- * Magicast options
28
- */
29
- magicast?: MagicAstOptions;
30
- /**
31
- * Update function.
32
- */
33
- onUpdate?: (config: any) => MaybePromise<void>;
34
- /**
35
- * Handle default config creation.
36
- *
37
- * Tip: you can use this option as a hook to prompt users about config creation.
38
- *
39
- * Context object:
40
- * - path: determined full path to the config file
41
- *
42
- * Returns types:
43
- * - string: custom config template
44
- * - true: write the template
45
- * - false: abort the operation
46
- */
47
- onCreate?: (ctx: {
48
- configFile: string;
49
- }) => MaybePromise<string | boolean>;
50
+ }) => MaybePromise<string | boolean>;
50
51
  }
51
-
52
- export { updateConfig };
53
- export type { UpdateConfigOptions, UpdateConfigResult };
52
+ //#endregion
53
+ export { UpdateConfigOptions, UpdateConfigResult, updateConfig };