rojects/workspace/history/2026/07-July/03-Friday/index.html

222 lines
9.7 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Session Summary — 3 July 2026</title>
<link rel="stylesheet" href="../../../../_assets_/styles.css">
<link rel="stylesheet" href="../../../../_assets_/nav.css">
</head>
<body>
<div class="page">
<header>
<p class="date">Friday, 3 July 2026</p>
<h1>Roject — ES Modules &amp; Library Integration</h1>
<p class="subtitle">Session summary: confirm-dialog fix, ES module refactor, shared library submodule, TypeScript project references.</p>
</header>
<section>
<h2>What we fixed</h2>
<div class="card">
<h3>Confirm Dialog &amp; Build Workflow</h3>
<p>
The project delete confirm dialog was not working because <code>npm run build</code>
had not been run after the last code change, and the server had not been restarted.
The compiled <code>.js</code> in <code>public/</code> was stale. No code change
was needed — the fix was running the build and restart. Established that debugging
frontend issues always requires a fresh build first.
</p>
<div class="tags">
<span class="tag">npm run build</span>
<span class="tag">stale compiled output</span>
<span class="tag">confirm-dialog</span>
</div>
</div>
</section>
<section>
<h2>What we built</h2>
<div class="card">
<h3>ES Module Refactor</h3>
<p>
The frontend was rewritten from <code>module: none</code> (global scripts) to
proper ES modules. <code>tsconfig.client.json</code> now uses
<code>module: ESNext</code> and <code>moduleResolution: bundler</code>.
All HTML pages switched from <code>&lt;script src&gt;</code> to
<code>&lt;script type="module" src&gt;</code>. Components now use
<code>import</code> / <code>export</code> and no longer rely on global scope.
The browser deduplicates shared module imports automatically.
</p>
<div class="tags">
<span class="tag">module: ESNext</span>
<span class="tag">moduleResolution: bundler</span>
<span class="tag">script type="module"</span>
<span class="tag">import / export</span>
</div>
</div>
<div class="card">
<h3>EditorState as a Proper Module</h3>
<p>
<code>EditorState</code> was extracted from <code>editor-shell.ts</code> into its
own module at <code>src/components/editor-state.ts</code>. It exports
<code>setEditorState()</code> (called by <code>editor-shell</code> on init) and
<code>getEditorState()</code> (called by any component that needs it).
The <code>window.editorState</code> global is gone. Components import what they
need directly.
</p>
<div class="tags">
<span class="tag">editor-state.ts</span>
<span class="tag">getEditorState()</span>
<span class="tag">setEditorState()</span>
<span class="tag">no window globals</span>
</div>
</div>
<div class="card">
<h3>Confirm Dialog Export</h3>
<p>
<code>showConfirmDialog</code> and <code>ConfirmDialogOptions</code> are now
properly exported from <code>confirm-dialog.ts</code>.
<code>project-editor.ts</code> imports <code>showConfirmDialog</code> directly
instead of using a <code>/// &lt;reference path&gt;</code> directive. The
redundant <code>&lt;script&gt;</code> tag for <code>confirm-dialog.js</code> in
<code>projects.html</code> was removed — the browser loads it via the import graph.
</p>
<div class="tags">
<span class="tag">export showConfirmDialog</span>
<span class="tag">import instead of reference</span>
<span class="tag">no redundant script tag</span>
</div>
</div>
<div class="card">
<h3>Shared Library as Git Submodule</h3>
<p>
A personal TypeScript library was added as a git submodule at
<code>src/library-ts/</code>. The library has two parts:
<code>browser/</code> (DOM-capable, usable with shims on Node) and
<code>node/</code> (Node.js only). Placing the submodule inside <code>src/</code>
keeps <code>rootDir: "src"</code> intact so the output URL structure in
<code>public/</code> is unchanged.
</p>
<div class="tags">
<span class="tag">git submodule</span>
<span class="tag">src/library-ts/</span>
<span class="tag">browser/ + node/</span>
</div>
</div>
<div class="card">
<h3>TypeScript Project References</h3>
<p>
The library was written without <code>strict: true</code>, causing hundreds of
errors when compiled with Roject's strict settings. TypeScript project references
solve this: a new <code>tsconfig.roject.json</code> inside
<code>src/library-ts/browser/</code> compiles the browser part separately with
<code>strict: false</code>, <code>composite: true</code>, and
<code>declaration: true</code>. Roject's <code>tsconfig.client.json</code>
excludes <code>src/library-ts/**/*</code> and references the library project.
Build now runs as <code>tsc --build tsconfig.client.json</code>.
</p>
<div class="tags">
<span class="tag">project references</span>
<span class="tag">composite: true</span>
<span class="tag">declaration: true</span>
<span class="tag">tsc --build</span>
</div>
</div>
<div class="card">
<h3>Server-Side Library Configuration</h3>
<p>
The node part of the library caused the same strict errors when compiled by
<code>ts-node</code>. A dedicated <code>tsconfig.ts-node.json</code> extends the
server tsconfig but turns off <code>strictNullChecks</code> (the only check the
library violates) and adds <code>src/library-ts/node/**/*</code> to the include.
The start script now passes <code>--project tsconfig.ts-node.json</code> to
<code>ts-node</code>.
</p>
<div class="tags">
<span class="tag">tsconfig.ts-node.json</span>
<span class="tag">strictNullChecks: false</span>
<span class="tag">ts-node --project</span>
</div>
</div>
</section>
<section>
<h2>Key Decisions</h2>
<div class="decision">
<strong>ES modules over global scripts</strong>
<p>
<code>module: none</code> was originally chosen to avoid a bundler, but it also
ruled out <code>import</code> / <code>export</code> and forced the
<code>window.editorState</code> workaround. Browsers support ES modules natively
via <code>type="module"</code> scripts — no bundler needed. The switch removes
all global-scope workarounds and makes the library integration straightforward.
</p>
</div>
<div class="decision">
<strong>Submodule inside <code>src/</code>, not at project root</strong>
<p>
Placing the submodule at <code>src/library-ts/</code> keeps
<code>rootDir: "src"</code> in the client tsconfig unchanged. A submodule at the
project root would require either changing rootDir (breaking the
<code>/components/...</code> URL structure) or setting up path aliases.
</p>
</div>
<div class="decision">
<strong>Separate tsconfig per compilation unit, not a single monolithic one</strong>
<p>
Three tsconfigs now serve distinct purposes: <code>tsconfig.json</code> (server,
strict), <code>tsconfig.client.json</code> (frontend, strict, references library),
<code>tsconfig.ts-node.json</code> (runtime, relaxed for library compatibility).
This keeps strict checking on all first-party code without patching the library.
</p>
</div>
<div class="decision">
<strong>Only <code>strictNullChecks</code> turned off for ts-node</strong>
<p>
All three errors in the node library were <code>strictNullChecks</code> violations.
Rather than disabling all of <code>strict</code>, only that one flag is overridden
in <code>tsconfig.ts-node.json</code>. Server code retains
<code>noImplicitAny</code>, <code>strictFunctionTypes</code>,
<code>strictPropertyInitialization</code>, and all other strict checks.
</p>
</div>
</section>
<section>
<h2>Project Structure</h2>
<div class="card">
<p>
<code>src/components/editor-state.ts</code> — EditorState module (getEditorState / setEditorState)<br>
<code>src/library-ts/browser/</code> — shared browser library (git submodule)<br>
<code>src/library-ts/node/</code> — shared node library (git submodule)<br>
<code>src/library-ts/browser/tsconfig.roject.json</code> — library browser tsconfig (strict: false, composite)<br>
<code>tsconfig.client.json</code> — frontend: ESNext modules, references library<br>
<code>tsconfig.ts-node.json</code> — ts-node runtime: extends server tsconfig, strictNullChecks: false<br>
<code>public/library-ts/browser/</code> — compiled library output with .d.ts files
</p>
</div>
</section>
<footer>
Roject &mdash; session log &mdash; 3 July 2026
</footer>
</div>
<script>var NAV_ROOT = '../../../../';</script>
<script src="../../../../_assets_/nav-data.js"></script>
<script src="../../../../_assets_/nav.js"></script>
</body>
</html>