Compare commits

..

No commits in common. "main" and "v13.6.24" have entirely different histories.

4 changed files with 12 additions and 70 deletions

View File

@ -99,6 +99,7 @@ Showcase](https://yjs-diagram.synergy.codes/).
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine * [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine
Learning Models Learning Models
* [linear](https://linear.app) Streamline issues, projects, and product roadmaps. * [linear](https://linear.app) Streamline issues, projects, and product roadmaps.
* [btw](https://www.btw.so) - Personal website builder
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) - Machine Learning Service * [AWS SageMaker](https://aws.amazon.com/sagemaker/) - Machine Learning Service
* [Arkiter](https://www.arkiter.com/) - Live interview software * [Arkiter](https://www.arkiter.com/) - Live interview software
* [Appflowy](https://www.appflowy.io/) - They use Yrs * [Appflowy](https://www.appflowy.io/) - They use Yrs
@ -164,7 +165,6 @@ are implemented in separate modules.
| React / Vue / Svelte / MobX | | [SyncedStore](https://syncedstore.org) | [demo](https://syncedstore.org/docs/react) | | React / Vue / Svelte / MobX | | [SyncedStore](https://syncedstore.org) | [demo](https://syncedstore.org/docs/react) |
| [mobx-keystone](https://mobx-keystone.js.org/) | | [mobx-keystone-yjs](https://github.com/xaviergonz/mobx-keystone/tree/master/packages/mobx-keystone-yjs) | [demo](https://mobx-keystone.js.org/examples/yjs-binding) | | [mobx-keystone](https://mobx-keystone.js.org/) | | [mobx-keystone-yjs](https://github.com/xaviergonz/mobx-keystone/tree/master/packages/mobx-keystone-yjs) | [demo](https://mobx-keystone.js.org/examples/yjs-binding) |
| [PSPDFKit](https://www.nutrient.io/) | | [yjs-pspdfkit](https://github.com/hoangqwe159/yjs-pspdfkit) | [demo](https://github.com/hoangqwe159/yjs-pspdfkit) | | [PSPDFKit](https://www.nutrient.io/) | | [yjs-pspdfkit](https://github.com/hoangqwe159/yjs-pspdfkit) | [demo](https://github.com/hoangqwe159/yjs-pspdfkit) |
| [Rows n'Columns](https://www.rowsncolumns.app/) | ✔ | [@rowsncolumns/y-spreadsheet](https://docs.rowsncolumns.app/collaboration/yjs-collaboration) | |
### Providers ### Providers
@ -300,10 +300,6 @@ A database and connection provider for Yjs based on Firestore.
Provides persistent storage for a web server using PostgreSQL and Provides persistent storage for a web server using PostgreSQL and
is easily compatible with y-websocket. is easily compatible with y-websocket.
</dd> </dd>
<dt><a href="https://github.com/kapv89/k_yrs_go">k_yrs_go</a></dt>
<dd>
Golang database server for YJS CRDT using Postgres + Redis
</dd>
</dl> </dl>
### Tooling ### Tooling

View File

@ -34,19 +34,20 @@
] ]
}, },
{ {
"guid": "Titanic", "guid": "ystream",
"name": "Y/Titanic", "name": "Y/Stream",
"description": "A provider for syncing millions of docs efficiently with other peers. This will become the foundation for building real local-first apps with Yjs.", "description": "A provider for syncing millions of docs efficiently with other peers. This will become the foundation for building real local-first apps with Yjs.",
"webpageUrl": { "webpageUrl": {
"url": "https://github.com/yjs/titanic", "url": "https://github.com/yjs/ystream",
"wellKnown": "https://github.com/yjs/titanic/blob/main/.well-known/funding-manifest-urls" "wellKnown": "https://github.com/yjs/ystream/blob/main/.well-known/funding-manifest-urls"
}, },
"repositoryUrl": { "repositoryUrl": {
"url": "https://github.com/yjs/titanic", "url": "https://github.com/yjs/ystream",
"wellKnown": "https://github.com/yjs/titanic/blob/main/.well-known/funding-manifest-urls" "wellKnown": "https://github.com/yjs/ystream/blob/main/.well-known/funding-manifest-urls"
}, },
"licenses": [ "licenses": [
"spdx:MIT" "spdx:MIT",
"spdx:GPL-3.0"
], ],
"tags": [ "tags": [
"privacy", "privacy",
@ -89,9 +90,9 @@
] ]
}, },
{ {
"guid": "titanic-funding", "guid": "ystream-funding",
"status": "active", "status": "active",
"name": "Titanic Funding", "name": "YStream Funding",
"description": "Fund the next generation of local-first providers.", "description": "Fund the next generation of local-first providers.",
"amount": 30000, "amount": 30000,
"currency": "USD", "currency": "USD",

View File

@ -159,7 +159,7 @@ const popStackItem = (undoManager, stack, eventType) => {
*/ */
export class UndoManager extends ObservableV2 { export class UndoManager extends ObservableV2 {
/** /**
* @param {Doc|AbstractType<any>|Array<AbstractType<any>>} typeScope Limits the scope of the UndoManager. If this is set to a ydoc instance, all changes on that ydoc will be undone. If set to a specific type, only changes on that type or its children will be undone. Also accepts an array of types. * @param {Doc|AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
* @param {UndoManagerOptions} options * @param {UndoManagerOptions} options
*/ */
constructor (typeScope, { constructor (typeScope, {
@ -272,8 +272,6 @@ export class UndoManager extends ObservableV2 {
} }
/** /**
* Extend the scope.
*
* @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes * @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes
*/ */
addToScope (ytypes) { addToScope (ytypes) {

View File

@ -116,59 +116,6 @@ export const testEmptyTypeScope = _tc => {
t.assert(yarray.length === 0) t.assert(yarray.length === 0)
} }
/**
* @param {t.TestCase} _tc
*/
export const testRejectUpdateExample = _tc => {
const tmpydoc1 = new Y.Doc()
tmpydoc1.getArray('restricted').insert(0, [1])
tmpydoc1.getArray('public').insert(0, [1])
const update1 = Y.encodeStateAsUpdate(tmpydoc1)
const tmpydoc2 = new Y.Doc()
tmpydoc2.getArray('public').insert(0, [2])
const update2 = Y.encodeStateAsUpdate(tmpydoc2)
const ydoc = new Y.Doc()
const restrictedType = ydoc.getArray('restricted')
/**
* Assume this function handles incoming updates via a communication channel like websockets.
* Changes to the `ydoc.getMap('restricted')` type should be rejected.
*
* - set up undo manager on the restricted types
* - cache pending* updates from the Ydoc to avoid certain attacks
* - apply received update and check whether the restricted type (or any of its children) has been changed.
* - catch errors that might try to circumvent the restrictions
* - undo changes on restricted types
* - reapply pending* updates
*
* @param {Uint8Array} update
*/
const updateHandler = (update) => {
// don't handle changes of the local undo manager, which is used to undo invalid changes
const um = new Y.UndoManager(restrictedType, { trackedOrigins: new Set(['remote change']) })
const beforePendingDs = ydoc.store.pendingDs
const beforePendingStructs = ydoc.store.pendingStructs?.update
try {
Y.applyUpdate(ydoc, update, 'remote change')
} finally {
while (um.undoStack.length) {
um.undo()
}
um.destroy()
ydoc.store.pendingDs = beforePendingDs
ydoc.store.pendingStructs = null
if (beforePendingStructs) {
Y.applyUpdateV2(ydoc, beforePendingStructs)
}
}
}
updateHandler(update1)
updateHandler(update2)
t.assert(restrictedType.length === 0)
t.assert(ydoc.getArray('public').length === 2)
}
/** /**
* Test case to fix #241 * Test case to fix #241
* @param {t.TestCase} _tc * @param {t.TestCase} _tc