@notur/sdk 1.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/dist/createExtension.d.ts +21 -0
- package/dist/createExtension.d.ts.map +1 -0
- package/dist/createExtension.js +65 -0
- package/dist/createExtension.js.map +1 -0
- package/dist/hooks/useExtensionConfig.d.ts +17 -0
- package/dist/hooks/useExtensionConfig.d.ts.map +1 -0
- package/dist/hooks/useExtensionConfig.js +94 -0
- package/dist/hooks/useExtensionConfig.js.map +1 -0
- package/dist/hooks/useNavigate.d.ts +12 -0
- package/dist/hooks/useNavigate.d.ts.map +1 -0
- package/dist/hooks/useNavigate.js +19 -0
- package/dist/hooks/useNavigate.js.map +1 -0
- package/dist/hooks/useNoturEvent.d.ts +10 -0
- package/dist/hooks/useNoturEvent.d.ts.map +1 -0
- package/dist/hooks/useNoturEvent.js +23 -0
- package/dist/hooks/useNoturEvent.js.map +1 -0
- package/dist/hooks/usePermission.d.ts +5 -0
- package/dist/hooks/usePermission.d.ts.map +1 -0
- package/dist/hooks/usePermission.js +25 -0
- package/dist/hooks/usePermission.js.map +1 -0
- package/dist/hooks/useServerContext.d.ts +15 -0
- package/dist/hooks/useServerContext.d.ts.map +1 -0
- package/dist/hooks/useServerContext.js +31 -0
- package/dist/hooks/useServerContext.js.map +1 -0
- package/dist/hooks/useUserContext.d.ts +12 -0
- package/dist/hooks/useUserContext.d.ts.map +1 -0
- package/dist/hooks/useUserContext.js +38 -0
- package/dist/hooks/useUserContext.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +146 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
- package/templates/ExampleComponent.tsx.template +40 -0
- package/templates/ServiceProvider.php.template +54 -0
- package/templates/extension.yaml.template +43 -0
- package/webpack.extension.config.js +52 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ExtensionDefinition } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Factory for registering a Notur extension.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createExtension } from '@notur/sdk';
|
|
8
|
+
*
|
|
9
|
+
* createExtension({
|
|
10
|
+
* config: { id: 'acme/analytics', name: 'Analytics', version: '1.0.0' },
|
|
11
|
+
* slots: [
|
|
12
|
+
* { slot: 'dashboard.widgets', component: AnalyticsWidget, order: 10 },
|
|
13
|
+
* ],
|
|
14
|
+
* routes: [
|
|
15
|
+
* { area: 'server', path: '/analytics', name: 'Analytics', component: AnalyticsPage },
|
|
16
|
+
* ],
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function createExtension(definition: ExtensionDefinition): void;
|
|
21
|
+
//# sourceMappingURL=createExtension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createExtension.d.ts","sourceRoot":"","sources":["../src/createExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAe,MAAM,SAAS,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,IAAI,CA+BrE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { getNoturApi } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Factory for registering a Notur extension.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createExtension } from '@notur/sdk';
|
|
8
|
+
*
|
|
9
|
+
* createExtension({
|
|
10
|
+
* config: { id: 'acme/analytics', name: 'Analytics', version: '1.0.0' },
|
|
11
|
+
* slots: [
|
|
12
|
+
* { slot: 'dashboard.widgets', component: AnalyticsWidget, order: 10 },
|
|
13
|
+
* ],
|
|
14
|
+
* routes: [
|
|
15
|
+
* { area: 'server', path: '/analytics', name: 'Analytics', component: AnalyticsPage },
|
|
16
|
+
* ],
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function createExtension(definition) {
|
|
21
|
+
const { config, slots = [], routes = [], onInit, onDestroy, cssIsolation } = definition;
|
|
22
|
+
const api = getNoturApi();
|
|
23
|
+
const resolvedCssIsolation = resolveCssIsolation(api, config.id, cssIsolation);
|
|
24
|
+
// Register the extension
|
|
25
|
+
api.registry.registerExtension({
|
|
26
|
+
id: config.id,
|
|
27
|
+
name: config.name,
|
|
28
|
+
version: config.version,
|
|
29
|
+
slots: slots.map(s => ({ ...s, extensionId: config.id })),
|
|
30
|
+
routes: routes.map(r => ({ ...r, extensionId: config.id })),
|
|
31
|
+
cssIsolation: resolvedCssIsolation,
|
|
32
|
+
});
|
|
33
|
+
// Register destroy callback
|
|
34
|
+
if (onDestroy) {
|
|
35
|
+
api.registry.registerDestroyCallback(config.id, onDestroy);
|
|
36
|
+
}
|
|
37
|
+
// Run init callback
|
|
38
|
+
if (onInit) {
|
|
39
|
+
try {
|
|
40
|
+
onInit();
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
console.error(`[Notur] Extension ${config.id} init error:`, e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
console.log(`[Notur] Extension registered: ${config.id} v${config.version}`);
|
|
47
|
+
}
|
|
48
|
+
function resolveCssIsolation(api, extensionId, local) {
|
|
49
|
+
var _a, _b;
|
|
50
|
+
if (local === true) {
|
|
51
|
+
return { mode: 'root-class' };
|
|
52
|
+
}
|
|
53
|
+
if (local && typeof local === 'object') {
|
|
54
|
+
return local;
|
|
55
|
+
}
|
|
56
|
+
const manifestConfig = (_b = (_a = api.extensions) === null || _a === void 0 ? void 0 : _a.find(ext => ext.id === extensionId)) === null || _b === void 0 ? void 0 : _b.cssIsolation;
|
|
57
|
+
if (manifestConfig && typeof manifestConfig === 'object') {
|
|
58
|
+
if ('class' in manifestConfig && !manifestConfig.className) {
|
|
59
|
+
return { ...manifestConfig, className: manifestConfig.class };
|
|
60
|
+
}
|
|
61
|
+
return manifestConfig;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=createExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createExtension.js","sourceRoot":"","sources":["../src/createExtension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAAC,UAA+B;IAC3D,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,UAAU,CAAC;IACxF,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAE1B,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;IAE/E,yBAAyB;IACzB,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC3B,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3D,YAAY,EAAE,oBAAoB;KACrC,CAAC,CAAC;IAEH,4BAA4B;IAC5B,IAAI,SAAS,EAAE,CAAC;QACZ,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED,oBAAoB;IACpB,IAAI,MAAM,EAAE,CAAC;QACT,IAAI,CAAC;YACD,MAAM,EAAE,CAAC;QACb,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,mBAAmB,CACxB,GAAmC,EACnC,WAAmB,EACnB,KAA2C;;IAE3C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,YAAqB,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,cAAc,GAAG,MAAA,MAAA,GAAG,CAAC,UAAU,0CAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,WAAW,CAAC,0CAAE,YAAY,CAAC;IACzF,IAAI,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;QACvD,IAAI,OAAO,IAAK,cAAsB,IAAI,CAAE,cAAsB,CAAC,SAAS,EAAE,CAAC;YAC3E,OAAO,EAAE,GAAG,cAAc,EAAE,SAAS,EAAG,cAAsB,CAAC,KAAK,EAAE,CAAC;QAC3E,CAAC;QACD,OAAO,cAAc,CAAC;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface UseExtensionConfigOptions<T> {
|
|
2
|
+
baseUrl?: string;
|
|
3
|
+
initial?: T;
|
|
4
|
+
pollInterval?: number;
|
|
5
|
+
}
|
|
6
|
+
interface ExtensionConfigState<T> {
|
|
7
|
+
config: T;
|
|
8
|
+
loading: boolean;
|
|
9
|
+
error: string | null;
|
|
10
|
+
refresh: () => Promise<T>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fetch public extension settings exposed via admin.settings.*.public.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useExtensionConfig<T extends Record<string, any> = Record<string, any>>(extensionId: string, options?: UseExtensionConfigOptions<T>): ExtensionConfigState<T>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=useExtensionConfig.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Fetch public extension settings exposed via admin.settings.*.public.
|
|
4
|
+
*/
|
|
5
|
+
export function useExtensionConfig(extensionId, options = {}) {
|
|
6
|
+
const { baseUrl, initial, pollInterval } = options;
|
|
7
|
+
const [config, setConfig] = useState((initial !== null && initial !== void 0 ? initial : {}));
|
|
8
|
+
const [loading, setLoading] = useState(true);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
const mountedRef = useRef(true);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
mountedRef.current = true;
|
|
13
|
+
return () => {
|
|
14
|
+
mountedRef.current = false;
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
const refresh = useCallback(async () => {
|
|
18
|
+
var _a;
|
|
19
|
+
if (!extensionId) {
|
|
20
|
+
const empty = (initial !== null && initial !== void 0 ? initial : {});
|
|
21
|
+
if (mountedRef.current) {
|
|
22
|
+
setConfig(empty);
|
|
23
|
+
setLoading(false);
|
|
24
|
+
setError(null);
|
|
25
|
+
}
|
|
26
|
+
return empty;
|
|
27
|
+
}
|
|
28
|
+
if (mountedRef.current) {
|
|
29
|
+
setLoading(true);
|
|
30
|
+
setError(null);
|
|
31
|
+
}
|
|
32
|
+
const apiBase = baseUrl || '/api/client/notur';
|
|
33
|
+
const url = `${apiBase}/extensions/${extensionId}/settings`;
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
method: 'GET',
|
|
37
|
+
headers: { Accept: 'application/json' },
|
|
38
|
+
credentials: 'same-origin',
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
let message = `Settings request failed: ${response.status} ${response.statusText}`;
|
|
42
|
+
try {
|
|
43
|
+
const body = await response.json();
|
|
44
|
+
if (body === null || body === void 0 ? void 0 : body.message) {
|
|
45
|
+
message = body.message;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (_b) {
|
|
49
|
+
// Ignore JSON parse failures
|
|
50
|
+
}
|
|
51
|
+
throw new Error(message);
|
|
52
|
+
}
|
|
53
|
+
const payload = await response.json();
|
|
54
|
+
const data = ((_a = payload === null || payload === void 0 ? void 0 : payload.data) !== null && _a !== void 0 ? _a : {});
|
|
55
|
+
if (mountedRef.current) {
|
|
56
|
+
setConfig(data);
|
|
57
|
+
setLoading(false);
|
|
58
|
+
setError(null);
|
|
59
|
+
}
|
|
60
|
+
return data;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const message = (err === null || err === void 0 ? void 0 : err.message) || 'Failed to load settings.';
|
|
64
|
+
if (mountedRef.current) {
|
|
65
|
+
setLoading(false);
|
|
66
|
+
setError(message);
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}, [baseUrl, extensionId, initial]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
refresh();
|
|
73
|
+
}, [refresh]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!pollInterval || pollInterval <= 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const id = window.setInterval(() => {
|
|
79
|
+
refresh().catch(() => {
|
|
80
|
+
// ignore polling errors; surface via hook state
|
|
81
|
+
});
|
|
82
|
+
}, pollInterval);
|
|
83
|
+
return () => {
|
|
84
|
+
window.clearInterval(id);
|
|
85
|
+
};
|
|
86
|
+
}, [pollInterval, refresh]);
|
|
87
|
+
return {
|
|
88
|
+
config,
|
|
89
|
+
loading,
|
|
90
|
+
error,
|
|
91
|
+
refresh,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=useExtensionConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExtensionConfig.js","sourceRoot":"","sources":["../../src/hooks/useExtensionConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface UseNavigateOptions {
|
|
2
|
+
extensionId: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Returns a navigate function scoped to the extension's route namespace.
|
|
6
|
+
* Navigates to `/notur/{extensionId}/{path}` using pushState.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useNavigate({ extensionId }: UseNavigateOptions): (path: string, options?: {
|
|
9
|
+
replace?: boolean;
|
|
10
|
+
}) => void;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=useNavigate.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a navigate function scoped to the extension's route namespace.
|
|
4
|
+
* Navigates to `/notur/{extensionId}/{path}` using pushState.
|
|
5
|
+
*/
|
|
6
|
+
export function useNavigate({ extensionId }) {
|
|
7
|
+
return useCallback((path, options) => {
|
|
8
|
+
const fullPath = `/notur/${extensionId}${path.startsWith('/') ? path : '/' + path}`;
|
|
9
|
+
if (options === null || options === void 0 ? void 0 : options.replace) {
|
|
10
|
+
window.history.replaceState(null, '', fullPath);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
window.history.pushState(null, '', fullPath);
|
|
14
|
+
}
|
|
15
|
+
// Dispatch popstate so RouteRenderer picks up the change
|
|
16
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
17
|
+
}, [extensionId]);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=useNavigate.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe to an inter-extension event.
|
|
3
|
+
* Automatically unsubscribes on unmount.
|
|
4
|
+
*/
|
|
5
|
+
export declare function useNoturEvent(event: string, handler: (data?: unknown) => void): void;
|
|
6
|
+
/**
|
|
7
|
+
* Returns a function to emit events on the inter-extension event bus.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useEmitEvent(): (event: string, data?: unknown) => void;
|
|
10
|
+
//# sourceMappingURL=useNoturEvent.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useCallback } from 'react';
|
|
2
|
+
import { getNoturApi } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Subscribe to an inter-extension event.
|
|
5
|
+
* Automatically unsubscribes on unmount.
|
|
6
|
+
*/
|
|
7
|
+
export function useNoturEvent(event, handler) {
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const api = getNoturApi();
|
|
10
|
+
const unsubscribe = api.registry.onEvent(event, handler);
|
|
11
|
+
return unsubscribe;
|
|
12
|
+
}, [event, handler]);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns a function to emit events on the inter-extension event bus.
|
|
16
|
+
*/
|
|
17
|
+
export function useEmitEvent() {
|
|
18
|
+
return useCallback((event, data) => {
|
|
19
|
+
const api = getNoturApi();
|
|
20
|
+
api.registry.emitEvent(event, data);
|
|
21
|
+
}, []);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=useNoturEvent.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useServerContext } from './useServerContext';
|
|
3
|
+
/**
|
|
4
|
+
* Hook to check if the current user has a specific extension permission.
|
|
5
|
+
*/
|
|
6
|
+
export function usePermission(permission) {
|
|
7
|
+
const serverContext = useServerContext();
|
|
8
|
+
const [hasPermission, setHasPermission] = useState(false);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!serverContext) {
|
|
11
|
+
setHasPermission(false);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Admin override
|
|
15
|
+
if (serverContext.isOwner) {
|
|
16
|
+
setHasPermission(true);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Check permissions array
|
|
20
|
+
const perms = serverContext.permissions || [];
|
|
21
|
+
setHasPermission(perms.includes('*') || perms.includes(permission));
|
|
22
|
+
}, [serverContext, permission]);
|
|
23
|
+
return hasPermission;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=usePermission.js.map
|
|
@@ -0,0 +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,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CACpD,CAAC;IACN,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;IAEhC,OAAO,aAAa,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface ServerContext {
|
|
2
|
+
uuid: string;
|
|
3
|
+
name: string;
|
|
4
|
+
node: string;
|
|
5
|
+
isOwner: boolean;
|
|
6
|
+
status: string | null;
|
|
7
|
+
permissions: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access the current server context from the Pterodactyl panel.
|
|
11
|
+
* Only available within server-scoped pages.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useServerContext(): ServerContext | null;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=useServerContext.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access the current server context from the Pterodactyl panel.
|
|
4
|
+
* Only available within server-scoped pages.
|
|
5
|
+
*/
|
|
6
|
+
export function useServerContext() {
|
|
7
|
+
const [context, setContext] = useState(null);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
// Pterodactyl stores server data in the ServerContext React context
|
|
10
|
+
// We read it from the DOM data attribute as a fallback
|
|
11
|
+
const serverElement = document.getElementById('app');
|
|
12
|
+
if (!serverElement)
|
|
13
|
+
return;
|
|
14
|
+
const serverData = serverElement.dataset.server;
|
|
15
|
+
if (serverData) {
|
|
16
|
+
try {
|
|
17
|
+
setContext(JSON.parse(serverData));
|
|
18
|
+
}
|
|
19
|
+
catch (_a) {
|
|
20
|
+
// Not on a server page
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Also check the URL for server UUID
|
|
24
|
+
const match = window.location.pathname.match(/\/server\/([a-f0-9-]+)/);
|
|
25
|
+
if (match) {
|
|
26
|
+
setContext(prev => prev || { uuid: match[1], name: '', node: '', isOwner: false, status: null, permissions: [] });
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=useServerContext.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface UserContext {
|
|
2
|
+
uuid: string;
|
|
3
|
+
username: string;
|
|
4
|
+
email: string;
|
|
5
|
+
isAdmin: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Hook to access the current user context from the Pterodactyl panel.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useUserContext(): UserContext | null;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=useUserContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUserContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useUserContext.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAoCnD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access the current user context from the Pterodactyl panel.
|
|
4
|
+
*/
|
|
5
|
+
export function useUserContext() {
|
|
6
|
+
const [user, setUser] = useState(null);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
let cancelled = false;
|
|
9
|
+
// Try reading from Pterodactyl's global state
|
|
10
|
+
const storeState = window.PterodactylUser;
|
|
11
|
+
if (storeState) {
|
|
12
|
+
setUser(storeState);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
// Fallback: fetch from API
|
|
16
|
+
fetch('/api/client/account', {
|
|
17
|
+
headers: { Accept: 'application/json' },
|
|
18
|
+
credentials: 'same-origin',
|
|
19
|
+
})
|
|
20
|
+
.then(r => r.json())
|
|
21
|
+
.then(data => {
|
|
22
|
+
if (cancelled)
|
|
23
|
+
return;
|
|
24
|
+
if (data.attributes) {
|
|
25
|
+
setUser({
|
|
26
|
+
uuid: data.attributes.uuid,
|
|
27
|
+
username: data.attributes.username,
|
|
28
|
+
email: data.attributes.email,
|
|
29
|
+
isAdmin: data.attributes.admin || false,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.catch(() => { });
|
|
34
|
+
return () => { cancelled = true; };
|
|
35
|
+
}, []);
|
|
36
|
+
return user;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=useUserContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUserContext.js","sourceRoot":"","sources":["../../src/hooks/useUserContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAS5C;;GAEG;AACH,MAAM,UAAU,cAAc;IAC1B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAE3D,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,8CAA8C;QAC9C,MAAM,UAAU,GAAI,MAAc,CAAC,eAAe,CAAC;QACnD,IAAI,UAAU,EAAE,CAAC;YACb,OAAO,CAAC,UAAU,CAAC,CAAC;YACpB,OAAO;QACX,CAAC;QAED,2BAA2B;QAC3B,KAAK,CAAC,qBAAqB,EAAE;YACzB,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACvC,WAAW,EAAE,aAAa;SAC7B,CAAC;aACG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACnB,IAAI,CAAC,IAAI,CAAC,EAAE;YACT,IAAI,SAAS;gBAAE,OAAO;YACtB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,OAAO,CAAC;oBACJ,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI;oBAC1B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ;oBAClC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;oBAC5B,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,KAAK;iBAC1C,CAAC,CAAC;YACP,CAAC;QACL,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAErB,OAAO,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { createExtension } from './createExtension';
|
|
2
|
+
export { getNoturApi } from './types';
|
|
3
|
+
export type { ExtensionConfig, SlotConfig, RouteConfig, ExtensionDefinition, NoturApi, } from './types';
|
|
4
|
+
export { useServerContext } from './hooks/useServerContext';
|
|
5
|
+
export { useUserContext } from './hooks/useUserContext';
|
|
6
|
+
export { usePermission } from './hooks/usePermission';
|
|
7
|
+
export { useExtensionConfig } from './hooks/useExtensionConfig';
|
|
8
|
+
export { useNoturEvent, useEmitEvent } from './hooks/useNoturEvent';
|
|
9
|
+
export { useNavigate } from './hooks/useNavigate';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EACR,eAAe,EACf,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,QAAQ,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createExtension } from './createExtension';
|
|
2
|
+
export { getNoturApi } from './types';
|
|
3
|
+
export { useServerContext } from './hooks/useServerContext';
|
|
4
|
+
export { useUserContext } from './hooks/useUserContext';
|
|
5
|
+
export { usePermission } from './hooks/usePermission';
|
|
6
|
+
export { useExtensionConfig } from './hooks/useExtensionConfig';
|
|
7
|
+
export { useNoturEvent, useEmitEvent } from './hooks/useNoturEvent';
|
|
8
|
+
export { useNavigate } from './hooks/useNavigate';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export interface ExtensionConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CssIsolationConfig {
|
|
7
|
+
mode: 'root-class';
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SlotRenderContext {
|
|
11
|
+
path: string;
|
|
12
|
+
area: 'server' | 'dashboard' | 'account' | 'admin' | 'auth' | 'other';
|
|
13
|
+
isServer: boolean;
|
|
14
|
+
isDashboard: boolean;
|
|
15
|
+
isAccount: boolean;
|
|
16
|
+
isAdmin: boolean;
|
|
17
|
+
isAuth: boolean;
|
|
18
|
+
permissions: string[] | null;
|
|
19
|
+
}
|
|
20
|
+
export interface SlotRenderWhen {
|
|
21
|
+
area?: SlotRenderContext['area'];
|
|
22
|
+
areas?: Array<SlotRenderContext['area']>;
|
|
23
|
+
path?: string | string[];
|
|
24
|
+
pathStartsWith?: string | string[];
|
|
25
|
+
pathIncludes?: string | string[];
|
|
26
|
+
pathMatches?: string | RegExp;
|
|
27
|
+
permission?: string | string[];
|
|
28
|
+
server?: boolean;
|
|
29
|
+
dashboard?: boolean;
|
|
30
|
+
account?: boolean;
|
|
31
|
+
admin?: boolean;
|
|
32
|
+
auth?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export type SlotRenderCondition = boolean | SlotRenderWhen | ((context: SlotRenderContext) => boolean);
|
|
35
|
+
export interface SlotConfig {
|
|
36
|
+
slot: string;
|
|
37
|
+
component: React.ComponentType<any>;
|
|
38
|
+
order?: number;
|
|
39
|
+
priority?: number;
|
|
40
|
+
label?: string;
|
|
41
|
+
icon?: string;
|
|
42
|
+
permission?: string;
|
|
43
|
+
props?: Record<string, any>;
|
|
44
|
+
when?: SlotRenderCondition;
|
|
45
|
+
}
|
|
46
|
+
export interface RouteConfig {
|
|
47
|
+
area: 'server' | 'dashboard' | 'account';
|
|
48
|
+
path: string;
|
|
49
|
+
name: string;
|
|
50
|
+
component: React.ComponentType<any>;
|
|
51
|
+
icon?: string;
|
|
52
|
+
permission?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ExtensionDefinition {
|
|
55
|
+
config: ExtensionConfig;
|
|
56
|
+
slots?: SlotConfig[];
|
|
57
|
+
routes?: RouteConfig[];
|
|
58
|
+
cssIsolation?: CssIsolationConfig | boolean;
|
|
59
|
+
onInit?: () => void;
|
|
60
|
+
onDestroy?: () => void;
|
|
61
|
+
}
|
|
62
|
+
export interface SlotRegistration {
|
|
63
|
+
extensionId: string;
|
|
64
|
+
slot: string;
|
|
65
|
+
component: React.ComponentType<any>;
|
|
66
|
+
order?: number;
|
|
67
|
+
priority?: number;
|
|
68
|
+
label?: string;
|
|
69
|
+
icon?: string;
|
|
70
|
+
permission?: string;
|
|
71
|
+
scopeClass?: string;
|
|
72
|
+
props?: Record<string, any>;
|
|
73
|
+
when?: SlotRenderCondition;
|
|
74
|
+
}
|
|
75
|
+
export interface RouteRegistration {
|
|
76
|
+
extensionId: string;
|
|
77
|
+
area: 'server' | 'dashboard' | 'account';
|
|
78
|
+
path: string;
|
|
79
|
+
name: string;
|
|
80
|
+
component: React.ComponentType<any>;
|
|
81
|
+
icon?: string;
|
|
82
|
+
permission?: string;
|
|
83
|
+
scopeClass?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface NoturApi {
|
|
86
|
+
version: string;
|
|
87
|
+
registry: {
|
|
88
|
+
registerSlot: (registration: Omit<SlotRegistration, 'extensionId'> & {
|
|
89
|
+
extensionId?: string;
|
|
90
|
+
}) => void;
|
|
91
|
+
registerRoute: (area: RouteRegistration['area'], route: Omit<RouteRegistration, 'extensionId' | 'area'> & {
|
|
92
|
+
extensionId?: string;
|
|
93
|
+
}) => void;
|
|
94
|
+
registerExtension: (ext: {
|
|
95
|
+
id: string;
|
|
96
|
+
name: string;
|
|
97
|
+
version: string;
|
|
98
|
+
slots: SlotRegistration[];
|
|
99
|
+
routes: RouteRegistration[];
|
|
100
|
+
theme?: {
|
|
101
|
+
variables: Record<string, string>;
|
|
102
|
+
priority?: number;
|
|
103
|
+
};
|
|
104
|
+
cssIsolation?: CssIsolationConfig;
|
|
105
|
+
}) => void;
|
|
106
|
+
registerDestroyCallback: (extensionId: string, callback: () => void) => void;
|
|
107
|
+
unregisterExtension: (extensionId: string) => void;
|
|
108
|
+
getSlot: (slotId: string) => SlotRegistration[];
|
|
109
|
+
getRoutes: (area: RouteRegistration['area']) => RouteRegistration[];
|
|
110
|
+
on: (event: string, callback: () => void) => () => void;
|
|
111
|
+
emitEvent: (event: string, data?: unknown) => void;
|
|
112
|
+
onEvent: (event: string, callback: (data?: unknown) => void) => () => void;
|
|
113
|
+
};
|
|
114
|
+
hooks: {
|
|
115
|
+
useSlot: (slotId: string) => SlotRegistration[];
|
|
116
|
+
useExtensionApi: (options: {
|
|
117
|
+
extensionId: string;
|
|
118
|
+
baseUrl?: string;
|
|
119
|
+
}) => {
|
|
120
|
+
data: unknown;
|
|
121
|
+
loading: boolean;
|
|
122
|
+
error: string | null;
|
|
123
|
+
get: (path: string) => Promise<unknown>;
|
|
124
|
+
post: (path: string, body?: unknown) => Promise<unknown>;
|
|
125
|
+
put: (path: string, body?: unknown) => Promise<unknown>;
|
|
126
|
+
patch: (path: string, body?: unknown) => Promise<unknown>;
|
|
127
|
+
delete: (path: string) => Promise<unknown>;
|
|
128
|
+
request: (path: string, options?: RequestInit) => Promise<unknown>;
|
|
129
|
+
};
|
|
130
|
+
useExtensionState: <T extends Record<string, any>>(extensionId: string, initialState: T) => [T, (partial: Partial<T>) => void, () => void];
|
|
131
|
+
useNoturTheme: () => Record<string, string>;
|
|
132
|
+
};
|
|
133
|
+
SLOT_IDS: Record<string, string>;
|
|
134
|
+
unregisterExtension: (id: string) => void;
|
|
135
|
+
extensions?: Array<{
|
|
136
|
+
id: string;
|
|
137
|
+
bundle?: string;
|
|
138
|
+
styles?: string;
|
|
139
|
+
cssIsolation?: CssIsolationConfig;
|
|
140
|
+
}>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get the Notur API from the window global.
|
|
144
|
+
*/
|
|
145
|
+
export declare function getNoturApi(): NoturApi;
|
|
146
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the Notur API from the window global.
|
|
3
|
+
*/
|
|
4
|
+
export function getNoturApi() {
|
|
5
|
+
const api = window.__NOTUR__;
|
|
6
|
+
if (!api) {
|
|
7
|
+
throw new Error('[Notur SDK] Bridge runtime not found. Ensure bridge.js is loaded first.');
|
|
8
|
+
}
|
|
9
|
+
return api;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAuIA;;GAEG;AACH,MAAM,UAAU,WAAW;IACvB,MAAM,GAAG,GAAI,MAAc,CAAC,SAAS,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@notur/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Notur Extension Developer SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/sak0a/notur.git",
|
|
12
|
+
"directory": "sdk"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"notur",
|
|
19
|
+
"pterodactyl",
|
|
20
|
+
"extension",
|
|
21
|
+
"plugin",
|
|
22
|
+
"sdk"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/",
|
|
26
|
+
"webpack.extension.config.js",
|
|
27
|
+
"templates/"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"dev": "tsc --watch",
|
|
32
|
+
"prepublishOnly": "bun run build"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": "^16.14.0",
|
|
36
|
+
"react-dom": "^16.14.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"typescript": "^5.3.0",
|
|
40
|
+
"@types/react": "^16.14.0",
|
|
41
|
+
"@types/react-dom": "^16.9.0"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { createExtension } from '@notur/sdk';
|
|
3
|
+
|
|
4
|
+
const ExampleWidget: React.FC<{ extensionId: string }> = ({ extensionId }) => {
|
|
5
|
+
return (
|
|
6
|
+
<div
|
|
7
|
+
style={{
|
|
8
|
+
padding: '1rem',
|
|
9
|
+
background: 'var(--notur-glass-bg, var(--notur-bg-secondary))',
|
|
10
|
+
border: '1px solid var(--notur-glass-border, var(--notur-border))',
|
|
11
|
+
borderRadius: 'var(--notur-radius-lg)',
|
|
12
|
+
boxShadow: 'var(--notur-glass-shadow, 0 12px 30px rgba(0, 0, 0, 0.35))',
|
|
13
|
+
backdropFilter: 'blur(var(--notur-glass-blur, 12px))',
|
|
14
|
+
WebkitBackdropFilter: 'blur(var(--notur-glass-blur, 12px))',
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
<h3 style={{ color: 'var(--notur-text-primary)' }}>
|
|
18
|
+
{{displayName}}
|
|
19
|
+
</h3>
|
|
20
|
+
<p style={{ color: 'var(--notur-text-secondary)' }}>
|
|
21
|
+
Hello from {{vendor}}/{{name}}!
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
createExtension({
|
|
28
|
+
config: {
|
|
29
|
+
id: '{{vendor}}/{{name}}',
|
|
30
|
+
name: '{{displayName}}',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
},
|
|
33
|
+
slots: [
|
|
34
|
+
{
|
|
35
|
+
slot: 'dashboard.widgets',
|
|
36
|
+
component: ExampleWidget,
|
|
37
|
+
order: 100,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace {{namespace}};
|
|
6
|
+
|
|
7
|
+
use Notur\Contracts\ExtensionInterface;
|
|
8
|
+
use Notur\Contracts\HasRoutes;
|
|
9
|
+
use Notur\Contracts\HasFrontendSlots;
|
|
10
|
+
|
|
11
|
+
class {{className}} implements ExtensionInterface, HasRoutes, HasFrontendSlots
|
|
12
|
+
{
|
|
13
|
+
public function getId(): string
|
|
14
|
+
{
|
|
15
|
+
return '{{vendor}}/{{name}}';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public function getName(): string
|
|
19
|
+
{
|
|
20
|
+
return '{{displayName}}';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public function getVersion(): string
|
|
24
|
+
{
|
|
25
|
+
return '1.0.0';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public function register(): void
|
|
29
|
+
{
|
|
30
|
+
//
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public function boot(): void
|
|
34
|
+
{
|
|
35
|
+
//
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public function getBasePath(): string
|
|
39
|
+
{
|
|
40
|
+
return __DIR__ . '/..';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public function getRouteFiles(): array
|
|
44
|
+
{
|
|
45
|
+
return [
|
|
46
|
+
'api-client' => 'src/routes/api-client.php',
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public function getFrontendSlots(): array
|
|
51
|
+
{
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
notur: "1.0"
|
|
2
|
+
id: "{{vendor}}/{{name}}"
|
|
3
|
+
name: "{{displayName}}"
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
description: "{{description}}"
|
|
6
|
+
authors:
|
|
7
|
+
- name: "{{authorName}}"
|
|
8
|
+
license: "MIT"
|
|
9
|
+
|
|
10
|
+
requires:
|
|
11
|
+
notur: "^1.0"
|
|
12
|
+
pterodactyl: "^1.11"
|
|
13
|
+
php: "^8.2"
|
|
14
|
+
|
|
15
|
+
capabilities:
|
|
16
|
+
routes: "^1"
|
|
17
|
+
health: "^1"
|
|
18
|
+
schedules: "^1"
|
|
19
|
+
css_isolation: "^1"
|
|
20
|
+
|
|
21
|
+
entrypoint: "{{namespace}}\\{{className}}"
|
|
22
|
+
|
|
23
|
+
autoload:
|
|
24
|
+
psr-4:
|
|
25
|
+
"{{namespace}}\\": "src/"
|
|
26
|
+
|
|
27
|
+
backend:
|
|
28
|
+
routes:
|
|
29
|
+
api-client: "src/routes/api-client.php"
|
|
30
|
+
migrations: "database/migrations"
|
|
31
|
+
permissions: []
|
|
32
|
+
|
|
33
|
+
frontend:
|
|
34
|
+
bundle: "resources/frontend/dist/extension.js"
|
|
35
|
+
css_isolation:
|
|
36
|
+
mode: "root-class"
|
|
37
|
+
slots: {}
|
|
38
|
+
|
|
39
|
+
health:
|
|
40
|
+
checks: []
|
|
41
|
+
|
|
42
|
+
schedules:
|
|
43
|
+
tasks: []
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base webpack configuration for Notur extensions.
|
|
3
|
+
*
|
|
4
|
+
* Extension developers can import and extend this config:
|
|
5
|
+
*
|
|
6
|
+
* ```js
|
|
7
|
+
* const base = require('@notur/sdk/webpack.extension.config');
|
|
8
|
+
*
|
|
9
|
+
* module.exports = {
|
|
10
|
+
* ...base,
|
|
11
|
+
* output: {
|
|
12
|
+
* ...base.output,
|
|
13
|
+
* library: { name: '__NOTUR_EXT_MyExtension__', type: 'umd' },
|
|
14
|
+
* },
|
|
15
|
+
* };
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
module.exports = {
|
|
21
|
+
entry: './src/index.ts',
|
|
22
|
+
output: {
|
|
23
|
+
filename: 'bundle.js',
|
|
24
|
+
path: path.resolve(process.cwd(), 'dist'),
|
|
25
|
+
library: {
|
|
26
|
+
name: '__NOTUR_EXT__',
|
|
27
|
+
type: 'umd',
|
|
28
|
+
},
|
|
29
|
+
clean: true,
|
|
30
|
+
},
|
|
31
|
+
resolve: {
|
|
32
|
+
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
|
33
|
+
},
|
|
34
|
+
module: {
|
|
35
|
+
rules: [
|
|
36
|
+
{
|
|
37
|
+
test: /\.tsx?$/,
|
|
38
|
+
use: 'ts-loader',
|
|
39
|
+
exclude: /node_modules/,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
test: /\.css$/,
|
|
43
|
+
use: ['style-loader', 'css-loader'],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
externals: {
|
|
48
|
+
react: 'React',
|
|
49
|
+
'react-dom': 'ReactDOM',
|
|
50
|
+
'@notur/sdk': '__NOTUR__',
|
|
51
|
+
},
|
|
52
|
+
};
|