Add internationalization support with astro-i18next integration
- Implemented astro-i18next for multi-language support, including English, Dutch, and Italian. - Configured default locale and language fallback settings. - Defined routes for localized content in the configuration. - Updated package.json and package-lock.json to include new dependencies for i18next and related plugins.
This commit is contained in:
91
node_modules/@proload/core/CHANGELOG.md
generated
vendored
Normal file
91
node_modules/@proload/core/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
# Changelog
|
||||
|
||||
## 0.3.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0133f2a: Fix: make ESM parse errors catch-able
|
||||
|
||||
## 0.3.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- a3046e3: Fix bug introduced by supporting empty config files
|
||||
|
||||
## 0.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5c011e2: Update types to expose `resolve`
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- ddce5c6: Improve `extends` behavior related to dependencies
|
||||
- a93907f: Add `resolve` export
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4c7215e: Improve handling when matched file is empty
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 910284a: Fix transform hook bug
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0eb82f0: Adds the `filePath` option, which supports loading a config file from a user-specified input path
|
||||
- 806cfa6: Fix Windows compatability issue
|
||||
|
||||
## v0.2.0
|
||||
|
||||
**Features**
|
||||
|
||||
- Introduce the `mustExist` flag, which controls Proload's behavior when a configuration is not found.
|
||||
- Introduce the `ProloadError` class export, which can be used in `instanceof` checks to determine if an Error is coming from Proload internals or somewhere else.
|
||||
|
||||
**Docs**
|
||||
|
||||
- Document the `mustExist` flag
|
||||
|
||||
## v0.1.4
|
||||
|
||||
**Fixes**
|
||||
|
||||
- Do not attempt to resolve "extends" for unrecognized formats.
|
||||
|
||||
## v0.1.3
|
||||
|
||||
**Fixes**
|
||||
|
||||
- Improves accuracy of TypeScript declarations for CJS entrypoint.
|
||||
|
||||
**Docs**
|
||||
|
||||
- Added inline documentation to the TypeScript declarations.
|
||||
|
||||
## v0.1.2
|
||||
|
||||
**Chores**
|
||||
|
||||
- Exclude `test` files from package
|
||||
|
||||
## v0.1.1
|
||||
|
||||
**Added**
|
||||
|
||||
- Custom `accept` handler exposes complete control over resolution logic
|
||||
|
||||
**Docs**
|
||||
|
||||
- Added examples and more detail to README
|
||||
- Added docs on `accept` handler
|
||||
|
||||
## v0.1.0
|
||||
|
||||
Initial release
|
333
node_modules/@proload/core/README.md
generated
vendored
Normal file
333
node_modules/@proload/core/README.md
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
# `@proload/core`
|
||||
|
||||
Proload searches for and loads your tool's JavaScript configuration files. Users have complex expectations when it comes to configuration files—the goal of Proload is to offer a single, straightforward and extensible API for loading them.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
> `@proload/core` can be used in `node@12.20.1` and up. It relies on Node's native ESM semantics.
|
||||
|
||||
## Motivation
|
||||
|
||||
Configuration files are really difficult to get right. Tool authors tend to think, "Easy solve! I'll just have everyone use one `namespace.config.js`!" In most cases that should work, but since `node@12.17.0`, plain `.js` files can be written in either ESM or CJS—both formats are officially supported and can be configured on a per-project basis. Additionally, `node` is able to load any file using a `.cjs` or `.mjs` extension, not just `.js`.
|
||||
|
||||
Many popular libraries get these semantics wrong, but maintaining and testing this resolution logic in library code can be a huge maintanence burden. As a library author, you don't need to know (or care) which module format your users choose—you just need to load the contents of the config file. `@proload/core` is a well-tested solution that gets these semantics right, so you can focus on more important things.
|
||||
|
||||
> You probably have TypeScript users, too! They would definitely appreciate being able to write a `.ts` config file. `@proload/core` uses a plugin system to load non-JavaScript files. See [Plugins](https://github.com/natemoo-re/proload/tree/main/packages/core#plugins) or [`@proload/plugin-typescript`](https://github.com/natemoo-re/proload/tree/main/packages/core#typescript) specifically.
|
||||
|
||||
## Resolution
|
||||
|
||||
Out of the box, `@proload/core` searches up the directory tree for the following files:
|
||||
|
||||
- a `[namespace].config.js`, `[namespace].config.cjs`, or `[namespace].config.mjs` file
|
||||
- any of the `js/cjs/mjs` files inside of `config/` directory
|
||||
- a `package.json` file with a top-level `[namespace]` key
|
||||
|
||||
|
||||
Here's an overview of all the files supported by default for a tool named `donut`.
|
||||
|
||||
```
|
||||
await load('donut');
|
||||
|
||||
.
|
||||
├── donut.config.js // Either ESM or CJS supported
|
||||
├── donut.config.cjs
|
||||
├── donut.config.mjs
|
||||
├── config/ // Great for organizing many configs
|
||||
│ ├── donut.config.js
|
||||
│ ├── donut.config.cjs
|
||||
│ └── donut.config.mjs
|
||||
└── package.json // with top-level "donut" property
|
||||
```
|
||||
|
||||
## `resolve`
|
||||
|
||||
`resolve` is an additional named export of `@proload/core`. It is an `async` function that resolves **but does not load** a configuration file.
|
||||
|
||||
- `namespace` is the name of your tool. As an example, `donut` would search for `donut.config.[ext]`.
|
||||
- `opts` configure the behavior of `load`. See [Options](https://github.com/natemoo-re/proload/tree/main/packages/core#options).
|
||||
|
||||
```ts
|
||||
resolve(namespace: string, opts?: ResolveOptions);
|
||||
```
|
||||
|
||||
## `load`
|
||||
|
||||
The `default` export of `@proload/core` is an `async` function to load a configuration file.
|
||||
|
||||
- `namespace` is the name of your tool. As an example, `donut` would search for `donut.config.[ext]`.
|
||||
- `opts` configure the behavior of `load`. See [Options](https://github.com/natemoo-re/proload/tree/main/packages/core#options).
|
||||
|
||||
```ts
|
||||
load(namespace: string, opts?: LoadOptions);
|
||||
```
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### cwd
|
||||
`load` searches up the directory tree, beginning from this loaction. Defaults to `process.cwd()`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
await load('namespace', { cwd: '/path/to/user/project' });
|
||||
```
|
||||
|
||||
### filePath
|
||||
If you already have the exact (absolute or relative) `filePath` of your user's config file, set the `filePath` option to disable Proload's search algorithm.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
await load('namespace', { cwd: '/path/to/user/project', filePath: './custom-user-config.js' });
|
||||
```
|
||||
|
||||
### mustExist
|
||||
`mustExist` controls whether a configuration _must_ be found. Defaults to `true`—Proload will throw an error when a configuration is not found. To customize error handling, you may check the shape of the thrown error.
|
||||
|
||||
Setting this option to `false` allows a return value of `undefined` when a configuration is not found.
|
||||
|
||||
```js
|
||||
import load, { ProloadError } from '@proload/core';
|
||||
|
||||
try {
|
||||
await load('namespace', { mustExist: true });
|
||||
} catch (err) {
|
||||
// Proload couldn't resolve a configuration, log a custom contextual error
|
||||
if (err instanceof ProloadError && err.code === 'ERR_PROLOAD_NOT_FOUND') {
|
||||
console.error(`See the "namespace" docs for configuration info`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
```
|
||||
|
||||
### context
|
||||
|
||||
Users may want to dynamically generate a different configuration based on some contextual information passed from your tool. Any `{ context }` passed to the `load` function will be forwarded to configuration "factory" functions.
|
||||
|
||||
```js
|
||||
// Library code
|
||||
import load from '@proload/core';
|
||||
await load('namespace', { context: { isDev: true }});
|
||||
|
||||
// namespace.config.js
|
||||
export default ({ isDev }) => {
|
||||
return { featureFlag: isDev }
|
||||
}
|
||||
```
|
||||
|
||||
### accept
|
||||
If you need complete control over which file to load, the `accept` handler can customize resolution behavior. A return value of `true` marks a file to be loaded, any other return values (even truthy ones) is ignored.
|
||||
|
||||
See the [`accept`](https://github.com/natemoo-re/proload/blob/34413acf87d98d3ef310ce2873103455cb2eb379/packages/core/lib/index.d.ts#L11) interface.
|
||||
|
||||
> Note that [Plugins](https://github.com/natemoo-re/proload/tree/main/packages/core#plugins) are able to modify similar behavior. To load non-JavaScript files, you should use a plugin instead of `accept`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
|
||||
await load('donut', {
|
||||
accept(fileName) {
|
||||
// Support alternative spelling for any European friends
|
||||
return fileName.startsWith('doughnut.config');
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The following example uses `@proload/plugin-typescript` to add support for loading `.ts` files and an `accept` handler to require all config files to use the `.ts` extension.
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import typescript from '@proload/plugin-typescript';
|
||||
|
||||
load.use([typescript]);
|
||||
await load('namespace', {
|
||||
accept(fileName) {
|
||||
// Only accept `.ts` config files
|
||||
return fileName.endsWith('.ts');
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### merge
|
||||
|
||||
To customize `extends` behavior, you may pass a custom `merge` function to the `load` function. By default, [`deepmerge`](https://github.com/TehShrike/deepmerge) is used.
|
||||
|
||||
```js
|
||||
// Library code
|
||||
import load from '@proload/core';
|
||||
|
||||
const shallowMerge = (a, b) => ({ ...a, ...b })
|
||||
await load('namespace', { merge: shallowMerge });
|
||||
|
||||
// namespace.config.js
|
||||
export default {
|
||||
extends: ['./a.js', './b.js']
|
||||
}
|
||||
|
||||
// a.js
|
||||
export default {
|
||||
a: true
|
||||
}
|
||||
|
||||
// b.js
|
||||
export default {
|
||||
b: true
|
||||
}
|
||||
|
||||
// result
|
||||
{
|
||||
a: true,
|
||||
b: true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Automatic `extends`
|
||||
|
||||
Tools like `typescript` and `babel` have popularized the ability to share configuration presets through a top-level `extends` clause. `extends` also allows you to share a local base configuration with other packages, which is extremely useful for monorepo users.
|
||||
|
||||
Custom implementation of this behavior can be difficult, so `@proload/core` automatically recognizes top-level `extends` clauses (`string[]`) for you. It recursively resolves and merges all dependent configurations.
|
||||
|
||||
```js
|
||||
// namespace.config.js
|
||||
export default {
|
||||
extends: ['@namespace/preset', '../namespace.base.config.js']
|
||||
}
|
||||
```
|
||||
|
||||
### Extending local configuration files
|
||||
In many cases, particularly in monorepos, it's useful to have a base configuration file and use `extends` in any sub-packages to inherit the base configuration. `@proload/core` resolves paths in `extends` relative to the configuration file itself.
|
||||
|
||||
```
|
||||
.
|
||||
├── namespace.base.config.js
|
||||
└── packages/
|
||||
├── package-a/
|
||||
│ └── namespace.config.js
|
||||
└── package-b/
|
||||
└── namespace.config.js
|
||||
```
|
||||
|
||||
### Extending configuration presets
|
||||
`@proload/core` uses the same strategy to resolve a configuration file from project `dependencies` as it does for user configurations. When publishing a configuration preset, use the same file naming strategy as you would for local configuration.
|
||||
|
||||
```
|
||||
.
|
||||
├── node_modules/
|
||||
│ └── @namespace/
|
||||
│ └── preset-env/
|
||||
│ ├── package.json
|
||||
│ └── namespace.config.js
|
||||
├── package.json
|
||||
└── namespace.config.js
|
||||
```
|
||||
|
||||
Assuming `@namespace/preset-env` is a project dependency, the top-level `namespace.config.js` file can use `extends` to reference the dependency.
|
||||
|
||||
```js
|
||||
export default {
|
||||
extends: ['@namespace/preset-env']
|
||||
}
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
In order to support as many use cases as possible, `@proload/core` uses a plugin system. Plugins build on each other and are designed to be combined. For example, to support a `namespacerc.json` file, you could use both `@proload/plugin-json` and `@proload/plugin-rc`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import rc from '@proload/plugin-rc';
|
||||
import json from '@proload/plugin-json';
|
||||
|
||||
load.use([rc, json]);
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
In order to load a `[namespace].config.ts` file, use `@proload/plugin-typescript`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import typescript from '@proload/plugin-typescript';
|
||||
|
||||
load.use([typescript]);
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
### JSON
|
||||
In order to load a `[namespace].config.json` file, use `@proload/plugin-json`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import json from '@proload/plugin-json';
|
||||
|
||||
load.use([json]);
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
### YAML
|
||||
In order to load a `[namespace].config.yaml` or `[namespace].config.yml` file, use `@proload/plugin-yaml`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import yaml from '@proload/plugin-yaml';
|
||||
|
||||
load.use([yaml]);
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
### RC files
|
||||
In order to load a `[namespace]rc` file with any extension, use `@proload/plugin-rc`.
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import rc from '@proload/plugin-rc';
|
||||
|
||||
load.use([rc]);
|
||||
await load('namespace');
|
||||
```
|
||||
|
||||
### All Plugins
|
||||
For illustrative purposes (please don't do this), combining all of these plugins would support the following resolution logic:
|
||||
|
||||
```
|
||||
.
|
||||
├── namespace.config.js
|
||||
├── namespace.config.cjs
|
||||
├── namespace.config.mjs
|
||||
├── namespace.config.ts
|
||||
├── namespace.config.json
|
||||
├── namespace.config.yaml
|
||||
├── namespace.config.yml
|
||||
├── namespacerc.js
|
||||
├── namespacerc.cjs
|
||||
├── namespacerc.mjs
|
||||
├── namespacerc.ts
|
||||
├── namespacerc.json
|
||||
├── namespacerc.yaml
|
||||
├── namespacerc.yml
|
||||
├── config/
|
||||
│ ├── namespace.config.js
|
||||
│ ├── namespace.config.cjs
|
||||
│ ├── namespace.config.mjs
|
||||
│ ├── namespace.config.ts
|
||||
│ ├── namespace.config.json
|
||||
│ ├── namespace.config.yaml
|
||||
│ ├── namespace.config.yml
|
||||
│ ├── namespacerc.js
|
||||
│ ├── namespacerc.cjs
|
||||
│ ├── namespacerc.mjs
|
||||
│ ├── namespacerc.ts
|
||||
│ ├── namespacerc.json
|
||||
│ ├── namespacerc.yaml
|
||||
│ └── namespacerc.yml
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Proload is heavily inspired by tools like [`cosmiconfig`](https://github.com/davidtheclark/cosmiconfig#readme) and [`rc`](https://github.com/dominictarr/rc).
|
||||
|
||||
Proload would not be possible without [@lukeed](https://github.com/lukeed)'s amazing work on [`escalade`](https://github.com/lukeed/escalade) and [`uvu`](https://github.com/lukeed/uvu).
|
8
node_modules/@proload/core/lib/cjs/index.cjs
generated
vendored
Normal file
8
node_modules/@proload/core/lib/cjs/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const { ProloadError } = require('../error.cjs');
|
||||
function load(...args) {
|
||||
return import('../esm/index.mjs').then(({ default: loader }) => loader(...args));
|
||||
}
|
||||
|
||||
load.default = load;
|
||||
load.ProloadError = ProloadError;
|
||||
module.exports = load;
|
25
node_modules/@proload/core/lib/error.cjs
generated
vendored
Normal file
25
node_modules/@proload/core/lib/error.cjs
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @type import('./error.cjs').ProloadError
|
||||
*/
|
||||
class ProloadError extends Error {
|
||||
constructor(opts={}) {
|
||||
super(opts.message);
|
||||
this.name = 'ProloadError';
|
||||
this.code = opts.code || 'ERR_PROLOAD_INVALID';
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type import('./error.cjs').assert
|
||||
*/
|
||||
function assert(bool, message, code) {
|
||||
if (bool) return;
|
||||
if (message instanceof Error) throw message;
|
||||
throw new ProloadError({ message, code });
|
||||
}
|
||||
|
||||
module.exports.ProloadError = ProloadError;
|
||||
module.exports.assert = assert;
|
15
node_modules/@proload/core/lib/error.cjs.d.ts
generated
vendored
Normal file
15
node_modules/@proload/core/lib/error.cjs.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export type Message = string | Error;
|
||||
|
||||
export type PROLOAD_ERROR_CODE = 'ERR_PROLOAD_INVALID' | 'ERR_PROLOAD_NOT_FOUND';
|
||||
|
||||
export class ProloadError extends Error {
|
||||
name: 'ProloadError';
|
||||
code: PROLOAD_ERROR_CODE;
|
||||
message: string;
|
||||
constructor(options?: {
|
||||
message: string;
|
||||
code?: string
|
||||
});
|
||||
}
|
||||
|
||||
export function assert(condition: boolean, message: Message, code?: PROLOAD_ERROR_CODE): asserts condition;
|
284
node_modules/@proload/core/lib/esm/index.mjs
generated
vendored
Normal file
284
node_modules/@proload/core/lib/esm/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
import escalade from "escalade";
|
||||
import { join, dirname, extname, resolve } from "path";
|
||||
import deepmerge from "deepmerge";
|
||||
|
||||
import { existsSync, readdir, readFile, stat } from "fs";
|
||||
import { promisify } from "util";
|
||||
import { createRequire } from "module";
|
||||
import requireOrImport from "./requireOrImport.mjs";
|
||||
import { assert, ProloadError } from "../error.cjs";
|
||||
|
||||
export { ProloadError };
|
||||
|
||||
const toStats = promisify(stat);
|
||||
const toRead = promisify(readdir);
|
||||
const toReadFile = promisify(readFile);
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
let merge = deepmerge;
|
||||
const defaultExtensions = ['js', 'cjs', 'mjs'];
|
||||
const defaultFileNames = ['[name].config'];
|
||||
|
||||
const validNames = (namespace) => {
|
||||
const extensionPlugins = load.plugins.filter(p => Array.isArray(p.extensions));
|
||||
const fileNamePlugins = load.plugins.filter(p => Array.isArray(p.fileNames));
|
||||
const validExtensions = [...defaultExtensions].concat(...extensionPlugins.map(p => p.extensions));
|
||||
const validFileNames = [...defaultFileNames].concat(...fileNamePlugins.map(p => p.fileNames));
|
||||
|
||||
const result = validFileNames
|
||||
.map(fileName => fileName.replace('[name]', namespace))
|
||||
.reduce((acc, fileName) => {
|
||||
return [...acc].concat(...validExtensions.map(ext => `${fileName}${ext ? '.' + ext.replace(/^\./, '') : ''}`))
|
||||
}, []);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} val
|
||||
* @returns {val is Record<any, any>}
|
||||
*/
|
||||
const isObject = (val) =>
|
||||
val != null && typeof val === "object" && Array.isArray(val) === false;
|
||||
|
||||
const requireOrImportWithMiddleware = (filePath) => {
|
||||
let registerPlugins = load.plugins.filter(
|
||||
(plugin) => typeof plugin.register !== "undefined"
|
||||
);
|
||||
let transformPlugins = load.plugins.filter(
|
||||
(plugin) => typeof plugin.transform !== "undefined"
|
||||
);
|
||||
return requireOrImport(filePath, { middleware: registerPlugins }).then(
|
||||
async (mdl) => Promise.all(
|
||||
transformPlugins.map((plugin) => {
|
||||
return Promise.resolve(plugin.transform(mdl)).then((result) => {
|
||||
if (result) mdl = result;
|
||||
});
|
||||
})
|
||||
).then(() => mdl)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} namespace
|
||||
* @param {{ filePath: string, extension: string }} opts
|
||||
* @returns {Promise<{ filePath: string, value: string }>}
|
||||
*/
|
||||
async function resolveExtension(namespace, { filePath, extension }) {
|
||||
let resolvedPath;
|
||||
if (extension.startsWith("./") || extension.startsWith("../")) {
|
||||
if (extname(extension) === "") {
|
||||
resolvedPath = resolve(
|
||||
dirname(filePath),
|
||||
`${extension}${extname(filePath)}`
|
||||
);
|
||||
}
|
||||
if (!existsSync(resolvedPath)) resolvedPath = null;
|
||||
|
||||
if (!resolvedPath) {
|
||||
resolvedPath = resolve(dirname(filePath), extension);
|
||||
}
|
||||
if (!existsSync(resolvedPath)) resolvedPath = null;
|
||||
}
|
||||
if (!resolvedPath) {
|
||||
const pkg = require.resolve(extension, {
|
||||
cwd: dirname(filePath),
|
||||
});
|
||||
const accepted = validNames(namespace);
|
||||
for (const config of accepted) {
|
||||
try {
|
||||
resolvedPath = `${pkg}/${config}`;
|
||||
if (resolvedPath && existsSync(resolvedPath)) {
|
||||
break;
|
||||
} else {
|
||||
resolvedPath = null
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
if (!resolvedPath) {
|
||||
resolvedPath = require.resolve(extension, { cwd: dirname(filePath) });
|
||||
}
|
||||
if (!resolvedPath) return
|
||||
const value = await requireOrImportWithMiddleware(resolvedPath);
|
||||
|
||||
return { filePath: resolvedPath, value };
|
||||
}
|
||||
|
||||
async function resolveExtensions(
|
||||
namespace,
|
||||
{ filePath, value: raw, context },
|
||||
acc = {}
|
||||
) {
|
||||
let value = typeof raw === "function" ? await raw(context) : raw;
|
||||
if (Array.isArray(value)) return value;
|
||||
|
||||
assert(
|
||||
isObject(value),
|
||||
`${namespace} configuration expects an "object" but encountered ${value}`
|
||||
);
|
||||
acc = merge(acc, value);
|
||||
if (!("extends" in value)) return acc;
|
||||
|
||||
assert(
|
||||
Array.isArray(value.extends),
|
||||
`${namespace} "extends" must be an array`
|
||||
);
|
||||
|
||||
const configs = await Promise.all(
|
||||
value.extends.map((extension) =>
|
||||
resolveExtension(namespace, { filePath, extension }).then((config) =>
|
||||
resolveExtensions(namespace, { ...config, context }, acc)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
for (const config of configs) {
|
||||
acc = merge(acc, config);
|
||||
}
|
||||
|
||||
delete acc.extends;
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} namespace
|
||||
* @param {import('../index').LoadOptions} opts
|
||||
*/
|
||||
async function resolveConfig(namespace, opts = {}) {
|
||||
const accepted = validNames(namespace);
|
||||
const { context, accept } = opts;
|
||||
const input = opts.cwd || process.cwd();
|
||||
|
||||
let mustExist = true;
|
||||
if (typeof opts.mustExist !== "undefined") {
|
||||
mustExist = opts.mustExist;
|
||||
}
|
||||
if (typeof opts.merge === "function") {
|
||||
merge = opts.merge;
|
||||
}
|
||||
|
||||
let filePath;
|
||||
if (typeof opts.filePath === "string") {
|
||||
const absPath = opts.filePath.startsWith(".")
|
||||
? resolve(opts.filePath, input)
|
||||
: opts.filePath;
|
||||
if (existsSync(absPath)) {
|
||||
filePath = absPath;
|
||||
}
|
||||
} else {
|
||||
filePath = await escalade(input, async (dir, names) => {
|
||||
if (accept) {
|
||||
for (const n of names) {
|
||||
if (accept(n, { directory: dir }) === true) return n;
|
||||
}
|
||||
}
|
||||
|
||||
for (const n of accepted) {
|
||||
if (names.includes(n)) return n;
|
||||
}
|
||||
|
||||
if (names.includes("config")) {
|
||||
let d = join(dir, "config");
|
||||
let _,
|
||||
stats = await toStats(d);
|
||||
let entries = [];
|
||||
if (stats.isDirectory()) {
|
||||
entries = await toRead(d);
|
||||
for (const n of accepted) {
|
||||
if (entries.includes(n)) return join("config", n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (names.includes("package.json")) {
|
||||
let file = join(dir, "package.json");
|
||||
let _,
|
||||
contents = await toReadFile(file).then((r) =>
|
||||
JSON.parse(r.toString())
|
||||
);
|
||||
if (contents[namespace]) return "package.json";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (mustExist) {
|
||||
assert(
|
||||
!!filePath,
|
||||
`Unable to resolve a ${namespace} configuration`,
|
||||
"ERR_PROLOAD_NOT_FOUND"
|
||||
);
|
||||
} else if (!filePath) {
|
||||
return;
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} namespace
|
||||
* @param {import('../index').LoadOptions} opts
|
||||
*/
|
||||
async function load(namespace, opts = {}) {
|
||||
const { context } = opts;
|
||||
let mustExist = true;
|
||||
if (typeof opts.mustExist !== 'undefined') {
|
||||
mustExist = opts.mustExist
|
||||
}
|
||||
const filePath = await resolveConfig(namespace, opts);
|
||||
if (mustExist) {
|
||||
assert(!!filePath, `Unable to resolve a ${namespace} configuration`, 'ERR_PROLOAD_NOT_FOUND');
|
||||
} else if (!filePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
let rawValue = await requireOrImportWithMiddleware(filePath);
|
||||
if (filePath.endsWith('package.json')) rawValue = rawValue[namespace];
|
||||
// Important: "empty" config files will be returned as `Module {}`
|
||||
// We should handle them here
|
||||
if (rawValue && !(rawValue instanceof Object)) {
|
||||
if (mustExist) {
|
||||
assert(
|
||||
true,
|
||||
`Resolved a ${namespace} configuration, but no configuration was exported`,
|
||||
"ERR_PROLOAD_NOT_FOUND"
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const resolvedValue = await resolveExtensions(namespace, {
|
||||
filePath,
|
||||
value: rawValue,
|
||||
context,
|
||||
});
|
||||
|
||||
return {
|
||||
filePath,
|
||||
raw: rawValue,
|
||||
value: resolvedValue,
|
||||
};
|
||||
}
|
||||
|
||||
const defaultPlugins = [
|
||||
{
|
||||
name: "@proload/extract-default",
|
||||
transform(mdl) {
|
||||
if (mdl.default && Object.keys(mdl).length === 1) {
|
||||
return mdl.default;
|
||||
};
|
||||
|
||||
return mdl;
|
||||
},
|
||||
},
|
||||
];
|
||||
/** @type import('../index').Plugin[] */
|
||||
load.plugins = defaultPlugins;
|
||||
load.use = (plugins) => {
|
||||
load.plugins = [...load.plugins, ...plugins];
|
||||
};
|
||||
export default load;
|
||||
export { resolveConfig as resolve };
|
30
node_modules/@proload/core/lib/esm/requireOrImport.mjs
generated
vendored
Normal file
30
node_modules/@proload/core/lib/esm/requireOrImport.mjs
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
import { createRequire } from 'module';
|
||||
import { pathToFileURL } from 'url';
|
||||
let require = createRequire(import.meta.url);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} filePath
|
||||
*/
|
||||
export default async function requireOrImport(filePath, { middleware = [] } = {}) {
|
||||
await Promise.all(middleware.map(plugin => plugin.register(filePath)));
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
let mdl = require(filePath);
|
||||
resolve(mdl);
|
||||
} catch (e) {
|
||||
if (e.code === 'ERR_REQUIRE_ESM') {
|
||||
const fileUrl = pathToFileURL(filePath).toString();
|
||||
try {
|
||||
const mdl = await import(fileUrl);
|
||||
return resolve(mdl);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
}
|
1
node_modules/@proload/core/lib/esm/requireOrImport.mjs.d.ts
generated
vendored
Normal file
1
node_modules/@proload/core/lib/esm/requireOrImport.mjs.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default function requireOrImport(filePath: string, opts?: { middleware: any[] }): Promise<any>;
|
120
node_modules/@proload/core/lib/index.d.ts
generated
vendored
Normal file
120
node_modules/@proload/core/lib/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
export { ProloadError } from './error.cjs';
|
||||
|
||||
export interface Config<T> {
|
||||
/** An absolute path to a resolved configuration file */
|
||||
filePath: string;
|
||||
/** The raw value of a resolved configuration file, before being merged with any `extends` configurations */
|
||||
raw: any;
|
||||
/** The final, resolved value of a resolved configuration file */
|
||||
value: T;
|
||||
}
|
||||
|
||||
export interface ResolveOptions {
|
||||
/**
|
||||
* An exact filePath to a configuration file which should be loaded. If passed, this will keep proload from searching
|
||||
* for matching files.
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#filepath)
|
||||
*/
|
||||
filePath?: string;
|
||||
/**
|
||||
* The location from which to begin searching up the directory tree
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#cwd)
|
||||
*/
|
||||
cwd?: string;
|
||||
/**
|
||||
* If a configuration _must_ be resolved. If `true`, Proload will throw an error when a configuration is not found
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#mustExist)
|
||||
*/
|
||||
mustExist?: boolean;
|
||||
/**
|
||||
* A function to completely customize module resolution
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#accept)
|
||||
*/
|
||||
accept?(fileName: string, context: { directory: string }): boolean|void;
|
||||
}
|
||||
|
||||
export interface LoadOptions<T> {
|
||||
/**
|
||||
* An exact filePath to a configuration file which should be loaded. If passed, this will keep proload from searching
|
||||
* for matching files.
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#filepath)
|
||||
*/
|
||||
filePath?: string;
|
||||
/**
|
||||
* The location from which to begin searching up the directory tree
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#cwd)
|
||||
*/
|
||||
cwd?: string;
|
||||
/**
|
||||
* If a configuration _must_ be resolved. If `true`, Proload will throw an error when a configuration is not found
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#mustExist)
|
||||
*/
|
||||
mustExist?: boolean;
|
||||
/**
|
||||
* If a resolved configuration file exports a factory function, this value will be passed as arguments to the function
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#context)
|
||||
*/
|
||||
context?: any;
|
||||
/**
|
||||
* A function to customize the `merge` behavior when a config with `extends` is encountered
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#merge)
|
||||
*/
|
||||
merge?(x: Partial<T>, y: Partial<T>): Partial<T>;
|
||||
/**
|
||||
* A function to completely customize module resolution
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#accept)
|
||||
*/
|
||||
accept?(fileName: string, context: { directory: string }): boolean|void;
|
||||
}
|
||||
|
||||
export interface Plugin {
|
||||
/** a unique identifier for your plugin */
|
||||
name: string;
|
||||
/** extensions which should be resolved, including the leading period */
|
||||
extensions?: string[];
|
||||
/** fileName patterns which should be resolved, excluding the trailing extension */
|
||||
fileNames?: string[];
|
||||
/** Executed before require/import of config file */
|
||||
register?(filePath: string): Promise<void>;
|
||||
/** Modify the config file before passing it along */
|
||||
transform?(module: any): Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An `async` function which searches for a configuration file
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#resolve)
|
||||
*/
|
||||
export async function resolve(namespace: string, opts?: ResolveOptions): Promise<string|undefined>;
|
||||
|
||||
interface Load<T extends Record<any, any> = Record<any, any>> {
|
||||
/**
|
||||
* @param namespace The namespace which will be searched for the configuration file.
|
||||
*
|
||||
* For example, passing `"donut"` would resolve a files like `donut.config.js`, `donut.config.cjs`, and `donut.config.mjs` as well as a `package.json` with a `donut` property.
|
||||
*
|
||||
* @param opts Options to customize loader behavior
|
||||
*/
|
||||
(namespace: string, opts?: LoadOptions<T>): Promise<Config<T>|undefined>;
|
||||
use(plugins: Plugin[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An `async` function which searches for and loads a configuration file
|
||||
*
|
||||
* [Read the `@proload/core` docs](https://github.com/natemoo-re/proload/tree/main/packages/core#load)
|
||||
*/
|
||||
declare const load: Load;
|
||||
|
||||
export = load;
|
||||
export default load;
|
45
node_modules/@proload/core/package.json
generated
vendored
Normal file
45
node_modules/@proload/core/package.json
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "@proload/core",
|
||||
"version": "0.3.3",
|
||||
"description": "Searches for and loads your tool's JavaScript configuration files with full support for CJS, ESM, TypeScript and more.",
|
||||
"main": "./lib/cjs/index.cjs",
|
||||
"module": "./lib/esm/index.mjs",
|
||||
"types": "./lib/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"!test"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/esm/index.mjs",
|
||||
"require": "./lib/cjs/index.cjs"
|
||||
},
|
||||
"./esm": "./lib/esm/index.mjs",
|
||||
"./cjs": "./lib/cjs/index.cjs",
|
||||
"./lib/index.d.ts": "./lib/index.d.ts",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"load",
|
||||
"configuration",
|
||||
"config",
|
||||
"esm",
|
||||
"cjs",
|
||||
"typescript"
|
||||
],
|
||||
"author": "Nate Moore <nate@natemoo.re>",
|
||||
"dependencies": {
|
||||
"deepmerge": "^4.2.2",
|
||||
"escalade": "^3.1.1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/natemoo-re/proload.git",
|
||||
"directory": "packages/core"
|
||||
},
|
||||
"homepage": "https://github.com/natemoo-re/proload#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/natemoo-re/proload/issues"
|
||||
}
|
||||
}
|
34
node_modules/@proload/plugin-tsm/CHANGELOG.md
generated
vendored
Normal file
34
node_modules/@proload/plugin-tsm/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [72c8577]
|
||||
- @proload/core@0.3.2
|
||||
|
||||
## 0.2.1-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5cbbe02]
|
||||
- @proload/core@0.3.2-next.0
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [4c7215e]
|
||||
- Updated dependencies [ddce5c6]
|
||||
- @proload/core@0.3.0
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- dae1cce: Update @proload/core dependency
|
||||
- 645446c: Fix support for `.cts` and `.mts` files
|
||||
|
||||
## v0.1.0
|
||||
|
||||
Initial release
|
11
node_modules/@proload/plugin-tsm/README.md
generated
vendored
Normal file
11
node_modules/@proload/plugin-tsm/README.md
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# `@proload/plugin-tsm`
|
||||
|
||||
Enables the loading of `[namespace].config.ts`, `[namespace].config.cts`, and `[namespace].config.mts` files using [`@proload/core`](https://github.com/natemoo-re/proload).
|
||||
|
||||
```js
|
||||
import load from '@proload/core';
|
||||
import typescript from '@proload/plugin-tsm';
|
||||
|
||||
load.use([typescript]);
|
||||
await load('namespace');
|
||||
```
|
9
node_modules/@proload/plugin-tsm/lib/index.cjs
generated
vendored
Normal file
9
node_modules/@proload/plugin-tsm/lib/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
name: '@proload/plugin-tsm',
|
||||
extensions: ['ts', 'tsx', 'cts', 'mts'],
|
||||
async register(fileName) {
|
||||
if (/\.([cm]ts|tsx?)$/.test(fileName)) {
|
||||
require('tsm');
|
||||
}
|
||||
}
|
||||
}
|
5
node_modules/@proload/plugin-tsm/lib/index.d.ts
generated
vendored
Normal file
5
node_modules/@proload/plugin-tsm/lib/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Plugin } from '@proload/core';
|
||||
|
||||
declare const typescriptPlugin: Plugin;
|
||||
|
||||
export default typescriptPlugin;
|
2
node_modules/@proload/plugin-tsm/lib/index.mjs
generated
vendored
Normal file
2
node_modules/@proload/plugin-tsm/lib/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import plugin from './index.cjs';
|
||||
export default plugin;
|
36
node_modules/@proload/plugin-tsm/package.json
generated
vendored
Normal file
36
node_modules/@proload/plugin-tsm/package.json
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "@proload/plugin-tsm",
|
||||
"version": "0.2.1",
|
||||
"description": "A proload plugin to support TypeScript files using TSM",
|
||||
"main": "./lib/index.cjs",
|
||||
"module": "./lib/index.mjs",
|
||||
"types": "./lib/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/index.mjs",
|
||||
"require": "./lib/index.cjs"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"proload-plugin",
|
||||
"typescript"
|
||||
],
|
||||
"author": "Nate Moore <nate@natemoo.re>",
|
||||
"peerDependencies": {
|
||||
"@proload/core": "^0.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tsm": "^2.1.4"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/natemoo-re/proload.git",
|
||||
"directory": "packages/plugin-typescript"
|
||||
},
|
||||
"homepage": "https://github.com/natemoo-re/proload#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/natemoo-re/proload/issues"
|
||||
}
|
||||
}
|
24
node_modules/@proload/plugin-tsm/test/index.mjs
generated
vendored
Normal file
24
node_modules/@proload/plugin-tsm/test/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { test } from 'uvu';
|
||||
import { is, type } from 'uvu/assert';
|
||||
import { resolve } from 'path';
|
||||
import load from '@proload/core';
|
||||
import typescript from '@proload/plugin-tsm';
|
||||
|
||||
test.before(() => {
|
||||
load.use([typescript]);
|
||||
})
|
||||
|
||||
test('sanity', () => {
|
||||
type(typescript, 'object');
|
||||
})
|
||||
|
||||
const fixtures = ['ts', 'ts-config', 'cts', 'mts'];
|
||||
|
||||
for (const fixture of fixtures) {
|
||||
test(fixture, async () => {
|
||||
let mdl = await load('test', { cwd: resolve(`fixtures/${fixture}`) });
|
||||
is(mdl.value.value, fixture)
|
||||
});
|
||||
}
|
||||
|
||||
test.run();
|
Reference in New Issue
Block a user