@adonisjs/cache 1.0.0-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/LICENSE.md +9 -0
- package/README.md +33 -0
- package/build/commands/cache_clear.d.ts +17 -0
- package/build/commands/cache_clear.js +77 -0
- package/build/commands/commands.json +1 -0
- package/build/commands/main.d.ts +4 -0
- package/build/commands/main.js +36 -0
- package/build/configure.d.ts +5 -0
- package/build/configure.js +61 -0
- package/build/index.d.ts +6 -0
- package/build/index.js +14 -0
- package/build/providers/cache_provider.d.ts +42 -0
- package/build/providers/cache_provider.js +64 -0
- package/build/services/main.d.ts +3 -0
- package/build/services/main.js +17 -0
- package/build/src/bindings/repl.d.ts +6 -0
- package/build/src/bindings/repl.js +28 -0
- package/build/src/define_config.d.ts +12 -0
- package/build/src/define_config.js +14 -0
- package/build/src/drivers.d.ts +20 -0
- package/build/src/drivers.js +101 -0
- package/build/src/store.d.ts +46 -0
- package/build/src/store.js +64 -0
- package/build/src/types.d.ts +26 -0
- package/build/src/types.js +9 -0
- package/build/stubs/config.stub +45 -0
- package/build/stubs/main.d.ts +1 -0
- package/build/stubs/main.js +10 -0
- package/package.json +127 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @adonisjs/cache
|
|
2
|
+
|
|
3
|
+
<br />
|
|
4
|
+
|
|
5
|
+
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
|
|
6
|
+
|
|
7
|
+
## Introduction
|
|
8
|
+
Cache module for AdonisJS built on top of BentoCache. Support multiples drivers, File, In-Memory, Redis, SQLs databases and more.
|
|
9
|
+
|
|
10
|
+
## Official Documentation
|
|
11
|
+
The documentation is available on the [AdonisJS website](https://docs.adonisjs.com/guides/cache/introduction).
|
|
12
|
+
|
|
13
|
+
## Contributing
|
|
14
|
+
One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believes in the principles of the framework.
|
|
15
|
+
|
|
16
|
+
We encourage you to read the [contribution guide](https://github.com/adonisjs/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
|
|
17
|
+
|
|
18
|
+
## Code of Conduct
|
|
19
|
+
In order to ensure that the AdonisJS community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/adonisjs/.github/blob/main/docs/CODE_OF_CONDUCT.md).
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
AdonisJS Lucid is open-sourced software licensed under the [MIT license](LICENSE.md).
|
|
23
|
+
|
|
24
|
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/cache/test.yml?style=for-the-badge
|
|
25
|
+
[gh-workflow-url]: https://github.com/adonisjs/cache/actions/workflows/test.yml "Github action"
|
|
26
|
+
|
|
27
|
+
[npm-image]: https://img.shields.io/npm/v/@adonisjs/cache/latest.svg?style=for-the-badge&logo=npm
|
|
28
|
+
[npm-url]: https://www.npmjs.com/package/@adonisjs/cache/v/latest "npm"
|
|
29
|
+
|
|
30
|
+
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
|
31
|
+
|
|
32
|
+
[license-url]: LICENSE.md
|
|
33
|
+
[license-image]: https://img.shields.io/github/license/adonisjs/cache?style=for-the-badge
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
+
export default class CacheClear extends BaseCommand {
|
|
4
|
+
#private;
|
|
5
|
+
static commandName: string;
|
|
6
|
+
static description: string;
|
|
7
|
+
static options: CommandOptions;
|
|
8
|
+
/**
|
|
9
|
+
* Choose a custom cache store to clear. Otherwise, we use the
|
|
10
|
+
* default one
|
|
11
|
+
*/
|
|
12
|
+
store: string;
|
|
13
|
+
/**
|
|
14
|
+
* Handle command
|
|
15
|
+
*/
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
10
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
11
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
12
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
13
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14
|
+
};
|
|
15
|
+
import { BaseCommand, flags } from '@adonisjs/core/ace';
|
|
16
|
+
export default class CacheClear extends BaseCommand {
|
|
17
|
+
static commandName = 'cache:clear';
|
|
18
|
+
static description = 'Clear the application cache';
|
|
19
|
+
static options = {
|
|
20
|
+
startApp: true,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Prompts to take consent when clearing the cache in production
|
|
24
|
+
*/
|
|
25
|
+
async #takeProductionConsent() {
|
|
26
|
+
const question = 'You are in production environment. Want to continue clearing the cache?';
|
|
27
|
+
try {
|
|
28
|
+
return await this.prompt.confirm(question);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if the given cache exist
|
|
36
|
+
*/
|
|
37
|
+
#cacheExists(cache, cacheName) {
|
|
38
|
+
try {
|
|
39
|
+
cache.use(cacheName);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Handle command
|
|
48
|
+
*/
|
|
49
|
+
async run() {
|
|
50
|
+
const cache = await this.app.container.make('cache');
|
|
51
|
+
this.store = this.store || cache.defaultStoreName;
|
|
52
|
+
/**
|
|
53
|
+
* Exit if cache store doesn't exists
|
|
54
|
+
*/
|
|
55
|
+
if (!this.#cacheExists(cache, this.store)) {
|
|
56
|
+
this.logger.error(`"${this.store}" is not a valid cache store. Double check config/cache.ts file`);
|
|
57
|
+
this.exitCode = 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Take consent when clearing the cache in production
|
|
62
|
+
*/
|
|
63
|
+
if (this.app.inProduction) {
|
|
64
|
+
const shouldClear = await this.#takeProductionConsent();
|
|
65
|
+
if (!shouldClear)
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Finally clear the cache
|
|
70
|
+
*/
|
|
71
|
+
await cache.use(this.store).clear();
|
|
72
|
+
this.logger.success(`Cleared "${this.store}" cache successfully`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
__decorate([
|
|
76
|
+
flags.string({ description: 'Define a custom cache store to clear', alias: 's' })
|
|
77
|
+
], CacheClear.prototype, "store", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"commands":[{"commandName":"cache:clear","description":"Clear the application cache","help":"","namespace":"cache","aliases":[],"flags":[{"name":"store","flagName":"store","required":false,"type":"string","description":"Define a custom cache store to clear","alias":"s"}],"args":[],"options":{"startApp":true},"filePath":"cache_clear.js","absoluteFilePath":"/home/julienr/code/adonis/cache/build/commands/cache_clear.js"}],"version":1}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-memory cache of commands after they have been loaded
|
|
5
|
+
*/
|
|
6
|
+
let commandsMetaData
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Reads the commands from the "./commands.json" file. Since, the commands.json
|
|
10
|
+
* file is generated automatically, we do not have to validate its contents
|
|
11
|
+
*/
|
|
12
|
+
export async function getMetaData() {
|
|
13
|
+
if (commandsMetaData) {
|
|
14
|
+
return commandsMetaData
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const commandsIndex = await readFile(new URL('./commands.json', import.meta.url), 'utf-8')
|
|
18
|
+
commandsMetaData = JSON.parse(commandsIndex).commands
|
|
19
|
+
|
|
20
|
+
return commandsMetaData
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Imports the command by lookingup its path from the commands
|
|
25
|
+
* metadata
|
|
26
|
+
*/
|
|
27
|
+
export async function getCommand(metaData) {
|
|
28
|
+
const commands = await getMetaData()
|
|
29
|
+
const command = commands.find(({ commandName }) => metaData.commandName === commandName)
|
|
30
|
+
if (!command) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { default: commandConstructor } = await import(new URL(command.filePath, import.meta.url).href)
|
|
35
|
+
return commandConstructor
|
|
36
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
const DRIVERS = ['redis', 'file', 'memory', 'database', 'dynamodb'];
|
|
10
|
+
const DRIVERS_INFO = {
|
|
11
|
+
file: {},
|
|
12
|
+
memory: {},
|
|
13
|
+
redis: {},
|
|
14
|
+
database: {},
|
|
15
|
+
dynamodb: {
|
|
16
|
+
envValidations: {
|
|
17
|
+
AWS_ACCESS_KEY_ID: `Env.schema.string()`,
|
|
18
|
+
AWS_SECRET_ACCESS_KEY: `Env.schema.string()`,
|
|
19
|
+
AWS_REGION: `Env.schema.string()`,
|
|
20
|
+
DYNAMODB_ENDPOINT: `Env.schema.string()`,
|
|
21
|
+
},
|
|
22
|
+
envVars: {
|
|
23
|
+
AWS_ACCESS_KEY_ID: '',
|
|
24
|
+
AWS_SECRET_ACCESS_KEY: '',
|
|
25
|
+
AWS_REGION: '',
|
|
26
|
+
DYNAMODB_ENDPOINT: '',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Configures the package
|
|
32
|
+
*/
|
|
33
|
+
export async function configure(command) {
|
|
34
|
+
const driver = await command.prompt.choice('Select the cache driver you plan to use', ['redis', 'file', 'memory', 'database', 'dynamodb'], {
|
|
35
|
+
hint: 'You can always change it later',
|
|
36
|
+
});
|
|
37
|
+
const { envVars, envValidations } = DRIVERS_INFO[driver];
|
|
38
|
+
const codemods = await command.createCodemods();
|
|
39
|
+
/**
|
|
40
|
+
* Publish provider
|
|
41
|
+
*/
|
|
42
|
+
await codemods.updateRcFile((rcFile) => {
|
|
43
|
+
rcFile.addProvider('@adonisjs/cache/cache_provider').addCommand('@adonisjs/cache/commands');
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Define environment variables
|
|
47
|
+
*/
|
|
48
|
+
if (envVars) {
|
|
49
|
+
codemods.defineEnvVariables(envVars);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Define environment validations
|
|
53
|
+
*/
|
|
54
|
+
if (envValidations) {
|
|
55
|
+
codemods.defineEnvValidations({ variables: envValidations });
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Publish config
|
|
59
|
+
*/
|
|
60
|
+
await command.publishStub('config.stub', { driver: driver });
|
|
61
|
+
}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { errors } from 'bentocache';
|
|
2
|
+
export { configure } from './configure.js';
|
|
3
|
+
export { stubsRoot } from './stubs/main.js';
|
|
4
|
+
export { defineConfig } from './src/define_config.js';
|
|
5
|
+
export { drivers } from './src/drivers.js';
|
|
6
|
+
export { store } from './src/store.js';
|
package/build/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
export { errors } from 'bentocache';
|
|
10
|
+
export { configure } from './configure.js';
|
|
11
|
+
export { stubsRoot } from './stubs/main.js';
|
|
12
|
+
export { defineConfig } from './src/define_config.js';
|
|
13
|
+
export { drivers } from './src/drivers.js';
|
|
14
|
+
export { store } from './src/store.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
+
import type { CacheEvents } from 'bentocache/types';
|
|
3
|
+
import type { CacheService } from '../src/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Extend Adonis.js types to include cache
|
|
6
|
+
*/
|
|
7
|
+
declare module '@adonisjs/core/types' {
|
|
8
|
+
/**
|
|
9
|
+
* Adding cache type to the application container
|
|
10
|
+
*/
|
|
11
|
+
interface ContainerBindings {
|
|
12
|
+
cache: CacheService;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Add cache events to the application events list
|
|
16
|
+
*/
|
|
17
|
+
interface EventsList {
|
|
18
|
+
'cache:cleared': CacheEvents['cache:cleared'];
|
|
19
|
+
'cache:deleted': CacheEvents['cache:deleted'];
|
|
20
|
+
'cache:hit': CacheEvents['cache:hit'];
|
|
21
|
+
'cache:miss': CacheEvents['cache:miss'];
|
|
22
|
+
'cache:written': CacheEvents['cache:written'];
|
|
23
|
+
'bus:message:published': CacheEvents['bus:message:published'];
|
|
24
|
+
'bus:message:received': CacheEvents['bus:message:received'];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Cache provider to register cache specific bindings
|
|
29
|
+
*/
|
|
30
|
+
export default class CacheProvider {
|
|
31
|
+
#private;
|
|
32
|
+
protected app: ApplicationService;
|
|
33
|
+
constructor(app: ApplicationService);
|
|
34
|
+
/**
|
|
35
|
+
* Register bindings
|
|
36
|
+
*/
|
|
37
|
+
register(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Disconnect all cache stores when shutting down the app
|
|
40
|
+
*/
|
|
41
|
+
shutdown(): Promise<void>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import { defineReplBindings } from '../src/bindings/repl.js';
|
|
10
|
+
/**
|
|
11
|
+
* Cache provider to register cache specific bindings
|
|
12
|
+
*/
|
|
13
|
+
export default class CacheProvider {
|
|
14
|
+
app;
|
|
15
|
+
constructor(app) {
|
|
16
|
+
this.app = app;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Register the cache manager to the container
|
|
20
|
+
*/
|
|
21
|
+
async #registerCacheManager() {
|
|
22
|
+
const cacheConfig = this.app.config.get('cache');
|
|
23
|
+
this.app.container.singleton('cache', async () => {
|
|
24
|
+
const { BentoCache } = await import('bentocache');
|
|
25
|
+
const emitter = await this.app.container.make('emitter');
|
|
26
|
+
/**
|
|
27
|
+
* Resolve all store config providers
|
|
28
|
+
*/
|
|
29
|
+
const resolvedStores = Object.entries(cacheConfig.stores).map(async ([name, store]) => {
|
|
30
|
+
return [name, await store.entry().resolver(this.app)];
|
|
31
|
+
});
|
|
32
|
+
return new BentoCache({
|
|
33
|
+
...cacheConfig,
|
|
34
|
+
emitter: emitter,
|
|
35
|
+
default: cacheConfig.default,
|
|
36
|
+
stores: Object.fromEntries(await Promise.all(resolvedStores)),
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Register REPL bindings
|
|
42
|
+
*/
|
|
43
|
+
async #registerReplBindings() {
|
|
44
|
+
if (this.app.getEnvironment() !== 'repl') {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const repl = await this.app.container.make('repl');
|
|
48
|
+
defineReplBindings(this.app, repl);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Register bindings
|
|
52
|
+
*/
|
|
53
|
+
async register() {
|
|
54
|
+
this.#registerCacheManager();
|
|
55
|
+
this.#registerReplBindings();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Disconnect all cache stores when shutting down the app
|
|
59
|
+
*/
|
|
60
|
+
async shutdown() {
|
|
61
|
+
const cache = await this.app.container.make('cache');
|
|
62
|
+
await cache.disconnectAll().catch(() => { });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import app from '@adonisjs/core/services/app';
|
|
10
|
+
let cache;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a singleton instance of the Cache manager
|
|
13
|
+
*/
|
|
14
|
+
await app.booted(async () => {
|
|
15
|
+
cache = await app.container.make('cache');
|
|
16
|
+
});
|
|
17
|
+
export { cache as default };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Helper to define REPL state
|
|
11
|
+
*/
|
|
12
|
+
function setupReplState(repl, key, value) {
|
|
13
|
+
repl.server.context[key] = value;
|
|
14
|
+
repl.notify(`Loaded ${key} module. You can access it using the "${repl.colors.underline(key)}" variable`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Define REPL bindings
|
|
18
|
+
*/
|
|
19
|
+
export function defineReplBindings(app, Repl) {
|
|
20
|
+
/**
|
|
21
|
+
* Load cache provider to the cache property
|
|
22
|
+
*/
|
|
23
|
+
Repl.addMethod('loadCache', async (repl) => {
|
|
24
|
+
setupReplState(repl, 'cache', await app.container.make('cache'));
|
|
25
|
+
}, {
|
|
26
|
+
description: 'Load cache provider to the "cache" property',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Store } from './store.js';
|
|
2
|
+
import { CacheOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Define cache configuration
|
|
5
|
+
*/
|
|
6
|
+
export declare function defineConfig<KnownCaches extends Record<string, Store>>(config: CacheOptions & {
|
|
7
|
+
default: keyof KnownCaches;
|
|
8
|
+
stores: KnownCaches;
|
|
9
|
+
}): CacheOptions & {
|
|
10
|
+
default: keyof KnownCaches;
|
|
11
|
+
stores: KnownCaches;
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Define cache configuration
|
|
11
|
+
*/
|
|
12
|
+
export function defineConfig(config) {
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ConfigProvider } from '@adonisjs/core/types';
|
|
2
|
+
import type { RedisConnections } from '@adonisjs/redis/types';
|
|
3
|
+
import { MemoryConfig, CreateDriverResult, L1CacheDriver, L2CacheDriver, CreateBusDriverResult, DynamoDBConfig, FileConfig } from 'bentocache/types';
|
|
4
|
+
/**
|
|
5
|
+
* Different drivers supported by the cache module
|
|
6
|
+
*/
|
|
7
|
+
export declare const drivers: {
|
|
8
|
+
memory: (config: MemoryConfig) => ConfigProvider<CreateDriverResult<L1CacheDriver>>;
|
|
9
|
+
redis: (config: {
|
|
10
|
+
connectionName?: keyof RedisConnections;
|
|
11
|
+
}) => ConfigProvider<CreateDriverResult<L2CacheDriver>>;
|
|
12
|
+
redisBus: (config: {
|
|
13
|
+
connectionName?: keyof RedisConnections;
|
|
14
|
+
}) => ConfigProvider<CreateBusDriverResult>;
|
|
15
|
+
database: (config?: {
|
|
16
|
+
connectionName?: string;
|
|
17
|
+
}) => ConfigProvider<CreateDriverResult<L2CacheDriver>>;
|
|
18
|
+
dynamodb: (config: DynamoDBConfig) => ConfigProvider<CreateDriverResult<L2CacheDriver>>;
|
|
19
|
+
file: (config: FileConfig) => ConfigProvider<CreateDriverResult<L2CacheDriver>>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
/// <reference types="@adonisjs/redis/redis_provider" />
|
|
10
|
+
/// <reference types="@adonisjs/lucid/database_provider" />
|
|
11
|
+
import { configProvider } from '@adonisjs/core';
|
|
12
|
+
/**
|
|
13
|
+
* Different drivers supported by the cache module
|
|
14
|
+
*/
|
|
15
|
+
export const drivers = {
|
|
16
|
+
/**
|
|
17
|
+
* Redis driver for L2 layer
|
|
18
|
+
* You must install @adonisjs/redis to use this driver
|
|
19
|
+
*/
|
|
20
|
+
redis(config) {
|
|
21
|
+
return configProvider.create(async (app) => {
|
|
22
|
+
const redis = await app.container.make('redis');
|
|
23
|
+
const { redisDriver } = await import('bentocache/drivers/redis');
|
|
24
|
+
const redisConnection = redis.connection(config.connectionName);
|
|
25
|
+
return redisDriver({ connection: redisConnection.ioConnection });
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Redis driver for the sync bus
|
|
30
|
+
* You must install @adonisjs/redis to use this driver
|
|
31
|
+
*/
|
|
32
|
+
redisBus(config) {
|
|
33
|
+
return configProvider.create(async (app) => {
|
|
34
|
+
const redis = await app.container.make('redis');
|
|
35
|
+
const { redisBusDriver } = await import('bentocache/drivers/redis');
|
|
36
|
+
const redisConnection = redis.connection(config.connectionName);
|
|
37
|
+
return redisBusDriver({ connection: redisConnection.ioConnection.options });
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Memory driver for L1 layer
|
|
42
|
+
*/
|
|
43
|
+
memory(config) {
|
|
44
|
+
return configProvider.create(async () => {
|
|
45
|
+
const { memoryDriver } = await import('bentocache/drivers/memory');
|
|
46
|
+
return memoryDriver(config);
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* Database driver for L2 layer
|
|
51
|
+
* You must install @adonisjs/lucid to use this driver
|
|
52
|
+
*/
|
|
53
|
+
database(config) {
|
|
54
|
+
return configProvider.create(async (app) => {
|
|
55
|
+
const db = await app.container.make('lucid.db');
|
|
56
|
+
const connectionName = config?.connectionName || db.primaryConnectionName;
|
|
57
|
+
const dialect = db.connection(connectionName).dialect.name;
|
|
58
|
+
/**
|
|
59
|
+
* We only support pg, mysql, better-sqlite3 and sqlite3 dialects for now
|
|
60
|
+
*/
|
|
61
|
+
const supportedDialects = ['pg', 'mysql', 'better-sqlite3', 'sqlite3'];
|
|
62
|
+
if (!supportedDialects.includes(dialect)) {
|
|
63
|
+
throw new Error(`Unsupported dialect "${dialect}"`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the knex connection for the given connection name
|
|
67
|
+
*/
|
|
68
|
+
const rawConnection = db.getRawConnection(connectionName);
|
|
69
|
+
if (!rawConnection?.connection?.client) {
|
|
70
|
+
throw new Error(`Unable to get raw connection for "${connectionName}"`);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create the driver
|
|
74
|
+
*/
|
|
75
|
+
const { knexDriver } = await import('bentocache/drivers/sql');
|
|
76
|
+
return knexDriver({
|
|
77
|
+
connection: rawConnection.connection.client,
|
|
78
|
+
dialect: dialect === 'postgres' ? 'pg' : dialect,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* DynamoDB driver for L2 layer
|
|
84
|
+
* You must install @aws-sdk/client-dynamodb to use this driver
|
|
85
|
+
*/
|
|
86
|
+
dynamodb(config) {
|
|
87
|
+
return configProvider.create(async () => {
|
|
88
|
+
const { dynamoDbDriver } = await import('bentocache/drivers/dynamodb');
|
|
89
|
+
return dynamoDbDriver(config);
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* File driver for L2 layer
|
|
94
|
+
*/
|
|
95
|
+
file(config) {
|
|
96
|
+
return configProvider.create(async () => {
|
|
97
|
+
const { fileDriver } = await import('bentocache/drivers/file');
|
|
98
|
+
return fileDriver(config);
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ConfigProvider } from '@adonisjs/core/types';
|
|
2
|
+
import { RawCommonOptions, CreateDriverResult, L1CacheDriver, CreateBusDriverResult, L2CacheDriver } from 'bentocache/types';
|
|
3
|
+
/**
|
|
4
|
+
* Create a new store
|
|
5
|
+
*/
|
|
6
|
+
export declare function store(options?: RawCommonOptions & {
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}): Store;
|
|
9
|
+
export declare class Store {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(baseOptions?: RawCommonOptions & {
|
|
12
|
+
prefix?: string;
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Add a L1 layer to your store. This is usually a memory driver
|
|
16
|
+
* for fast access purposes.
|
|
17
|
+
*/
|
|
18
|
+
useL1Layer(driver: ConfigProvider<CreateDriverResult<L1CacheDriver>>): this;
|
|
19
|
+
/**
|
|
20
|
+
* Add a L2 layer to your store. This is usually something
|
|
21
|
+
* distributed like Redis, DynamoDB, Sql database, etc.
|
|
22
|
+
*/
|
|
23
|
+
useL2Layer(driver: ConfigProvider<CreateDriverResult<L2CacheDriver>>): this;
|
|
24
|
+
/**
|
|
25
|
+
* Add a bus to your store. It will be used to synchronize L1 layers between
|
|
26
|
+
* different instances of your application.
|
|
27
|
+
*/
|
|
28
|
+
useBus(bus: ConfigProvider<CreateBusDriverResult>): this;
|
|
29
|
+
/**
|
|
30
|
+
* Create a config provider for the store
|
|
31
|
+
*/
|
|
32
|
+
entry(): ConfigProvider<{
|
|
33
|
+
"__#70@#private": any;
|
|
34
|
+
useL1Layer(driver: CreateDriverResult<L1CacheDriver>): any;
|
|
35
|
+
useL2Layer(driver: CreateDriverResult<L2CacheDriver>): any;
|
|
36
|
+
useBus(bus: CreateBusDriverResult): any;
|
|
37
|
+
readonly entry: {
|
|
38
|
+
options: RawCommonOptions & {
|
|
39
|
+
prefix?: string | undefined;
|
|
40
|
+
};
|
|
41
|
+
l1: CreateDriverResult<L1CacheDriver> | undefined;
|
|
42
|
+
l2: CreateDriverResult<L2CacheDriver> | undefined;
|
|
43
|
+
bus: CreateBusDriverResult | undefined;
|
|
44
|
+
};
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import { bentostore } from 'bentocache';
|
|
10
|
+
import { configProvider } from '@adonisjs/core';
|
|
11
|
+
/**
|
|
12
|
+
* Create a new store
|
|
13
|
+
*/
|
|
14
|
+
export function store(options) {
|
|
15
|
+
return new Store(options);
|
|
16
|
+
}
|
|
17
|
+
export class Store {
|
|
18
|
+
#baseOptions = {};
|
|
19
|
+
#l1;
|
|
20
|
+
#l2;
|
|
21
|
+
#bus;
|
|
22
|
+
constructor(baseOptions = {}) {
|
|
23
|
+
this.#baseOptions = baseOptions;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Add a L1 layer to your store. This is usually a memory driver
|
|
27
|
+
* for fast access purposes.
|
|
28
|
+
*/
|
|
29
|
+
useL1Layer(driver) {
|
|
30
|
+
this.#l1 = driver;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Add a L2 layer to your store. This is usually something
|
|
35
|
+
* distributed like Redis, DynamoDB, Sql database, etc.
|
|
36
|
+
*/
|
|
37
|
+
useL2Layer(driver) {
|
|
38
|
+
this.#l2 = driver;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Add a bus to your store. It will be used to synchronize L1 layers between
|
|
43
|
+
* different instances of your application.
|
|
44
|
+
*/
|
|
45
|
+
useBus(bus) {
|
|
46
|
+
this.#bus = bus;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a config provider for the store
|
|
51
|
+
*/
|
|
52
|
+
entry() {
|
|
53
|
+
return configProvider.create(async (app) => {
|
|
54
|
+
const storeInstance = bentostore(this.#baseOptions);
|
|
55
|
+
if (this.#l1)
|
|
56
|
+
storeInstance.useL1Layer(await this.#l1?.resolver(app));
|
|
57
|
+
if (this.#l2)
|
|
58
|
+
storeInstance.useL2Layer(await this.#l2?.resolver(app));
|
|
59
|
+
if (this.#bus)
|
|
60
|
+
storeInstance.useBus(await this.#bus?.resolver(app));
|
|
61
|
+
return storeInstance;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BentoCache, bentostore } from 'bentocache';
|
|
2
|
+
import type { RawBentoCacheOptions } from 'bentocache/types';
|
|
3
|
+
import type { store } from './store.js';
|
|
4
|
+
/**
|
|
5
|
+
* The options accepted by the cache module
|
|
6
|
+
*/
|
|
7
|
+
export type CacheOptions = Omit<RawBentoCacheOptions, 'logger' | 'emitter'>;
|
|
8
|
+
/**
|
|
9
|
+
* Infer the stores from the user config
|
|
10
|
+
*/
|
|
11
|
+
export type InferStores<T extends {
|
|
12
|
+
stores: Record<string, ReturnType<typeof store>>;
|
|
13
|
+
}> = {
|
|
14
|
+
[K in keyof T['stores']]: any;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A list of known caches stores inferred from the user config
|
|
18
|
+
* This interface must be extended in user-land
|
|
19
|
+
*/
|
|
20
|
+
export interface CacheStores {
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The cache service interface registered with the container
|
|
24
|
+
*/
|
|
25
|
+
export interface CacheService extends BentoCache<CacheStores extends Record<string, ReturnType<typeof bentostore>> ? CacheStores : never> {
|
|
26
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.configPath('cache.ts') })
|
|
3
|
+
}}}
|
|
4
|
+
import env from '#start/env'
|
|
5
|
+
{{#if driver === 'file'}}
|
|
6
|
+
import app from '@adonisjs/core/services/app'
|
|
7
|
+
{{/if}}
|
|
8
|
+
import { defineConfig, store, drivers } from '@adonisjs/cache'
|
|
9
|
+
|
|
10
|
+
const cacheConfig = defineConfig({
|
|
11
|
+
default: '{{ driver }}',
|
|
12
|
+
stores: {
|
|
13
|
+
{{#if driver === 'database'}}
|
|
14
|
+
database: store().useL2Layer(drivers.database({
|
|
15
|
+
connectionName: 'primary',
|
|
16
|
+
}))
|
|
17
|
+
{{#elif driver === 'redis'}}
|
|
18
|
+
redis: store().useL2Layer(drivers.redis({
|
|
19
|
+
connectionName: 'primary',
|
|
20
|
+
}))
|
|
21
|
+
{{#elif driver === 'memory'}}
|
|
22
|
+
memory: store().useL1Layer(drivers.memory())
|
|
23
|
+
{{#elif driver === 'file'}}
|
|
24
|
+
file: store().useL2Layer(drivers.file({
|
|
25
|
+
directory: app.tmpPath('cache')
|
|
26
|
+
}))
|
|
27
|
+
{{#elif driver === 'dynamodb'}}
|
|
28
|
+
dynamodb: store().useL2Layer(drivers.dynamodb({
|
|
29
|
+
table: { name: 'cache' },
|
|
30
|
+
credentials: {
|
|
31
|
+
accessKeyId: env.get('AWS_ACCESS_KEY_ID'),
|
|
32
|
+
secretAccessKey: env.get('AWS_SECRET_ACCESS_KEY')
|
|
33
|
+
},
|
|
34
|
+
region: env.get('AWS_REGION'),
|
|
35
|
+
endpoint: env.get('DYNAMODB_ENDPOINT')
|
|
36
|
+
}))
|
|
37
|
+
{{/if}}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export default cacheConfig
|
|
42
|
+
|
|
43
|
+
declare module '@adonisjs/cache/types' {
|
|
44
|
+
interface CacheStores extends InferStores<typeof cacheConfig> {}
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const stubsRoot: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/cache
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import { getDirname } from '@poppinss/utils';
|
|
10
|
+
export const stubsRoot = getDirname(import.meta.url);
|
package/package.json
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adonisjs/cache",
|
|
3
|
+
"description": "Official caching module for AdonisJS framework",
|
|
4
|
+
"version": "1.0.0-0",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=18.16.0"
|
|
7
|
+
},
|
|
8
|
+
"main": "build/index.js",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"build/configure.js",
|
|
12
|
+
"build/configure.d.ts",
|
|
13
|
+
"build/index.js",
|
|
14
|
+
"build/index.d.ts",
|
|
15
|
+
"build/factories",
|
|
16
|
+
"build/providers",
|
|
17
|
+
"build/services",
|
|
18
|
+
"build/commands",
|
|
19
|
+
"build/src",
|
|
20
|
+
"build/stubs"
|
|
21
|
+
],
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./build/index.js",
|
|
24
|
+
"./types": "./build/src/types.js",
|
|
25
|
+
"./commands/*": "./build/commands/*.js",
|
|
26
|
+
"./commands": "./build/commands/main.js",
|
|
27
|
+
"./services/main": "./build/services/main.js",
|
|
28
|
+
"./cache_provider": "./build/providers/cache_provider.js"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"clean": "del-cli build",
|
|
32
|
+
"copy:templates": "copyfiles \"stubs/**/*.stub\" build",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"index:commands": "adonis-kit index build/commands",
|
|
35
|
+
"lint": "eslint . --ext=.ts",
|
|
36
|
+
"format": "prettier --write .",
|
|
37
|
+
"quick:test": "node --enable-source-maps --loader=ts-node/esm bin/test.ts",
|
|
38
|
+
"pretest": "npm run lint",
|
|
39
|
+
"test": "c8 npm run quick:test",
|
|
40
|
+
"prebuild": "npm run lint && npm run clean",
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"postbuild": "npm run copy:templates && npm run index:commands",
|
|
43
|
+
"release": "np",
|
|
44
|
+
"version": "npm run build",
|
|
45
|
+
"prepublishOnly": "npm run build"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@adonisjs/assembler": "^6.1.3-25",
|
|
49
|
+
"@adonisjs/core": "^6.1.5-29",
|
|
50
|
+
"@adonisjs/eslint-config": "^1.1.8",
|
|
51
|
+
"@adonisjs/lucid": "19.0.0-3",
|
|
52
|
+
"@adonisjs/prettier-config": "^1.1.8",
|
|
53
|
+
"@adonisjs/redis": "8.0.0-12",
|
|
54
|
+
"@adonisjs/tsconfig": "^1.1.8",
|
|
55
|
+
"@japa/assert": "2.0.1",
|
|
56
|
+
"@japa/expect-type": "^2.0.0",
|
|
57
|
+
"@japa/file-system": "^2.0.1",
|
|
58
|
+
"@japa/runner": "^3.0.5",
|
|
59
|
+
"@japa/snapshot": "^2.0.1",
|
|
60
|
+
"@swc/core": "^1.3.96",
|
|
61
|
+
"@types/node": "^20.8.10",
|
|
62
|
+
"better-sqlite3": "^9.0.0",
|
|
63
|
+
"c8": "^8.0.1",
|
|
64
|
+
"copyfiles": "^2.4.1",
|
|
65
|
+
"del-cli": "^5.1.0",
|
|
66
|
+
"eslint": "^8.53.0",
|
|
67
|
+
"ioredis": "^5.3.2",
|
|
68
|
+
"luxon": "^3.4.3",
|
|
69
|
+
"np": "^8.0.4",
|
|
70
|
+
"p-event": "^6.0.0",
|
|
71
|
+
"prettier": "^3.0.3",
|
|
72
|
+
"ts-node": "^10.9.1",
|
|
73
|
+
"typescript": "^5.2.2"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"@poppinss/utils": "^6.5.1",
|
|
77
|
+
"bentocache": "1.0.0-beta.4"
|
|
78
|
+
},
|
|
79
|
+
"peerDependencies": {
|
|
80
|
+
"@adonisjs/assembler": "^6.1.3-22",
|
|
81
|
+
"@adonisjs/core": "^6.1.5-26",
|
|
82
|
+
"@adonisjs/lucid": "19.0.0-3",
|
|
83
|
+
"@adonisjs/redis": "8.0.0-12"
|
|
84
|
+
},
|
|
85
|
+
"peerDependenciesMeta": {
|
|
86
|
+
"@adonisjs/assembler": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"@adonisjs/redis": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@adonisjs/lucid": {
|
|
93
|
+
"optional": true
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"author": "adonisjs, Julien Ripouteau",
|
|
97
|
+
"license": "MIT",
|
|
98
|
+
"keywords": [
|
|
99
|
+
"adonisjs",
|
|
100
|
+
"cache",
|
|
101
|
+
"caching",
|
|
102
|
+
"bentocache"
|
|
103
|
+
],
|
|
104
|
+
"eslintConfig": {
|
|
105
|
+
"extends": "@adonisjs/eslint-config/package"
|
|
106
|
+
},
|
|
107
|
+
"prettier": "@adonisjs/prettier-config",
|
|
108
|
+
"publishConfig": {
|
|
109
|
+
"access": "public",
|
|
110
|
+
"tag": "latest"
|
|
111
|
+
},
|
|
112
|
+
"np": {
|
|
113
|
+
"message": "chore(release): %s",
|
|
114
|
+
"tag": "latest",
|
|
115
|
+
"branch": "main",
|
|
116
|
+
"anyBranch": false
|
|
117
|
+
},
|
|
118
|
+
"c8": {
|
|
119
|
+
"reporter": [
|
|
120
|
+
"text",
|
|
121
|
+
"html"
|
|
122
|
+
],
|
|
123
|
+
"exclude": [
|
|
124
|
+
"tests/**"
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|