Repository navigation
feat: rewrite v2 - #206
feat: rewrite v2#206Exeloo wants to merge 7 commits into
Conversation
| (child) => (child.redo ?? child.do).call(child), | ||
| ), | ||
| redo: () => runAll(children, (child) => (child.redo ?? child.do).call(child)), | ||
| async isValid() { |
There was a problem hiding this comment.
Every child is checked against the current text, but each child expects the text right after itself: two children editing the same file are always invalid, so the undo is refused and the history wiped. Check only the last child per file, or validate in reverse while undoing.
| (command) => (command.redo ?? command.do).call(command), | ||
| ), | ||
| redo: () => runAll([previous, next], (command) => (command.redo ?? command.do).call(command)), | ||
| async isValid() { |
There was a problem hiding this comment.
Same with mergeCommands: previous never matches once next ran, so a merged document edit can't be undone.
| undo: async () => { | ||
| for (const step of [...done].reverse()) await step.undo(); | ||
| }, | ||
| isValid: async () => { |
There was a problem hiding this comment.
Same bug: renaming a scene whose file moves edits main twice, so undoing that rename now wipes the Scenes history (it worked before).
| ARG PUBLIC_PM_URL | ||
|
|
||
| # The server reads its mode at runtime (packages/server-core/src/env/load-env.ts) | ||
| ENV PUBLIC_MODE=${PUBLIC_MODE} |
There was a problem hiding this comment.
Without the build arg, PUBLIC_MODE becomes "" and the env schema refuses it: a plain docker build no longer starts. Give it a default.
| * A repository's own folder is never reached through the file API: writing hooks or config there | ||
| * runs code on the next git command, and its config may hold credentials. | ||
| */ | ||
| const isGitPath = (path: string) => |
There was a problem hiding this comment.
Checked by name only: a committed g -> .git symlink still allows writing g/hooks/…. Check the real path from jail.resolve too.
| } | ||
| for (const [baseUrl, plugin] of located) { | ||
| if (!urlPath.startsWith(baseUrl)) continue; | ||
| const rel = decodeURIComponent(urlPath.slice(baseUrl.length)); |
There was a problem hiding this comment.
decodeURIComponent is still outside the try: /plugins/x/%E0 gives a 500.
| ); | ||
| let response: Response; | ||
| try { | ||
| response = await (this._options.fetch ?? fetch)(url.toString(), { |
There was a problem hiding this comment.
Redirects are followed, so a same-origin URL that redirects elsewhere still sends our headers. Use redirect: 'manual', or drop the headers after a redirect.
| const run = this._cli.run(['build', '--editor', '--directory', app.root || '.'], { | ||
| cwd: this._project.root, | ||
| env: { FORCE_COLOR: '0', NO_COLOR: '1' }, | ||
| signal: AbortSignal.any([this._abort.signal, AbortSignal.timeout(this._buildTimeoutMs)]), |
There was a problem hiding this comment.
The abort only kills nf: what it starts keeps running. Spawn it detached and kill the process group, like the game server.
| }); | ||
| } | ||
| for (const path of io.files()) { | ||
| if (!CODE.test(path) || !specifier(library.name).test(await io.read(path))) continue; |
There was a problem hiding this comment.
The pre-filter reads the disk, so an open file with unsaved edits that imports the library is skipped. Read it through DocumentService. The regex fallback is still there without a worker.
| const file: HistoryCommand = { | ||
| label: `${move ? 'Move' : 'Copy'} ${from}`, | ||
| do: async () => { | ||
| if (move) await fs.rename(from, to); |
There was a problem hiding this comment.
Rename then write: if the write fails, the file stays moved. Write first, or rename back on failure.
- Implement `readPackageContents` for loading and validating package manifests and sub-manifests. - Add validation logic for path constraints, nesting depth, and maximum manifests. - Introduce test suite for verifying manifest handling, edge cases, and error reporting. - Update related schemas, registry client, and API contract.
|
can you please not run e2e tests on ci to not run out of actions minutes please |
The repo is in public, so it doesn't use our action minutes |
What does this PR do?
Rewrites the NanoForge editor from scratch (
rewrite/v2). It keeps what the previous editor did (edit a NanoForge game in the browser, hosted or throughnf editor) on a new base: everything visible is a plugin, the game's code is the only source of truth, and every change can be undone. The full list of user-facing changes is inCHANGELOG-v2.md; the plan, phase by phase, is indocs/rewrite-plan.md.Resolves #174
Resolves #156
Resolves #154
Resolves #128
Resolves #127
Resolves #126
Resolves #125
Resolves #123
Resolves #97
Architecture
apps/editor(SvelteKit static SPA + Bun server),packages/*(kernel, sdk, settings, history, layout, ui, code, runtime, protocol, rpc, project, server-core, meta, registry),plugins/*(12 built-in plugins),tooling/*(vite plugin for building plugins, example plugin).@nanoforge-dev/editor-sdk(enforced by ESLint). The SDK and@nanoforge-dev/editor-vite-pluginare the public API for third-party plugins (guide indocs/docs/plugins)..nanoforge/*.save.json. Entities, components and systems are read from and written to the app'smain.tsthrough a TypeScript code worker (ts-morph stays in the worker, out of the page bundle).nanoforge.manifest.json,@scope/name, packages installed read-only innf_modules, plugins per user or per project. Shared libraries between client and server (ADR 0004).docs/api/documents the registry and settings-sync contracts the API does not offer yet; contract tests run against stand-ins (API_FEATURESgates the calls).index.tsbarrels, kebab-case files named after their main export, kind suffixes (.type.ts,.enum.ts,.exception.ts,.const.ts), tests intest/**/*.spec.tsmirroringsrc/.Built-in plugins
code-editor, file-manager, viewport, history-panel, settings-ui, ecs, console, command-palette, inspectors, git, packages, scene.
Repository
.prettierignore, labels and issue-form entry; published workspaces (apps/editor,packages/sdk,tooling/vite-plugin) have their changelog and release config.e2eworkflow; the old editor's files are removed.Not in this PR
feat/core-editor-bridge(andfeat/scenefor scenes), loaderfeat/server-editor-ipc, CLIfeat/editor-open-project(nf editor,nf create plugin).docs/api/).How do you test this PR?