@jenil94/plugin-sdk 0.1.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/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @jenil94/plugin-sdk
2
+
3
+ SDK for building Harness plugins with React. Provides communication utilities, context management, and routing synchronization for plugins running in iframes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @jenil94/plugin-sdk
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ This package requires the following peer dependencies:
14
+
15
+ - `react` (^18.0.0 || ^19.0.0)
16
+ - `react-dom` (^18.0.0 || ^19.0.0)
17
+ - `react-router-dom` (^6.0.0 || ^7.0.0)
18
+
19
+ ## Usage
20
+
21
+ ### Basic Setup
22
+
23
+ ```tsx
24
+ import { PluginAPI, PluginContextProvider, PluginRouter } from '@jenil94/plugin-sdk'
25
+
26
+ // Initialize the plugin as early as possible
27
+ PluginAPI.init()
28
+
29
+ function App() {
30
+ return (
31
+ <PluginContextProvider>
32
+ <PluginRouter>
33
+ {/* Your app routes here */}
34
+ </PluginRouter>
35
+ </PluginContextProvider>
36
+ )
37
+ }
38
+ ```
39
+
40
+ ### Using Plugin Context
41
+
42
+ ```tsx
43
+ import { usePluginContext } from '@jenil94/plugin-sdk'
44
+
45
+ function MyComponent() {
46
+ const context = usePluginContext()
47
+
48
+ if (!context) {
49
+ return <div>Loading...</div>
50
+ }
51
+
52
+ return (
53
+ <div>
54
+ <p>Theme: {context.theme}</p>
55
+ <p>Location: {context.location}</p>
56
+ </div>
57
+ )
58
+ }
59
+ ```
60
+
61
+ ### Proxy Fetch (for authenticated API calls)
62
+
63
+ ```tsx
64
+ import { PluginAPI } from '@jenil94/plugin-sdk'
65
+
66
+ async function fetchData() {
67
+ const response = await PluginAPI.proxyFetch('/api/some-endpoint')
68
+ const data = await response.json()
69
+ return data
70
+ }
71
+ ```
72
+
73
+ ## API Reference
74
+
75
+ ### PluginAPI
76
+
77
+ Static class for communication with the host application.
78
+
79
+ - `PluginAPI.init()` - Signals to the host that the plugin is ready
80
+ - `PluginAPI.getContext()` - Retrieves the current plugin context
81
+ - `PluginAPI.proxyFetch(url, init?)` - Proxies fetch requests through the host
82
+
83
+ ### PluginContextProvider
84
+
85
+ React context provider that manages plugin context state.
86
+
87
+ ### usePluginContext()
88
+
89
+ Hook to access the current plugin context.
90
+
91
+ ### PluginRouter
92
+
93
+ Router component that synchronizes with the parent page's URL.
94
+
95
+ ### useParentRoutingSync()
96
+
97
+ Hook for manual route synchronization with the parent page.
98
+
99
+ ## Development
100
+
101
+ ```bash
102
+ # Install dependencies
103
+ npm install
104
+
105
+ # Build the package
106
+ npm run build
107
+
108
+ # Watch mode
109
+ npm run dev
110
+ ```
111
+
112
+ ## License
113
+
114
+ MIT
115
+
package/dist/index.cjs ADDED
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ PluginAPI: () => PluginAPI,
24
+ PluginContextProvider: () => PluginContextProvider,
25
+ PluginMessageType: () => PluginMessageType,
26
+ PluginRouter: () => PluginRouter,
27
+ useParentRoutingSync: () => useParentRoutingSync,
28
+ usePluginContext: () => usePluginContext
29
+ });
30
+ module.exports = __toCommonJS(index_exports);
31
+
32
+ // src/plugin-api.ts
33
+ var PluginMessageType = {
34
+ Init: "init",
35
+ Context: "context",
36
+ GetContext: "getContext",
37
+ Fetch: "fetch",
38
+ FetchResponse: "fetchResponse"
39
+ };
40
+ var PluginAPI = class {
41
+ /**
42
+ * Signals to the host that the plugin is ready
43
+ * This should be called as early as possible in the plugin lifecycle
44
+ */
45
+ static async init() {
46
+ window.parent.postMessage({ type: PluginMessageType.Init }, "*");
47
+ }
48
+ /**
49
+ * Retrieves the current plugin context from the host
50
+ * Includes entity data, user info, theme settings, and API base URL
51
+ */
52
+ static async getContext() {
53
+ return new Promise((resolve) => {
54
+ const handler = (event) => {
55
+ if (event.data.type === PluginMessageType.Context) {
56
+ window.removeEventListener("message", handler);
57
+ resolve(event.data.data);
58
+ }
59
+ };
60
+ window.addEventListener("message", handler);
61
+ window.parent.postMessage({ type: PluginMessageType.GetContext }, "*");
62
+ });
63
+ }
64
+ /**
65
+ * Proxies a fetch request through the host application
66
+ * This allows the host to handle authentication and CORS
67
+ */
68
+ static async proxyFetch(url, init) {
69
+ return new Promise((resolve) => {
70
+ const handler = (event) => {
71
+ const response = event.data?.response;
72
+ if (response) {
73
+ window.removeEventListener("message", handler);
74
+ console.log("proxyFetch response from host:", event.data);
75
+ let body = response.body;
76
+ if (body !== null && typeof body === "object") {
77
+ body = JSON.stringify(body);
78
+ }
79
+ resolve(
80
+ new Response(body, {
81
+ status: response.status ?? 200,
82
+ statusText: response.statusText ?? "",
83
+ headers: response.headers
84
+ })
85
+ );
86
+ }
87
+ };
88
+ window.addEventListener("message", handler);
89
+ window.parent.postMessage(
90
+ {
91
+ type: PluginMessageType.Fetch,
92
+ url,
93
+ init
94
+ },
95
+ "*"
96
+ );
97
+ });
98
+ }
99
+ };
100
+
101
+ // src/plugin-context.tsx
102
+ var import_react = require("react");
103
+ var import_jsx_runtime = require("react/jsx-runtime");
104
+ var PluginDataContext = (0, import_react.createContext)(null);
105
+ function PluginContextProvider({ children }) {
106
+ const [context, setContext] = (0, import_react.useState)(null);
107
+ (0, import_react.useEffect)(() => {
108
+ const handler = (event) => {
109
+ if (event.data?.type === "context") {
110
+ console.log("Received context from host:", event.data.data);
111
+ setContext(event.data.data);
112
+ }
113
+ };
114
+ window.addEventListener("message", handler);
115
+ return () => window.removeEventListener("message", handler);
116
+ }, []);
117
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluginDataContext.Provider, { value: context, children });
118
+ }
119
+ function usePluginContext() {
120
+ const context = (0, import_react.useContext)(PluginDataContext);
121
+ return context;
122
+ }
123
+
124
+ // src/plugin-router.tsx
125
+ var import_react2 = require("react");
126
+ var import_react_router_dom = require("react-router-dom");
127
+ var import_jsx_runtime2 = require("react/jsx-runtime");
128
+ var toCamelCase = (str) => {
129
+ return str.split("-").filter((segment) => segment.length > 0).map(
130
+ (word, index) => index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
131
+ ).join("");
132
+ };
133
+ var useParentRoutingSync = () => {
134
+ const context = usePluginContext();
135
+ const tag = context?.tag;
136
+ const queryParamKey = (0, import_react2.useMemo)(() => {
137
+ return tag ? toCamelCase(tag) + "PluginRoute" : "pluginRoute";
138
+ }, [tag]);
139
+ const location = (0, import_react_router_dom.useLocation)();
140
+ const navigate = (0, import_react_router_dom.useNavigate)();
141
+ (0, import_react2.useEffect)(() => {
142
+ const newRoute = `${location.pathname}${location.search}${location.hash}`;
143
+ console.log("Syncing route to parent:", newRoute);
144
+ window.parent.postMessage(
145
+ {
146
+ type: "routeChange",
147
+ route: newRoute,
148
+ queryParamKey
149
+ },
150
+ "*"
151
+ );
152
+ }, [location, queryParamKey]);
153
+ (0, import_react2.useEffect)(() => {
154
+ const handleMessage = (event) => {
155
+ if (event.data?.type === "navigateTo" && event.data.route) {
156
+ console.log("Received navigation command from parent:", event.data.route);
157
+ navigate(event.data.route);
158
+ }
159
+ };
160
+ window.addEventListener("message", handleMessage);
161
+ return () => window.removeEventListener("message", handleMessage);
162
+ }, [navigate]);
163
+ };
164
+ var ParentRouterSync = () => {
165
+ useParentRoutingSync();
166
+ return null;
167
+ };
168
+ var PluginRouter = ({ children, initialEntries }) => {
169
+ const context = usePluginContext();
170
+ const tag = context?.tag;
171
+ const [initialRoute, setInitialRoute] = (0, import_react2.useState)(null);
172
+ const [isReady, setIsReady] = (0, import_react2.useState)(false);
173
+ (0, import_react2.useEffect)(() => {
174
+ const queryParamKey = tag ? toCamelCase(tag) + "PluginRoute" : "pluginRoute";
175
+ const handleMessage = (event) => {
176
+ if (event.data?.type === "initialRoute") {
177
+ console.log("Received initial route from parent:", event.data.route);
178
+ setInitialRoute(event.data.route || "/");
179
+ setIsReady(true);
180
+ }
181
+ };
182
+ window.addEventListener("message", handleMessage);
183
+ window.parent.postMessage(
184
+ {
185
+ type: "getInitialRoute",
186
+ queryParamKey
187
+ },
188
+ "*"
189
+ );
190
+ const timeout = setTimeout(() => {
191
+ if (!isReady) {
192
+ console.log("No initial route from parent, using default");
193
+ setInitialRoute("/");
194
+ setIsReady(true);
195
+ }
196
+ }, 300);
197
+ return () => {
198
+ window.removeEventListener("message", handleMessage);
199
+ clearTimeout(timeout);
200
+ };
201
+ }, [tag, isReady]);
202
+ const defaultInitialEntries = (0, import_react2.useMemo)(() => {
203
+ if (initialRoute) {
204
+ return [initialRoute.startsWith("/") ? initialRoute : "/" + initialRoute];
205
+ }
206
+ if (initialEntries && initialEntries.length > 0) {
207
+ return initialEntries;
208
+ }
209
+ return ["/"];
210
+ }, [initialEntries, initialRoute]);
211
+ if (!isReady) {
212
+ return null;
213
+ }
214
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_router_dom.MemoryRouter, { initialEntries: defaultInitialEntries, children: [
215
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ParentRouterSync, {}),
216
+ children
217
+ ] });
218
+ };
219
+ // Annotate the CommonJS export names for ESM import in node:
220
+ 0 && (module.exports = {
221
+ PluginAPI,
222
+ PluginContextProvider,
223
+ PluginMessageType,
224
+ PluginRouter,
225
+ useParentRoutingSync,
226
+ usePluginContext
227
+ });
@@ -0,0 +1,61 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1, { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Plugin API for communication with the host application
6
+ * Based on the Cortex plugin architecture pattern
7
+ */
8
+ interface PluginContext {
9
+ apiBaseUrl: string;
10
+ entity: unknown | null;
11
+ location: 'ENTITY' | 'GLOBAL';
12
+ tag: string | null;
13
+ user: unknown;
14
+ style: Record<string, string>;
15
+ theme: 'light' | 'dark';
16
+ }
17
+ declare const PluginMessageType: {
18
+ readonly Init: "init";
19
+ readonly Context: "context";
20
+ readonly GetContext: "getContext";
21
+ readonly Fetch: "fetch";
22
+ readonly FetchResponse: "fetchResponse";
23
+ };
24
+ declare class PluginAPI {
25
+ /**
26
+ * Signals to the host that the plugin is ready
27
+ * This should be called as early as possible in the plugin lifecycle
28
+ */
29
+ static init(): Promise<void>;
30
+ /**
31
+ * Retrieves the current plugin context from the host
32
+ * Includes entity data, user info, theme settings, and API base URL
33
+ */
34
+ static getContext(): Promise<PluginContext>;
35
+ /**
36
+ * Proxies a fetch request through the host application
37
+ * This allows the host to handle authentication and CORS
38
+ */
39
+ static proxyFetch(url: string, init?: RequestInit): Promise<Response>;
40
+ }
41
+
42
+ declare function PluginContextProvider({ children }: {
43
+ children: React.ReactNode;
44
+ }): react_jsx_runtime.JSX.Element;
45
+ declare function usePluginContext(): PluginContext | null;
46
+
47
+ /**
48
+ * Custom hook that synchronizes the in-app route with the parent page's URL via postMessage.
49
+ */
50
+ declare const useParentRoutingSync: () => void;
51
+ interface PluginRouterProps {
52
+ children: ReactNode;
53
+ initialEntries?: string[];
54
+ }
55
+ /**
56
+ * PluginRouter wraps your app's routing logic and sets the initial route
57
+ * based on the parent page's URL if no initial route is provided.
58
+ */
59
+ declare const PluginRouter: React$1.FC<PluginRouterProps>;
60
+
61
+ export { PluginAPI, type PluginContext, PluginContextProvider, PluginMessageType, PluginRouter, useParentRoutingSync, usePluginContext };
@@ -0,0 +1,61 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1, { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Plugin API for communication with the host application
6
+ * Based on the Cortex plugin architecture pattern
7
+ */
8
+ interface PluginContext {
9
+ apiBaseUrl: string;
10
+ entity: unknown | null;
11
+ location: 'ENTITY' | 'GLOBAL';
12
+ tag: string | null;
13
+ user: unknown;
14
+ style: Record<string, string>;
15
+ theme: 'light' | 'dark';
16
+ }
17
+ declare const PluginMessageType: {
18
+ readonly Init: "init";
19
+ readonly Context: "context";
20
+ readonly GetContext: "getContext";
21
+ readonly Fetch: "fetch";
22
+ readonly FetchResponse: "fetchResponse";
23
+ };
24
+ declare class PluginAPI {
25
+ /**
26
+ * Signals to the host that the plugin is ready
27
+ * This should be called as early as possible in the plugin lifecycle
28
+ */
29
+ static init(): Promise<void>;
30
+ /**
31
+ * Retrieves the current plugin context from the host
32
+ * Includes entity data, user info, theme settings, and API base URL
33
+ */
34
+ static getContext(): Promise<PluginContext>;
35
+ /**
36
+ * Proxies a fetch request through the host application
37
+ * This allows the host to handle authentication and CORS
38
+ */
39
+ static proxyFetch(url: string, init?: RequestInit): Promise<Response>;
40
+ }
41
+
42
+ declare function PluginContextProvider({ children }: {
43
+ children: React.ReactNode;
44
+ }): react_jsx_runtime.JSX.Element;
45
+ declare function usePluginContext(): PluginContext | null;
46
+
47
+ /**
48
+ * Custom hook that synchronizes the in-app route with the parent page's URL via postMessage.
49
+ */
50
+ declare const useParentRoutingSync: () => void;
51
+ interface PluginRouterProps {
52
+ children: ReactNode;
53
+ initialEntries?: string[];
54
+ }
55
+ /**
56
+ * PluginRouter wraps your app's routing logic and sets the initial route
57
+ * based on the parent page's URL if no initial route is provided.
58
+ */
59
+ declare const PluginRouter: React$1.FC<PluginRouterProps>;
60
+
61
+ export { PluginAPI, type PluginContext, PluginContextProvider, PluginMessageType, PluginRouter, useParentRoutingSync, usePluginContext };
package/dist/index.js ADDED
@@ -0,0 +1,195 @@
1
+ // src/plugin-api.ts
2
+ var PluginMessageType = {
3
+ Init: "init",
4
+ Context: "context",
5
+ GetContext: "getContext",
6
+ Fetch: "fetch",
7
+ FetchResponse: "fetchResponse"
8
+ };
9
+ var PluginAPI = class {
10
+ /**
11
+ * Signals to the host that the plugin is ready
12
+ * This should be called as early as possible in the plugin lifecycle
13
+ */
14
+ static async init() {
15
+ window.parent.postMessage({ type: PluginMessageType.Init }, "*");
16
+ }
17
+ /**
18
+ * Retrieves the current plugin context from the host
19
+ * Includes entity data, user info, theme settings, and API base URL
20
+ */
21
+ static async getContext() {
22
+ return new Promise((resolve) => {
23
+ const handler = (event) => {
24
+ if (event.data.type === PluginMessageType.Context) {
25
+ window.removeEventListener("message", handler);
26
+ resolve(event.data.data);
27
+ }
28
+ };
29
+ window.addEventListener("message", handler);
30
+ window.parent.postMessage({ type: PluginMessageType.GetContext }, "*");
31
+ });
32
+ }
33
+ /**
34
+ * Proxies a fetch request through the host application
35
+ * This allows the host to handle authentication and CORS
36
+ */
37
+ static async proxyFetch(url, init) {
38
+ return new Promise((resolve) => {
39
+ const handler = (event) => {
40
+ const response = event.data?.response;
41
+ if (response) {
42
+ window.removeEventListener("message", handler);
43
+ console.log("proxyFetch response from host:", event.data);
44
+ let body = response.body;
45
+ if (body !== null && typeof body === "object") {
46
+ body = JSON.stringify(body);
47
+ }
48
+ resolve(
49
+ new Response(body, {
50
+ status: response.status ?? 200,
51
+ statusText: response.statusText ?? "",
52
+ headers: response.headers
53
+ })
54
+ );
55
+ }
56
+ };
57
+ window.addEventListener("message", handler);
58
+ window.parent.postMessage(
59
+ {
60
+ type: PluginMessageType.Fetch,
61
+ url,
62
+ init
63
+ },
64
+ "*"
65
+ );
66
+ });
67
+ }
68
+ };
69
+
70
+ // src/plugin-context.tsx
71
+ import { createContext, useContext, useState, useEffect } from "react";
72
+ import { jsx } from "react/jsx-runtime";
73
+ var PluginDataContext = createContext(null);
74
+ function PluginContextProvider({ children }) {
75
+ const [context, setContext] = useState(null);
76
+ useEffect(() => {
77
+ const handler = (event) => {
78
+ if (event.data?.type === "context") {
79
+ console.log("Received context from host:", event.data.data);
80
+ setContext(event.data.data);
81
+ }
82
+ };
83
+ window.addEventListener("message", handler);
84
+ return () => window.removeEventListener("message", handler);
85
+ }, []);
86
+ return /* @__PURE__ */ jsx(PluginDataContext.Provider, { value: context, children });
87
+ }
88
+ function usePluginContext() {
89
+ const context = useContext(PluginDataContext);
90
+ return context;
91
+ }
92
+
93
+ // src/plugin-router.tsx
94
+ import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
95
+ import { MemoryRouter, useLocation, useNavigate } from "react-router-dom";
96
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
97
+ var toCamelCase = (str) => {
98
+ return str.split("-").filter((segment) => segment.length > 0).map(
99
+ (word, index) => index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
100
+ ).join("");
101
+ };
102
+ var useParentRoutingSync = () => {
103
+ const context = usePluginContext();
104
+ const tag = context?.tag;
105
+ const queryParamKey = useMemo(() => {
106
+ return tag ? toCamelCase(tag) + "PluginRoute" : "pluginRoute";
107
+ }, [tag]);
108
+ const location = useLocation();
109
+ const navigate = useNavigate();
110
+ useEffect2(() => {
111
+ const newRoute = `${location.pathname}${location.search}${location.hash}`;
112
+ console.log("Syncing route to parent:", newRoute);
113
+ window.parent.postMessage(
114
+ {
115
+ type: "routeChange",
116
+ route: newRoute,
117
+ queryParamKey
118
+ },
119
+ "*"
120
+ );
121
+ }, [location, queryParamKey]);
122
+ useEffect2(() => {
123
+ const handleMessage = (event) => {
124
+ if (event.data?.type === "navigateTo" && event.data.route) {
125
+ console.log("Received navigation command from parent:", event.data.route);
126
+ navigate(event.data.route);
127
+ }
128
+ };
129
+ window.addEventListener("message", handleMessage);
130
+ return () => window.removeEventListener("message", handleMessage);
131
+ }, [navigate]);
132
+ };
133
+ var ParentRouterSync = () => {
134
+ useParentRoutingSync();
135
+ return null;
136
+ };
137
+ var PluginRouter = ({ children, initialEntries }) => {
138
+ const context = usePluginContext();
139
+ const tag = context?.tag;
140
+ const [initialRoute, setInitialRoute] = useState2(null);
141
+ const [isReady, setIsReady] = useState2(false);
142
+ useEffect2(() => {
143
+ const queryParamKey = tag ? toCamelCase(tag) + "PluginRoute" : "pluginRoute";
144
+ const handleMessage = (event) => {
145
+ if (event.data?.type === "initialRoute") {
146
+ console.log("Received initial route from parent:", event.data.route);
147
+ setInitialRoute(event.data.route || "/");
148
+ setIsReady(true);
149
+ }
150
+ };
151
+ window.addEventListener("message", handleMessage);
152
+ window.parent.postMessage(
153
+ {
154
+ type: "getInitialRoute",
155
+ queryParamKey
156
+ },
157
+ "*"
158
+ );
159
+ const timeout = setTimeout(() => {
160
+ if (!isReady) {
161
+ console.log("No initial route from parent, using default");
162
+ setInitialRoute("/");
163
+ setIsReady(true);
164
+ }
165
+ }, 300);
166
+ return () => {
167
+ window.removeEventListener("message", handleMessage);
168
+ clearTimeout(timeout);
169
+ };
170
+ }, [tag, isReady]);
171
+ const defaultInitialEntries = useMemo(() => {
172
+ if (initialRoute) {
173
+ return [initialRoute.startsWith("/") ? initialRoute : "/" + initialRoute];
174
+ }
175
+ if (initialEntries && initialEntries.length > 0) {
176
+ return initialEntries;
177
+ }
178
+ return ["/"];
179
+ }, [initialEntries, initialRoute]);
180
+ if (!isReady) {
181
+ return null;
182
+ }
183
+ return /* @__PURE__ */ jsxs(MemoryRouter, { initialEntries: defaultInitialEntries, children: [
184
+ /* @__PURE__ */ jsx2(ParentRouterSync, {}),
185
+ children
186
+ ] });
187
+ };
188
+ export {
189
+ PluginAPI,
190
+ PluginContextProvider,
191
+ PluginMessageType,
192
+ PluginRouter,
193
+ useParentRoutingSync,
194
+ usePluginContext
195
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@jenil94/plugin-sdk",
3
+ "version": "0.1.0",
4
+ "description": "SDK for building Harness plugins with React",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
21
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "peerDependencies": {
25
+ "react": "^18.0.0 || ^19.0.0",
26
+ "react-dom": "^18.0.0 || ^19.0.0",
27
+ "react-router-dom": "^6.0.0 || ^7.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^19.2.5",
31
+ "@types/react-dom": "^19.2.3",
32
+ "react": "^19.2.0",
33
+ "react-dom": "^19.2.0",
34
+ "react-router-dom": "^7.13.0",
35
+ "tsup": "^8.0.0",
36
+ "typescript": "~5.9.3"
37
+ },
38
+ "keywords": [
39
+ "harness",
40
+ "plugin",
41
+ "sdk",
42
+ "react"
43
+ ],
44
+ "license": "MIT"
45
+ }
46
+