@notur/sdk 1.4.5 → 1.4.7

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.
Files changed (51) hide show
  1. package/README.md +136 -1
  2. package/bin/notur-create.js +586 -0
  3. package/bin/notur-doctor.js +123 -0
  4. package/bin/notur-pack.js +13 -7
  5. package/bin/notur-push.js +331 -0
  6. package/bin/notur-sync.js +199 -0
  7. package/bin/notur-validate.js +200 -0
  8. package/bin/notur.js +46 -0
  9. package/dist/events.d.ts +10 -0
  10. package/dist/events.d.ts.map +1 -1
  11. package/dist/events.js +7 -0
  12. package/dist/events.js.map +1 -1
  13. package/dist/hooks/useExtensionConfig.d.ts +23 -4
  14. package/dist/hooks/useExtensionConfig.d.ts.map +1 -1
  15. package/dist/hooks/useExtensionConfig.js +8 -1
  16. package/dist/hooks/useExtensionConfig.js.map +1 -1
  17. package/dist/hooks/useNavigate.d.ts +27 -6
  18. package/dist/hooks/useNavigate.d.ts.map +1 -1
  19. package/dist/hooks/useNavigate.js +11 -2
  20. package/dist/hooks/useNavigate.js.map +1 -1
  21. package/dist/hooks/useNoturEvent.d.ts +12 -0
  22. package/dist/hooks/useNoturEvent.d.ts.map +1 -1
  23. package/dist/hooks/useNoturEvent.js +12 -0
  24. package/dist/hooks/useNoturEvent.js.map +1 -1
  25. package/dist/hooks/usePermission.d.ts +10 -1
  26. package/dist/hooks/usePermission.d.ts.map +1 -1
  27. package/dist/hooks/usePermission.js +10 -1
  28. package/dist/hooks/usePermission.js.map +1 -1
  29. package/dist/hooks/useServerContext.d.ts +18 -3
  30. package/dist/hooks/useServerContext.d.ts.map +1 -1
  31. package/dist/hooks/useServerContext.js +8 -1
  32. package/dist/hooks/useServerContext.js.map +1 -1
  33. package/dist/hooks/useUserContext.d.ts +10 -2
  34. package/dist/hooks/useUserContext.d.ts.map +1 -1
  35. package/dist/hooks/useUserContext.js +2 -0
  36. package/dist/hooks/useUserContext.js.map +1 -1
  37. package/dist/index.d.ts +6 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/types.d.ts +179 -20
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/types.js +6 -1
  43. package/dist/types.js.map +1 -1
  44. package/examples/red-button/.env.example +2 -0
  45. package/examples/red-button/README.md +30 -0
  46. package/examples/red-button/extension.yaml +9 -0
  47. package/examples/red-button/package.json +29 -0
  48. package/examples/red-button/resources/frontend/src/index.tsx +32 -0
  49. package/examples/red-button/tsconfig.json +13 -0
  50. package/examples/red-button/webpack.config.js +17 -0
  51. package/package.json +11 -3
@@ -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 ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const { spawnSync } = require('child_process');
5
+
6
+ const commands = {
7
+ create: 'notur-create.js',
8
+ pack: 'notur-pack.js',
9
+ keygen: 'notur-keygen.js',
10
+ push: 'notur-push.js',
11
+ sync: 'notur-sync.js',
12
+ validate: 'notur-validate.js',
13
+ doctor: 'notur-doctor.js',
14
+ };
15
+
16
+ const [command, ...args] = process.argv.slice(2);
17
+
18
+ if (!command || command === '--help' || command === '-h') {
19
+ console.log(`Notur SDK CLI
20
+
21
+ Usage:
22
+ notur create <vendor/name> [options]
23
+ notur pack [path] [options]
24
+ notur push [path] --host <url> --key <token>
25
+ notur sync [path]
26
+ notur validate [path]
27
+ notur doctor [path]
28
+ notur keygen
29
+
30
+ Standalone bins are also available:
31
+ notur-create, notur-pack, notur-push, notur-sync, notur-validate, notur-doctor, notur-keygen`);
32
+ process.exit(command ? 0 : 1);
33
+ }
34
+
35
+ const script = commands[command];
36
+ if (!script) {
37
+ console.error(`Unknown command: ${command}`);
38
+ console.error('Run "notur --help" for usage.');
39
+ process.exit(1);
40
+ }
41
+
42
+ const result = spawnSync(process.execPath, [path.join(__dirname, script), ...args], {
43
+ stdio: 'inherit',
44
+ });
45
+
46
+ process.exit(result.status ?? 1);
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
@@ -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;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAchF"}
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();
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQtC;;;;;GAKG;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
+ {"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
- interface UseExtensionConfigOptions<T> {
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
- interface ExtensionConfigState<T> {
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 via admin.settings.*.public.
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,UAAU,yBAAyB,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,oBAAoB,CAAC,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC;IACV,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED;;GAEG;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
+ {"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 via admin.settings.*.public.
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":"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"}
1
+ {"version":3,"file":"useExtensionConfig.js","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,33 @@
1
- interface UseNavigateOptions {
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
- * Returns a navigate function scoped to the extension's route namespace.
6
- * Navigates to `/notur/{extensionId}/{path}` using pushState.
9
+ * Options accepted by the navigate function returned from `useNavigate()`.
7
10
  */
8
- export declare function useNavigate({ extensionId }: UseNavigateOptions): (path: string, options?: {
11
+ export interface NavigateOptions {
12
+ /** Replace the current history entry instead of pushing a new one. */
9
13
  replace?: boolean;
10
- }) => void;
11
- export {};
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,UAAU,kBAAkB;IACxB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,EAAE,kBAAkB,UAEhD,MAAM,YAAY;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,UAYrD"}
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's route namespace.
4
- * Navigates to `/notur/{extensionId}/{path}` using pushState.
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;AAMpC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,WAAW,EAAsB;IAC3D,OAAO,WAAW,CACd,CAAC,IAAY,EAAE,OAA+B,EAAE,EAAE;QAC9C,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
+ {"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;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAMpF;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAKtE"}
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;;;GAGG;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;;GAEG;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
+ {"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
- * Hook to check if the current user has a specific extension permission.
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;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAwBzD"}
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
- * Hook to check if the current user has a specific extension permission.
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;;GAEG;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
+ {"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
- interface ServerContext {
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
- * Only available within server-scoped pages.
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,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CA0BvD"}
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
- * Only available within server-scoped pages.
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;AAW5C;;;GAGG;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
+ {"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"}