manifest, schema, router and two panels. the editor is hosted and saving; the last step is not finished and the readme says so. designs are rows scoped per user, with userId in every WHERE rather than checked after the read — another person's design is 'not found', so the id space cannot be probed. the Doc is stored whole as jsonb because upstream adds fields to it constantly and none of them should be a migration here. the handoff is the reason the plugin exists and it is the part that does not work: /api/chat has NO session-creation route, a session is constructed by the browser opening a websocket, so a plugin has nothing to POST to. onExport returns false and the clipboard still runs, which is upstream's own behaviour — degraded, not broken. docs/handoff.md names the one platform change that would finish it, and argues it should be generic rather than ours. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
123 lines
5.5 KiB
Bash
Executable File
123 lines
5.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Re-vendor the M3E Canvas editor from upstream.
|
|
#
|
|
# ./scripts/vendor.sh [<git-ref>] default: main
|
|
#
|
|
# ── Why a script rather than a copy ──
|
|
#
|
|
# The vendored copy is NOT byte-identical to upstream, and it cannot be. Upstream imports through a
|
|
# `@/` path alias, and this platform already binds `@/*` to `src/apps/officer-web` and
|
|
# `@/components/*` to its own shared components. Left alone, `import { M3Node } from
|
|
# "@/components/M3Node"` inside the vendored editor would silently resolve to Officer's components
|
|
# directory — a wrong module rather than a build error, which is the worst way to be broken.
|
|
#
|
|
# So every import is rewritten to a relative path. That transformation is MECHANICAL and lives here,
|
|
# which is what keeps the copy reviewable: `git diff` after a re-vendor shows upstream's real changes,
|
|
# because the rewrite produces the same output for the same input every time.
|
|
#
|
|
# Nothing else is edited. Officer's own changes live outside `web/vendor/`, reached through
|
|
# `web/adapter.ts`.
|
|
set -euo pipefail
|
|
|
|
REF="${1:-main}"
|
|
UPSTREAM="https://github.com/lnkiai/m3e-canvas.git"
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DEST="$HERE/web/vendor"
|
|
WORK="$(mktemp -d)"
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
echo "cloning $UPSTREAM @ $REF"
|
|
git clone -q --depth 1 --branch "$REF" "$UPSTREAM" "$WORK/src"
|
|
SHA="$(git -C "$WORK/src" rev-parse HEAD)"
|
|
WHEN="$(git -C "$WORK/src" log -1 --format=%ad --date=short)"
|
|
|
|
rm -rf "$DEST"
|
|
mkdir -p "$DEST"
|
|
|
|
# lib/ and components/ only. `app/` is upstream's Next.js route and is deliberately NOT taken:
|
|
# app/page.tsx becomes web/vendor/Canvas.tsx below, and app/layout.tsx has no meaning here.
|
|
cp -r "$WORK/src/lib" "$DEST/lib"
|
|
cp -r "$WORK/src/components" "$DEST/components"
|
|
cp "$WORK/src/app/page.tsx" "$DEST/Canvas.tsx"
|
|
cp "$WORK/src/app/globals.css" "$DEST/globals.css"
|
|
cp "$WORK/src/LICENSE" "$DEST/LICENSE"
|
|
|
|
# Upstream's own tests are not taken. They import `vitest`, which this plugin has no runner for and
|
|
# no reason to install — and a test that cannot run is worse than no test, because it reads as
|
|
# coverage. Upstream runs them in its own CI, which is where they belong.
|
|
find "$DEST" \( -name '*.test.ts' -o -name '*.test.tsx' -o -name '*.spec.ts' -o -name '*.spec.tsx' \) -delete
|
|
|
|
# lib/ai.ts and components/AiPanel.tsx ARE vendored, despite being the parts Officer least needs.
|
|
#
|
|
# The first attempt deleted them — they keep model-provider API keys in localStorage and call the
|
|
# provider from the browser, which Officer has no use for and would not do that way. But Canvas.tsx
|
|
# references them in about a dozen places, so deleting meant editing vendored code, and the rule one
|
|
# paragraph up says not to. A faithful copy that carries an unused module beats a doctored one that
|
|
# cannot be re-vendored.
|
|
#
|
|
# They stay inert: the panel does nothing without a key, and Officer's shell does not surface the
|
|
# entry point. See ../README.md, "What we do not use".
|
|
|
|
# ── the mechanical rewrite ──
|
|
# `@/lib/x` -> relative path to vendor/lib/x
|
|
# `@/components/x` -> relative path to vendor/components/x
|
|
python3 - "$DEST" <<'PY'
|
|
import os, re, sys
|
|
dest = sys.argv[1]
|
|
for root, _, files in os.walk(dest):
|
|
for name in files:
|
|
if not name.endswith((".ts", ".tsx")):
|
|
continue
|
|
path = os.path.join(root, name)
|
|
depth = os.path.relpath(root, dest)
|
|
prefix = "./" if depth == "." else "../" * len(depth.split(os.sep))
|
|
src = open(path, encoding="utf-8").read()
|
|
out = re.sub(r'(["\'])@/(lib|components)/', lambda m: f"{m.group(1)}{prefix}{m.group(2)}/", src)
|
|
if out != src:
|
|
open(path, "w", encoding="utf-8").write(out)
|
|
PY
|
|
|
|
# Officer's own changes to the vendored code. Kept OUT of this script so the copy above is exactly
|
|
# upstream, and applied here so one command reproduces the whole state.
|
|
python3 "$HERE/scripts/apply-host.py"
|
|
|
|
cat > "$DEST/PROVENANCE.md" <<PROV
|
|
# Vendored from lnkiai/m3e-canvas
|
|
|
|
| | |
|
|
| --- | --- |
|
|
| upstream | $UPSTREAM |
|
|
| ref | \`$REF\` |
|
|
| commit | \`$SHA\` |
|
|
| dated | $WHEN |
|
|
| licence | MIT — see \`LICENSE\` beside this file |
|
|
| vendored | $(date -u +%Y-%m-%d) by \`scripts/vendor.sh\` |
|
|
|
|
**Do not edit anything in this directory.** Officer's changes live outside it, reached through
|
|
\`web/adapter.ts\`. Editing here makes the next \`vendor.sh\` run either clobber the change or
|
|
produce a diff nobody can read.
|
|
|
|
## What was taken, and what was not
|
|
|
|
Taken: \`lib/\`, \`components/\`, upstream's \`app/page.tsx\` as \`Canvas.tsx\`, and \`globals.css\`.
|
|
|
|
Not taken: \`app/layout.tsx\` — a Next.js route shell with no meaning here.
|
|
|
|
\`lib/ai.ts\` and \`components/AiPanel.tsx\` ARE taken even though Officer does not use them. They
|
|
keep model-provider API keys in \`localStorage\`, which is not how anything here should work — but
|
|
\`Canvas.tsx\` references them throughout, so removing them would mean editing vendored code. A
|
|
faithful copy carrying an unused module beats a doctored one that cannot be re-vendored. They are
|
|
inert without a key, and the shell does not surface them.
|
|
|
|
## The one edit \`vendor.sh\` makes
|
|
|
|
Every \`@/lib/…\` and \`@/components/…\` import is rewritten to a relative path. This platform already
|
|
binds \`@/*\` to \`src/apps/officer-web\` and \`@/components/*\` to its own shared components, so an
|
|
unrewritten import resolves to the WRONG module rather than failing — silent breakage.
|
|
|
|
The rewrite is deterministic, so a re-vendor produces a readable diff of upstream's real changes.
|
|
PROV
|
|
|
|
echo "vendored $SHA ($WHEN) -> web/vendor/"
|
|
echo " $(find "$DEST" -name '*.ts' -o -name '*.tsx' | wc -l) source files"
|