feat: add join callback to include options
BREAKING CHANGE: usage of the include type now requires a join option
This commit is contained in:
parent
dba9267828
commit
1d07d7c3ed
|
@ -9,5 +9,5 @@ The schema to be used for included files. This is necessary to work around circu
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
includeSchema: IncludeSchema
|
includeOptions: IncludeOptions
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export { CONFIG_SCHEMA } from './schema';
|
export { CONFIG_SCHEMA } from './schema';
|
||||||
export { envType } from './type/Env';
|
export { envType } from './type/Env';
|
||||||
export { includeSchema, includeType } from './type/Include';
|
export { includeOptions as includeSchema, includeType } from './type/Include';
|
||||||
export { regexpType } from './type/Regexp';
|
export { regexpType } from './type/Regexp';
|
||||||
export { streamType } from './type/Stream';
|
export { streamType } from './type/Stream';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { DEFAULT_SAFE_SCHEMA, Schema } from 'js-yaml';
|
import { DEFAULT_SAFE_SCHEMA, Schema } from 'js-yaml';
|
||||||
|
|
||||||
import { envType } from './type/Env';
|
import { envType } from './type/Env';
|
||||||
import { includeSchema, includeType } from './type/Include';
|
import { includeOptions, includeType } from './type/Include';
|
||||||
import { regexpType } from './type/Regexp';
|
import { regexpType } from './type/Regexp';
|
||||||
import { streamType } from './type/Stream';
|
import { streamType } from './type/Stream';
|
||||||
|
|
||||||
|
@ -17,4 +17,4 @@ export const CONFIG_SCHEMA = Schema.create([DEFAULT_SAFE_SCHEMA], [
|
||||||
streamType,
|
streamType,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
includeSchema.schema = CONFIG_SCHEMA;
|
includeOptions.schema = CONFIG_SCHEMA;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { InvalidArgumentError, NotFoundError } from '@apextoaster/js-utils';
|
import { InvalidArgumentError, NotFoundError, NotImplementedError } from '@apextoaster/js-utils';
|
||||||
import { SAFE_SCHEMA, safeLoad, Schema, Type as YamlType } from 'js-yaml';
|
import { SAFE_SCHEMA, safeLoad, Schema, Type as YamlType } from 'js-yaml';
|
||||||
import { join } from 'path';
|
|
||||||
|
|
||||||
export interface IncludeOptions {
|
export interface ReaderOptions {
|
||||||
encoding: string;
|
encoding: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IncludeReader = (path: string, options: IncludeOptions) => string;
|
export type IncludeReader = (path: string, options: ReaderOptions) => string;
|
||||||
|
|
||||||
export interface IncludeSchema {
|
export interface IncludeOptions {
|
||||||
exists: (path: string) => boolean;
|
exists: (path: string) => boolean;
|
||||||
|
join: (...path: Array<string>) => string;
|
||||||
read: IncludeReader;
|
read: IncludeReader;
|
||||||
resolve: (path: string) => string;
|
resolve: (path: string) => string;
|
||||||
schema: Schema;
|
schema: Schema;
|
||||||
|
@ -20,13 +20,16 @@ export interface IncludeSchema {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export const includeSchema: IncludeSchema = {
|
export const includeOptions: IncludeOptions = {
|
||||||
exists: (path: string) => false,
|
exists: (path: string) => false,
|
||||||
read: (path: string, encoding: IncludeOptions) => {
|
join: (...path: Array<string>) => {
|
||||||
throw new Error('read stub');
|
throw new NotImplementedError('join stub');
|
||||||
|
},
|
||||||
|
read: (path: string, encoding: ReaderOptions) => {
|
||||||
|
throw new NotImplementedError('read stub');
|
||||||
},
|
},
|
||||||
resolve: (path: string) => {
|
resolve: (path: string) => {
|
||||||
throw new Error('resolve stub');
|
throw new NotImplementedError('resolve stub');
|
||||||
},
|
},
|
||||||
schema: SAFE_SCHEMA,
|
schema: SAFE_SCHEMA,
|
||||||
};
|
};
|
||||||
|
@ -40,7 +43,7 @@ export const includeType = new YamlType('!include', {
|
||||||
try {
|
try {
|
||||||
const canonical = resolvePath(path);
|
const canonical = resolvePath(path);
|
||||||
// throws in node 11+
|
// throws in node 11+
|
||||||
if (includeSchema.exists(canonical)) {
|
if (includeOptions.exists(canonical)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw new NotFoundError('included file does not exist');
|
throw new NotFoundError('included file does not exist');
|
||||||
|
@ -51,10 +54,10 @@ export const includeType = new YamlType('!include', {
|
||||||
},
|
},
|
||||||
construct(path: string): unknown {
|
construct(path: string): unknown {
|
||||||
try {
|
try {
|
||||||
return safeLoad(includeSchema.read(resolvePath(path), {
|
return safeLoad(includeOptions.read(resolvePath(path), {
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
}), {
|
}), {
|
||||||
schema: includeSchema.schema,
|
schema: includeOptions.schema,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new InvalidArgumentError('error including file', err);
|
throw new InvalidArgumentError('error including file', err);
|
||||||
|
@ -62,10 +65,13 @@ export const includeType = new YamlType('!include', {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo take root parameter instead of __dirname
|
||||||
|
*/
|
||||||
export function resolvePath(path: string): string {
|
export function resolvePath(path: string): string {
|
||||||
if (path[0] === '.') {
|
if (path[0] === '.') {
|
||||||
return includeSchema.resolve(join(__dirname, path));
|
return includeOptions.resolve(includeOptions.join(__dirname, path));
|
||||||
} else {
|
} else {
|
||||||
return includeSchema.resolve(path);
|
return includeOptions.resolve(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,25 +2,27 @@ import { InvalidArgumentError, NotFoundError } from '@apextoaster/js-utils';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { IncludeSchema, includeSchema, includeType } from '../../src/type/Include';
|
import { IncludeOptions, includeOptions, includeType } from '../../src/type/Include';
|
||||||
|
|
||||||
const TEST_ROOT = '../test/type';
|
const TEST_ROOT = '../test/type';
|
||||||
|
|
||||||
const ORIGINAL_SCHEMA: IncludeSchema = {
|
const ORIGINAL_SCHEMA: IncludeOptions = {
|
||||||
...includeSchema,
|
...includeOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('include config type', async () => {
|
describe('include config type', async () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
includeSchema.exists = () => true;
|
includeOptions.exists = () => true;
|
||||||
includeSchema.read = () => 'test';
|
includeOptions.join = (...path) => path.join('/');
|
||||||
includeSchema.resolve = (path: string) => path;
|
includeOptions.read = () => 'test';
|
||||||
|
includeOptions.resolve = (path: string) => path;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
includeSchema.exists = ORIGINAL_SCHEMA.exists;
|
includeOptions.exists = ORIGINAL_SCHEMA.exists;
|
||||||
includeSchema.read = ORIGINAL_SCHEMA.read;
|
includeOptions.join = ORIGINAL_SCHEMA.join;
|
||||||
includeSchema.resolve = ORIGINAL_SCHEMA.resolve;
|
includeOptions.read = ORIGINAL_SCHEMA.read;
|
||||||
|
includeOptions.resolve = ORIGINAL_SCHEMA.resolve;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should resolve existing files', async () => {
|
it('should resolve existing files', async () => {
|
||||||
|
@ -28,7 +30,7 @@ describe('include config type', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when resolving missing files', async () => {
|
it('should throw when resolving missing files', async () => {
|
||||||
includeSchema.resolve = () => {
|
includeOptions.resolve = () => {
|
||||||
throw new NotFoundError();
|
throw new NotFoundError();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ describe('include config type', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when constructing missing files', async () => {
|
it('should throw when constructing missing files', async () => {
|
||||||
includeSchema.read = () => {
|
includeOptions.read = () => {
|
||||||
throw new InvalidArgumentError();
|
throw new InvalidArgumentError();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue