@wordrhyme/plugin 0.1.0-alpha.7 → 0.1.0-alpha.9
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/artifact.d.ts +1 -1
- package/dist/artifact.js +1 -1
- package/dist/{chunk-FOCLZY64.js → chunk-73JVDIZ7.js} +10 -1
- package/dist/chunk-73JVDIZ7.js.map +1 -0
- package/dist/{chunk-NAWUXVZQ.js → chunk-T6JK4EW3.js} +63 -3
- package/dist/chunk-T6JK4EW3.js.map +1 -0
- package/dist/{client-CKtDWayV.d.ts → client-DSV_8wW8.d.ts} +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/dev-utils.d.ts +33 -1
- package/dist/dev-utils.js +13 -1
- package/dist/{entity-extensions-gJuSTXYZ.d.ts → entity-extensions-BYc-Nwm0.d.ts} +2 -2
- package/dist/index.d.ts +44 -9
- package/dist/index.js +57 -5
- package/dist/index.js.map +1 -1
- package/dist/{manifest-CDTCsMYV.d.ts → manifest-DHyrYHR4.d.ts} +42 -0
- package/dist/react.d.ts +39 -4
- package/dist/react.js +38 -0
- package/dist/react.js.map +1 -1
- package/dist/server.d.ts +4 -4
- package/dist/trpc.d.ts +1 -1
- package/dist/{types-9v-WZ_NU.d.ts → types-USpPUB_J.d.ts} +46 -1
- package/package.json +1 -1
- package/dist/chunk-FOCLZY64.js.map +0 -1
- package/dist/chunk-NAWUXVZQ.js.map +0 -1
|
@@ -96,6 +96,14 @@ declare const targetSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
96
96
|
path: z.ZodString;
|
|
97
97
|
order: z.ZodOptional<z.ZodNumber>;
|
|
98
98
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
99
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
100
|
+
slot: z.ZodLiteral<"marketplace.tabs">;
|
|
101
|
+
value: z.ZodString;
|
|
102
|
+
order: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
104
|
+
platform: "platform";
|
|
105
|
+
all: "all";
|
|
106
|
+
}>>;
|
|
99
107
|
}, z.core.$strip>, z.ZodObject<{
|
|
100
108
|
slot: z.ZodLiteral<"settings.plugin">;
|
|
101
109
|
category: z.ZodOptional<z.ZodString>;
|
|
@@ -119,6 +127,7 @@ declare const adminExtensionSchema: z.ZodObject<{
|
|
|
119
127
|
id: z.ZodString;
|
|
120
128
|
label: z.ZodString;
|
|
121
129
|
icon: z.ZodOptional<z.ZodString>;
|
|
130
|
+
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
122
131
|
targets: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
123
132
|
slot: z.ZodLiteral<"nav.sidebar">;
|
|
124
133
|
path: z.ZodString;
|
|
@@ -141,6 +150,14 @@ declare const adminExtensionSchema: z.ZodObject<{
|
|
|
141
150
|
path: z.ZodString;
|
|
142
151
|
order: z.ZodOptional<z.ZodNumber>;
|
|
143
152
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
153
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
154
|
+
slot: z.ZodLiteral<"marketplace.tabs">;
|
|
155
|
+
value: z.ZodString;
|
|
156
|
+
order: z.ZodOptional<z.ZodNumber>;
|
|
157
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
158
|
+
platform: "platform";
|
|
159
|
+
all: "all";
|
|
160
|
+
}>>;
|
|
144
161
|
}, z.core.$strip>, z.ZodObject<{
|
|
145
162
|
slot: z.ZodLiteral<"settings.plugin">;
|
|
146
163
|
category: z.ZodOptional<z.ZodString>;
|
|
@@ -727,6 +744,10 @@ declare const webDesignBlockSchema: z.ZodObject<{
|
|
|
727
744
|
declare const webDesignSlotSchema: z.ZodObject<{
|
|
728
745
|
id: z.ZodString;
|
|
729
746
|
label: z.ZodOptional<z.ZodString>;
|
|
747
|
+
renderMode: z.ZodOptional<z.ZodEnum<{
|
|
748
|
+
island: "island";
|
|
749
|
+
react: "react";
|
|
750
|
+
}>>;
|
|
730
751
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
731
752
|
site: "site";
|
|
732
753
|
route: "route";
|
|
@@ -796,6 +817,10 @@ declare const webDesignSurfaceSchema: z.ZodObject<{
|
|
|
796
817
|
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
797
818
|
id: z.ZodString;
|
|
798
819
|
label: z.ZodOptional<z.ZodString>;
|
|
820
|
+
renderMode: z.ZodOptional<z.ZodEnum<{
|
|
821
|
+
island: "island";
|
|
822
|
+
react: "react";
|
|
823
|
+
}>>;
|
|
799
824
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
800
825
|
site: "site";
|
|
801
826
|
route: "route";
|
|
@@ -917,6 +942,10 @@ declare const webSurfaceSchema: z.ZodObject<{
|
|
|
917
942
|
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
918
943
|
id: z.ZodString;
|
|
919
944
|
label: z.ZodOptional<z.ZodString>;
|
|
945
|
+
renderMode: z.ZodOptional<z.ZodEnum<{
|
|
946
|
+
island: "island";
|
|
947
|
+
react: "react";
|
|
948
|
+
}>>;
|
|
920
949
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
921
950
|
site: "site";
|
|
922
951
|
route: "route";
|
|
@@ -1107,6 +1136,7 @@ declare const pluginManifestSchema: z.ZodObject<{
|
|
|
1107
1136
|
id: z.ZodString;
|
|
1108
1137
|
label: z.ZodString;
|
|
1109
1138
|
icon: z.ZodOptional<z.ZodString>;
|
|
1139
|
+
hidden: z.ZodOptional<z.ZodBoolean>;
|
|
1110
1140
|
targets: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
1111
1141
|
slot: z.ZodLiteral<"nav.sidebar">;
|
|
1112
1142
|
path: z.ZodString;
|
|
@@ -1129,6 +1159,14 @@ declare const pluginManifestSchema: z.ZodObject<{
|
|
|
1129
1159
|
path: z.ZodString;
|
|
1130
1160
|
order: z.ZodOptional<z.ZodNumber>;
|
|
1131
1161
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1162
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1163
|
+
slot: z.ZodLiteral<"marketplace.tabs">;
|
|
1164
|
+
value: z.ZodString;
|
|
1165
|
+
order: z.ZodOptional<z.ZodNumber>;
|
|
1166
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
1167
|
+
platform: "platform";
|
|
1168
|
+
all: "all";
|
|
1169
|
+
}>>;
|
|
1132
1170
|
}, z.core.$strip>, z.ZodObject<{
|
|
1133
1171
|
slot: z.ZodLiteral<"settings.plugin">;
|
|
1134
1172
|
category: z.ZodOptional<z.ZodString>;
|
|
@@ -1289,6 +1327,10 @@ declare const pluginManifestSchema: z.ZodObject<{
|
|
|
1289
1327
|
slots: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1290
1328
|
id: z.ZodString;
|
|
1291
1329
|
label: z.ZodOptional<z.ZodString>;
|
|
1330
|
+
renderMode: z.ZodOptional<z.ZodEnum<{
|
|
1331
|
+
island: "island";
|
|
1332
|
+
react: "react";
|
|
1333
|
+
}>>;
|
|
1292
1334
|
scope: z.ZodOptional<z.ZodEnum<{
|
|
1293
1335
|
site: "site";
|
|
1294
1336
|
route: "route";
|
package/dist/react.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { W as WebSlotRemoteExtension, P as PluginMediaInfo } from './types-USpPUB_J.js';
|
|
2
3
|
import { CurrencyInfo, FormatPriceOptions } from './globalization.js';
|
|
3
|
-
import { P as PluginMediaInfo } from './types-9v-WZ_NU.js';
|
|
4
|
-
import 'decimal.js';
|
|
5
|
-
import './locale.js';
|
|
6
4
|
import './release-CyapqJ3z.js';
|
|
7
5
|
import 'zod';
|
|
8
6
|
import './time.js';
|
|
7
|
+
import 'decimal.js';
|
|
8
|
+
import './locale.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* React utilities for plugin admin UIs.
|
|
@@ -147,6 +147,35 @@ declare function usePluginSlot(name: string): boolean;
|
|
|
147
147
|
* ```
|
|
148
148
|
*/
|
|
149
149
|
declare function PluginSlot(props: PluginSlotProps): React.ReactElement | null;
|
|
150
|
+
type WebPluginSlotLayout = 'bare' | 'inline' | 'stack' | 'grid';
|
|
151
|
+
interface WebPluginSlotRenderOptions {
|
|
152
|
+
name: string;
|
|
153
|
+
extensions: WebSlotRemoteExtension[];
|
|
154
|
+
props?: Record<string, unknown> | undefined;
|
|
155
|
+
layout?: WebPluginSlotLayout | undefined;
|
|
156
|
+
}
|
|
157
|
+
interface PublicWebPluginRuntime {
|
|
158
|
+
scan: (root?: ParentNode) => void;
|
|
159
|
+
renderSlot: (mount: HTMLElement, options: WebPluginSlotRenderOptions) => void;
|
|
160
|
+
unmountSlot: (mount: HTMLElement) => void;
|
|
161
|
+
}
|
|
162
|
+
declare const PUBLIC_PLUGIN_RUNTIME_READY_EVENT = "wr:public-plugin-runtime-ready";
|
|
163
|
+
declare global {
|
|
164
|
+
interface Window {
|
|
165
|
+
__WR_PUBLIC_PLUGIN_RUNTIME__?: PublicWebPluginRuntime;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
interface WebPluginSlotProps extends WebPluginSlotRenderOptions {
|
|
169
|
+
className?: string | undefined;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Declares a public-web plugin slot inside an owning React tree.
|
|
173
|
+
*
|
|
174
|
+
* The owner keeps control of live props and React lifecycle. The Web Host owns
|
|
175
|
+
* remote loading and renders extensions into the empty mount element through
|
|
176
|
+
* its shared Module Federation React runtime.
|
|
177
|
+
*/
|
|
178
|
+
declare function WebPluginSlot({ name, extensions, props, layout, className, }: WebPluginSlotProps): React.ReactElement | null;
|
|
150
179
|
/**
|
|
151
180
|
* Minimal ability interface for plugin permission checks.
|
|
152
181
|
* Matches CASL MongoAbility.can() signature.
|
|
@@ -179,6 +208,12 @@ interface MediaPickerOptions {
|
|
|
179
208
|
presentation?: 'dialog' | 'drawer';
|
|
180
209
|
mode?: 'single' | 'multi';
|
|
181
210
|
category?: 'all' | 'image' | 'document' | 'video' | 'audio' | 'archive' | 'other';
|
|
211
|
+
/** Allow callers to select an external image by entering its URL in the picker. */
|
|
212
|
+
allowExternalUrl?: boolean;
|
|
213
|
+
/** Prefer importing URL images into Media, or only allow a transient external reference. */
|
|
214
|
+
externalUrlMode?: 'import-preferred' | 'reference-only';
|
|
215
|
+
/** Publish selected images when needed and include an absolute public URL in each result. */
|
|
216
|
+
requirePublicUrl?: boolean;
|
|
182
217
|
onSelect: (media: PluginMediaInfo[]) => void;
|
|
183
218
|
}
|
|
184
219
|
/**
|
|
@@ -189,4 +224,4 @@ declare function useMediaPicker(): {
|
|
|
189
224
|
openDialog: (options: MediaPickerOptions) => void;
|
|
190
225
|
};
|
|
191
226
|
|
|
192
|
-
export { type MediaPickerOptions, type PluginAbility, PluginAbilityContext, PluginCurrencyContext, type PluginCurrencyValue, PluginI18nContext, type PluginI18nValue, type PluginLanguageOption, PluginSlot, type PluginSlotProps, type PluginSlotRegistry, __setPluginSlot, __setPluginSlotRegistry, __setTrpc, useHostTrpc, useMediaPicker, usePluginAbility, usePluginCurrency, usePluginSlot, usePluginTranslation, usePluginTrpc };
|
|
227
|
+
export { type MediaPickerOptions, PUBLIC_PLUGIN_RUNTIME_READY_EVENT, type PluginAbility, PluginAbilityContext, PluginCurrencyContext, type PluginCurrencyValue, PluginI18nContext, type PluginI18nValue, type PluginLanguageOption, PluginSlot, type PluginSlotProps, type PluginSlotRegistry, type PublicWebPluginRuntime, WebPluginSlot, type WebPluginSlotLayout, type WebPluginSlotProps, type WebPluginSlotRenderOptions, __setPluginSlot, __setPluginSlotRegistry, __setTrpc, useHostTrpc, useMediaPicker, usePluginAbility, usePluginCurrency, usePluginSlot, usePluginTranslation, usePluginTrpc };
|
package/dist/react.js
CHANGED
|
@@ -150,6 +150,42 @@ function PluginSlot(props) {
|
|
|
150
150
|
}
|
|
151
151
|
return React.createElement(_PluginSlotImpl, props);
|
|
152
152
|
}
|
|
153
|
+
var PUBLIC_PLUGIN_RUNTIME_READY_EVENT = "wr:public-plugin-runtime-ready";
|
|
154
|
+
function WebPluginSlot({
|
|
155
|
+
name,
|
|
156
|
+
extensions,
|
|
157
|
+
props,
|
|
158
|
+
layout = "bare",
|
|
159
|
+
className
|
|
160
|
+
}) {
|
|
161
|
+
const mountRef = React.useRef(null);
|
|
162
|
+
const latestRef = React.useRef({ name, extensions, props, layout });
|
|
163
|
+
latestRef.current = { name, extensions, props, layout };
|
|
164
|
+
const renderCurrent = React.useCallback(() => {
|
|
165
|
+
const mount = mountRef.current;
|
|
166
|
+
const runtime = typeof window === "undefined" ? void 0 : window.__WR_PUBLIC_PLUGIN_RUNTIME__;
|
|
167
|
+
if (!mount || !runtime) return;
|
|
168
|
+
runtime.renderSlot(mount, latestRef.current);
|
|
169
|
+
}, []);
|
|
170
|
+
React.useEffect(() => {
|
|
171
|
+
if (typeof window === "undefined") return void 0;
|
|
172
|
+
const mount = mountRef.current;
|
|
173
|
+
window.addEventListener(PUBLIC_PLUGIN_RUNTIME_READY_EVENT, renderCurrent);
|
|
174
|
+
return () => {
|
|
175
|
+
window.removeEventListener(PUBLIC_PLUGIN_RUNTIME_READY_EVENT, renderCurrent);
|
|
176
|
+
if (mount) window.__WR_PUBLIC_PLUGIN_RUNTIME__?.unmountSlot(mount);
|
|
177
|
+
};
|
|
178
|
+
}, [renderCurrent]);
|
|
179
|
+
React.useEffect(() => {
|
|
180
|
+
renderCurrent();
|
|
181
|
+
});
|
|
182
|
+
if (extensions.length === 0) return null;
|
|
183
|
+
return React.createElement("div", {
|
|
184
|
+
ref: mountRef,
|
|
185
|
+
className,
|
|
186
|
+
"data-wr-plugin-react-slot": name
|
|
187
|
+
});
|
|
188
|
+
}
|
|
153
189
|
var defaultAbility = { can: () => true };
|
|
154
190
|
var PluginAbilityContext = React.createContext(defaultAbility);
|
|
155
191
|
function usePluginAbility() {
|
|
@@ -170,10 +206,12 @@ function useMediaPicker() {
|
|
|
170
206
|
};
|
|
171
207
|
}
|
|
172
208
|
export {
|
|
209
|
+
PUBLIC_PLUGIN_RUNTIME_READY_EVENT,
|
|
173
210
|
PluginAbilityContext,
|
|
174
211
|
PluginCurrencyContext,
|
|
175
212
|
PluginI18nContext,
|
|
176
213
|
PluginSlot,
|
|
214
|
+
WebPluginSlot,
|
|
177
215
|
__setPluginSlot,
|
|
178
216
|
__setPluginSlotRegistry,
|
|
179
217
|
__setTrpc,
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts"],"sourcesContent":["/**\n * React utilities for plugin admin UIs.\n *\n * At runtime, this module is shared via Module Federation from the admin host.\n * Plugins should configure MF shared with `import: false` for this package.\n */\nimport React from 'react';\nimport {\n DEFAULT_CURRENCY,\n type CurrencyInfo,\n type FormatPriceOptions,\n} from './globalization';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _trpc: any = null;\nlet _hostTrpcFacade: any = null;\n\n/**\n * Called by the Admin Host at startup to inject the host's tRPC React client.\n * Plugin code should NOT call this directly.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function __setTrpc(trpc: any) {\n _trpc = trpc;\n _hostTrpcFacade = null;\n}\n\n/**\n * Hook for plugin components to access their tRPC namespace with React Query hooks.\n * Must be called within a component rendered inside the Admin Host.\n *\n * @param pluginId - Short plugin ID (e.g., 'storage-s3') or full ID (e.g., 'com.wordrhyme.storage-s3')\n * @returns tRPC proxy with useQuery/useMutation hooks\n *\n * @example\n * ```tsx\n * import { usePluginTrpc } from '@wordrhyme/plugin/react';\n *\n * function MyPluginPage() {\n * const api = usePluginTrpc('my-plugin');\n * const { data, isLoading } = api.listItems.useQuery();\n * const createItem = api.createItem.useMutation();\n * }\n * ```\n */\nexport function usePluginTrpc(pluginId: string) {\n if (!_trpc) {\n throw new Error(\n '[plugin/react] tRPC not initialized. ' +\n 'Ensure plugin is loaded within Admin Host context.',\n );\n }\n const normalizedId = pluginId\n .replace(/^com\\.wordrhyme\\./, '')\n .replace(/\\./g, '-');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (_trpc as any).pluginApis[normalizedId];\n}\n\n/**\n * Hook for plugin components to access the Admin Host's root tRPC React client.\n * Useful for shared host capabilities such as currency, media, auth, etc.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useHostTrpc(): any {\n if (!_trpc) {\n throw new Error(\n '[plugin/react] tRPC not initialized. ' +\n 'Ensure plugin is loaded within Admin Host context.',\n );\n }\n if (!_hostTrpcFacade) {\n _hostTrpcFacade = new Proxy(_trpc, {\n get(target, property, receiver) {\n if (property === 'i18n') {\n throw new Error(\n '[plugin/react] Host i18n APIs are not exposed to plugins. ' +\n 'Use the Host-bound usePluginTranslation() bridge.',\n );\n }\n return Reflect.get(target, property, receiver);\n },\n has(target, property) {\n return property === 'i18n' ? false : Reflect.has(target, property);\n },\n ownKeys(target) {\n return Reflect.ownKeys(target).filter((property) => property !== 'i18n');\n },\n });\n }\n return _hostTrpcFacade;\n}\n\n// ============================================================\n// I18n — host translation bridge\n// ============================================================\n\nexport interface PluginI18nValue {\n pluginId?: string | undefined;\n namespace?: string | undefined;\n locale: string;\n timezone: string;\n isLoading: boolean;\n availableLocales: readonly string[];\n languages: readonly PluginLanguageOption[];\n t: (key: string, paramsOrDefault?: Record<string, string | number> | string) => string;\n /** Host-bound Core common translator. Optional for compatibility with older Hosts. */\n tCommon?: (key: string, paramsOrDefault?: Record<string, string | number> | string) => string;\n addNamespace: (namespace: string) => void;\n}\n\nexport interface PluginLanguageOption {\n locale: string;\n name: string;\n nativeName: string;\n direction: 'ltr' | 'rtl';\n isDefault: boolean;\n sortOrder: number;\n}\n\nconst fallbackPluginTranslate = (\n key: string,\n paramsOrDefault?: Record<string, string | number> | string,\n) => (typeof paramsOrDefault === 'string' ? paramsOrDefault : key);\n\nconst defaultI18n: PluginI18nValue = {\n locale: 'en-US',\n timezone: 'UTC',\n isLoading: false,\n availableLocales: [],\n languages: [],\n t: fallbackPluginTranslate,\n tCommon: fallbackPluginTranslate,\n addNamespace: () => undefined,\n};\n\nexport const PluginI18nContext = React.createContext<PluginI18nValue>(defaultI18n);\n\nfunction normalizePluginNamespace(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nexport function usePluginTranslation(pluginId: string, customNamespace?: string) {\n const i18n = React.useContext(PluginI18nContext);\n if (!i18n.pluginId || !i18n.namespace) {\n throw new Error('[plugin/react] Plugin i18n boundary is missing');\n }\n if (pluginId !== i18n.pluginId) {\n throw new Error(\n `[plugin/react] Plugin i18n identity mismatch: expected ${i18n.pluginId}, received ${pluginId}`,\n );\n }\n const namespace = normalizePluginNamespace(pluginId);\n if (customNamespace && customNamespace !== namespace) {\n throw new Error(\n `[plugin/react] Plugin namespace mismatch: expected ${namespace}, received ${customNamespace}`,\n );\n }\n if (i18n.namespace !== namespace) {\n throw new Error(\n `[plugin/react] Host-bound namespace mismatch: expected ${namespace}, received ${i18n.namespace}`,\n );\n }\n\n const t = React.useCallback(\n (key: string, paramsOrDefault?: Record<string, string | number> | string): string => {\n const prefix = `${namespace}.`;\n const localKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;\n return i18n.t(localKey, paramsOrDefault);\n },\n [i18n],\n );\n const tCommon = i18n.tCommon ?? fallbackPluginTranslate;\n\n return React.useMemo(\n () => ({\n t,\n tCommon,\n locale: i18n.locale,\n timezone: i18n.timezone,\n isLoading: i18n.isLoading,\n availableLocales: i18n.availableLocales,\n languages: i18n.languages,\n namespace,\n }),\n [\n t,\n tCommon,\n i18n.locale,\n i18n.timezone,\n i18n.isLoading,\n i18n.availableLocales,\n i18n.languages,\n namespace,\n ],\n );\n}\n\n// ============================================================\n// Currency — host currency bridge\n// ============================================================\n\n/** Currency capabilities exposed by the Admin Host to plugin UIs. */\nexport interface PluginCurrencyValue {\n currency: CurrencyInfo;\n currencies: CurrencyInfo[];\n baseCurrency: CurrencyInfo;\n isLoading: boolean;\n isReady: boolean;\n changeCurrency: (currencyCode: string) => void;\n formatPrice: (\n cents: number,\n fromCurrency?: string | undefined,\n options?: FormatPriceOptions | undefined,\n ) => string;\n}\n\nconst defaultPluginCurrency: PluginCurrencyValue = {\n currency: DEFAULT_CURRENCY,\n currencies: [],\n baseCurrency: DEFAULT_CURRENCY,\n isLoading: false,\n isReady: false,\n changeCurrency: () => undefined,\n formatPrice: (cents, fromCurrency) => `${fromCurrency ?? DEFAULT_CURRENCY.code} ${(cents / 100).toFixed(2)}`,\n};\n\nexport const PluginCurrencyContext = React.createContext<PluginCurrencyValue>(defaultPluginCurrency);\n\nexport function usePluginCurrency(): PluginCurrencyValue {\n return React.useContext(PluginCurrencyContext);\n}\n\n// ============================================================\n// PluginSlot — runtime-injected from Admin Host\n// ============================================================\n\nexport interface PluginSlotProps {\n /** Slot name, e.g. 'shop.product.detail.actions' */\n name: string;\n /** React props passed to extensions rendered in this slot */\n props?: Record<string, unknown>;\n /** @deprecated Use props. Kept for legacy plugin slot call sites. */\n context?: Record<string, unknown>;\n /** Layout mode */\n layout?: 'inline' | 'stack' | 'tabs' | 'grid';\n /** Additional CSS class */\n className?: string;\n /** Fallback when no extensions registered */\n fallback?: React.ReactNode;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _PluginSlotImpl: React.ComponentType<PluginSlotProps> | null = null;\n\nexport interface PluginSlotRegistry {\n /** Returns whether at least one extension is registered for the slot. */\n has: (name: string) => boolean;\n /** Subscribes to extension registry changes. */\n subscribe: (onStoreChange: () => void) => () => void;\n}\n\nlet _pluginSlotRegistry: PluginSlotRegistry | null = null;\nconst emptyPluginSlotSubscribe = () => () => undefined;\n\n/**\n * Called by the Admin Host at startup to inject the PluginSlot component.\n * Plugin code should NOT call this directly.\n * @internal\n */\nexport function __setPluginSlot(component: React.ComponentType<PluginSlotProps>) {\n _PluginSlotImpl = component;\n}\n\n/**\n * Called by the Admin Host at startup to expose reactive slot availability.\n * Plugin code should NOT call this directly.\n * @internal\n */\nexport function __setPluginSlotRegistry(registry: PluginSlotRegistry | null) {\n _pluginSlotRegistry = registry;\n}\n\n/**\n * Returns whether the given slot currently has at least one registered extension.\n * The value updates when plugins are registered, reloaded, disabled, or removed.\n */\nexport function usePluginSlot(name: string): boolean {\n const getSnapshot = () => _pluginSlotRegistry?.has(name) ?? false;\n\n return React.useSyncExternalStore(\n _pluginSlotRegistry?.subscribe ?? emptyPluginSlotSubscribe,\n getSnapshot,\n getSnapshot,\n );\n}\n\n/**\n * Renders all plugin extensions registered for the given slot.\n *\n * @example\n * ```tsx\n * import { PluginSlot } from '@wordrhyme/plugin/react';\n *\n * function ProductDetailPage({ productId }) {\n * return (\n * <div>\n * <h1>Product Detail</h1>\n * <PluginSlot\n * name=\"shop.product.detail.actions\"\n * layout=\"inline\"\n * props={{ productId }}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function PluginSlot(props: PluginSlotProps): React.ReactElement | null {\n if (!_PluginSlotImpl) {\n // Silently render nothing if host hasn't injected yet\n return null;\n }\n return React.createElement(_PluginSlotImpl, props);\n}\n\n// Ability — runtime-injected from Admin Host (CASL permission)\n// ============================================================\n\n/**\n * Minimal ability interface for plugin permission checks.\n * Matches CASL MongoAbility.can() signature.\n */\nexport interface PluginAbility {\n can(action: string, subject: string): boolean;\n}\n\n/** Default allow-all ability (when host hasn't injected) */\nconst defaultAbility: PluginAbility = { can: () => true };\n\n/**\n * React Context for ability — shared between host and plugins.\n * Host injects via AbilityBridge, plugins consume via usePluginAbility.\n */\nexport const PluginAbilityContext = React.createContext<PluginAbility>(defaultAbility);\n\n/**\n * Hook for plugin components to check permissions.\n *\n * @example\n * ```tsx\n * import { usePluginAbility } from '@wordrhyme/plugin/react';\n *\n * function MyPluginPage() {\n * const ability = usePluginAbility();\n * const canCreate = ability.can('create', 'PluginResource');\n * const canDelete = ability.can('delete', 'PluginResource');\n * }\n * ```\n */\nexport function usePluginAbility(): PluginAbility {\n return React.useContext(PluginAbilityContext);\n}\n\n// ============================================================\n// Media Picker — accesses global imperative API\n// ============================================================\n\nimport type { PluginMediaInfo } from './types';\n\n// Define the options for the global MediaPicker\nexport interface MediaPickerOptions {\n presentation?: 'dialog' | 'drawer'; // Where to open the picker\n mode?: 'single' | 'multi';\n category?: 'all' | 'image' | 'document' | 'video' | 'audio' | 'archive' | 'other';\n onSelect: (media: PluginMediaInfo[]) => void;\n}\n\n/**\n * Hook to open the global Media Picker dialog (rendered by Admin Host).\n * Returns an imperative API `openDialog(options)`.\n */\nexport function useMediaPicker() {\n return {\n openDialog: (options: MediaPickerOptions) => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const picker = window.__WORDRHYME_MEDIA_PICKER__ || window.__OMNIDS_MEDIA_PICKER__;\n if (picker) {\n picker.open(options);\n return;\n }\n }\n console.warn('[plugin/react] Media Picker is not mounted by the Admin Host.');\n }\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts"],"sourcesContent":["/// <reference lib=\"dom\" />\n\n/**\n * React utilities for plugin admin UIs.\n *\n * At runtime, this module is shared via Module Federation from the admin host.\n * Plugins should configure MF shared with `import: false` for this package.\n */\nimport React from 'react';\nimport type { WebSlotRemoteExtension } from './types';\nimport {\n DEFAULT_CURRENCY,\n type CurrencyInfo,\n type FormatPriceOptions,\n} from './globalization';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _trpc: any = null;\nlet _hostTrpcFacade: any = null;\n\n/**\n * Called by the Admin Host at startup to inject the host's tRPC React client.\n * Plugin code should NOT call this directly.\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function __setTrpc(trpc: any) {\n _trpc = trpc;\n _hostTrpcFacade = null;\n}\n\n/**\n * Hook for plugin components to access their tRPC namespace with React Query hooks.\n * Must be called within a component rendered inside the Admin Host.\n *\n * @param pluginId - Short plugin ID (e.g., 'storage-s3') or full ID (e.g., 'com.wordrhyme.storage-s3')\n * @returns tRPC proxy with useQuery/useMutation hooks\n *\n * @example\n * ```tsx\n * import { usePluginTrpc } from '@wordrhyme/plugin/react';\n *\n * function MyPluginPage() {\n * const api = usePluginTrpc('my-plugin');\n * const { data, isLoading } = api.listItems.useQuery();\n * const createItem = api.createItem.useMutation();\n * }\n * ```\n */\nexport function usePluginTrpc(pluginId: string) {\n if (!_trpc) {\n throw new Error(\n '[plugin/react] tRPC not initialized. ' +\n 'Ensure plugin is loaded within Admin Host context.',\n );\n }\n const normalizedId = pluginId\n .replace(/^com\\.wordrhyme\\./, '')\n .replace(/\\./g, '-');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (_trpc as any).pluginApis[normalizedId];\n}\n\n/**\n * Hook for plugin components to access the Admin Host's root tRPC React client.\n * Useful for shared host capabilities such as currency, media, auth, etc.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useHostTrpc(): any {\n if (!_trpc) {\n throw new Error(\n '[plugin/react] tRPC not initialized. ' +\n 'Ensure plugin is loaded within Admin Host context.',\n );\n }\n if (!_hostTrpcFacade) {\n _hostTrpcFacade = new Proxy(_trpc, {\n get(target, property, receiver) {\n if (property === 'i18n') {\n throw new Error(\n '[plugin/react] Host i18n APIs are not exposed to plugins. ' +\n 'Use the Host-bound usePluginTranslation() bridge.',\n );\n }\n return Reflect.get(target, property, receiver);\n },\n has(target, property) {\n return property === 'i18n' ? false : Reflect.has(target, property);\n },\n ownKeys(target) {\n return Reflect.ownKeys(target).filter((property) => property !== 'i18n');\n },\n });\n }\n return _hostTrpcFacade;\n}\n\n// ============================================================\n// I18n — host translation bridge\n// ============================================================\n\nexport interface PluginI18nValue {\n pluginId?: string | undefined;\n namespace?: string | undefined;\n locale: string;\n timezone: string;\n isLoading: boolean;\n availableLocales: readonly string[];\n languages: readonly PluginLanguageOption[];\n t: (key: string, paramsOrDefault?: Record<string, string | number> | string) => string;\n /** Host-bound Core common translator. Optional for compatibility with older Hosts. */\n tCommon?: (key: string, paramsOrDefault?: Record<string, string | number> | string) => string;\n addNamespace: (namespace: string) => void;\n}\n\nexport interface PluginLanguageOption {\n locale: string;\n name: string;\n nativeName: string;\n direction: 'ltr' | 'rtl';\n isDefault: boolean;\n sortOrder: number;\n}\n\nconst fallbackPluginTranslate = (\n key: string,\n paramsOrDefault?: Record<string, string | number> | string,\n) => (typeof paramsOrDefault === 'string' ? paramsOrDefault : key);\n\nconst defaultI18n: PluginI18nValue = {\n locale: 'en-US',\n timezone: 'UTC',\n isLoading: false,\n availableLocales: [],\n languages: [],\n t: fallbackPluginTranslate,\n tCommon: fallbackPluginTranslate,\n addNamespace: () => undefined,\n};\n\nexport const PluginI18nContext = React.createContext<PluginI18nValue>(defaultI18n);\n\nfunction normalizePluginNamespace(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nexport function usePluginTranslation(pluginId: string, customNamespace?: string) {\n const i18n = React.useContext(PluginI18nContext);\n if (!i18n.pluginId || !i18n.namespace) {\n throw new Error('[plugin/react] Plugin i18n boundary is missing');\n }\n if (pluginId !== i18n.pluginId) {\n throw new Error(\n `[plugin/react] Plugin i18n identity mismatch: expected ${i18n.pluginId}, received ${pluginId}`,\n );\n }\n const namespace = normalizePluginNamespace(pluginId);\n if (customNamespace && customNamespace !== namespace) {\n throw new Error(\n `[plugin/react] Plugin namespace mismatch: expected ${namespace}, received ${customNamespace}`,\n );\n }\n if (i18n.namespace !== namespace) {\n throw new Error(\n `[plugin/react] Host-bound namespace mismatch: expected ${namespace}, received ${i18n.namespace}`,\n );\n }\n\n const t = React.useCallback(\n (key: string, paramsOrDefault?: Record<string, string | number> | string): string => {\n const prefix = `${namespace}.`;\n const localKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;\n return i18n.t(localKey, paramsOrDefault);\n },\n [i18n],\n );\n const tCommon = i18n.tCommon ?? fallbackPluginTranslate;\n\n return React.useMemo(\n () => ({\n t,\n tCommon,\n locale: i18n.locale,\n timezone: i18n.timezone,\n isLoading: i18n.isLoading,\n availableLocales: i18n.availableLocales,\n languages: i18n.languages,\n namespace,\n }),\n [\n t,\n tCommon,\n i18n.locale,\n i18n.timezone,\n i18n.isLoading,\n i18n.availableLocales,\n i18n.languages,\n namespace,\n ],\n );\n}\n\n// ============================================================\n// Currency — host currency bridge\n// ============================================================\n\n/** Currency capabilities exposed by the Admin Host to plugin UIs. */\nexport interface PluginCurrencyValue {\n currency: CurrencyInfo;\n currencies: CurrencyInfo[];\n baseCurrency: CurrencyInfo;\n isLoading: boolean;\n isReady: boolean;\n changeCurrency: (currencyCode: string) => void;\n formatPrice: (\n cents: number,\n fromCurrency?: string | undefined,\n options?: FormatPriceOptions | undefined,\n ) => string;\n}\n\nconst defaultPluginCurrency: PluginCurrencyValue = {\n currency: DEFAULT_CURRENCY,\n currencies: [],\n baseCurrency: DEFAULT_CURRENCY,\n isLoading: false,\n isReady: false,\n changeCurrency: () => undefined,\n formatPrice: (cents, fromCurrency) => `${fromCurrency ?? DEFAULT_CURRENCY.code} ${(cents / 100).toFixed(2)}`,\n};\n\nexport const PluginCurrencyContext = React.createContext<PluginCurrencyValue>(defaultPluginCurrency);\n\nexport function usePluginCurrency(): PluginCurrencyValue {\n return React.useContext(PluginCurrencyContext);\n}\n\n// ============================================================\n// PluginSlot — runtime-injected from Admin Host\n// ============================================================\n\nexport interface PluginSlotProps {\n /** Slot name, e.g. 'shop.product.detail.actions' */\n name: string;\n /** React props passed to extensions rendered in this slot */\n props?: Record<string, unknown>;\n /** @deprecated Use props. Kept for legacy plugin slot call sites. */\n context?: Record<string, unknown>;\n /** Layout mode */\n layout?: 'inline' | 'stack' | 'tabs' | 'grid';\n /** Additional CSS class */\n className?: string;\n /** Fallback when no extensions registered */\n fallback?: React.ReactNode;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _PluginSlotImpl: React.ComponentType<PluginSlotProps> | null = null;\n\nexport interface PluginSlotRegistry {\n /** Returns whether at least one extension is registered for the slot. */\n has: (name: string) => boolean;\n /** Subscribes to extension registry changes. */\n subscribe: (onStoreChange: () => void) => () => void;\n}\n\nlet _pluginSlotRegistry: PluginSlotRegistry | null = null;\nconst emptyPluginSlotSubscribe = () => () => undefined;\n\n/**\n * Called by the Admin Host at startup to inject the PluginSlot component.\n * Plugin code should NOT call this directly.\n * @internal\n */\nexport function __setPluginSlot(component: React.ComponentType<PluginSlotProps>) {\n _PluginSlotImpl = component;\n}\n\n/**\n * Called by the Admin Host at startup to expose reactive slot availability.\n * Plugin code should NOT call this directly.\n * @internal\n */\nexport function __setPluginSlotRegistry(registry: PluginSlotRegistry | null) {\n _pluginSlotRegistry = registry;\n}\n\n/**\n * Returns whether the given slot currently has at least one registered extension.\n * The value updates when plugins are registered, reloaded, disabled, or removed.\n */\nexport function usePluginSlot(name: string): boolean {\n const getSnapshot = () => _pluginSlotRegistry?.has(name) ?? false;\n\n return React.useSyncExternalStore(\n _pluginSlotRegistry?.subscribe ?? emptyPluginSlotSubscribe,\n getSnapshot,\n getSnapshot,\n );\n}\n\n/**\n * Renders all plugin extensions registered for the given slot.\n *\n * @example\n * ```tsx\n * import { PluginSlot } from '@wordrhyme/plugin/react';\n *\n * function ProductDetailPage({ productId }) {\n * return (\n * <div>\n * <h1>Product Detail</h1>\n * <PluginSlot\n * name=\"shop.product.detail.actions\"\n * layout=\"inline\"\n * props={{ productId }}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function PluginSlot(props: PluginSlotProps): React.ReactElement | null {\n if (!_PluginSlotImpl) {\n // Silently render nothing if host hasn't injected yet\n return null;\n }\n return React.createElement(_PluginSlotImpl, props);\n}\n\n// ============================================================\n// WebPluginSlot — declarative public-web React slot bridge\n// ============================================================\n\nexport type WebPluginSlotLayout = 'bare' | 'inline' | 'stack' | 'grid';\n\nexport interface WebPluginSlotRenderOptions {\n name: string;\n extensions: WebSlotRemoteExtension[];\n props?: Record<string, unknown> | undefined;\n layout?: WebPluginSlotLayout | undefined;\n}\n\nexport interface PublicWebPluginRuntime {\n scan: (root?: ParentNode) => void;\n renderSlot: (mount: HTMLElement, options: WebPluginSlotRenderOptions) => void;\n unmountSlot: (mount: HTMLElement) => void;\n}\n\nexport const PUBLIC_PLUGIN_RUNTIME_READY_EVENT = 'wr:public-plugin-runtime-ready';\n\ndeclare global {\n interface Window {\n __WR_PUBLIC_PLUGIN_RUNTIME__?: PublicWebPluginRuntime;\n }\n}\n\nexport interface WebPluginSlotProps extends WebPluginSlotRenderOptions {\n className?: string | undefined;\n}\n\n/**\n * Declares a public-web plugin slot inside an owning React tree.\n *\n * The owner keeps control of live props and React lifecycle. The Web Host owns\n * remote loading and renders extensions into the empty mount element through\n * its shared Module Federation React runtime.\n */\nexport function WebPluginSlot({\n name,\n extensions,\n props,\n layout = 'bare',\n className,\n}: WebPluginSlotProps): React.ReactElement | null {\n const mountRef = React.useRef<HTMLDivElement>(null);\n const latestRef = React.useRef<WebPluginSlotRenderOptions>({ name, extensions, props, layout });\n latestRef.current = { name, extensions, props, layout };\n\n const renderCurrent = React.useCallback(() => {\n const mount = mountRef.current;\n const runtime = typeof window === 'undefined' ? undefined : window.__WR_PUBLIC_PLUGIN_RUNTIME__;\n if (!mount || !runtime) return;\n runtime.renderSlot(mount, latestRef.current);\n }, []);\n\n React.useEffect(() => {\n if (typeof window === 'undefined') return undefined;\n const mount = mountRef.current;\n window.addEventListener(PUBLIC_PLUGIN_RUNTIME_READY_EVENT, renderCurrent);\n return () => {\n window.removeEventListener(PUBLIC_PLUGIN_RUNTIME_READY_EVENT, renderCurrent);\n if (mount) window.__WR_PUBLIC_PLUGIN_RUNTIME__?.unmountSlot(mount);\n };\n }, [renderCurrent]);\n\n React.useEffect(() => {\n renderCurrent();\n });\n\n if (extensions.length === 0) return null;\n\n return React.createElement('div', {\n ref: mountRef,\n className,\n 'data-wr-plugin-react-slot': name,\n });\n}\n\n// Ability — runtime-injected from Admin Host (CASL permission)\n// ============================================================\n\n/**\n * Minimal ability interface for plugin permission checks.\n * Matches CASL MongoAbility.can() signature.\n */\nexport interface PluginAbility {\n can(action: string, subject: string): boolean;\n}\n\n/** Default allow-all ability (when host hasn't injected) */\nconst defaultAbility: PluginAbility = { can: () => true };\n\n/**\n * React Context for ability — shared between host and plugins.\n * Host injects via AbilityBridge, plugins consume via usePluginAbility.\n */\nexport const PluginAbilityContext = React.createContext<PluginAbility>(defaultAbility);\n\n/**\n * Hook for plugin components to check permissions.\n *\n * @example\n * ```tsx\n * import { usePluginAbility } from '@wordrhyme/plugin/react';\n *\n * function MyPluginPage() {\n * const ability = usePluginAbility();\n * const canCreate = ability.can('create', 'PluginResource');\n * const canDelete = ability.can('delete', 'PluginResource');\n * }\n * ```\n */\nexport function usePluginAbility(): PluginAbility {\n return React.useContext(PluginAbilityContext);\n}\n\n// ============================================================\n// Media Picker — accesses global imperative API\n// ============================================================\n\nimport type { PluginMediaInfo } from './types';\n\n// Define the options for the global MediaPicker\nexport interface MediaPickerOptions {\n presentation?: 'dialog' | 'drawer'; // Where to open the picker\n mode?: 'single' | 'multi';\n category?: 'all' | 'image' | 'document' | 'video' | 'audio' | 'archive' | 'other';\n /** Allow callers to select an external image by entering its URL in the picker. */\n allowExternalUrl?: boolean;\n /** Prefer importing URL images into Media, or only allow a transient external reference. */\n externalUrlMode?: 'import-preferred' | 'reference-only';\n /** Publish selected images when needed and include an absolute public URL in each result. */\n requirePublicUrl?: boolean;\n onSelect: (media: PluginMediaInfo[]) => void;\n}\n\n/**\n * Hook to open the global Media Picker dialog (rendered by Admin Host).\n * Returns an imperative API `openDialog(options)`.\n */\nexport function useMediaPicker() {\n return {\n openDialog: (options: MediaPickerOptions) => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const picker = window.__WORDRHYME_MEDIA_PICKER__ || window.__OMNIDS_MEDIA_PICKER__;\n if (picker) {\n picker.open(options);\n return;\n }\n }\n console.warn('[plugin/react] Media Picker is not mounted by the Admin Host.');\n }\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export { createPluginContext, pluginProcedure, pluginRouter } from './trpc.js';
|
|
2
|
-
import { a as PluginContext } from './types-
|
|
3
|
-
export { H as HookContext, c as HookTransaction } from './types-
|
|
2
|
+
import { a as PluginContext } from './types-USpPUB_J.js';
|
|
3
|
+
export { H as HookContext, c as HookTransaction } from './types-USpPUB_J.js';
|
|
4
4
|
import { DateRangeResolver } from './time.js';
|
|
5
5
|
export { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
6
|
-
export { E as ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID, a as EXTENSION_PROJECT_SAVE_HOOK_ID, b as EntityExtensionProjectionValue, c as EntityExtensionValueSaveHandler, d as EntityExtensionValueSavePayload, e as EntityExtensionValueSaveResult, f as entityExtensions, r as registerEntityExtensionValueSaver } from './entity-extensions-
|
|
6
|
+
export { E as ENTITY_EXTENSION_VALUES_SAVE_HOOK_ID, a as EXTENSION_PROJECT_SAVE_HOOK_ID, b as EntityExtensionProjectionValue, c as EntityExtensionValueSaveHandler, d as EntityExtensionValueSavePayload, e as EntityExtensionValueSaveResult, f as entityExtensions, r as registerEntityExtensionValueSaver } from './entity-extensions-BYc-Nwm0.js';
|
|
7
7
|
import './globalization.js';
|
|
8
8
|
import 'decimal.js';
|
|
9
9
|
import './locale.js';
|
|
10
10
|
import './release-CyapqJ3z.js';
|
|
11
11
|
import 'zod';
|
|
12
|
-
import './manifest-
|
|
12
|
+
import './manifest-DHyrYHR4.js';
|
|
13
13
|
|
|
14
14
|
interface PluginRuntimeRequestContext {
|
|
15
15
|
requestId?: string | undefined;
|
package/dist/trpc.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _trpc_server from '@trpc/server';
|
|
2
2
|
export { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
3
|
-
import { a as PluginContext } from './types-
|
|
3
|
+
import { a as PluginContext } from './types-USpPUB_J.js';
|
|
4
4
|
import './globalization.js';
|
|
5
5
|
import 'decimal.js';
|
|
6
6
|
import './locale.js';
|
|
@@ -14,6 +14,8 @@ import { DateRangeResolver } from './time.js';
|
|
|
14
14
|
interface PluginContext {
|
|
15
15
|
/** Plugin ID from manifest */
|
|
16
16
|
pluginId: string;
|
|
17
|
+
/** Host-resolved uninstall retention choice; read-only lifecycle input. */
|
|
18
|
+
readonly uninstallRetention?: "retain" | "archive" | "delete" | undefined;
|
|
17
19
|
/** Current organization ID (from request context) */
|
|
18
20
|
organizationId?: string | undefined;
|
|
19
21
|
/** Original organization ID before any infrastructure policy context swap */
|
|
@@ -68,6 +70,8 @@ interface PluginContext {
|
|
|
68
70
|
marketplaceRegistryBaseUrl?: string | null | undefined;
|
|
69
71
|
/** Host-mediated Core organization creation for explicitly trusted plugins. */
|
|
70
72
|
organizationProvisioning?: PluginOrganizationProvisioningCapability | undefined;
|
|
73
|
+
/** Host-mediated exact membership lookup within the current organization. */
|
|
74
|
+
organizationMembers?: PluginOrganizationMembersCapability | undefined;
|
|
71
75
|
/**
|
|
72
76
|
* Shared database transaction for synchronous cross-plugin pipe calls.
|
|
73
77
|
*
|
|
@@ -133,6 +137,18 @@ interface PluginScopedDb {
|
|
|
133
137
|
selectDistinctOn(...args: any[]): any;
|
|
134
138
|
insert(table: any): any;
|
|
135
139
|
update(table: any): any;
|
|
140
|
+
/**
|
|
141
|
+
* Replace the dynamic visibility tags cached on matching rows.
|
|
142
|
+
*
|
|
143
|
+
* Use this after the plugin recalculates who may read its own records. The
|
|
144
|
+
* Host still enforces the current organization, existing row visibility,
|
|
145
|
+
* tag syntax and audit logging. An explicit `where` is required, and this
|
|
146
|
+
* cannot change row ownership or deny tags.
|
|
147
|
+
*/
|
|
148
|
+
setAclTags(table: any, input: {
|
|
149
|
+
tags: readonly string[];
|
|
150
|
+
where: any;
|
|
151
|
+
}): Promise<unknown>;
|
|
136
152
|
delete(table: any, options?: {
|
|
137
153
|
softDelete?: false;
|
|
138
154
|
}): any;
|
|
@@ -200,6 +216,21 @@ interface PluginOrganizationProvisioningCapability {
|
|
|
200
216
|
status: "created" | "existing";
|
|
201
217
|
}>;
|
|
202
218
|
}
|
|
219
|
+
interface PluginOrganizationMembersCapability {
|
|
220
|
+
find(input: {
|
|
221
|
+
userId: string;
|
|
222
|
+
roleSlugs?: readonly string[] | undefined;
|
|
223
|
+
}): Promise<{
|
|
224
|
+
id: string;
|
|
225
|
+
userId: string;
|
|
226
|
+
role: string;
|
|
227
|
+
status: string;
|
|
228
|
+
user: {
|
|
229
|
+
id: string;
|
|
230
|
+
banned: boolean | null;
|
|
231
|
+
};
|
|
232
|
+
} | null>;
|
|
233
|
+
}
|
|
203
234
|
/**
|
|
204
235
|
* Framework-neutral request envelope for plugin-owned public web routes.
|
|
205
236
|
*
|
|
@@ -267,8 +298,10 @@ interface WebSlotRemoteExtension {
|
|
|
267
298
|
queries?: WebSlotExtensionQuery[] | undefined;
|
|
268
299
|
queryResults?: WebSlotQueryResult[] | undefined;
|
|
269
300
|
}
|
|
301
|
+
type WebSlotRenderMode = "island" | "react";
|
|
270
302
|
interface WebSlotRenderResult {
|
|
271
303
|
html: string;
|
|
304
|
+
renderMode?: WebSlotRenderMode | undefined;
|
|
272
305
|
extensions?: WebSlotRemoteExtension[] | undefined;
|
|
273
306
|
head?: WebPluginHead | undefined;
|
|
274
307
|
initialData?: Record<string, unknown> | undefined;
|
|
@@ -1282,6 +1315,8 @@ interface PluginMediaUploadInput {
|
|
|
1282
1315
|
*/
|
|
1283
1316
|
interface PluginMediaInfo {
|
|
1284
1317
|
id: string;
|
|
1318
|
+
/** Browser-accessible URL resolved by the Admin Host media picker. */
|
|
1319
|
+
url?: string;
|
|
1285
1320
|
filename: string;
|
|
1286
1321
|
mimeType: string;
|
|
1287
1322
|
size: number;
|
|
@@ -1630,6 +1665,14 @@ interface HookHandlerOptions {
|
|
|
1630
1665
|
priority?: HookPriority;
|
|
1631
1666
|
/** Handler timeout in ms (default: 5000) */
|
|
1632
1667
|
timeout?: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* Let this handler read its owning plugin's current-organization data when
|
|
1670
|
+
* invoked by an allowlisted caller plugin. The caller never receives direct
|
|
1671
|
+
* database access; tenant, deny, ABAC, field and audit policies stay active.
|
|
1672
|
+
*/
|
|
1673
|
+
organizationRead?: {
|
|
1674
|
+
callers: readonly string[];
|
|
1675
|
+
};
|
|
1633
1676
|
}
|
|
1634
1677
|
/**
|
|
1635
1678
|
* Plugin Hook Capability - Register hook handlers
|
|
@@ -1790,6 +1833,8 @@ interface HookContext {
|
|
|
1790
1833
|
id: string;
|
|
1791
1834
|
hookId: string;
|
|
1792
1835
|
traceId?: string;
|
|
1836
|
+
/** Plugin that emitted the current hook. Host supplied and not payload controlled. */
|
|
1837
|
+
sourcePluginId?: string | undefined;
|
|
1793
1838
|
pluginId: string;
|
|
1794
1839
|
organizationId?: string | undefined;
|
|
1795
1840
|
userId?: string | undefined;
|
|
@@ -1825,4 +1870,4 @@ type ApiPayload<T> = {
|
|
|
1825
1870
|
[K in keyof T]: T[K] extends Date ? string : T[K] extends Date | null ? string | null : T[K] extends Date | undefined ? string | undefined : T[K];
|
|
1826
1871
|
};
|
|
1827
1872
|
|
|
1828
|
-
export { type
|
|
1873
|
+
export { type PluginActionInvokerCapability as $, type ActionContractMeta as A, type ApiPayload as B, type EAuthProvider as C, type EAuthRefreshInput as D, type EAuthModel as E, type EAuthRefreshResult as F, type EAuthStatus as G, type HookContext as H, type EAuthTokenResult as I, type EAuthUpsertInput as J, type EAuthUse as K, HookAbortError as L, type HookEmitOptions as M, HookPriority as N, MARKETPLACE_PUBLISH_AUTH_METHODS as O, type PluginMediaInfo as P, type MarketplaceAttestationTargetV1 as Q, type MarketplaceExecutionErrorCode as R, type MarketplaceExecutionFailureCode as S, type MarketplaceOrganizationExecutionV1 as T, type MarketplacePlatformReadAction as U, type MarketplacePublishActor as V, type WebSlotRemoteExtension as W, type MarketplacePublishAuthMethod as X, type MarketplacePublisherAction as Y, type MarketplaceRegistrySigningCapability as Z, type OpaquePublisherCandidateV1 as _, type PluginContext as a, type WebPluginRouteRequest as a$, type PluginAgentCapability as a0, type PluginAiCapability as a1, type PluginAiRuntimeCapability as a2, type PluginApisCapability as a3, type PluginArtifactCapability as a4, type PluginAssetCapability as a5, type PluginAssetCreateOptions as a6, type PluginAssetInfo as a7, type PluginAssetQuery as a8, type PluginAssetUpdateData as a9, type PluginNotificationSendResult as aA, type PluginNotificationTarget as aB, type PluginNotificationTemplate as aC, type PluginOrganizationMembersCapability as aD, type PluginOrganizationProvisioningCapability as aE, type PluginPaginatedResult as aF, type PluginPermissionCapability as aG, type PluginPermissionCheckContext as aH, type PluginPermissionDef as aI, type PluginQueueCapability as aJ, type PluginScopedDb as aK, type PluginSettingEntry as aL, type PluginSettingOptions as aM, type PluginSettingsCapability as aN, type PluginStorageCapability as aO, type PluginStorageProvider as aP, type PluginStorageProviderConfig as aQ, type PluginStorageProviderInfo as aR, type PluginStorageUploadInput as aS, type PluginStorageUploadResult as aT, type PluginTraceCapability as aU, type PluginUsageCapability as aV, type PluginWebCapability as aW, type ReadonlyPluginScopedDb as aX, type WebPluginHead as aY, type WebPluginHeadLink as aZ, type WebPluginRouteHandler as a_, type PluginAssetVariant as aa, type PluginCurrencyCapability as ab, type PluginEAuthCapability as ac, type PluginEntityExtensionCapability as ad, type PluginEntityExtensionFilter as ae, type PluginFileCapability as af, type PluginFileInfo as ag, type PluginFileQuery as ah, type PluginFileUploadInput as ai, type PluginHookCapability as aj, type PluginJobOptions as ak, type PluginJobStatus as al, type PluginMediaCapability as am, type PluginMediaQuery as an, type PluginMediaUpdateData as ao, type PluginMediaUploadInput as ap, type PluginMediaVariant as aq, type PluginMetricsAllowedLabels as ar, type PluginMetricsCapability as as, type PluginNotificationActor as at, type PluginNotificationCapability as au, type PluginNotificationChannel as av, type PluginNotificationEvent as aw, type PluginNotificationInput as ax, type PluginNotificationResult as ay, type PluginNotificationSendParams as az, type HookHandlerOptions as b, type WebPluginRouteResult as b0, type WebPluginTenantInfo as b1, type WebSlotExtensionQuery as b2, type WebSlotQueryResult as b3, type WebSlotRenderMode as b4, type WebSlotRenderOptions as b5, type WebSlotRenderRequest as b6, type WebSlotRenderResult as b7, type WebSlotRenderer as b8, type HookTransaction as c, type PluginLogger as d, type WebPluginSiteInfo as e, type ActionDescriptor as f, type ActionInvokeRequest as g, type AgentToolDescriptor as h, type AiAliasDescriptor as i, type AiBudget as j, type AiModelCatalog as k, type AiModelHint as l, type AiModelListRequest as m, type AiModelOption as n, type AiObjectRequest as o, type AiObjectResult as p, type AiObjectSchema as q, type AiRuntimeHandler as r, type AiRuntimeHost as s, type AiRuntimeInvocation as t, type AiStreamEvent as u, type AiTextRequest as v, type AiTextResult as w, type AiUsage as x, type AiUsageAuthorization as y, type AiUsageObservation as z };
|