Add @pascal-app/nodes package skeleton with empty builtinPlugin

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) <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-05-14 11:24:59 -04:00
co-authored by Claude Opus 4.7
parent 1d7ec0b5a7
commit fc36b5b600
4 changed files with 107 additions and 0 deletions
+54
View File
@@ -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"
}
+20
View File
@@ -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)
})
})
+18
View File
@@ -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/<kind>/` 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: [],
}
+15
View File
@@ -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" }]
}