feat: plugin template + create-plugin scaffold#34
Closed
kayodebristol wants to merge 1 commit into
Closed
Conversation
Adds a complete plugin template at template/ and a create-plugin.sh script that scaffolds new plugins with all placeholders replaced. The template encodes the .px-first development pattern: - px/ directory for declarative logic (auto-compiled by radix) - src/handlers/ for ActionHandler implementations (IO boundary) - tests/ for executable .px test scenarios - manifest.json with full schema-compliant metadata Usage: ./scripts/create-plugin.sh my-plugin "My Plugin" author This gives pares-radix plugin development the same 'batteries included' experience that svelte-tauri-template provides for general app development.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new template/ directory intended to serve as the starting point for pares-radix plugins, plus a scripts/create-plugin.sh scaffolder that copies the template into plugins/<id> and substitutes placeholders.
Changes:
- Introduces a plugin template containing a manifest, TypeScript entry/handlers,
.pxexamples, and.px-based tests. - Adds
scripts/create-plugin.shto scaffold a new plugin from the template and replace placeholders. - Adds template documentation describing the plugin architecture and publishing flow.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| template/tests/plugin.px | Adds an example executable .px test procedure. |
| template/src/index.ts | Adds a template plugin entrypoint and lifecycle hooks. |
| template/src/handlers/index.ts | Adds an example action handler and handler map. |
| template/README.md | Documents the template structure, workflow, and publishing steps. |
| template/px/main.px | Adds example .px procedures and trigger documentation. |
| template/px/constraints.px | Adds example constraint documentation for .px. |
| template/manifest.json | Adds a template plugin manifest with placeholders. |
| scripts/create-plugin.sh | Adds a scaffold script to copy the template and substitute placeholders. |
Comments suppressed due to low confidence (3)
template/src/index.ts:32
console.login the plugin lifecycle entrypoint conflicts with the repo’s platform guidance to avoid manual console logging for business events (see plures/no-manual-logging). Since this file is intended to be copied into plugins/, it will introduce lint warnings in new plugins; prefer removing it or routing through the platform’s structured/contract-based observability mechanism.
// .px files in the px/ directory are automatically compiled and
// registered by pares-radix. You don't need to do anything here
// for .px procedures to work — just drop .px files in px/.
console.log(`[{{plugin-id}}] loaded`);
},
template/src/index.ts:40
onActivateandonDeactivatedeclare actxparameter that isn't used. In this repo ESLint enforces@typescript-eslint/no-unused-varsas an error for plugin sources, so scaffolded plugins will fail lint unless the param is used or renamed (e.g._ctx) / removed.
async onActivate(ctx: PluginContext) {
// Plugin activated — start any background work, subscriptions, etc.
},
async onDeactivate(ctx: PluginContext) {
// Plugin deactivated — clean up subscriptions, timers, etc.
},
template/src/handlers/index.ts:23
- The example handler destructures
paramsvia a type assertion without runtime validation. If a procedure callshellowith a non-object/null payload, this will throw at runtime. Since this is the scaffolded starting point, it’s better to demonstrate safe parsing/validation (or at least guardtypeof params === 'object' && params !== null).
const hello: ActionHandler = async (params: unknown) => {
const { name } = params as { name: string };
return { greeting: `Hello, ${name}!` };
};
| "dependencies": [], | ||
| "peerDependencies": {}, | ||
| "entry": "src/index.ts", | ||
| "px": "px/", |
| "keywords": [], | ||
| "homepage": "https://github.com/plures/pares-modulus/tree/main/plugins/{{plugin-id}}", | ||
| "repository": "https://github.com/plures/pares-modulus", | ||
| "radix": ">=1.44.0", |
| * and register your action handlers here. | ||
| */ | ||
|
|
||
| import type { PluginContext, PluginLifecycle } from '@pares/radix-plugin'; |
| * and returns whatever $result should be. | ||
| */ | ||
|
|
||
| import type { ActionHandler } from '@pares/radix-plugin'; |
| @@ -0,0 +1,17 @@ | |||
| # Plugin tests — executable .px test scenarios. | |||
| # | |||
| # These run via `px run tests.px` or the pares-radix test harness. | |||
|
|
||
| ## Publishing | ||
|
|
||
| 1. Validate your manifest: `scripts/validate-manifest.sh plugins/my-plugin` |
Comment on lines
+10
to
+11
| # timer("name") — fires on a scheduled timer | ||
| # state_change("key") — fires when a PluresDB key is written |
Comment on lines
+8
to
+32
| PLUGIN_ID="${1:-}" | ||
| PLUGIN_NAME="${2:-}" | ||
| AUTHOR="${3:-plures}" | ||
|
|
||
| if [[ -z "$PLUGIN_ID" ]]; then | ||
| echo "Usage: $0 <plugin-id> [\"Plugin Name\"] [author]" | ||
| echo "" | ||
| echo "Example: $0 weather-advisor \"Weather Advisor\" kayodebristol" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [[ -z "$PLUGIN_NAME" ]]; then | ||
| # Convert kebab-case to Title Case | ||
| PLUGIN_NAME=$(echo "$PLUGIN_ID" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1))substr($i,2)}1') | ||
| fi | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| REPO_ROOT="$(dirname "$SCRIPT_DIR")" | ||
| TEMPLATE_DIR="$REPO_ROOT/template" | ||
| DEST_DIR="$REPO_ROOT/plugins/$PLUGIN_ID" | ||
|
|
||
| if [[ -d "$DEST_DIR" ]]; then | ||
| echo "Error: plugins/$PLUGIN_ID already exists" | ||
| exit 1 | ||
| fi |
Comment on lines
+44
to
+49
| find "$DEST_DIR" -type f \( -name "*.json" -o -name "*.ts" -o -name "*.px" -o -name "*.md" \) -exec sed -i \ | ||
| -e "s/{{plugin-id}}/$PLUGIN_ID/g" \ | ||
| -e "s/{{Plugin Name}}/$PLUGIN_NAME/g" \ | ||
| -e "s/{{your-name}}/$AUTHOR/g" \ | ||
| -e "s/{{Brief description of your plugin}}/A pares-radix plugin/g" \ | ||
| {} \; |
Contributor
Author
|
Closing: CI uses npm but package.json has workspace:* deps (requires pnpm). Stale since May 20. Will recreate with corrected CI config when plugin template work resumes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a complete plugin template and scaffolding script. Usage: ./scripts/create-plugin.sh my-plugin 'My Plugin' author. Encodes the .px-first development pattern. Equivalent to svelte-tauri-template for plugin-scoped development.