@vikukumar/propvault-pdk 0.1.4

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,129 @@
1
+ # PropVault CMS — Plugin Development Kit (PDK)
2
+
3
+ Extend the functionality of the PropVault Real Estate CMS and Page Builder platform with dynamic plugins. Custom plugins can register Action hooks to trigger custom logic on events (e.g. sending CRM leads) and Filter hooks to intercept and mutate variables/configs before operations complete.
4
+
5
+ ---
6
+
7
+ ## Getting Started
8
+
9
+ ### 1. Requirements
10
+ Ensure you have **Node.js >= 18** and **TypeScript** installed locally.
11
+
12
+ ### 2. Scaffold a New Plugin
13
+ Run the PDK CLI initializer inside the directory where you want to scaffold your plugin.
14
+
15
+ ```bash
16
+ # Initialize a new plugin template
17
+ npx @vikukumar/propvault-pdk create my-custom-plugin
18
+ ```
19
+
20
+ This scaffolds the following plugin directory structure:
21
+ ```
22
+ my-custom-plugin/
23
+ ├── src/
24
+ │ └── index.ts # Core plugin logic & hooks registration
25
+ ├── dist/ # Compiled distribution (created on build)
26
+ ├── package.json # Node config & build scripts
27
+ ├── tsconfig.json # TypeScript compiler configurations
28
+ └── plugin.json # Plugin manifest metadata block
29
+ ```
30
+
31
+ ### 3. Install Scaffolding Dependencies
32
+ ```bash
33
+ cd my-custom-plugin
34
+ npm install
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Writing Plugin Logic
40
+
41
+ Plugins register hook handlers inside `src/index.ts` using `addAction` and `addFilter` from the `@vikukumar/propvault-pdk` package.
42
+
43
+ ### 1. Action Hooks
44
+ Action hooks trigger custom operations when specific system events occur (e.g., lead submission, newsletter registration, theme swap).
45
+
46
+ ```typescript
47
+ import { addAction } from "@vikukumar/propvault-pdk";
48
+
49
+ // Send WhatsApp telemetry notifications on new lead submissions
50
+ addAction("after_lead_submit", async (lead: any) => {
51
+ console.log("New Lead submitted in CMS:", lead.email);
52
+
53
+ // Call webhook endpoint
54
+ await fetch("https://api.mycrm.com/v1/leads", {
55
+ method: "POST",
56
+ headers: { "Content-Type": "application/json" },
57
+ body: JSON.stringify(lead),
58
+ });
59
+ }, 10);
60
+ ```
61
+
62
+ ### 2. Filter Hooks
63
+ Filter hooks intercept, modify, and return modified values/variables before the CMS processes them.
64
+
65
+ ```typescript
66
+ import { addFilter } from "@vikukumar/propvault-pdk";
67
+
68
+ // Force a premium badge suffix on project titles before they are stored in the database
69
+ addFilter("before_project_save", async (project: any) => {
70
+ if (project.title && !project.title.includes("[Verified]")) {
71
+ project.title = `${project.title} [Verified]`;
72
+ }
73
+ return project;
74
+ });
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Core Hooks Registry API
80
+
81
+ ### Action Hooks
82
+ | Hook Slug | Arguments | Description |
83
+ |---|---|---|
84
+ | `after_lead_submit` | `(lead: Lead)` | Fires after a contact form submission is registered. |
85
+ | `after_newsletter_subscribe` | `(subscription: Subscription)` | Fires after a newsletter email subscription is verified. |
86
+
87
+ ### Filter Hooks
88
+ | Hook Slug | Arguments | Description |
89
+ |---|---|---|
90
+ | `before_project_save` | `(project: Project)` | Filters project attributes before SQLite/PostgreSQL insertion. |
91
+ | `before_lead_save` | `(lead: Lead)` | Filters lead fields before database submission. |
92
+
93
+ ---
94
+
95
+ ## Build & Packaging
96
+
97
+ Once development is complete, compile and compress your plugin files into a distribution-ready bundle:
98
+
99
+ ```bash
100
+ # 1. Compile TypeScript to JavaScript dist/index.js
101
+ npm run build
102
+
103
+ # 2. Package manifest and built script into plugin.zip
104
+ npm run package
105
+ ```
106
+
107
+ The CLI outputs a **`plugin.zip`** package.
108
+
109
+ ---
110
+
111
+ ## Publishing and Installation Options
112
+
113
+ PropVault CMS supports three installation pathways:
114
+
115
+ ### Option A: Direct Zip Upload (Recommended)
116
+ 1. Go to **PropVault Admin Panel** -> **Plugins**.
117
+ 2. Locate the **Upload Zip Archive** card.
118
+ 3. Select your built `plugin.zip` file.
119
+ 4. Click **Upload** and toggle **Activate**.
120
+
121
+ ### Option B: Package Manager (NPM Release)
122
+ Publish your compiled folder structure containing `plugin.json` to npm:
123
+ ```bash
124
+ npm publish
125
+ ```
126
+ CMS administrators can install it in their workspace by entering the package name (e.g. `my-propvault-plugin`) in the **NPM Package Registry** dashboard card.
127
+
128
+ ### Option C: Git Releases
129
+ Host your plugin repository on GitHub/GitLab. Make sure it contains `plugin.json` in the root (or pre-compiled outputs). Administrators can install it dynamically by entering the Git clone URL inside the **Clone Git Repository** card.
package/bin/build.js ADDED
@@ -0,0 +1,46 @@
1
+ import { build } from "esbuild";
2
+ import { execSync } from "child_process";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const rootDir = path.join(__dirname, "..");
10
+
11
+ async function run() {
12
+ console.log("Building PropVault PDK package...");
13
+
14
+ // Clean dist
15
+ const distDir = path.join(rootDir, "dist");
16
+ if (fs.existsSync(distDir)) {
17
+ fs.rmSync(distDir, { recursive: true, force: true });
18
+ }
19
+ fs.mkdirSync(distDir, { recursive: true });
20
+
21
+ // 1. Compile TS with esbuild
22
+ await build({
23
+ entryPoints: [path.join(rootDir, "src", "index.ts")],
24
+ bundle: true,
25
+ platform: "node",
26
+ format: "esm",
27
+ outfile: path.join(distDir, "index.js"),
28
+ minify: false,
29
+ sourcemap: true,
30
+ external: []
31
+ });
32
+ console.log("✔ Compiled PDK ES modules successfully.");
33
+
34
+ // 2. Generate typings (.d.ts) using TypeScript compiler
35
+ try {
36
+ console.log("Generating typings (.d.ts)...");
37
+ execSync("npx tsc", { cwd: rootDir, stdio: "inherit" });
38
+ console.log("✔ Generated types successfully.");
39
+ } catch (err) {
40
+ console.warn("⚠ Warning: Failed to generate typings with tsc compiler:", err);
41
+ }
42
+
43
+ console.log("✔ PDK Build complete!");
44
+ }
45
+
46
+ run();
package/bin/pdk-cli.js ADDED
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PropVault CMS — PDK CLI Utility
5
+ * Scaffolds, builds, and packages custom plugins for PropVault CMS.
6
+ */
7
+
8
+ import fs from "fs";
9
+ import path from "path";
10
+ import { execSync } from "child_process";
11
+ import { fileURLToPath } from "url";
12
+ import archiver from "archiver";
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+
17
+ const BANNER = `
18
+ \x1b[38;5;214m _____ __ __ _ _ ____ ____ _ __
19
+ | __ \\ \\ \\ / / | | | | _ \\| _ \\| |/ /
20
+ | |__) | __ ___ _ __ \\ V /__ _ _ _ _| | |_ | |_) | |_) | ' /
21
+ | ___/ '__/ _ \\| '_ \\ \\ / _\` | | | | | | __| | __/| _ <| <
22
+ | | | | | (_) | |_) | | | (_| | |_| | | | |_ | | | |_) | . \\
23
+ |_| |_| \\___/| .__/ |_|\\__,_|\\__,_|_|_|\\__| |_| |____/|_|\\_\\
24
+ |_|
25
+ \x1b[39m
26
+ \x1b[90m PropVault CMS Plugin Development Kit (PDK) CLI — v0.1.0\x1b[0m
27
+ `;
28
+
29
+ function printHelp() {
30
+ console.log(BANNER);
31
+ console.log("\x1b[1mUsage:\x1b[0m");
32
+ console.log(" npx propvault-pdk <command> [options]\n");
33
+ console.log("\x1b[1mCommands:\x1b[0m");
34
+ console.log(" \x1b[32mcreate <name>\x1b[0m Scaffold a new custom plugin directory");
35
+ console.log(" \x1b[32mbuild\x1b[0m Compile TS/JS files and assemble distribution");
36
+ console.log(" \x1b[32mpackage\x1b[0m Compress build distribution into plugin.zip for CMS upload");
37
+ console.log("\n\x1b[1mExamples:\x1b[0m");
38
+ console.log(" npx propvault-pdk create my-custom-integration");
39
+ console.log(" npx propvault-pdk build\n");
40
+ }
41
+
42
+ async function main() {
43
+ const args = process.argv.slice(2);
44
+ const command = args[0];
45
+
46
+ if (!command || command === "--help" || command === "-h") {
47
+ printHelp();
48
+ return;
49
+ }
50
+
51
+ const workspaceRoot = process.cwd();
52
+
53
+ switch (command) {
54
+ case "create": {
55
+ const pluginName = args[1];
56
+ if (!pluginName) {
57
+ console.error("\x1b[31m[Error]\x1b[0m Please specify the plugin folder name: npx propvault-pdk create <plugin-name>");
58
+ process.exit(1);
59
+ }
60
+
61
+ const slug = pluginName.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
62
+ const destDir = path.join(workspaceRoot, slug);
63
+
64
+ if (fs.existsSync(destDir)) {
65
+ console.error(`\x1b[31m[Error]\x1b[0m Directory "${slug}" already exists.`);
66
+ process.exit(1);
67
+ }
68
+
69
+ console.log(BANNER);
70
+ console.log(`\x1b[34m[Scaffold]\x1b[0m Creating plugin template for "${slug}"...`);
71
+
72
+ // Load local PDK version dynamically
73
+ let pdkVersion = "0.1.0";
74
+ try {
75
+ const pdkPkgPath = path.join(__dirname, "..", "package.json");
76
+ if (fs.existsSync(pdkPkgPath)) {
77
+ const pdkPkg = JSON.parse(fs.readFileSync(pdkPkgPath, "utf8"));
78
+ pdkVersion = pdkPkg.version || "0.1.0";
79
+ }
80
+ } catch {}
81
+
82
+ // 1. Create folders
83
+ fs.mkdirSync(path.join(destDir, "src"), { recursive: true });
84
+
85
+ // 2. Write package.json
86
+ const pkgContent = {
87
+ name: slug,
88
+ version: "1.0.0",
89
+ description: "Custom plugin integration for PropVault CMS",
90
+ main: "./dist/index.js",
91
+ type: "module",
92
+ scripts: {
93
+ "build": "npx propvault-pdk build",
94
+ "package": "npx propvault-pdk package"
95
+ },
96
+ dependencies: {},
97
+ devDependencies: {
98
+ "@vikukumar/propvault-pdk": `^${pdkVersion}`,
99
+ "typescript": "^5.3.3"
100
+ }
101
+ };
102
+ fs.writeFileSync(path.join(destDir, "package.json"), JSON.stringify(pkgContent, null, 2) + "\n");
103
+
104
+ // 3. Write tsconfig.json
105
+ const tsconfigContent = {
106
+ compilerOptions: {
107
+ target: "ES2022",
108
+ module: "NodeNext",
109
+ moduleResolution: "NodeNext",
110
+ strict: true,
111
+ skipLibCheck: true,
112
+ esModuleInterop: true,
113
+ outDir: "./dist"
114
+ },
115
+ include: ["src/**/*"]
116
+ };
117
+ fs.writeFileSync(path.join(destDir, "tsconfig.json"), JSON.stringify(tsconfigContent, null, 2) + "\n");
118
+
119
+ // 4. Write plugin.json manifest
120
+ const manifestContent = {
121
+ name: slug.split("-").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
122
+ slug: slug,
123
+ version: "1.0.0",
124
+ description: "A custom plugin for real-time CRM webhooks and layout filters.",
125
+ author: "Developer",
126
+ entry: "./dist/index.js"
127
+ };
128
+ fs.writeFileSync(path.join(destDir, "plugin.json"), JSON.stringify(manifestContent, null, 2) + "\n");
129
+
130
+ // 5. Write src/index.ts (sample hooks integration)
131
+ const srcContent = `import { addAction, addFilter } from "@vikukumar/propvault-pdk";
132
+
133
+ // Example Action: Triggered whenever a new lead is submitted on the website
134
+ addAction("after_lead_submit", async (lead: any) => {
135
+ console.log("[${slug.toUpperCase()}] New lead submitted:", lead.email);
136
+ // Add custom integrations here (e.g. call Slack webhooks, SendGrid, Salesforce CRM, etc.)
137
+ }, 10);
138
+
139
+ // Example Filter: Modify the RERA project title before saving in database
140
+ addFilter("before_project_save", async (project: any) => {
141
+ if (project.title) {
142
+ // Append verified suffix
143
+ project.title = \`\${project.title} [Verified]\`;
144
+ }
145
+ return project;
146
+ });
147
+ `;
148
+ fs.writeFileSync(path.join(destDir, "src", "index.ts"), srcContent);
149
+
150
+ console.log(`\x1b[32m✔ Scaffold complete! Plugin directory created at ./${slug}\x1b[0m`);
151
+ console.log("\x1b[1mNext Steps:\x1b[0m");
152
+ console.log(` cd ${slug}`);
153
+ console.log(" npm install");
154
+ console.log(" npm run build && npm run package\n");
155
+ break;
156
+ }
157
+
158
+ case "build": {
159
+ console.log("\x1b[34m[Build]\x1b[0m Compiling custom plugin TypeScript entry points...");
160
+
161
+ const pkgPath = path.join(workspaceRoot, "package.json");
162
+ if (!fs.existsSync(pkgPath)) {
163
+ console.error("\x1b[31m[Error]\x1b[0m package.json not found in active directory. Run from the plugin root directory.");
164
+ process.exit(1);
165
+ }
166
+
167
+ // Compile using local typescript compiler
168
+ try {
169
+ execSync("npx tsc", { cwd: workspaceRoot, stdio: "inherit" });
170
+ console.log("\x1b[32m✔ TypeScript compilation complete!\x1b[0m");
171
+ } catch (err) {
172
+ console.error("\x1b[31m[Error]\x1b[0m Compilation failed. Check syntax.");
173
+ process.exit(1);
174
+ }
175
+ break;
176
+ }
177
+
178
+ case "package": {
179
+ console.log("\x1b[34m[Package]\x1b[0m Bundling plugin into zip distribution...");
180
+
181
+ const manifestPath = path.join(workspaceRoot, "plugin.json");
182
+ const distJsPath = path.join(workspaceRoot, "dist", "index.js");
183
+
184
+ if (!fs.existsSync(manifestPath) || !fs.existsSync(distJsPath)) {
185
+ console.error("\x1b[31m[Error]\x1b[0m Build artifacts not found. Run 'npm run build' first.");
186
+ process.exit(1);
187
+ }
188
+
189
+ const archiveName = path.join(workspaceRoot, "plugin.zip");
190
+ const output = fs.createWriteStream(archiveName);
191
+ const archive = archiver("zip", { zlib: { level: 9 } });
192
+
193
+ output.on("close", () => {
194
+ console.log(`\x1b[32m✔ Zip packaging complete! Created archive: ./plugin.zip (${archive.pointer()} bytes)\x1b[0m`);
195
+ console.log("You can now upload this plugin.zip file in the PropVault CMS Plugins dashboard panel!");
196
+ });
197
+
198
+ archive.on("error", (err) => {
199
+ throw err;
200
+ });
201
+
202
+ archive.pipe(output);
203
+
204
+ // Add compiled folder
205
+ archive.directory(path.join(workspaceRoot, "dist"), "dist");
206
+ // Add manifest
207
+ archive.file(manifestPath, { name: "plugin.json" });
208
+
209
+ await archive.finalize();
210
+ break;
211
+ }
212
+
213
+ default:
214
+ console.error(`\x1b[31m[Error]\x1b[0m Unknown command: ${command}`);
215
+ printHelp();
216
+ process.exit(1);
217
+ }
218
+ }
219
+
220
+ main().catch(err => {
221
+ console.error("\x1b[31m[Error]\x1b[0m Operation failed:", err);
222
+ process.exit(1);
223
+ });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PropVault CMS — Plugin Development Kit (PDK) Core API
3
+ */
4
+ export interface HookAction {
5
+ slug: string;
6
+ handler: (...args: any[]) => void | Promise<void>;
7
+ priority?: number;
8
+ }
9
+ export interface HookFilter {
10
+ slug: string;
11
+ handler: (value: any, ...args: any[]) => any | Promise<any>;
12
+ priority?: number;
13
+ }
14
+ export interface PluginManifest {
15
+ name: string;
16
+ slug: string;
17
+ version: string;
18
+ description: string;
19
+ author: string;
20
+ entry: string;
21
+ }
22
+ /**
23
+ * Registers an action hook handler. Action hooks trigger code at specific system events.
24
+ */
25
+ export declare function addAction(slug: string, handler: (...args: any[]) => void | Promise<void>, priority?: number): void;
26
+ /**
27
+ * Registers a filter hook handler. Filter hooks allow modifying variables/inputs before they are stored/saved.
28
+ */
29
+ export declare function addFilter(slug: string, handler: (value: any, ...args: any[]) => any | Promise<any>, priority?: number): void;
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * PropVault CMS — Plugin Development Kit (PDK) Core API
3
+ */
4
+ /**
5
+ * Registers an action hook handler. Action hooks trigger code at specific system events.
6
+ */
7
+ export function addAction(slug, handler, priority = 10) {
8
+ if (typeof window !== "undefined")
9
+ return;
10
+ // Register dynamic handler into global hooks registry
11
+ const globalHooks = globalThis.__propvault_hooks || { actions: {}, filters: {} };
12
+ if (!globalHooks.actions[slug]) {
13
+ globalHooks.actions[slug] = [];
14
+ }
15
+ globalHooks.actions[slug].push({ handler, priority });
16
+ globalHooks.actions[slug].sort((a, b) => a.priority - b.priority);
17
+ globalThis.__propvault_hooks = globalHooks;
18
+ }
19
+ /**
20
+ * Registers a filter hook handler. Filter hooks allow modifying variables/inputs before they are stored/saved.
21
+ */
22
+ export function addFilter(slug, handler, priority = 10) {
23
+ if (typeof window !== "undefined")
24
+ return;
25
+ const globalHooks = globalThis.__propvault_hooks || { actions: {}, filters: {} };
26
+ if (!globalHooks.filters[slug]) {
27
+ globalHooks.filters[slug] = [];
28
+ }
29
+ globalHooks.filters[slug].push({ handler, priority });
30
+ globalHooks.filters[slug].sort((a, b) => a.priority - b.priority);
31
+ globalThis.__propvault_hooks = globalHooks;
32
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["/**\n * PropVault CMS \u2014 Plugin Development Kit (PDK) Core API\n */\n\nexport interface HookAction {\n slug: string;\n handler: (...args: any[]) => void | Promise<void>;\n priority?: number;\n}\n\nexport interface HookFilter {\n slug: string;\n handler: (value: any, ...args: any[]) => any | Promise<any>;\n priority?: number;\n}\n\nexport interface PluginManifest {\n name: string;\n slug: string;\n version: string;\n description: string;\n author: string;\n entry: string;\n}\n\n/**\n * Registers an action hook handler. Action hooks trigger code at specific system events.\n */\nexport function addAction(slug: string, handler: (...args: any[]) => void | Promise<void>, priority = 10): void {\n if (typeof window !== \"undefined\") return;\n \n // Register dynamic handler into global hooks registry\n const globalHooks = (globalThis as any).__propvault_hooks || { actions: {}, filters: {} };\n if (!globalHooks.actions[slug]) {\n globalHooks.actions[slug] = [];\n }\n \n globalHooks.actions[slug].push({ handler, priority });\n globalHooks.actions[slug].sort((a: any, b: any) => a.priority - b.priority);\n \n (globalThis as any).__propvault_hooks = globalHooks;\n}\n\n/**\n * Registers a filter hook handler. Filter hooks allow modifying variables/inputs before they are stored/saved.\n */\nexport function addFilter(slug: string, handler: (value: any, ...args: any[]) => any | Promise<any>, priority = 10): void {\n if (typeof window !== \"undefined\") return;\n \n const globalHooks = (globalThis as any).__propvault_hooks || { actions: {}, filters: {} };\n if (!globalHooks.filters[slug]) {\n globalHooks.filters[slug] = [];\n }\n \n globalHooks.filters[slug].push({ handler, priority });\n globalHooks.filters[slug].sort((a: any, b: any) => a.priority - b.priority);\n \n (globalThis as any).__propvault_hooks = globalHooks;\n}\n"],
5
+ "mappings": ";AA4BO,SAAS,UAAU,MAAc,SAAmD,WAAW,IAAU;AAC9G,MAAI,OAAO,WAAW;AAAa;AAGnC,QAAM,cAAe,WAAmB,qBAAqB,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AACxF,MAAI,CAAC,YAAY,QAAQ,IAAI,GAAG;AAC9B,gBAAY,QAAQ,IAAI,IAAI,CAAC;AAAA,EAC/B;AAEA,cAAY,QAAQ,IAAI,EAAE,KAAK,EAAE,SAAS,SAAS,CAAC;AACpD,cAAY,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAQ,MAAW,EAAE,WAAW,EAAE,QAAQ;AAE1E,EAAC,WAAmB,oBAAoB;AAC1C;AAKO,SAAS,UAAU,MAAc,SAA6D,WAAW,IAAU;AACxH,MAAI,OAAO,WAAW;AAAa;AAEnC,QAAM,cAAe,WAAmB,qBAAqB,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AACxF,MAAI,CAAC,YAAY,QAAQ,IAAI,GAAG;AAC9B,gBAAY,QAAQ,IAAI,IAAI,CAAC;AAAA,EAC/B;AAEA,cAAY,QAAQ,IAAI,EAAE,KAAK,EAAE,SAAS,SAAS,CAAC;AACpD,cAAY,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAQ,MAAW,EAAE,WAAW,EAAE,QAAQ;AAE1E,EAAC,WAAmB,oBAAoB;AAC1C;",
6
+ "names": []
7
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@vikukumar/propvault-pdk",
3
+ "version": "0.1.4",
4
+ "description": "Plugin Development Kit (PDK) for the PropVault CMS Platform",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "propvault-pdk": "./bin/pdk-cli.js"
10
+ },
11
+ "scripts": {
12
+ "build": "node bin/build.js",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "dependencies": {
16
+ "archiver": "^6.0.2",
17
+ "esbuild": "^0.20.1"
18
+ },
19
+ "devDependencies": {
20
+ "typescript": "^5.3.3"
21
+ },
22
+ "engines": {
23
+ "node": ">=18.0.0"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ }
28
+ }
package/src/index.ts ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * PropVault CMS — Plugin Development Kit (PDK) Core API
3
+ */
4
+
5
+ export interface HookAction {
6
+ slug: string;
7
+ handler: (...args: any[]) => void | Promise<void>;
8
+ priority?: number;
9
+ }
10
+
11
+ export interface HookFilter {
12
+ slug: string;
13
+ handler: (value: any, ...args: any[]) => any | Promise<any>;
14
+ priority?: number;
15
+ }
16
+
17
+ export interface PluginManifest {
18
+ name: string;
19
+ slug: string;
20
+ version: string;
21
+ description: string;
22
+ author: string;
23
+ entry: string;
24
+ }
25
+
26
+ /**
27
+ * Registers an action hook handler. Action hooks trigger code at specific system events.
28
+ */
29
+ export function addAction(slug: string, handler: (...args: any[]) => void | Promise<void>, priority = 10): void {
30
+ if (typeof window !== "undefined") return;
31
+
32
+ // Register dynamic handler into global hooks registry
33
+ const globalHooks = (globalThis as any).__propvault_hooks || { actions: {}, filters: {} };
34
+ if (!globalHooks.actions[slug]) {
35
+ globalHooks.actions[slug] = [];
36
+ }
37
+
38
+ globalHooks.actions[slug].push({ handler, priority });
39
+ globalHooks.actions[slug].sort((a: any, b: any) => a.priority - b.priority);
40
+
41
+ (globalThis as any).__propvault_hooks = globalHooks;
42
+ }
43
+
44
+ /**
45
+ * Registers a filter hook handler. Filter hooks allow modifying variables/inputs before they are stored/saved.
46
+ */
47
+ export function addFilter(slug: string, handler: (value: any, ...args: any[]) => any | Promise<any>, priority = 10): void {
48
+ if (typeof window !== "undefined") return;
49
+
50
+ const globalHooks = (globalThis as any).__propvault_hooks || { actions: {}, filters: {} };
51
+ if (!globalHooks.filters[slug]) {
52
+ globalHooks.filters[slug] = [];
53
+ }
54
+
55
+ globalHooks.filters[slug].push({ handler, priority });
56
+ globalHooks.filters[slug].sort((a: any, b: any) => a.priority - b.priority);
57
+
58
+ (globalThis as any).__propvault_hooks = globalHooks;
59
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src/**/*"]
15
+ }