|
|
@@ -0,0 +1,262 @@
|
|
|
+# Design Document: upgrade-fixed-packages
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+**Purpose**: This feature audits and upgrades version-pinned packages in `apps/app/package.json` that were frozen due to upstream bugs, ESM-only migrations, or licensing constraints. The build environment has shifted from webpack to Turbopack, and the runtime now targets Node.js 24 with stable `require(esm)` support, invalidating several original pinning reasons.
|
|
|
+
|
|
|
+**Users**: Maintainers and developers benefit from up-to-date dependencies with bug fixes, security patches, and reduced technical debt.
|
|
|
+
|
|
|
+**Impact**: Modifies `apps/app/package.json` dependency versions and comment blocks; touches source files where `escape-string-regexp` is replaced by native `RegExp.escape()`.
|
|
|
+
|
|
|
+### Goals
|
|
|
+- Verify each pinning reason against current upstream status
|
|
|
+- Upgrade packages where the original constraint no longer applies
|
|
|
+- Replace `escape-string-regexp` with native `RegExp.escape()` (Node.js 24)
|
|
|
+- Update or remove comment blocks to reflect current state
|
|
|
+- Produce audit documentation for future reference
|
|
|
+
|
|
|
+### Non-Goals
|
|
|
+- Replacing handsontable with an alternative library (license constraint remains; replacement is a separate initiative)
|
|
|
+- Upgrading `@keycloak/keycloak-admin-client` to v19+ (significant API breaking changes; deferred to separate task)
|
|
|
+- Major version upgrades of unrelated packages
|
|
|
+- Modifying the build pipeline or Turbopack configuration
|
|
|
+
|
|
|
+## Architecture
|
|
|
+
|
|
|
+This is a dependency maintenance task, not a feature implementation. No new components or architectural changes are introduced.
|
|
|
+
|
|
|
+### Existing Architecture Analysis
|
|
|
+
|
|
|
+The pinned packages fall into distinct categories by their usage context:
|
|
|
+
|
|
|
+| Category | Packages | Build Context |
|
|
|
+|----------|----------|---------------|
|
|
|
+| Server-only (tsc → CJS) | `escape-string-regexp`, `@aws-sdk/*`, `@keycloak/*` | Express server compiled by tsc |
|
|
|
+| Client-only (Turbopack) | `string-width` (via @growi/editor), `bootstrap` | Bundled by Turbopack/Vite |
|
|
|
+| Client + SSR | `next-themes` | Turbopack + SSR rendering |
|
|
|
+| License-pinned | `handsontable`, `@handsontable/react` | Client-only |
|
|
|
+
|
|
|
+Key enabler: Node.js ^24 provides stable `require(esm)` support, removing the fundamental CJS/ESM incompatibility that caused several pins.
|
|
|
+
|
|
|
+### Technology Stack
|
|
|
+
|
|
|
+| Layer | Choice / Version | Role in Feature | Notes |
|
|
|
+|-------|------------------|-----------------|-------|
|
|
|
+| Runtime | Node.js ^24 | Enables `require(esm)` and `RegExp.escape()` | ES2026 Stage 4 features available |
|
|
|
+| Build (client) | Turbopack (Next.js 16) | Bundles ESM-only packages without issues | No changes needed |
|
|
|
+| Build (server) | tsc (CommonJS output) | `require(esm)` handles ESM-only imports | Node.js 24 native support |
|
|
|
+| Package manager | pnpm v10 | Manages dependency resolution | No changes needed |
|
|
|
+
|
|
|
+## System Flows
|
|
|
+
|
|
|
+### Upgrade Verification Flow
|
|
|
+
|
|
|
+```mermaid
|
|
|
+flowchart TD
|
|
|
+ Start[Select package to upgrade] --> Update[Update version in package.json]
|
|
|
+ Update --> Install[pnpm install]
|
|
|
+ Install --> Build{turbo run build}
|
|
|
+ Build -->|Pass| Lint{turbo run lint}
|
|
|
+ Build -->|Fail| Revert[Revert package change]
|
|
|
+ Lint -->|Pass| Test{turbo run test}
|
|
|
+ Lint -->|Fail| Revert
|
|
|
+ Test -->|Pass| Verify[Verify .next/node_modules symlinks]
|
|
|
+ Test -->|Fail| Revert
|
|
|
+ Verify --> Next[Proceed to next package]
|
|
|
+ Revert --> Document[Document failure reason]
|
|
|
+ Document --> Next
|
|
|
+```
|
|
|
+
|
|
|
+Each package is upgraded and verified independently. Failures are isolated and reverted without affecting other upgrades.
|
|
|
+
|
|
|
+## Requirements Traceability
|
|
|
+
|
|
|
+| Requirement | Summary | Components | Action |
|
|
|
+|-------------|---------|------------|--------|
|
|
|
+| 1.1 | Bootstrap bug investigation | PackageAudit | Verify #39798 fixed in v5.3.4 |
|
|
|
+| 1.2 | next-themes issue investigation | PackageAudit | Verify #122 resolved; check v0.4.x compatibility |
|
|
|
+| 1.3 | @aws-sdk constraint verification | PackageAudit | Confirm mongodb constraint is on different package |
|
|
|
+| 1.4 | Document investigation results | AuditReport | Summary table in research.md |
|
|
|
+| 2.1 | ESM compatibility per package | PackageAudit | Assess escape-string-regexp, string-width, @keycloak |
|
|
|
+| 2.2 | Server build ESM support | PackageAudit | Verify Node.js 24 require(esm) for server context |
|
|
|
+| 2.3 | Client build ESM support | PackageAudit | Confirm Turbopack handles ESM-only packages |
|
|
|
+| 2.4 | Compatibility matrix | AuditReport | Table in research.md |
|
|
|
+| 3.1 | Handsontable license check | PackageAudit | Confirm v7+ still non-MIT |
|
|
|
+| 3.2 | Document pinning requirement | AuditReport | Note in audit summary |
|
|
|
+| 4.1 | Update package.json versions and comments | UpgradeExecution | Modify versions and comment blocks |
|
|
|
+| 4.2 | Build verification | UpgradeExecution | `turbo run build --filter @growi/app` |
|
|
|
+| 4.3 | Lint verification | UpgradeExecution | `turbo run lint --filter @growi/app` |
|
|
|
+| 4.4 | Test verification | UpgradeExecution | `turbo run test --filter @growi/app` |
|
|
|
+| 4.5 | Revert on failure | UpgradeExecution | Git revert per package |
|
|
|
+| 4.6 | Update comment blocks | UpgradeExecution | Remove or update comments |
|
|
|
+| 5.1 | Audit summary table | AuditReport | Final summary with decisions |
|
|
|
+| 5.2 | Document continued pinning | AuditReport | Reasons for remaining pins |
|
|
|
+| 5.3 | Document upgrade rationale | AuditReport | What changed upstream |
|
|
|
+
|
|
|
+## Components and Interfaces
|
|
|
+
|
|
|
+| Component | Domain | Intent | Req Coverage | Key Dependencies |
|
|
|
+|-----------|--------|--------|--------------|------------------|
|
|
|
+| PackageAudit | Investigation | Research upstream status for each pinned package | 1.1–1.4, 2.1–2.4, 3.1–3.2 | GitHub issues, npm registry |
|
|
|
+| UpgradeExecution | Implementation | Apply version changes and verify build | 4.1–4.6 | pnpm, turbo, tsc |
|
|
|
+| SourceMigration | Implementation | Replace escape-string-regexp with RegExp.escape() | 4.1 | 9 source files |
|
|
|
+| AuditReport | Documentation | Produce summary of all decisions | 5.1–5.3 | research.md |
|
|
|
+
|
|
|
+### Investigation Layer
|
|
|
+
|
|
|
+#### PackageAudit
|
|
|
+
|
|
|
+| Field | Detail |
|
|
|
+|-------|--------|
|
|
|
+| Intent | Investigate upstream status of each pinned package and determine upgrade feasibility |
|
|
|
+| Requirements | 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2 |
|
|
|
+
|
|
|
+**Responsibilities & Constraints**
|
|
|
+- Check upstream issue trackers for bug fix status
|
|
|
+- Verify ESM compatibility against Node.js 24 `require(esm)` and Turbopack
|
|
|
+- Confirm license status for handsontable
|
|
|
+- Produce actionable recommendation per package
|
|
|
+
|
|
|
+**Audit Decision Matrix**
|
|
|
+
|
|
|
+| Package | Current | Action | Target | Risk | Rationale |
|
|
|
+|---------|---------|--------|--------|------|-----------|
|
|
|
+| `bootstrap` | `=5.3.2` | Upgrade | `^5.3.4` | Low | Bug #39798 fixed in v5.3.4 |
|
|
|
+| `next-themes` | `^0.2.1` | Upgrade | `^0.4.4` | Medium | Original issue was misattributed; v0.4.x works with Pages Router |
|
|
|
+| `escape-string-regexp` | `^4.0.0` | Replace | Remove dep | Low | Native `RegExp.escape()` in Node.js 24 |
|
|
|
+| `string-width` | `=4.2.2` | Upgrade | `^7.0.0` | Low | Used only in ESM context (@growi/editor) |
|
|
|
+| `@aws-sdk/client-s3` | `3.454.0` | Relax | `^3.454.0` | Low | Pinning comment was misleading |
|
|
|
+| `@aws-sdk/s3-request-presigner` | `3.454.0` | Relax | `^3.454.0` | Low | Same as above |
|
|
|
+| `@keycloak/keycloak-admin-client` | `^18.0.0` | Defer | No change | N/A | API breaking changes; separate task |
|
|
|
+| `handsontable` | `=6.2.2` | Keep | No change | N/A | License constraint (non-MIT since v7) |
|
|
|
+| `@handsontable/react` | `=2.1.0` | Keep | No change | N/A | Requires handsontable >= 7 |
|
|
|
+
|
|
|
+### Implementation Layer
|
|
|
+
|
|
|
+#### UpgradeExecution
|
|
|
+
|
|
|
+| Field | Detail |
|
|
|
+|-------|--------|
|
|
|
+| Intent | Apply version changes incrementally with build verification |
|
|
|
+| Requirements | 4.1, 4.2, 4.3, 4.4, 4.5, 4.6 |
|
|
|
+
|
|
|
+**Responsibilities & Constraints**
|
|
|
+- Upgrade one package at a time to isolate failures
|
|
|
+- Run full verification suite (build, lint, test) after each change
|
|
|
+- Revert and document any package that causes failures
|
|
|
+- Update `// comments for dependencies` block to reflect new state
|
|
|
+
|
|
|
+**Upgrade Order** (lowest risk first):
|
|
|
+1. `@aws-sdk/*` — relax version range (no code changes)
|
|
|
+2. `string-width` — upgrade in @growi/editor (isolated ESM package)
|
|
|
+3. `bootstrap` — upgrade to ^5.3.4 (verify SCSS compilation)
|
|
|
+4. `escape-string-regexp` → `RegExp.escape()` — source code changes across 9 files
|
|
|
+5. `next-themes` — upgrade to ^0.4.x (review API changes across 12 files)
|
|
|
+
|
|
|
+**Implementation Notes**
|
|
|
+- After each upgrade, verify `.next/node_modules/` symlinks for Turbopack externalisation compliance (per `package-dependencies` rule)
|
|
|
+- For bootstrap: run `pnpm run pre:styles-commons` and `pnpm run pre:styles-components` to verify SCSS compilation
|
|
|
+- For next-themes: review v0.3.0 and v0.4.0 changelogs for breaking API changes before modifying code
|
|
|
+
|
|
|
+#### SourceMigration
|
|
|
+
|
|
|
+| Field | Detail |
|
|
|
+|-------|--------|
|
|
|
+| Intent | Replace all `escape-string-regexp` usage with native `RegExp.escape()` |
|
|
|
+| Requirements | 4.1 |
|
|
|
+
|
|
|
+**Files to Modify**:
|
|
|
+
|
|
|
+`apps/app/src/` (6 files):
|
|
|
+- `server/models/page.ts`
|
|
|
+- `server/service/page/index.ts`
|
|
|
+- `server/service/page-grant.ts`
|
|
|
+- `server/routes/apiv3/users.js`
|
|
|
+- `server/models/obsolete-page.js`
|
|
|
+- `features/openai/server/services/openai.ts`
|
|
|
+
|
|
|
+`packages/` (3 files):
|
|
|
+- `packages/core/src/utils/page-path-utils/` (2 files)
|
|
|
+- `packages/remark-lsx/src/server/routes/list-pages/index.ts`
|
|
|
+
|
|
|
+**Migration Pattern**:
|
|
|
+```typescript
|
|
|
+// Before
|
|
|
+import escapeStringRegexp from 'escape-string-regexp';
|
|
|
+const pattern = new RegExp(escapeStringRegexp(input));
|
|
|
+
|
|
|
+// After
|
|
|
+const pattern = new RegExp(RegExp.escape(input));
|
|
|
+```
|
|
|
+
|
|
|
+**Implementation Notes**
|
|
|
+- Remove `escape-string-regexp` from `apps/app/package.json` dependencies after migration
|
|
|
+- Remove from `packages/core/package.json` and `packages/remark-lsx/package.json` if listed
|
|
|
+- Verify `RegExp.escape()` TypeScript types are available (may need `@types/node` update or lib config)
|
|
|
+
|
|
|
+### Documentation Layer
|
|
|
+
|
|
|
+#### AuditReport
|
|
|
+
|
|
|
+| Field | Detail |
|
|
|
+|-------|--------|
|
|
|
+| Intent | Document all audit decisions for future maintainers |
|
|
|
+| Requirements | 5.1, 5.2, 5.3 |
|
|
|
+
|
|
|
+**Deliverables**:
|
|
|
+- Updated `// comments for dependencies` in package.json (only retained pins with current reasons)
|
|
|
+- Updated `// comments for defDependencies` (handsontable entries unchanged)
|
|
|
+- Summary in research.md with final decision per package
|
|
|
+
|
|
|
+**Updated Comment Blocks** (target state):
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "// comments for dependencies": {
|
|
|
+ "@keycloak/keycloak-admin-client": "19.0.0 or above exports only ESM. API breaking changes require separate migration effort.",
|
|
|
+ "next-themes": "(if upgrade fails) Document specific failure reason here"
|
|
|
+ },
|
|
|
+ "// comments for defDependencies": {
|
|
|
+ "@handsontable/react": "v3 requires handsontable >= 7.0.0.",
|
|
|
+ "handsontable": "v7.0.0 or above is no longer MIT license."
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Note: The exact final state depends on which upgrades succeed. If all planned upgrades pass, only `@keycloak` and `handsontable` entries remain.
|
|
|
+
|
|
|
+## Testing Strategy
|
|
|
+
|
|
|
+### Build Verification (per package)
|
|
|
+- `turbo run build --filter @growi/app` — Turbopack client build + tsc server build
|
|
|
+- `ls apps/app/.next/node_modules/ | grep <package>` — Externalisation check
|
|
|
+- `pnpm run pre:styles-commons` — SCSS compilation (bootstrap only)
|
|
|
+
|
|
|
+### Lint Verification (per package)
|
|
|
+- `turbo run lint --filter @growi/app` — TypeScript type check + Biome
|
|
|
+
|
|
|
+### Unit/Integration Tests (per package)
|
|
|
+- `turbo run test --filter @growi/app` — Full test suite
|
|
|
+- For `RegExp.escape()` migration: run tests for page model, page service, page-grant service specifically
|
|
|
+
|
|
|
+### Regression Verification (final)
|
|
|
+- Full build + lint + test after all upgrades applied together
|
|
|
+- Verify `.next/node_modules/` symlink integrity via `check-next-symlinks.sh` (if available locally)
|
|
|
+
|
|
|
+## Migration Strategy
|
|
|
+
|
|
|
+```mermaid
|
|
|
+flowchart LR
|
|
|
+ Phase1[Phase 1: Low Risk] --> Phase2[Phase 2: Medium Risk]
|
|
|
+ Phase1 --> P1a[aws-sdk relax range]
|
|
|
+ Phase1 --> P1b[string-width upgrade]
|
|
|
+ Phase2 --> P2a[bootstrap upgrade]
|
|
|
+ Phase2 --> P2b[escape-string-regexp replace]
|
|
|
+ Phase2 --> P2c[next-themes upgrade]
|
|
|
+```
|
|
|
+
|
|
|
+- **Phase 1** (low risk): @aws-sdk range relaxation, string-width upgrade — minimal code changes
|
|
|
+- **Phase 2** (medium risk): bootstrap, escape-string-regexp replacement, next-themes — requires code review and/or source changes
|
|
|
+- Each upgrade is independently revertible
|
|
|
+- Deferred: @keycloak (high risk, separate task)
|
|
|
+- No change: handsontable (license constraint)
|