first commit

This commit is contained in:
2025-04-24 13:11:28 +08:00
commit ff9c54d5e4
5960 changed files with 834111 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
let id = 0
export function nextId() {
return id++
}

View File

@@ -0,0 +1,41 @@
/* eslint-disable
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import { expect } from 'chai'
import request from 'request'
import Settings from '@overleaf/settings'
export function getLatestContent(olProjectId, callback) {
if (callback == null) {
callback = function () {}
}
return request.get(
{
url: `${Settings.overleaf.history.host}/projects/${olProjectId}/latest/content`,
auth: {
user: Settings.overleaf.history.user,
pass: Settings.overleaf.history.pass,
sendImmediately: true,
},
},
(error, res, body) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
callback(
new Error(
`history store a non-success status code: ${res.statusCode}`
)
)
}
return callback(error, JSON.parse(body))
}
)
}

View File

@@ -0,0 +1,41 @@
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import { app } from '../../../../app/js/server.js'
let running = false
let initing = false
const callbacks = []
export function ensureRunning(callback) {
if (callback == null) {
callback = function () {}
}
if (running) {
return callback()
} else if (initing) {
return callbacks.push(callback)
}
initing = true
callbacks.push(callback)
app.listen(3054, '127.0.0.1', error => {
if (error != null) {
throw error
}
running = true
return (() => {
const result = []
for (callback of Array.from(callbacks)) {
result.push(callback())
}
return result
})()
})
}

View File

@@ -0,0 +1,354 @@
import { expect } from 'chai'
import request from 'request'
import Settings from '@overleaf/settings'
import RedisWrapper from '@overleaf/redis-wrapper'
import { db } from '../../../../app/js/mongodb.js'
const rclient = RedisWrapper.createClient(Settings.redis.project_history)
const Keys = Settings.redis.project_history.key_schema
export function resetDatabase(callback) {
rclient.flushdb(callback)
}
export function initializeProject(historyId, callback) {
request.post(
{
url: 'http://127.0.0.1:3054/project',
json: { historyId },
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(null, body.project)
}
)
}
export function flushProject(projectId, options, callback) {
if (typeof options === 'function') {
callback = options
options = null
}
if (!options) {
options = { allowErrors: false }
}
request.post(
{
url: `http://127.0.0.1:3054/project/${projectId}/flush`,
},
(error, res, body) => {
if (error) {
return callback(error)
}
if (!options.allowErrors) {
expect(res.statusCode).to.equal(204)
}
callback(error, res)
}
)
}
export function getSummarizedUpdates(projectId, query, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/updates`,
qs: query,
json: true,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(error, body)
}
)
}
export function getDiff(projectId, pathname, from, to, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/diff`,
qs: {
pathname,
from,
to,
},
json: true,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(error, body)
}
)
}
export function getFileTreeDiff(projectId, from, to, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/filetree/diff`,
qs: {
from,
to,
},
json: true,
},
(error, res, body) => {
if (error) {
return callback(error)
}
callback(error, body, res.statusCode)
}
)
}
export function getChangesInChunkSince(projectId, since, options, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/changes-in-chunk`,
qs: {
since,
},
json: true,
},
(error, res, body) => {
if (error) return callback(error)
if (!options.allowErrors) {
expect(res.statusCode).to.equal(200)
}
callback(null, body, res.statusCode)
}
)
}
export function getLatestSnapshot(projectId, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/snapshot`,
json: true,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(null, body)
}
)
}
export function getSnapshot(projectId, pathname, version, options, callback) {
if (typeof options === 'function') {
callback = options
options = null
}
if (!options) {
options = { allowErrors: false }
}
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/version/${version}/${encodeURIComponent(
pathname
)}`,
},
(error, res, body) => {
if (error) {
return callback(error)
}
if (!options.allowErrors) {
expect(res.statusCode).to.equal(200)
}
callback(error, body, res.statusCode)
}
)
}
export function pushRawUpdate(projectId, update, callback) {
rclient.rpush(
Keys.projectHistoryOps({ project_id: projectId }),
JSON.stringify(update),
callback
)
}
export function setFirstOpTimestamp(projectId, timestamp, callback) {
rclient.set(
Keys.projectHistoryFirstOpTimestamp({ project_id: projectId }),
timestamp,
callback
)
}
export function getFirstOpTimestamp(projectId, callback) {
rclient.get(
Keys.projectHistoryFirstOpTimestamp({ project_id: projectId }),
callback
)
}
export function clearFirstOpTimestamp(projectId, callback) {
rclient.del(
Keys.projectHistoryFirstOpTimestamp({ project_id: projectId }),
callback
)
}
export function getQueueLength(projectId, callback) {
rclient.llen(Keys.projectHistoryOps({ project_id: projectId }), callback)
}
export function getQueueCounts(callback) {
return request.get(
{
url: 'http://127.0.0.1:3054/status/queue',
json: true,
},
callback
)
}
export function resyncHistory(projectId, callback) {
request.post(
{
url: `http://127.0.0.1:3054/project/${projectId}/resync`,
json: true,
body: { origin: { kind: 'test-origin' } },
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(204)
callback(error)
}
)
}
export function createLabel(
projectId,
userId,
version,
comment,
createdAt,
callback
) {
request.post(
{
url: `http://127.0.0.1:3054/project/${projectId}/labels`,
json: { comment, version, created_at: createdAt, user_id: userId },
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(null, body)
}
)
}
export function getLabels(projectId, callback) {
request.get(
{
url: `http://127.0.0.1:3054/project/${projectId}/labels`,
json: true,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(200)
callback(null, body)
}
)
}
export function deleteLabelForUser(projectId, userId, labelId, callback) {
request.delete(
{
url: `http://127.0.0.1:3054/project/${projectId}/user/${userId}/labels/${labelId}`,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(204)
callback(null, body)
}
)
}
export function deleteLabel(projectId, labelId, callback) {
request.delete(
{
url: `http://127.0.0.1:3054/project/${projectId}/labels/${labelId}`,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(204)
callback(null, body)
}
)
}
export function setFailure(failureEntry, callback) {
db.projectHistoryFailures.deleteOne(
{ project_id: { $exists: true } },
(err, result) => {
if (err) {
return callback(err)
}
db.projectHistoryFailures.insertOne(failureEntry, callback)
}
)
}
export function getFailure(projectId, callback) {
db.projectHistoryFailures.findOne({ project_id: projectId }, callback)
}
export function transferLabelOwnership(fromUser, toUser, callback) {
request.post(
{
url: `http://127.0.0.1:3054/user/${fromUser}/labels/transfer/${toUser}`,
},
(error, res, body) => {
if (error) {
return callback(error)
}
expect(res.statusCode).to.equal(204)
callback(null, body)
}
)
}
export function getDump(projectId, callback) {
request.get(
`http://127.0.0.1:3054/project/${projectId}/dump`,
(err, res, body) => {
if (err) {
return callback(err)
}
expect(res.statusCode).to.equal(200)
callback(null, JSON.parse(body))
}
)
}
export function deleteProject(projectId, callback) {
request.delete(`http://127.0.0.1:3054/project/${projectId}`, (err, res) => {
if (err) {
return callback(err)
}
expect(res.statusCode).to.equal(204)
callback()
})
}