@notur/sdk 1.4.6 → 1.5.3
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/README.md +44 -0
- package/bin/notur-create.js +24 -18
- package/bin/notur-doctor.js +123 -0
- package/bin/notur-pack.js +13 -7
- package/bin/notur-sync.js +199 -0
- package/bin/notur-validate.js +200 -0
- package/bin/notur.js +7 -1
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +7 -0
- package/dist/events.js.map +1 -1
- package/dist/hooks/useExtensionConfig.d.ts +23 -4
- package/dist/hooks/useExtensionConfig.d.ts.map +1 -1
- package/dist/hooks/useExtensionConfig.js +8 -1
- package/dist/hooks/useExtensionConfig.js.map +1 -1
- package/dist/hooks/useNavigate.d.ts +27 -6
- package/dist/hooks/useNavigate.d.ts.map +1 -1
- package/dist/hooks/useNavigate.js +11 -2
- package/dist/hooks/useNavigate.js.map +1 -1
- package/dist/hooks/useNoturEvent.d.ts +12 -0
- package/dist/hooks/useNoturEvent.d.ts.map +1 -1
- package/dist/hooks/useNoturEvent.js +12 -0
- package/dist/hooks/useNoturEvent.js.map +1 -1
- package/dist/hooks/usePermission.d.ts +10 -1
- package/dist/hooks/usePermission.d.ts.map +1 -1
- package/dist/hooks/usePermission.js +10 -1
- package/dist/hooks/usePermission.js.map +1 -1
- package/dist/hooks/useServerContext.d.ts +18 -3
- package/dist/hooks/useServerContext.d.ts.map +1 -1
- package/dist/hooks/useServerContext.js +8 -1
- package/dist/hooks/useServerContext.js.map +1 -1
- package/dist/hooks/useUserContext.d.ts +10 -2
- package/dist/hooks/useUserContext.d.ts.map +1 -1
- package/dist/hooks/useUserContext.js +2 -0
- package/dist/hooks/useUserContext.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +179 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/examples/red-button/extension.yaml +0 -10
- package/examples/red-button/package-lock.json +1665 -0
- package/examples/red-button/package.json +9 -6
- package/examples/red-button/tsconfig.json +1 -1
- package/package.json +12 -6
- package/examples/red-button/src/RedButtonExtension.php +0 -11
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const yaml = require('yaml');
|
|
6
|
+
|
|
7
|
+
const KNOWN_SLOTS = new Set([
|
|
8
|
+
'navbar', 'navbar.left', 'navbar.before', 'navbar.after',
|
|
9
|
+
'server.subnav', 'server.subnav.before', 'server.subnav.after', 'server.header', 'server.page', 'server.footer',
|
|
10
|
+
'server.terminal.buttons', 'server.console.header', 'server.console.info.before', 'server.console.info.after',
|
|
11
|
+
'server.console.sidebar', 'server.console.command', 'server.console.footer', 'server.files.actions',
|
|
12
|
+
'server.files.header', 'server.files.footer', 'server.files.dropdown', 'server.files.edit.before',
|
|
13
|
+
'server.files.edit.after', 'server.databases.before', 'server.databases.after', 'server.schedules.before',
|
|
14
|
+
'server.schedules.after', 'server.schedules.edit.before', 'server.schedules.edit.after', 'server.users.before',
|
|
15
|
+
'server.users.after', 'server.backups.before', 'server.backups.after', 'server.backups.dropdown',
|
|
16
|
+
'server.network.before', 'server.network.after', 'server.startup.before', 'server.startup.after',
|
|
17
|
+
'server.settings.before', 'server.settings.after', 'dashboard.header', 'dashboard.widgets',
|
|
18
|
+
'dashboard.serverlist.before', 'dashboard.serverlist.after', 'dashboard.serverrow.name.before',
|
|
19
|
+
'dashboard.serverrow.name.after', 'dashboard.serverrow.description.before', 'dashboard.serverrow.description.after',
|
|
20
|
+
'dashboard.serverrow.limits', 'dashboard.footer', 'dashboard.page', 'account.header', 'account.page',
|
|
21
|
+
'account.footer', 'account.subnav', 'account.subnav.before', 'account.subnav.after',
|
|
22
|
+
'account.overview.before', 'account.overview.after', 'account.api.before', 'account.api.after',
|
|
23
|
+
'account.ssh.before', 'account.ssh.after', 'auth.container.before', 'auth.container.after',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
function parseArgs() {
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const options = { path: '.', strict: false };
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
if (arg === '--strict') {
|
|
32
|
+
options.strict = true;
|
|
33
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
34
|
+
usage(0);
|
|
35
|
+
} else if (!arg.startsWith('-')) {
|
|
36
|
+
options.path = arg;
|
|
37
|
+
} else {
|
|
38
|
+
console.error(`Unknown argument: ${arg}`);
|
|
39
|
+
usage(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return options;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function usage(code) {
|
|
46
|
+
console.log(`Usage:
|
|
47
|
+
npx notur-validate [path]
|
|
48
|
+
npx @notur/sdk validate [path]
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
--strict Treat warnings as errors`);
|
|
52
|
+
process.exit(code);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readManifest(basePath, result) {
|
|
56
|
+
const manifestPath = ['extension.yaml', 'extension.yml']
|
|
57
|
+
.map(file => path.join(basePath, file))
|
|
58
|
+
.find(file => fs.existsSync(file));
|
|
59
|
+
if (!manifestPath) {
|
|
60
|
+
result.errors.push('extension.yaml not found.');
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
return yaml.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
result.errors.push(`extension.yaml could not be parsed: ${error.message}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function validateManifest(basePath, manifest, result) {
|
|
73
|
+
if (!manifest) return;
|
|
74
|
+
|
|
75
|
+
for (const field of ['id', 'name', 'version']) {
|
|
76
|
+
if (!manifest[field]) {
|
|
77
|
+
result.errors.push(`extension.yaml is missing required field: ${field}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (manifest.id && !/^[a-z0-9-]+\/[a-z0-9-]+$/.test(manifest.id)) {
|
|
82
|
+
result.errors.push(`extension id "${manifest.id}" must use vendor/name with lowercase letters, numbers, and hyphens.`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (manifest.frontend?.bundle) {
|
|
86
|
+
const bundlePath = path.join(basePath, manifest.frontend.bundle);
|
|
87
|
+
if (!fs.existsSync(bundlePath)) {
|
|
88
|
+
result.warnings.push(`frontend.bundle does not exist yet: ${manifest.frontend.bundle}. Run your build before packaging.`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const routes = manifest.backend?.routes;
|
|
93
|
+
if (routes && typeof routes === 'object') {
|
|
94
|
+
for (const [group, routeFile] of Object.entries(routes)) {
|
|
95
|
+
if (typeof routeFile !== 'string') {
|
|
96
|
+
result.errors.push(`backend.routes.${group} must be a string path.`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (!fs.existsSync(path.join(basePath, routeFile))) {
|
|
100
|
+
result.errors.push(`backend.routes.${group} points to missing file: ${routeFile}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function readPackage(basePath, result) {
|
|
107
|
+
const packagePath = path.join(basePath, 'package.json');
|
|
108
|
+
if (!fs.existsSync(packagePath)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
113
|
+
} catch (error) {
|
|
114
|
+
result.errors.push(`package.json could not be parsed: ${error.message}`);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function validatePackage(manifest, pkg, result) {
|
|
120
|
+
if (!manifest || !pkg) return;
|
|
121
|
+
|
|
122
|
+
const expectedName = manifest.id?.replace('/', '-');
|
|
123
|
+
if (expectedName && pkg.name && pkg.name !== expectedName) {
|
|
124
|
+
result.warnings.push(`package.json name "${pkg.name}" differs from manifest-derived "${expectedName}". Run npx notur-sync.`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (manifest.version && pkg.version && pkg.version !== manifest.version) {
|
|
128
|
+
result.warnings.push(`package.json version "${pkg.version}" differs from extension.yaml version "${manifest.version}". Run npx notur-sync.`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const script of ['build', 'pack', 'push', 'sync']) {
|
|
132
|
+
if (!pkg.scripts?.[script]) {
|
|
133
|
+
result.warnings.push(`package.json is missing "${script}" script.`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function validateFrontendSource(basePath, manifest, result) {
|
|
139
|
+
const indexPath = path.join(basePath, 'resources/frontend/src/index.tsx');
|
|
140
|
+
if (!fs.existsSync(indexPath)) {
|
|
141
|
+
if (manifest?.frontend) {
|
|
142
|
+
result.warnings.push('frontend is configured but resources/frontend/src/index.tsx was not found.');
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const source = fs.readFileSync(indexPath, 'utf8');
|
|
148
|
+
if (!source.includes('createExtension')) {
|
|
149
|
+
result.warnings.push('frontend entry does not appear to call createExtension().');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (manifest?.id && !source.includes(manifest.id)) {
|
|
153
|
+
result.warnings.push(`frontend entry does not appear to reference manifest id "${manifest.id}".`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const slotMatches = source.matchAll(/slot:\s*['"`]([^'"`]+)['"`]/g);
|
|
157
|
+
for (const match of slotMatches) {
|
|
158
|
+
if (!KNOWN_SLOTS.has(match[1])) {
|
|
159
|
+
result.warnings.push(`unknown slot id "${match[1]}". Check docs/slot-reference.md or SDK SlotId.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function printResult(result, strict) {
|
|
165
|
+
for (const warning of result.warnings) {
|
|
166
|
+
console.warn(`warning: ${warning}`);
|
|
167
|
+
}
|
|
168
|
+
for (const error of result.errors) {
|
|
169
|
+
console.error(`error: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const failed = result.errors.length > 0 || (strict && result.warnings.length > 0);
|
|
173
|
+
if (failed) {
|
|
174
|
+
console.error(`Notur validation failed (${result.errors.length} errors, ${result.warnings.length} warnings).`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log(`Notur validation passed (${result.warnings.length} warnings).`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function main() {
|
|
182
|
+
const options = parseArgs();
|
|
183
|
+
const basePath = path.resolve(options.path);
|
|
184
|
+
const result = { errors: [], warnings: [] };
|
|
185
|
+
|
|
186
|
+
if (!fs.existsSync(basePath) || !fs.statSync(basePath).isDirectory()) {
|
|
187
|
+
result.errors.push(`path does not exist or is not a directory: ${basePath}`);
|
|
188
|
+
printResult(result, options.strict);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const manifest = readManifest(basePath, result);
|
|
193
|
+
validateManifest(basePath, manifest, result);
|
|
194
|
+
const pkg = readPackage(basePath, result);
|
|
195
|
+
validatePackage(manifest, pkg, result);
|
|
196
|
+
validateFrontendSource(basePath, manifest, result);
|
|
197
|
+
printResult(result, options.strict);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
main();
|
package/bin/notur.js
CHANGED
|
@@ -8,6 +8,9 @@ const commands = {
|
|
|
8
8
|
pack: 'notur-pack.js',
|
|
9
9
|
keygen: 'notur-keygen.js',
|
|
10
10
|
push: 'notur-push.js',
|
|
11
|
+
sync: 'notur-sync.js',
|
|
12
|
+
validate: 'notur-validate.js',
|
|
13
|
+
doctor: 'notur-doctor.js',
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
const [command, ...args] = process.argv.slice(2);
|
|
@@ -19,10 +22,13 @@ Usage:
|
|
|
19
22
|
notur create <vendor/name> [options]
|
|
20
23
|
notur pack [path] [options]
|
|
21
24
|
notur push [path] --host <url> --key <token>
|
|
25
|
+
notur sync [path]
|
|
26
|
+
notur validate [path]
|
|
27
|
+
notur doctor [path]
|
|
22
28
|
notur keygen
|
|
23
29
|
|
|
24
30
|
Standalone bins are also available:
|
|
25
|
-
notur-create, notur-pack, notur-push, notur-keygen`);
|
|
31
|
+
notur-create, notur-pack, notur-push, notur-sync, notur-validate, notur-doctor, notur-keygen`);
|
|
26
32
|
process.exit(command ? 0 : 1);
|
|
27
33
|
}
|
|
28
34
|
|
package/dist/events.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export interface ScopedEventChannel {
|
|
2
|
+
/** Convert a local event name into the fully scoped global event name. */
|
|
2
3
|
eventName: (name: string) => string;
|
|
4
|
+
/** Emit a scoped event with optional payload data. */
|
|
3
5
|
emit: (name: string, data?: unknown) => void;
|
|
6
|
+
/** Subscribe to a scoped event. Returns an unsubscribe function. */
|
|
4
7
|
on: (name: string, callback: (data?: unknown) => void) => () => void;
|
|
5
8
|
}
|
|
6
9
|
/**
|
|
@@ -8,6 +11,13 @@ export interface ScopedEventChannel {
|
|
|
8
11
|
*
|
|
9
12
|
* This avoids accidental collisions in global event names by scoping
|
|
10
13
|
* all events to `ext:<extensionId>:<event>`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const channel = createScopedEventChannel('acme/tools');
|
|
18
|
+
* channel.emit('saved', { id: 1 });
|
|
19
|
+
* channel.on('saved', data => console.log(data));
|
|
20
|
+
* ```
|
|
11
21
|
*/
|
|
12
22
|
export declare function createScopedEventChannel(extensionId: string): ScopedEventChannel;
|
|
13
23
|
//# sourceMappingURL=events.d.ts.map
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CACxE;AAED
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IAC/B,0EAA0E;IAC1E,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,sDAAsD;IACtD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,oEAAoE;IACpE,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CACxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAchF"}
|
package/dist/events.js
CHANGED
|
@@ -4,6 +4,13 @@ import { getNoturApi } from './types';
|
|
|
4
4
|
*
|
|
5
5
|
* This avoids accidental collisions in global event names by scoping
|
|
6
6
|
* all events to `ext:<extensionId>:<event>`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const channel = createScopedEventChannel('acme/tools');
|
|
11
|
+
* channel.emit('saved', { id: 1 });
|
|
12
|
+
* channel.on('saved', data => console.log(data));
|
|
13
|
+
* ```
|
|
7
14
|
*/
|
|
8
15
|
export function createScopedEventChannel(extensionId) {
|
|
9
16
|
const api = getNoturApi();
|
package/dist/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAWtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IACxD,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAE1B,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,OAAO,WAAW,IAAI,IAAI,EAAE,CAAC;IAEzE,OAAO;QACH,SAAS;QACT,IAAI,EAAE,CAAC,IAAY,EAAE,IAAc,EAAQ,EAAE;YACzC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;QACD,EAAE,EAAE,CAAC,IAAY,EAAE,QAAkC,EAAgB,EAAE;YACnE,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3D,CAAC;KACJ,CAAC;AACN,CAAC"}
|
|
@@ -1,17 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Options for `useExtensionConfig()`.
|
|
3
|
+
*/
|
|
4
|
+
export interface UseExtensionConfigOptions<T> {
|
|
5
|
+
/** Override the Notur client API base URL. Defaults to `/api/client/notur`. */
|
|
2
6
|
baseUrl?: string;
|
|
7
|
+
/** Initial config value used before the first request completes. */
|
|
3
8
|
initial?: T;
|
|
9
|
+
/** Optional polling interval in milliseconds. Omit or set `0` to disable polling. */
|
|
4
10
|
pollInterval?: number;
|
|
5
11
|
}
|
|
6
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Return value from `useExtensionConfig()`.
|
|
14
|
+
*/
|
|
15
|
+
export interface ExtensionConfigState<T> {
|
|
16
|
+
/** Public settings object for the extension. */
|
|
7
17
|
config: T;
|
|
18
|
+
/** True while a request is in flight. */
|
|
8
19
|
loading: boolean;
|
|
20
|
+
/** Last error message, or `null` when config loaded successfully. */
|
|
9
21
|
error: string | null;
|
|
22
|
+
/** Re-fetch config immediately and resolve with the latest value. */
|
|
10
23
|
refresh: () => Promise<T>;
|
|
11
24
|
}
|
|
12
25
|
/**
|
|
13
|
-
* Fetch public extension settings exposed
|
|
26
|
+
* Fetch public extension settings exposed by `admin.settings` fields marked `public: true`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* const { config, loading, error, refresh } = useExtensionConfig('acme/red-button', {
|
|
31
|
+
* initial: { enabled: true },
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
14
34
|
*/
|
|
15
35
|
export declare function useExtensionConfig<T extends Record<string, any> = Record<string, any>>(extensionId: string, options?: UseExtensionConfigOptions<T>): ExtensionConfigState<T>;
|
|
16
|
-
export {};
|
|
17
36
|
//# sourceMappingURL=useExtensionConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExtensionConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"useExtensionConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC;IACxC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACnC,gDAAgD;IAChD,MAAM,EAAE,CAAC,CAAC;IACV,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,qEAAqE;IACrE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClF,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,yBAAyB,CAAC,CAAC,CAAM,GAC3C,oBAAoB,CAAC,CAAC,CAAC,CAoGzB"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* Fetch public extension settings exposed
|
|
3
|
+
* Fetch public extension settings exposed by `admin.settings` fields marked `public: true`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const { config, loading, error, refresh } = useExtensionConfig('acme/red-button', {
|
|
8
|
+
* initial: { enabled: true },
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
4
11
|
*/
|
|
5
12
|
export function useExtensionConfig(extensionId, options = {}) {
|
|
6
13
|
const { baseUrl, initial, pollInterval } = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExtensionConfig.js","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useExtensionConfig.js","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA4BjE;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAC9B,WAAmB,EACnB,UAAwC,EAAE;IAE1C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACnD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAI,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACX,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,OAAO,GAAG,EAAE;YACR,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC;QAC/B,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAgB,EAAE;;QAC/C,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAM,CAAC;YACnC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACrB,SAAS,CAAC,KAAK,CAAC,CAAC;gBACjB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,IAAI,mBAAmB,CAAC;QAC/C,MAAM,GAAG,GAAG,GAAG,OAAO,eAAe,WAAW,WAAW,CAAC;QAE5D,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC9B,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;gBACvC,WAAW,EAAE,aAAa;aAC7B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACf,IAAI,OAAO,GAAG,4BAA4B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACnF,IAAI,CAAC;oBACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACnC,IAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,EAAE,CAAC;wBAChB,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC3B,CAAC;gBACL,CAAC;gBAAC,WAAM,CAAC;oBACL,6BAA6B;gBACjC,CAAC;gBAED,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,CAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,mCAAI,EAAE,CAAM,CAAC;YAExC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACrB,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YAED,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,KAAI,0BAA0B,CAAC;YAC3D,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACrB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YACD,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpC,SAAS,CAAC,GAAG,EAAE;QACX,OAAO,EAAE,CAAC;IACd,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,YAAY,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;YACrC,OAAO;QACX,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE;YAC/B,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBACjB,gDAAgD;YACpD,CAAC,CAAC,CAAC;QACP,CAAC,EAAE,YAAY,CAAC,CAAC;QAEjB,OAAO,GAAG,EAAE;YACR,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5B,OAAO;QACH,MAAM;QACN,OAAO;QACP,KAAK;QACL,OAAO;KACV,CAAC;AACN,CAAC"}
|
|
@@ -1,12 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Options for `useNavigate()`.
|
|
3
|
+
*/
|
|
4
|
+
export interface UseNavigateOptions {
|
|
5
|
+
/** Owning extension id. Used to build `/notur/{extensionId}/...` URLs. */
|
|
2
6
|
extensionId: string;
|
|
3
7
|
}
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
6
|
-
* Navigates to `/notur/{extensionId}/{path}` using pushState.
|
|
9
|
+
* Options accepted by the navigate function returned from `useNavigate()`.
|
|
7
10
|
*/
|
|
8
|
-
export
|
|
11
|
+
export interface NavigateOptions {
|
|
12
|
+
/** Replace the current history entry instead of pushing a new one. */
|
|
9
13
|
replace?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Function returned by `useNavigate()`.
|
|
17
|
+
*/
|
|
18
|
+
export type NavigateFunction = (path: string, options?: NavigateOptions) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Returns a navigate function scoped to the extension route namespace.
|
|
21
|
+
*
|
|
22
|
+
* Navigates to `/notur/{extensionId}/{path}` using the browser History API and
|
|
23
|
+
* dispatches `popstate` so Notur route renderers update immediately.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* const navigate = useNavigate({ extensionId: 'acme/tools' });
|
|
28
|
+
* navigate('/settings');
|
|
29
|
+
* navigate('/overview', { replace: true });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function useNavigate({ extensionId }: UseNavigateOptions): NavigateFunction;
|
|
12
33
|
//# sourceMappingURL=useNavigate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNavigate.d.ts","sourceRoot":"","sources":["../../src/hooks/useNavigate.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"useNavigate.d.ts","sourceRoot":"","sources":["../../src/hooks/useNavigate.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,IAAI,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,EAAE,kBAAkB,GAAG,gBAAgB,CAcjF"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* Returns a navigate function scoped to the extension
|
|
4
|
-
*
|
|
3
|
+
* Returns a navigate function scoped to the extension route namespace.
|
|
4
|
+
*
|
|
5
|
+
* Navigates to `/notur/{extensionId}/{path}` using the browser History API and
|
|
6
|
+
* dispatches `popstate` so Notur route renderers update immediately.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const navigate = useNavigate({ extensionId: 'acme/tools' });
|
|
11
|
+
* navigate('/settings');
|
|
12
|
+
* navigate('/overview', { replace: true });
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
export function useNavigate({ extensionId }) {
|
|
7
16
|
return useCallback((path, options) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNavigate.js","sourceRoot":"","sources":["../../src/hooks/useNavigate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useNavigate.js","sourceRoot":"","sources":["../../src/hooks/useNavigate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAuBpC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,WAAW,EAAsB;IAC3D,OAAO,WAAW,CACd,CAAC,IAAY,EAAE,OAAyB,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,UAAU,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC;QACpF,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,EAAE,CAAC;YACnB,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACJ,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;QACD,yDAAyD;QACzD,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AACN,CAAC"}
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Subscribe to an inter-extension event.
|
|
3
|
+
*
|
|
3
4
|
* Automatically unsubscribes on unmount.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* useNoturEvent('acme:refresh', data => console.log(data));
|
|
9
|
+
* ```
|
|
4
10
|
*/
|
|
5
11
|
export declare function useNoturEvent(event: string, handler: (data?: unknown) => void): void;
|
|
6
12
|
/**
|
|
7
13
|
* Returns a function to emit events on the inter-extension event bus.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const emit = useEmitEvent();
|
|
18
|
+
* emit('acme:refresh', { source: 'button' });
|
|
19
|
+
* ```
|
|
8
20
|
*/
|
|
9
21
|
export declare function useEmitEvent(): (event: string, data?: unknown) => void;
|
|
10
22
|
//# sourceMappingURL=useNoturEvent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNoturEvent.d.ts","sourceRoot":"","sources":["../../src/hooks/useNoturEvent.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"useNoturEvent.d.ts","sourceRoot":"","sources":["../../src/hooks/useNoturEvent.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAMpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAKtE"}
|
|
@@ -2,7 +2,13 @@ import { useEffect, useCallback } from 'react';
|
|
|
2
2
|
import { getNoturApi } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Subscribe to an inter-extension event.
|
|
5
|
+
*
|
|
5
6
|
* Automatically unsubscribes on unmount.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* useNoturEvent('acme:refresh', data => console.log(data));
|
|
11
|
+
* ```
|
|
6
12
|
*/
|
|
7
13
|
export function useNoturEvent(event, handler) {
|
|
8
14
|
useEffect(() => {
|
|
@@ -13,6 +19,12 @@ export function useNoturEvent(event, handler) {
|
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
15
21
|
* Returns a function to emit events on the inter-extension event bus.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const emit = useEmitEvent();
|
|
26
|
+
* emit('acme:refresh', { source: 'button' });
|
|
27
|
+
* ```
|
|
16
28
|
*/
|
|
17
29
|
export function useEmitEvent() {
|
|
18
30
|
return useCallback((event, data) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNoturEvent.js","sourceRoot":"","sources":["../../src/hooks/useNoturEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"useNoturEvent.js","sourceRoot":"","sources":["../../src/hooks/useNoturEvent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,OAAiC;IAC1E,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,WAAW,CAAC;IACvB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IACxB,OAAO,WAAW,CAAC,CAAC,KAAa,EAAE,IAAc,EAAE,EAAE;QACjD,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACxC,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Check whether the current server user has a permission.
|
|
3
|
+
*
|
|
4
|
+
* This hook reads server context permissions when available. It returns `false`
|
|
5
|
+
* outside server pages, while context is unavailable, or when the permission is
|
|
6
|
+
* missing. Server owners are treated as allowed.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const canInstall = usePermission('notur.acme/tools.install');
|
|
11
|
+
* ```
|
|
3
12
|
*/
|
|
4
13
|
export declare function usePermission(permission: string): boolean;
|
|
5
14
|
//# sourceMappingURL=usePermission.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePermission.d.ts","sourceRoot":"","sources":["../../src/hooks/usePermission.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"usePermission.d.ts","sourceRoot":"","sources":["../../src/hooks/usePermission.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAwBzD"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import { useServerContext } from './useServerContext';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Check whether the current server user has a permission.
|
|
5
|
+
*
|
|
6
|
+
* This hook reads server context permissions when available. It returns `false`
|
|
7
|
+
* outside server pages, while context is unavailable, or when the permission is
|
|
8
|
+
* missing. Server owners are treated as allowed.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const canInstall = usePermission('notur.acme/tools.install');
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
export function usePermission(permission) {
|
|
7
16
|
const serverContext = useServerContext();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePermission.js","sourceRoot":"","sources":["../../src/hooks/usePermission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD
|
|
1
|
+
{"version":3,"file":"usePermission.js","sourceRoot":"","sources":["../../src/hooks/usePermission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC5C,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO;QACX,CAAC;QAED,iBAAiB;QACjB,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YACxB,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,OAAO;QACX,CAAC;QAED,0BAA0B;QAC1B,MAAM,KAAK,GAAG,aAAa,CAAC,WAAW,IAAI,EAAE,CAAC;QAC9C,gBAAgB,CACZ,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAChE,CAAC;IACN,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;IAEhC,OAAO,aAAa,CAAC;AACzB,CAAC"}
|
|
@@ -1,15 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Server metadata available when the current page is scoped to a Pterodactyl server.
|
|
3
|
+
*/
|
|
4
|
+
export interface ServerContext {
|
|
5
|
+
/** Server UUID from the current URL or panel data payload. */
|
|
2
6
|
uuid: string;
|
|
7
|
+
/** Server display name when available. */
|
|
3
8
|
name: string;
|
|
9
|
+
/** Node name/identifier when available. */
|
|
4
10
|
node: string;
|
|
11
|
+
/** True when the current user owns the server or has owner-level access. */
|
|
5
12
|
isOwner: boolean;
|
|
13
|
+
/** Runtime status reported by the panel, or `null` when unknown. */
|
|
6
14
|
status: string | null;
|
|
15
|
+
/** Server permission keys available to the current user. */
|
|
7
16
|
permissions: string[];
|
|
8
17
|
}
|
|
9
18
|
/**
|
|
10
19
|
* Hook to access the current server context from the Pterodactyl panel.
|
|
11
|
-
*
|
|
20
|
+
*
|
|
21
|
+
* Returns `null` outside server-scoped pages or while context is unavailable.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const server = useServerContext();
|
|
26
|
+
* return <span>{server?.uuid}</span>;
|
|
27
|
+
* ```
|
|
12
28
|
*/
|
|
13
29
|
export declare function useServerContext(): ServerContext | null;
|
|
14
|
-
export {};
|
|
15
30
|
//# sourceMappingURL=useServerContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useServerContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useServerContext.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"useServerContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useServerContext.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CA0BvD"}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* Hook to access the current server context from the Pterodactyl panel.
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Returns `null` outside server-scoped pages or while context is unavailable.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const server = useServerContext();
|
|
10
|
+
* return <span>{server?.uuid}</span>;
|
|
11
|
+
* ```
|
|
5
12
|
*/
|
|
6
13
|
export function useServerContext() {
|
|
7
14
|
const [context, setContext] = useState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useServerContext.js","sourceRoot":"","sources":["../../src/hooks/useServerContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useServerContext.js","sourceRoot":"","sources":["../../src/hooks/useServerContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoB5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB;IAC5B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAuB,IAAI,CAAC,CAAC;IAEnE,SAAS,CAAC,GAAG,EAAE;QACX,oEAAoE;QACpE,uDAAuD;QACvD,MAAM,aAAa,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,CAAC,aAAa;YAAE,OAAO;QAE3B,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;QAChD,IAAI,UAAU,EAAE,CAAC;YACb,IAAI,CAAC;gBACD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACvC,CAAC;YAAC,WAAM,CAAC;gBACL,uBAAuB;YAC3B,CAAC;QACL,CAAC;QAED,qCAAqC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACvE,IAAI,KAAK,EAAE,CAAC;YACR,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QACtH,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,OAAO,CAAC;AACnB,CAAC"}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Current Pterodactyl user metadata returned by `useUserContext()`.
|
|
3
|
+
*/
|
|
4
|
+
export interface UserContext {
|
|
5
|
+
/** User UUID. */
|
|
2
6
|
uuid: string;
|
|
7
|
+
/** Username shown in the panel. */
|
|
3
8
|
username: string;
|
|
9
|
+
/** User email address. */
|
|
4
10
|
email: string;
|
|
11
|
+
/** True when the user is a root/admin user. */
|
|
5
12
|
isAdmin: boolean;
|
|
6
13
|
}
|
|
7
14
|
/**
|
|
8
15
|
* Hook to access the current user context from the Pterodactyl panel.
|
|
16
|
+
*
|
|
17
|
+
* Returns `null` while loading or when the user cannot be resolved.
|
|
9
18
|
*/
|
|
10
19
|
export declare function useUserContext(): UserContext | null;
|
|
11
|
-
export {};
|
|
12
20
|
//# sourceMappingURL=useUserContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUserContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserContext.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"useUserContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserContext.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAiDnD"}
|