/
Piece.ts
160 lines (139 loc) · 3.96 KB
/
Piece.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import type { Awaitable } from '@sapphire/utilities';
import { container, type Container } from '../shared/Container';
import { PieceLocation, type PieceLocationJSON } from './PieceLocation';
import type { Store } from './Store';
import type { StoreOf, StoreRegistryKey } from './StoreRegistry';
/**
* The context for the piece, contains extra information from the store,
* the piece's path, and the store that loaded it.
*/
export interface LoaderPieceContext<StoreName extends StoreRegistryKey = StoreRegistryKey> {
/**
* The root directory the piece was loaded from.
*/
readonly root: string;
/**
* The path the module was loaded from, relative to {@link LoaderPieceContext.root}.
*/
readonly path: string;
/**
* The module's name extracted from the path.
*/
readonly name: string;
/**
* The store that loaded the piece.
*/
readonly store: StoreOf<StoreName>;
}
/** @deprecated Use {@linkcode LoaderPieceContext} instead. */
export interface PieceContext<StoreName extends StoreRegistryKey = StoreRegistryKey> extends LoaderPieceContext<StoreName> {}
/**
* The options for the {@link Piece}.
*/
export interface PieceOptions {
/**
* The name for the piece.
* @default ''
*/
readonly name?: string;
/**
* Whether or not the piece should be enabled. If set to false, the piece will be unloaded.
* @default true
*/
readonly enabled?: boolean;
}
/**
* The piece to be stored in {@link Store} instances.
*/
export class Piece<Options extends PieceOptions = PieceOptions, StoreName extends StoreRegistryKey = StoreRegistryKey> {
/**
* The store that contains the piece.
*/
public readonly store: StoreOf<StoreName>;
/**
* The location metadata for the piece's file.
*/
public readonly location: PieceLocation;
/**
* The name of the piece.
*/
public readonly name: string;
/**
* Whether or not the piece is enabled.
*/
public enabled: boolean;
/**
* The raw options passed to this {@link Piece}
*/
public readonly options: Options;
public constructor(context: Piece.LoaderContext<StoreName>, options: PieceOptions = {}) {
this.store = context.store;
this.location = new PieceLocation(context.path, context.root);
this.name = options.name ?? context.name;
this.enabled = options.enabled ?? true;
this.options = options as Options;
}
/**
* A reference to the {@link Container} object for ease of use.
* @see container
*/
public get container(): Container {
return container;
}
/**
* Per-piece listener that is called when the piece is loaded into the store.
* Useful to set-up asynchronous initialization tasks.
*/
public onLoad(): Awaitable<unknown> {
return undefined;
}
/**
* Per-piece listener that is called when the piece is unloaded from the store.
* Useful to set-up clean-up tasks.
*/
public onUnload(): Awaitable<unknown> {
return undefined;
}
/**
* Unloads and disables the piece.
*/
public async unload() {
await this.store.unload(this.name);
this.enabled = false;
}
/**
* Reloads the piece by loading the same path in the store.
*/
public async reload() {
await this.store.load(this.location.root, this.location.relative);
}
/**
* Defines the `JSON.stringify` behavior of this piece.
*/
public toJSON(): PieceJSON {
return {
location: this.location.toJSON(),
name: this.name,
enabled: this.enabled,
options: this.options
};
}
}
/**
* The return type of {@link Piece.toJSON}.
*/
export interface PieceJSON {
location: PieceLocationJSON;
name: string;
enabled: boolean;
options: PieceOptions;
}
export namespace Piece {
export const Location = PieceLocation;
export type Options = PieceOptions;
/** @deprecated Use {@linkcode LoaderContext} instead. */
export type Context<StoreName extends StoreRegistryKey = StoreRegistryKey> = LoaderPieceContext<StoreName>;
export type LoaderContext<StoreName extends StoreRegistryKey = StoreRegistryKey> = LoaderPieceContext<StoreName>;
export type JSON = PieceJSON;
export type LocationJSON = PieceLocationJSON;
}