From fc36b5b600935a1c8164e104387894bc2a3c473a Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Thu, 14 May 2026 11:24:59 -0400 Subject: [PATCH] Add @pascal-app/nodes package skeleton with empty builtinPlugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New workspace package that owns built-in node bundles, one folder per kind. Today the plugin is empty — no behavior change. Future commits will add column/, shelf/, wall/, etc. and append each definition to builtinPlugin.nodes. The package depends on core (registry types) at v1; viewer, editor, react, three are declared as peer deps so future node bundles can use them without bumping their own version on every monorepo bump. External plugins land as separate packages with the exact same shape — this package is the dogfooded reference. Tests: builtinPlugin shape + loadPlugin succeeds with zero kinds. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/nodes/package.json | 54 ++++++++++++++++++++++++++++++++ packages/nodes/src/index.test.ts | 20 ++++++++++++ packages/nodes/src/index.ts | 18 +++++++++++ packages/nodes/tsconfig.json | 15 +++++++++ 4 files changed, 107 insertions(+) create mode 100644 packages/nodes/package.json create mode 100644 packages/nodes/src/index.test.ts create mode 100644 packages/nodes/src/index.ts create mode 100644 packages/nodes/tsconfig.json diff --git a/packages/nodes/package.json b/packages/nodes/package.json new file mode 100644 index 00000000..a485a275 --- /dev/null +++ b/packages/nodes/package.json @@ -0,0 +1,54 @@ +{ + "name": "@pascal-app/nodes", + "version": "0.1.0", + "description": "Built-in node bundles for the Pascal 3D editor — one folder per kind, exported as `builtinPlugin`", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "default": "./dist/index.js" + } + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "build": "tsc --build", + "dev": "tsc --build --watch", + "test": "bun test", + "prepublishOnly": "bun run build && bun test" + }, + "peerDependencies": { + "@pascal-app/core": "^0.8.0", + "@react-three/drei": "^10", + "@react-three/fiber": "^9", + "react": "^18 || ^19", + "three": "^0.184" + }, + "devDependencies": { + "@pascal-app/core": "^0.8.0", + "@pascal/typescript-config": "*", + "@types/bun": "^1.3.0", + "@types/react": "^19.2.2", + "@types/three": "^0.184.0", + "typescript": "6.0.2" + }, + "keywords": [ + "pascal", + "3d", + "editor", + "node-registry" + ], + "repository": { + "type": "git", + "url": "https://github.com/pascalorg/editor.git", + "directory": "packages/nodes" + }, + "license": "MIT", + "homepage": "https://github.com/pascalorg/editor/tree/main/packages/nodes#readme", + "bugs": "https://github.com/pascalorg/editor/issues" +} diff --git a/packages/nodes/src/index.test.ts b/packages/nodes/src/index.test.ts new file mode 100644 index 00000000..f358a5a5 --- /dev/null +++ b/packages/nodes/src/index.test.ts @@ -0,0 +1,20 @@ +import { beforeEach, describe, expect, test } from 'bun:test' +import { loadPlugin, nodeRegistry } from '@pascal-app/core' +import { builtinPlugin } from './index' + +describe('builtinPlugin', () => { + beforeEach(() => { + nodeRegistry._reset() + }) + + test('has the expected manifest shape', () => { + expect(builtinPlugin.id).toBe('pascal:core') + expect(builtinPlugin.apiVersion).toBe(1) + expect(Array.isArray(builtinPlugin.nodes)).toBe(true) + }) + + test('loads with zero kinds today (Phase 0 — registry empty)', async () => { + await loadPlugin(builtinPlugin) + expect(nodeRegistry.size).toBe(0) + }) +}) diff --git a/packages/nodes/src/index.ts b/packages/nodes/src/index.ts new file mode 100644 index 00000000..3539615b --- /dev/null +++ b/packages/nodes/src/index.ts @@ -0,0 +1,18 @@ +import type { Plugin } from '@pascal-app/core' + +/** + * Built-in plugin bundling every node kind shipped with the Pascal editor. + * + * Apps load this once at bootstrap (`loadPlugin(builtinPlugin)`) before + * mounting the viewer. New built-in nodes are added by creating a folder + * here under `src//` and appending its `NodeDefinition` to `nodes`. + * + * External plugins follow the exact same shape — same `Plugin` type, same + * `loadPlugin` call path. This is intentional: the API is stress-tested + * by built-ins before any third-party plugin lands. + */ +export const builtinPlugin: Plugin = { + id: 'pascal:core', + apiVersion: 1, + nodes: [], +} diff --git a/packages/nodes/tsconfig.json b/packages/nodes/tsconfig.json new file mode 100644 index 00000000..523aa369 --- /dev/null +++ b/packages/nodes/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@pascal/typescript-config/base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "noEmit": false, + "composite": true, + "incremental": true, + "jsx": "react-jsx", + "lib": ["DOM", "ES2022"] + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"], + "references": [{ "path": "../core" }] +}