Skip to content

Commit 8cd0bbc

Browse files
authored
chore(moon)!: upgrade to Next 16, React 19, and Node 26 (#2153)
Move Moon to Node 26 / pnpm 11, Next 16.2.11, and React 19; refresh the pnpm catalog with deferred majors documented; drop unused Call surfaces; and land small-wave dependency bumps needed for a green web build.
1 parent f5d22b9 commit 8cd0bbc

669 files changed

Lines changed: 12861 additions & 36416 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/web-sync-server-deploy.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131

3232
- uses: actions/setup-node@v4
3333
with:
34-
node-version: "20"
34+
node-version: "26"
3535

3636
- name: Configure AWS Credentials
3737
uses: aws-actions/configure-aws-credentials@v4

‎.github/workflows/web-test.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ jobs:
2121

2222
- uses: actions/setup-node@v4
2323
with:
24-
node-version: '20'
24+
node-version: '26'
2525

2626
- name: Setup pnpm
27-
uses: pnpm/action-setup@v4.0.0
27+
uses: pnpm/action-setup@v4
2828
with:
29-
version: 9
29+
package_json_file: moon/package.json
3030

3131
- name: Get pnpm store directory
3232
shell: bash

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ orion-server/docker-compose.override.yml
6363
# Claude Code configuration and cache
6464
.claude
6565

66+
# pnpm content-addressable store (local / custom store-dir)
67+
.pnpm-store
68+
6669
tools/**
6770

6871
.libra

‎moon/.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
node_modules
55
.pnp
66
.pnp.js
7+
.pnpm-store
78
dist
89
*.tsbuildinfo
910

‎moon/.nvmrc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20
1+
26

‎moon/apps/sync-server/Dockerfile‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# syntax = docker/dockerfile:1
22

3-
FROM node:22-slim AS base
3+
FROM node:26-slim AS base
44

5-
# configure pnpm
5+
# configure pnpm (node:26 images no longer ship corepack)
66
ENV PNPM_HOME="/pnpm"
77
ENV PATH="$PNPM_HOME/bin:$PNPM_HOME:$PATH"
8-
RUN corepack enable && corepack prepare pnpm@9.7.1 --activate
8+
RUN npm install -g pnpm@11.17.0
99

1010

1111
# ENV SENTRY_PROPERTIES=sentry.properties

‎moon/apps/sync-server/package.json‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"build": "tsup",
77
"clean": "rm -rf .turbo dist node_modules",
88
"dev": "tsup --watch --onSuccess \"node dist/index.mjs\"",
9-
"sentry:sourcemaps": "sentry-cli sourcemaps inject --org mega --project sync-server ./dist && sentry-cli sourcemaps upload --org mega --project sync-server --log-level=debug ./dist",
109
"start": "node dist/index.mjs"
1110
},
1211
"dependencies": {
@@ -16,7 +15,6 @@
1615
"@hocuspocus/extension-logger": "catalog:",
1716
"@hocuspocus/server": "catalog:",
1817
"@hocuspocus/transformer": "catalog:",
19-
"@sentry/node": "catalog:",
2018
"@tiptap/core": "catalog:",
2119
"@tiptap/html": "catalog:",
2220
"@tiptap/pm": "catalog:",
@@ -27,7 +25,6 @@
2725
"devDependencies": {
2826
"@flydotio/dockerfile": "catalog:",
2927
"@gitmono/tsconfig": "workspace:*",
30-
"@sentry/cli": "catalog:",
3128
"tsup": "catalog:",
3229
"typescript": "catalog:"
3330
}

‎moon/apps/sync-server/src/database.ts‎

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Database } from '@hocuspocus/extension-database'
22
import { Document } from '@hocuspocus/server'
33
import { TiptapTransformer } from '@hocuspocus/transformer'
4-
import * as Sentry from '@sentry/node'
54
import { generateHTML, generateJSON } from '@tiptap/html'
65
import { fromUint8Array, toUint8Array } from 'js-base64'
76
import * as Y from 'yjs'
@@ -14,14 +13,14 @@ import { Context } from './types'
1413
const extensions = getNoteExtensions()
1514

1615
export function sendVersionToConnections(document: Document, version: number) {
17-
document.connections.forEach((connection) => {
18-
const connectionSchemaVersion = connection.connection.context.schemaVersion ?? 0
16+
document.getConnections().forEach((connection) => {
17+
const connectionSchemaVersion = (connection.context as Context | undefined)?.schemaVersion ?? 0
1918

2019
// Update connections to readOnly if the schema version is lower than the current version
21-
connection.connection.readOnly = connectionSchemaVersion < version
20+
connection.readOnly = connectionSchemaVersion < version
2221

2322
// Send the schema version to the client
24-
connection.connection.sendStateless(
23+
connection.sendStateless(
2524
JSON.stringify({
2625
type: 'schema',
2726
version
@@ -45,20 +44,41 @@ export async function getResource({ token, id, type, organization }: GetResource
4544
}
4645
}
4746

47+
function resolveContext(data: {
48+
context?: Context
49+
lastContext?: Context
50+
requestParameters?: URLSearchParams
51+
}): Context | undefined {
52+
const fromPayload = data.lastContext ?? data.context
53+
54+
if (fromPayload?.token && fromPayload.organization) {
55+
return fromPayload
56+
}
57+
58+
const organization = data.requestParameters?.get('organization') ?? fromPayload?.organization
59+
const type = data.requestParameters?.get('type') ?? fromPayload?.type ?? null
60+
const token = fromPayload?.token
61+
const schemaVersion = fromPayload?.schemaVersion ?? 0
62+
63+
if (!token || !organization) return fromPayload
64+
65+
return { token, schemaVersion, organization, type }
66+
}
67+
4868
export const database = new Database({
4969
/**
5070
* Fetch the document state from Campsite, or generate a new document from the existing
5171
* HTML if the document has never been edited before.
5272
*/
5373
async fetch(data) {
54-
const context: Context = data.context
74+
const context = resolveContext(data)
5575

5676
const id = data.documentName
57-
const organization = data.requestParameters.get('organization')
58-
const type = data.requestParameters.get('type')
77+
const organization = context?.organization
78+
const type = context?.type ?? null
5979

6080
try {
61-
if (!organization) return new Uint8Array()
81+
if (!context?.token || !organization) return new Uint8Array()
6282

6383
const state = await getResource({ token: context.token, id, type, organization })
6484

@@ -79,16 +99,11 @@ export const database = new Database({
7999

80100
return Y.encodeStateAsUpdate(ydoc)
81101
} catch (error) {
82-
Sentry.setContext('document', {
83-
id,
84-
organization,
85-
type
86-
})
87-
Sentry.setContext('context', {
88-
schemaVersion: context.schemaVersion,
89-
token: context.token
102+
console.error('database.fetch failed', {
103+
document: { id, organization, type },
104+
schemaVersion: context?.schemaVersion,
105+
error
90106
})
91-
Sentry.captureException(error)
92107
throw error
93108
}
94109
},
@@ -97,14 +112,14 @@ export const database = new Database({
97112
* Store the document state in Campsite.
98113
*/
99114
async store(data) {
100-
const context: Context = data.context
115+
const context = resolveContext(data)
101116

102117
const id = data.documentName
103-
const organization = data.requestParameters.get('organization')
104-
const type = data.requestParameters.get('type')
118+
const organization = context?.organization
119+
const type = context?.type ?? null
105120

106121
try {
107-
if (!organization) return
122+
if (!context?.token || !organization) return
108123

109124
// Generate a state from the Yjs document
110125
const state = Y.encodeStateAsUpdate(data.document)
@@ -128,16 +143,11 @@ export const database = new Database({
128143
}
129144
)
130145
} catch (error) {
131-
Sentry.setContext('document', {
132-
id,
133-
organization,
134-
type
135-
})
136-
Sentry.setContext('context', {
137-
schemaVersion: context.schemaVersion,
138-
token: context.token
146+
console.error('database.store failed', {
147+
document: { id, organization, type },
148+
schemaVersion: context?.schemaVersion,
149+
error
139150
})
140-
Sentry.captureException(error)
141151
throw error
142152
}
143153
}

‎moon/apps/sync-server/src/index.ts‎

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { Logger } from '@hocuspocus/extension-logger'
2-
import { Hocuspocus } from '@hocuspocus/server'
3-
import * as Sentry from '@sentry/node'
2+
import { Server } from '@hocuspocus/server'
43

54
import { PORT } from './config'
65
import { database, getResource, sendVersionToConnections } from './database'
76
import { AuthenticationError, Context } from './types'
87

9-
const server = new Hocuspocus({
8+
const server = new Server({
109
port: PORT,
1110

1211
async onAuthenticate(data): Promise<Context> {
@@ -32,23 +31,20 @@ const server = new Hocuspocus({
3231
const document = data.instance.documents.get(data.documentName)
3332

3433
if (document) sendVersionToConnections(document, state.description_schema_version)
35-
data.connection.readOnly = schemaVersion < state.description_schema_version
34+
data.connectionConfig.readOnly = schemaVersion < state.description_schema_version
3635

3736
return {
3837
token: data.token,
39-
schemaVersion
40-
}
41-
} catch (error) {
42-
Sentry.setContext('document', {
43-
id: data.documentName,
38+
schemaVersion,
4439
organization,
4540
type
41+
}
42+
} catch (error) {
43+
console.error('onAuthenticate failed', {
44+
document: { id: data.documentName, organization, type },
45+
schemaVersion,
46+
error
4647
})
47-
Sentry.setContext('context', {
48-
schemaVersion: schemaVersion,
49-
token: data.token
50-
})
51-
Sentry.captureException(error)
5248
throw error
5349
}
5450
},

‎moon/apps/sync-server/src/types.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export interface Context {
22
token: string
33
schemaVersion: number
4+
organization: string
5+
type: string | null
46
}
57

68
export type AuthenticationErrorType = 'no-token' | 'invalid-type'

0 commit comments

Comments
 (0)