refactor(web): move calendar generators to src/utils for proper compilation

The calendar generation scripts were in scripts/ directory which wasn't
included in tsconfig.server.json, so they weren't being compiled during
build. This required tsx in production just to import .tsx files at runtime.

Changes:
- Moved generateCalendarComposite.tsx and generateCalendarAbacus.tsx to src/utils/calendar/
- Removed CLI interface code from these files (they're now pure utility modules)
- Updated imports in API routes to use @/utils/calendar/...
- Moved tsx back to devDependencies where it belongs
- Removed scripts/ copy from Dockerfile (no longer needed)

Now these files are compiled to JavaScript during the build process and
don't require tsx at runtime. This fixes the architecture issue properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-11-04 14:26:17 -06:00
parent ffae9c1bdb
commit 379698fea3
7 changed files with 23 additions and 68 deletions

View File

@@ -146,9 +146,6 @@ COPY --from=builder --chown=nextjs:nodejs /app/apps/web/dist ./apps/web/dist
# Copy database migrations
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/drizzle ./apps/web/drizzle
# Copy scripts directory (needed for calendar generation)
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/scripts ./apps/web/scripts
# Copy PRODUCTION node_modules only (no dev dependencies)
COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=deps --chown=nextjs:nodejs /app/apps/web/node_modules ./apps/web/node_modules

View File

@@ -81,7 +81,6 @@
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
"three": "^0.169.0",
"tsx": "^4.20.5",
"y-protocols": "^1.0.6",
"y-websocket": "^3.0.0",
"yjs": "^13.6.27",
@@ -112,6 +111,7 @@
"jsdom": "^27.0.0",
"storybook": "^9.1.7",
"tsc-alias": "^1.8.16",
"tsx": "^4.20.5",
"typescript": "^5.0.0",
"vitest": "^1.0.0"
},

View File

@@ -1,40 +0,0 @@
#!/usr/bin/env tsx
/**
* Generate a simple abacus SVG (no customization for now - just get it working)
* Usage: npx tsx scripts/generateCalendarAbacus.tsx <value> <columns>
* Example: npx tsx scripts/generateCalendarAbacus.tsx 15 2
*
* Uses AbacusStatic for server-side rendering (no client hooks)
*/
import React from 'react'
import { AbacusStatic } from '@soroban/abacus-react/static'
export function generateAbacusElement(value: number, columns: number) {
return (
<AbacusStatic
value={value}
columns={columns}
scaleFactor={1}
showNumbers={false}
frameVisible={true}
/>
)
}
// CLI interface (if run directly)
if (require.main === module) {
// Only import react-dom/server for CLI usage
const { renderToStaticMarkup } = require('react-dom/server')
const value = parseInt(process.argv[2], 10)
const columns = parseInt(process.argv[3], 10)
if (isNaN(value) || isNaN(columns)) {
console.error('Usage: npx tsx scripts/generateCalendarAbacus.tsx <value> <columns>')
process.exit(1)
}
process.stdout.write(renderToStaticMarkup(generateAbacusElement(value, columns)))
}

View File

@@ -5,8 +5,8 @@ import { join } from 'path'
import { execSync } from 'child_process'
import { generateMonthlyTypst, generateDailyTypst, getDaysInMonth } from '../utils/typstGenerator'
import type { AbacusConfig } from '@soroban/abacus-react'
import { generateCalendarComposite } from '@/../../scripts/generateCalendarComposite'
import { generateAbacusElement } from '@/../../scripts/generateCalendarAbacus'
import { generateCalendarComposite } from '@/utils/calendar/generateCalendarComposite'
import { generateAbacusElement } from '@/utils/calendar/generateCalendarAbacus'
interface CalendarRequest {
month: number

View File

@@ -4,7 +4,7 @@ import { tmpdir } from 'os'
import { join } from 'path'
import { execSync } from 'child_process'
import { generateMonthlyTypst, getDaysInMonth } from '../utils/typstGenerator'
import { generateCalendarComposite } from '@/../../scripts/generateCalendarComposite'
import { generateCalendarComposite } from '@/utils/calendar/generateCalendarComposite'
interface PreviewRequest {
month: number

View File

@@ -0,0 +1,19 @@
/**
* Generate a simple abacus SVG element
* Uses AbacusStatic for server-side rendering (no client hooks)
*/
import React from 'react'
import { AbacusStatic } from '@soroban/abacus-react/static'
export function generateAbacusElement(value: number, columns: number) {
return (
<AbacusStatic
value={value}
columns={columns}
scaleFactor={1}
showNumbers={false}
frameVisible={true}
/>
)
}

View File

@@ -1,11 +1,6 @@
#!/usr/bin/env tsx
/**
* Generate a complete monthly calendar as a single SVG
* This prevents multi-page overflow - one image scales to fit
*
* Usage: npx tsx scripts/generateCalendarComposite.tsx <month> <year>
* Example: npx tsx scripts/generateCalendarComposite.tsx 12 2025
*/
import React from 'react'
@@ -190,19 +185,3 @@ const compositeSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="${WIDTH}" h
return compositeSVG
}
// CLI interface (if run directly)
if (require.main === module) {
// Only import react-dom/server for CLI usage
const { renderToStaticMarkup } = require('react-dom/server')
const month = parseInt(process.argv[2], 10)
const year = parseInt(process.argv[3], 10)
if (isNaN(month) || isNaN(year) || month < 1 || month > 12) {
console.error('Usage: npx tsx scripts/generateCalendarComposite.tsx <month> <year>')
process.exit(1)
}
process.stdout.write(generateCalendarComposite({ month, year, renderToString: renderToStaticMarkup }))
}