diff --git a/app/client/aclui/AccessRules.ts b/app/client/aclui/AccessRules.ts index a576bfc0..3686e17c 100644 --- a/app/client/aclui/AccessRules.ts +++ b/app/client/aclui/AccessRules.ts @@ -1067,7 +1067,7 @@ class ObsUserAttributeRule extends Disposable { // TODO this weirdly only works on the first click (editor as any).completer?.showPopup(editor); } - }) + }); }) }), testId('rule-userattr-attr'), diff --git a/app/client/components/ActionLog.ts b/app/client/components/ActionLog.ts index e3aa0c7a..b3f44b31 100644 --- a/app/client/components/ActionLog.ts +++ b/app/client/components/ActionLog.ts @@ -440,7 +440,7 @@ export class ActionLog extends dispose.Disposable implements IDomComponent { const fieldIndex = viewSection.viewFields().peek().findIndex((f: any) => f.colId.peek() === colId); // Finally, move cursor position to the section, column (if we found it), and row. - this._gristDoc.moveToCursorPos({rowId, sectionId, fieldIndex}).catch(() => { /* do nothing */}); + this._gristDoc.moveToCursorPos({rowId, sectionId, fieldIndex}).catch(() => { /* do nothing */ }); } } diff --git a/app/client/components/CellPosition.ts b/app/client/components/CellPosition.ts index ea3e9770..3624f806 100644 --- a/app/client/components/CellPosition.ts +++ b/app/client/components/CellPosition.ts @@ -28,8 +28,9 @@ export function samePosition(a: CellPosition, b: CellPosition) { * @param docModel Document model */ export function fromCursor(position: CursorPos, docModel: DocModel): CellPosition | null { - if (!position.sectionId || !position.rowId || position.fieldIndex == null) + if (!position.sectionId || !position.rowId || position.fieldIndex == null) { return null; + } const section = docModel.viewSections.getRowModel(position.sectionId); const colRef = section.viewFields().peek()[position.fieldIndex]?.colRef.peek(); diff --git a/app/client/components/CodeEditorPanel.js b/app/client/components/CodeEditorPanel.js index 86bf244d..5162e7bf 100644 --- a/app/client/components/CodeEditorPanel.js +++ b/app/client/components/CodeEditorPanel.js @@ -31,6 +31,7 @@ CodeEditorPanel.prototype.buildDom = function() { kd.scope(this._schema, function(schema) { // The reason to scope and rebuild instead of using `kd.text(schema)` is because // hljs.highlightBlock(elem) replaces `elem` with a whole new dom tree. + if (!schema) { return null; } return dom( 'code.g-code-viewer.python', schema, diff --git a/app/client/components/Comm.ts b/app/client/components/Comm.ts index 9a0e23c7..a5a1789f 100644 --- a/app/client/components/Comm.ts +++ b/app/client/components/Comm.ts @@ -204,15 +204,16 @@ export class Comm extends dispose.Disposable implements GristServerAPI, DocListA public pendingRequests: Map; public nextRequestNumber: number = 0; + protected listenTo: BackboneEvents["listenTo"]; // set by Backbone + protected trigger: BackboneEvents["trigger"]; // set by Backbone + protected stopListening: BackboneEvents["stopListening"]; // set by Backbone + // This is a map from docId to the connection for the server that manages // that docId. In classic Grist, which doesn't have fixed docIds or multiple // servers, the key is always "null". private _connections: Map = new Map(); private _collectedUserActions: UserAction[] | null; private _singleWorkerMode: boolean = getInitialDocAssignment() === null; // is this classic Grist? - private listenTo: BackboneEvents["listenTo"]; // set by Backbone - private trigger: BackboneEvents["trigger"]; // set by Backbone - private stopListening: BackboneEvents["stopListening"]; // set by Backbone public create() { this.autoDisposeCallback(() => { diff --git a/app/client/components/Cursor.ts b/app/client/components/Cursor.ts index 3d7b2494..21cf5122 100644 --- a/app/client/components/Cursor.ts +++ b/app/client/components/Cursor.ts @@ -79,7 +79,7 @@ export class Cursor extends Disposable { optCursorPos = optCursorPos || {}; this.viewData = baseView.viewData; - this._sectionId = this.autoDispose(ko.computed(() => baseView.viewSection.id())) + this._sectionId = this.autoDispose(ko.computed(() => baseView.viewSection.id())); this._rowId = ko.observable(optCursorPos.rowId || 0); this.rowIndex = this.autoDispose(ko.computed({ read: () => { diff --git a/app/client/components/CursorMonitor.ts b/app/client/components/CursorMonitor.ts index 5d4bd5ef..3ed1eed9 100644 --- a/app/client/components/CursorMonitor.ts +++ b/app/client/components/CursorMonitor.ts @@ -48,33 +48,33 @@ export class CursorMonitor extends Disposable { // whenever current position changes, store it in the memory this.autoDispose(doc.cursorPosition.addListener(pos => { // if current position is not restored yet, don't change it - if (!this._restored) return; - if (pos) this.storePosition(pos); - })) + if (!this._restored) { return; } + if (pos) { this._storePosition(pos); } + })); } private _whenDocumentLoadsRestorePosition(doc: GristDoc) { // on view shown this.autoDispose(doc.currentView.addListener(async view => { // if the position was restored for this document do nothing - if (this._restored) return; + if (this._restored) { return; } // set that we already restored the position, as some view is shown to the user this._restored = true; // if view wasn't rendered (page is displaying history or code view) do nothing - if (!view) return; + if (!view) { return; } const viewId = doc.activeViewId.get(); - const position = this.restoreLastPosition(viewId); + const position = this._restoreLastPosition(viewId); if (position) { await doc.recursiveMoveToCursorPos(position, true); } })); } - private storePosition(pos: ViewCursorPos) { + private _storePosition(pos: ViewCursorPos) { this._store.update(this._docId, pos); } - private restoreLastPosition(view: IDocPage) { + private _restoreLastPosition(view: IDocPage) { const lastPosition = this._store.read(this._docId); this._store.clear(this._docId); if (lastPosition && lastPosition.position.viewId == view) { @@ -87,13 +87,13 @@ export class CursorMonitor extends Disposable { // Internal implementations for working with local storage class StorageWrapper { - constructor(private storage = getStorage()) { + constructor(private _storage = getStorage()) { } public update(docId: string, position: ViewCursorPos): void { try { - const storage = this.storage; + const storage = this._storage; const data = { docId, position, timestamp: Date.now() }; storage.setItem(this._key(docId), JSON.stringify(data)); } catch (e) { @@ -102,14 +102,14 @@ class StorageWrapper { } public clear(docId: string,): void { - const storage = this.storage; + const storage = this._storage; storage.removeItem(this._key(docId)); } public read(docId: string): { docId: string; position: ViewCursorPos; } | undefined { - const storage = this.storage; + const storage = this._storage; const result = storage.getItem(this._key(docId)); - if (!result) return undefined; + if (!result) { return undefined; } return JSON.parse(result); } diff --git a/app/client/components/EditorMonitor.ts b/app/client/components/EditorMonitor.ts index 57604192..345b0bf3 100644 --- a/app/client/components/EditorMonitor.ts +++ b/app/client/components/EditorMonitor.ts @@ -25,7 +25,7 @@ export class EditorMonitor extends Disposable { this._store = new EditMemoryStorage(doc.docId(), store); // listen to document events to handle view load event - this._listenToReload(doc) + this._listenToReload(doc); } /** @@ -67,7 +67,7 @@ export class EditorMonitor extends Disposable { } executed = true; // if view wasn't rendered (page is displaying history or code view) do nothing - if (!view) return; + if (!view) { return; } const lastEdit = this._restorePosition(); if (lastEdit) { // set the cursor at right cell @@ -98,11 +98,11 @@ function typedListener(owner: IDisposableOwner) { type EditorState = any; // Schema for value stored in the local storage -type LastEditData = { +interface LastEditData { // absolute position for a cell - position: CellPosition, + position: CellPosition; // editor's state - value: EditorState + value: EditorState; } // Abstraction for working with local storage @@ -111,7 +111,7 @@ class EditMemoryStorage { private _entry: LastEditData | null = null; private _timestamp = 0; - constructor(private _docId: string, private storage = getStorage()) { + constructor(private _docId: string, private _storage = getStorage()) { } public updateValue(pos: CellPosition, value: EditorState): void { @@ -138,7 +138,7 @@ class EditMemoryStorage { } protected load() { - const storage = this.storage; + const storage = this._storage; const data = storage.getItem(this._key()); this._entry = null; this._timestamp = 0; @@ -150,7 +150,7 @@ class EditMemoryStorage { console.error("[EditMemory] Data in local storage has a different structure"); return; } - this._entry = entry + this._entry = entry; this._timestamp = timestamp; } catch (e) { console.error("[EditMemory] Can't deserialize date from local storage"); @@ -159,7 +159,7 @@ class EditMemoryStorage { } protected save(): void { - const storage = this.storage; + const storage = this._storage; // if entry was removed - clear the storage if (!this._entry) { diff --git a/app/client/components/GristDoc.ts b/app/client/components/GristDoc.ts index 36b5df60..67b7888a 100644 --- a/app/client/components/GristDoc.ts +++ b/app/client/components/GristDoc.ts @@ -111,10 +111,10 @@ export class GristDoc extends DisposableWithEvents { public readonly fieldEditorHolder = Holder.create(this); // Holds current view that is currently rendered - public currentView : Observable; + public currentView: Observable; // Holds current cursor position with a view id - public cursorPosition : Computed; + public cursorPosition: Computed; private _actionLog: ActionLog; private _undoStack: UndoStack; @@ -250,22 +250,22 @@ export class GristDoc extends DisposableWithEvents { }); // then listen if the view is present, because we still need to wait for it load properly this.autoDispose(viewInstance.addListener(async (view) => { - if (!view) return; + if (!view) { return; } await view.getLoadingDonePromise(); this.currentView.set(view); - })) + })); // create observable for current cursor position this.cursorPosition = Computed.create(this, use => { // get the BaseView const view = use(viewInstance); - if (!view) return undefined; + if (!view) { return undefined; } // get current viewId const viewId = use(this.activeViewId); - if (typeof viewId != 'number') return undefined; + if (typeof viewId != 'number') { return undefined; } // read latest position const currentPosition = use(view.cursor.currentPosition); - if (currentPosition) return { ...currentPosition, viewId } + if (currentPosition) { return { ...currentPosition, viewId }; } return undefined; }); @@ -333,7 +333,7 @@ export class GristDoc extends DisposableWithEvents { return; } try { - const viewInstance = await this._switchToSectionId(cursorPos.sectionId) + const viewInstance = await this._switchToSectionId(cursorPos.sectionId); if (viewInstance) { viewInstance.setCursorPos(cursorPos); } @@ -643,7 +643,7 @@ export class GristDoc extends DisposableWithEvents { } const view: ViewRec = section.view.peek(); const viewId = view.getRowId(); - if (viewId != this.activeViewId.get()) await this.openDocPage(view.getRowId()); + if (viewId != this.activeViewId.get()) { await this.openDocPage(view.getRowId()); } if (setAsActiveSection) { view.activeSectionId(cursorPos.sectionId); } const fieldIndex = cursorPos.fieldIndex; const viewInstance = await waitObs(section.viewInstance); @@ -669,14 +669,14 @@ export class GristDoc extends DisposableWithEvents { * @param input Optional. Cell's initial value */ public async activateEditorAtCursor(options: { init?: string, state?: any}) { - const view = await this.waitForView(); + const view = await this._waitForView(); view?.activateEditorAtCursor(options); } /** * Waits for a view to be ready */ - private async waitForView() { + private async _waitForView() { const view = await waitObs(this.viewModel.activeSection.peek().viewInstance); await view?.getLoadingDonePromise(); return view; @@ -788,13 +788,13 @@ export class GristDoc extends DisposableWithEvents { * Convert a url hash to a cursor position. */ private _getCursorPosFromHash(hash: HashLink): CursorPos { - const cursorPos : CursorPos = { rowId: hash.rowId, sectionId: hash.sectionId }; + const cursorPos: CursorPos = { rowId: hash.rowId, sectionId: hash.sectionId }; if (cursorPos.sectionId != undefined && hash.colRef !== undefined){ // translate colRef to a fieldIndex const section = this.docModel.viewSections.getRowModel(cursorPos.sectionId); const fieldIndex = section.viewFields.peek().all() .findIndex(x=> x.colRef.peek() == hash.colRef); - if (fieldIndex >= 0) cursorPos.fieldIndex = fieldIndex; + if (fieldIndex >= 0) { cursorPos.fieldIndex = fieldIndex; } } return cursorPos; } diff --git a/app/client/components/GristWSConnection.ts b/app/client/components/GristWSConnection.ts index 05871f59..82be5ac8 100644 --- a/app/client/components/GristWSConnection.ts +++ b/app/client/components/GristWSConnection.ts @@ -106,6 +106,8 @@ export class GristWSConnection extends Disposable { public useCount: number = 0; public on: BackboneEvents['on']; // set by Backbone + protected trigger: BackboneEvents['trigger']; // set by Backbone + private _clientId: string|null; private _clientCounter: string; // Identifier of this GristWSConnection object in this browser tab session private _assignmentId: string|null; @@ -118,7 +120,6 @@ export class GristWSConnection extends Disposable { private _reconnectAttempts: number = 0; private _wantReconnect: boolean = true; private _ws: WebSocket|null = null; - private trigger: BackboneEvents['trigger']; // set by Backbone constructor(private _settings: GristWSSettings = new GristWSSettingsBrowser()) { super(); diff --git a/app/client/components/TypeTransform.ts b/app/client/components/TypeTransform.ts index a8c43e37..c7a92cce 100644 --- a/app/client/components/TypeTransform.ts +++ b/app/client/components/TypeTransform.ts @@ -28,8 +28,8 @@ import pickBy = require('lodash/pickBy'); * Creates an instance of TypeTransform for a single field. Extends ColumnTransform. */ export class TypeTransform extends ColumnTransform { - private reviseTypeChange = Observable.create(this, false); - private transformWidget: Computed; + private _reviseTypeChange = Observable.create(this, false); + private _transformWidget: Computed; constructor(gristDoc: GristDoc, fieldBuilder: FieldBuilder) { super(gristDoc, fieldBuilder); @@ -37,7 +37,7 @@ export class TypeTransform extends ColumnTransform { // The display widget of the new transform column. Used to build the transform config menu. // Only set while transforming. - this.transformWidget = Computed.create(this, fromKo(fieldBuilder.widgetImpl), (use, widget) => { + this._transformWidget = Computed.create(this, fromKo(fieldBuilder.widgetImpl), (use, widget) => { return use(this.origColumn.isTransforming) ? widget : null; }); } @@ -49,12 +49,12 @@ export class TypeTransform extends ColumnTransform { // An observable to disable all buttons before the dom get removed. const disableButtons = Observable.create(null, false); - this.reviseTypeChange.set(false); + this._reviseTypeChange.set(false); this.editor = this.autoDispose(AceEditor.create({ observable: this.transformColumn.formula })); return dom('div', testId('type-transform-top'), - dom.maybe(this.transformWidget, transformWidget => transformWidget.buildTransformConfigDom()), - dom.maybe(this.reviseTypeChange, () => + dom.maybe(this._transformWidget, transformWidget => transformWidget.buildTransformConfigDom()), + dom.maybe(this._reviseTypeChange, () => dom('div.transform_editor', this.buildEditorDom(), testId("type-transform-formula") ) @@ -64,7 +64,7 @@ export class TypeTransform extends ColumnTransform { 'Cancel', testId("type-transform-cancel"), dom.cls('disabled', disableButtons) ), - dom.domComputed(this.reviseTypeChange, revising => { + dom.domComputed(this._reviseTypeChange, revising => { if (revising) { return basicButton(dom.on('click', () => this.editor.writeObservable()), 'Preview', testId("type-transform-update"), @@ -72,7 +72,7 @@ export class TypeTransform extends ColumnTransform { { title: 'Update formula (Shift+Enter)' } ); } else { - return basicButton(dom.on('click', () => { this.reviseTypeChange.set(true); }), + return basicButton(dom.on('click', () => { this._reviseTypeChange.set(true); }), 'Revise', testId("type-transform-revise"), dom.cls('disabled', disableButtons) ); diff --git a/app/client/components/UndoStack.ts b/app/client/components/UndoStack.ts index 90a5ec0f..0d652710 100644 --- a/app/client/components/UndoStack.ts +++ b/app/client/components/UndoStack.ts @@ -117,13 +117,13 @@ export class UndoStack extends dispose.Disposable { // context where the change was originally made. We jump first immediately to feel more // responsive, then again when the action is done. The second jump matters more for most // changes, but the first is the important one when Undoing an AddRecord. - this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => {/* do nothing */}) + this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => { /* do nothing */ }); await this._gristDoc.docComm.applyUserActionsById( actionGroups.map(a => a.actionNum), actionGroups.map(a => a.actionHash), isUndo, { otherId: ag.actionNum }); - this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => {/* do nothing */}) + this._gristDoc.moveToCursorPos(ag.cursorPos, ag).catch(() => { /* do nothing */ }); } catch (err) { err.message = `Failed to apply ${isUndo ? 'undo' : 'redo'} action: ${err.message}`; throw err; diff --git a/app/client/components/duplicatePage.ts b/app/client/components/duplicatePage.ts index 5a6762f7..feffaaec 100644 --- a/app/client/components/duplicatePage.ts +++ b/app/client/components/duplicatePage.ts @@ -18,7 +18,7 @@ export async function duplicatePage(gristDoc: GristDoc, pageId: number) { const pagesTable = gristDoc.docModel.pages; const pageName = pagesTable.rowModels[pageId].view.peek().name.peek(); let inputEl: HTMLInputElement; - setTimeout(() => {inputEl.focus(); inputEl.select(); }, 100); + setTimeout(() => { inputEl.focus(); inputEl.select(); }, 100); confirmModal('Duplicate page', 'Save', () => makeDuplicate(gristDoc, pageId, inputEl.value), ( dom('div', [ diff --git a/app/client/declarations.d.ts b/app/client/declarations.d.ts index 92075f8a..a05a202f 100644 --- a/app/client/declarations.d.ts +++ b/app/client/declarations.d.ts @@ -45,9 +45,9 @@ declare module "app/client/components/BaseView" { import {DomArg} from 'grainjs'; import {IOpenController} from 'popweasel'; - type Options = { - init? : string, - state? : any + interface Options { + init?: string; + state?: any; } namespace BaseView {} @@ -68,7 +68,7 @@ declare module "app/client/components/BaseView" { public createFilterMenu(ctl: IOpenController, field: ViewFieldRec, onClose?: () => void): HTMLElement; public buildTitleControls(): DomArg; public getLoadingDonePromise(): Promise; - public activateEditorAtCursor(options?: Options) : void; + public activateEditorAtCursor(options?: Options): void; public onResize(): void; public prepareToPrint(onOff: boolean): void; public moveEditRowToCursor(): DataRowModel; diff --git a/app/client/lib/autocomplete.ts b/app/client/lib/autocomplete.ts index 6b15e256..4f07441a 100644 --- a/app/client/lib/autocomplete.ts +++ b/app/client/lib/autocomplete.ts @@ -55,18 +55,18 @@ export class Autocomplete extends Disposable { constructor( private _triggerElem: HTMLInputElement | HTMLTextAreaElement, - private readonly options: IAutocompleteOptions, + private readonly _options: IAutocompleteOptions, ) { super(); const content = cssMenuWrap( - this._menuContent = cssMenu({class: options.menuCssClass || ''}, - dom.forEach(this._items, (item) => options.renderItem(item, this._highlightFunc)), + this._menuContent = cssMenu({class: _options.menuCssClass || ''}, + dom.forEach(this._items, (item) => _options.renderItem(item, this._highlightFunc)), dom.style('min-width', _triggerElem.getBoundingClientRect().width + 'px'), dom.on('mouseleave', (ev) => this._setSelected(-1, true)), dom.on('click', (ev) => { this._setSelected(this._findTargetItem(ev.target), true); - if (options.onClick) { options.onClick(); } + if (_options.onClick) { _options.onClick(); } }) ), // Prevent trigger element from being blurred on click. @@ -91,7 +91,7 @@ export class Autocomplete extends Disposable { this.onDispose(() => { dom.domDispose(content); content.remove(); }); // Prepare and create the Popper instance, which places the content according to the options. - const popperOptions = merge({}, defaultPopperOptions, options.popperOptions); + const popperOptions = merge({}, defaultPopperOptions, _options.popperOptions); this._popper = createPopper(_triggerElem, content, popperOptions); this.onDispose(() => this._popper.destroy()); } @@ -110,7 +110,7 @@ export class Autocomplete extends Disposable { const elem = (this._menuContent.children[index] as HTMLElement) || null; const prev = this._selected; if (elem !== prev) { - const clsName = this.options.selectedCssClass || 'selected'; + const clsName = this._options.selectedCssClass || 'selected'; if (prev) { prev.classList.remove(clsName); } if (elem) { elem.classList.add(clsName); @@ -123,7 +123,7 @@ export class Autocomplete extends Disposable { if (updateValue) { // Update trigger's value with the selected choice, or else with the last typed value. if (elem) { - this._triggerElem.value = this.options.getItemText(this.getSelectedItem()!); + this._triggerElem.value = this._options.getItemText(this.getSelectedItem()!); } else { this._triggerElem.value = this._lastAsTyped; } @@ -147,7 +147,7 @@ export class Autocomplete extends Disposable { this._lastAsTyped = inputVal; // TODO We should perhaps debounce the search() call in some clever way, to avoid unnecessary // searches while typing. Today, search() is synchronous in practice, so it doesn't matter. - const acResults = await this.options.search(inputVal); + const acResults = await this._options.search(inputVal); this._highlightFunc = acResults.highlightFunc; this._items.set(acResults.items); diff --git a/app/client/models/ColumnFilter.ts b/app/client/models/ColumnFilter.ts index 2cbd10d9..7ca174d0 100644 --- a/app/client/models/ColumnFilter.ts +++ b/app/client/models/ColumnFilter.ts @@ -31,7 +31,7 @@ export function isEquivalentFilter(state: FilterState, spec: FilterSpec): boolea const other = makeFilterState(spec); if (state.include !== other.include) { return false; } if (state.values.size !== other.values.size) { return false; } - for (const val of other.values) { if (!state.values.has(val)) { return false; }} + for (const val of other.values) { if (!state.values.has(val)) { return false; } } return true; } diff --git a/app/client/models/SearchModel.ts b/app/client/models/SearchModel.ts index 60016a62..ca8db6c0 100644 --- a/app/client/models/SearchModel.ts +++ b/app/client/models/SearchModel.ts @@ -92,7 +92,7 @@ export class SearchModelImpl extends Disposable implements SearchModel { this.autoDispose(this.value.addListener(v => { void findFirst(v); })); // Set this.noMatch to false when multiPage gets turned ON. - this.autoDispose(this.multiPage.addListener(v => { if (v) { this.noMatch.set(false); }})); + this.autoDispose(this.multiPage.addListener(v => { if (v) { this.noMatch.set(false); } })); // Schedule a search restart when user changes pages (otherwise search would resume from the // previous page that is not shown anymore). Also revert noMatch flag when in single page mode. diff --git a/app/client/models/TreeModel.ts b/app/client/models/TreeModel.ts index cf58486d..a25c468f 100644 --- a/app/client/models/TreeModel.ts +++ b/app/client/models/TreeModel.ts @@ -207,7 +207,7 @@ export class TreeNodeRecord implements TreeNode { // Get all the records included in this item. public getRecords(): TreeRecord[] { const records = [] as TreeRecord[]; - if (this.index !== "root") {records.push(this._records[this.index]); } + if (this.index !== "root") { records.push(this._records[this.index]); } walkTree(this, (item: TreeItemRecord) => records.push(this._records[item.index])); return records; } @@ -255,7 +255,7 @@ export function find(model: TreeNode, func: (item: TreeItem) => boolean): TreeIt if (children) { for (const child of children.get()) { const found = func(child) && child || find(child, func); - if (found) {return found; } + if (found) { return found; } } } } diff --git a/app/client/models/gristUrlState.ts b/app/client/models/gristUrlState.ts index 09080a42..a9271ee8 100644 --- a/app/client/models/gristUrlState.ts +++ b/app/client/models/gristUrlState.ts @@ -91,7 +91,7 @@ function _getLoginLogoutUrl(method: 'login'|'logout'|'signin', nextUrl: string): * only public interface is the urlState() accessor. */ export class UrlStateImpl { - constructor(private window: {gristConfig?: Partial}) {} + constructor(private _window: {gristConfig?: Partial}) {} /** * The actual serialization of a url state into a URL. The URL has the form @@ -105,7 +105,7 @@ export class UrlStateImpl { * localhost:8080/o/ */ public encodeUrl(state: IGristUrlState, baseLocation: Location | URL): string { - const gristConfig = this.window.gristConfig || {}; + const gristConfig = this._window.gristConfig || {}; return encodeUrl(gristConfig, state, baseLocation); } @@ -113,7 +113,7 @@ export class UrlStateImpl { * Parse a URL location into an IGristUrlState object. See encodeUrl() documentation. */ public decodeUrl(location: Location | URL): IGristUrlState { - const gristConfig = this.window.gristConfig || {}; + const gristConfig = this._window.gristConfig || {}; return decodeUrl(gristConfig, location); } @@ -136,7 +136,7 @@ export class UrlStateImpl { * a matter of DocWorker requiring a different version (e.g. /v/OTHER/doc/...). */ public needPageLoad(prevState: IGristUrlState, newState: IGristUrlState): boolean { - const gristConfig = this.window.gristConfig || {}; + const gristConfig = this._window.gristConfig || {}; const orgReload = prevState.org !== newState.org; // Reload when moving to/from a document or between doc and non-doc. const docReload = prevState.doc !== newState.doc; diff --git a/app/client/models/rowset.ts b/app/client/models/rowset.ts index 4881bd6e..c7c72e32 100644 --- a/app/client/models/rowset.ts +++ b/app/client/models/rowset.ts @@ -368,25 +368,25 @@ export class FilteredRowSource extends BaseFilteredRowSource { * Private helper object that maintains a set of rows for a particular group. */ class RowGroupHelper extends RowSource { - private rows: Set = new Set(); + private _rows: Set = new Set(); constructor(public readonly groupValue: Value) { super(); } public getAllRows() { - return this.rows.values(); + return this._rows.values(); } public getNumRows(): number { - return this.rows.size; + return this._rows.size; } public _addAll(rows: RowList) { - for (const r of rows) { this.rows.add(r); } + for (const r of rows) { this._rows.add(r); } } public _removeAll(rows: RowList) { - for (const r of rows) { this.rows.delete(r); } + for (const r of rows) { this._rows.delete(r); } } } diff --git a/app/client/ui/DocMenu.ts b/app/client/ui/DocMenu.ts index 7e3cfc37..3460993d 100644 --- a/app/client/ui/DocMenu.ts +++ b/app/client/ui/DocMenu.ts @@ -245,8 +245,8 @@ function buildWorkspaceDocBlock(home: HomeModel, workspace: Workspace, flashDocI // The flash value may change to true, and then immediately to false. We highlight it // using a transition, and scroll into view, when it turns back to false. transition(flash, { - prepare(elem, val) { if (!val) { elem.style.backgroundColor = colors.slate.toString(); }}, - run(elem, val) { if (!val) { elem.style.backgroundColor = ''; scrollIntoViewIfNeeded(elem); }}, + prepare(elem, val) { if (!val) { elem.style.backgroundColor = colors.slate.toString(); } }, + run(elem, val) { if (!val) { elem.style.backgroundColor = ''; scrollIntoViewIfNeeded(elem); } }, }) ), css.docRowWrapper.cls('-renaming', isRenaming), diff --git a/app/client/ui/MultiSelector.ts b/app/client/ui/MultiSelector.ts index 3969f536..26652db9 100644 --- a/app/client/ui/MultiSelector.ts +++ b/app/client/ui/MultiSelector.ts @@ -45,7 +45,7 @@ export abstract class MultiItemSelector extends Disposabl return cssMultiSelectorWrapper( cssItemList(testId('list'), dom.forEach(this._incItems, item => this.buildItemDom(item)), - this.buildAddItemDom(this._options.addItemLabel, this._options.addItemText) + this._buildAddItemDom(this._options.addItemLabel, this._options.addItemText) ), ); } @@ -60,7 +60,7 @@ export abstract class MultiItemSelector extends Disposabl // Called with an item from `_allItems` protected async remove(item: Item): Promise { - const idx = this.findIncIndex(item); + const idx = this._findIncIndex(item); if (idx === -1) { return; } this._incItems.splice(idx, 1); } @@ -70,7 +70,7 @@ export abstract class MultiItemSelector extends Disposabl // Replaces an existing item (if found) with a new one protected async changeItem(item: Item, newItem: Item): Promise { - const idx = this.findIncIndex(item); + const idx = this._findIncIndex(item); if (idx === -1) { return; } this._incItems.splice(idx, 1, newItem); } @@ -82,7 +82,7 @@ export abstract class MultiItemSelector extends Disposabl selectCb: (newItem: Item) => void, selectOptions?: {}): Element { const obs = computed(use => selectedValue).onWrite(async value => { - const newItem = this.findItemByValue(value); + const newItem = this._findItemByValue(value); if (newItem) { selectCb(newItem); } @@ -115,17 +115,17 @@ export abstract class MultiItemSelector extends Disposabl } // Returns the index (order) of the item if it's been included, or -1 otherwise. - private findIncIndex(item: Item): number { + private _findIncIndex(item: Item): number { return this._incItems.get().findIndex(_item => _item === item); } // Returns the item object given it's value, or undefined if not found. - private findItemByValue(value: string): Item | undefined { + private _findItemByValue(value: string): Item | undefined { return this._allItems.get().find(_item => _item.value === value); } // Builds the about-to-be-added item - private buildAddItemDom(defLabel: string, defText: string): Element { + private _buildAddItemDom(defLabel: string, defText: string): Element { const addNewItem: Observable = observable(false); return dom('li', testId('add-item'), dom.domComputed(addNewItem, isAdding => isAdding diff --git a/app/client/ui/PageWidgetPicker.ts b/app/client/ui/PageWidgetPicker.ts index 6ccecf7c..8defff7e 100644 --- a/app/client/ui/PageWidgetPicker.ts +++ b/app/client/ui/PageWidgetPicker.ts @@ -196,7 +196,7 @@ export function buildPageWidgetPicker( dom.create(PageWidgetSelect, value, tables, columns, onSaveCB, options), // gives focus and binds keydown events - (elem: any) => {setTimeout(() => elem.focus(), 0); }, + (elem: any) => { setTimeout(() => elem.focus(), 0); }, onKeyDown({ Escape: () => ctl.close(), Enter: () => isValid() && onSaveCB() diff --git a/app/client/ui2018/ColorSelect.ts b/app/client/ui2018/ColorSelect.ts index 894e0c70..a32d7177 100644 --- a/app/client/ui2018/ColorSelect.ts +++ b/app/client/ui2018/ColorSelect.ts @@ -82,7 +82,7 @@ function buildColorPicker(ctl: IOpenController, textColor: Observable, f }), // gives focus and binds keydown events - (elem: any) => {setTimeout(() => elem.focus(), 0); }, + (elem: any) => { setTimeout(() => elem.focus(), 0); }, onKeyDown({ Escape: () => { revert(); }, Enter: () => { ctl.close(); }, @@ -158,7 +158,7 @@ class PickerComponent extends Disposable { ), cssHexBox( this._color, - async (val) => { if (isValidHex(val)) {this._model.setValue(val); }}, + async (val) => { if (isValidHex(val)) { this._model.setValue(val); } }, testId(`${title}-hex`), // select the hex value on click. Doing it using settimeout allows to avoid some // sporadically losing the selection just after the click. diff --git a/app/client/ui2018/editableLabel.ts b/app/client/ui2018/editableLabel.ts index e5762217..2c9ee031 100644 --- a/app/client/ui2018/editableLabel.ts +++ b/app/client/ui2018/editableLabel.ts @@ -105,7 +105,7 @@ export function rawTextInput(value: Observable, save: SaveFunc, onChange let inputEl: HTMLInputElement; // When label changes updates the input, unless in the middle of editing. - const lis = value.addListener((val) => { if (status !== Status.EDITING) { setValue(val); }}); + const lis = value.addListener((val) => { if (status !== Status.EDITING) { setValue(val); } }); function setValue(val: string) { inputEl.value = val; diff --git a/app/client/ui2018/search.ts b/app/client/ui2018/search.ts index 57e9a347..8e2c5c3e 100644 --- a/app/client/ui2018/search.ts +++ b/app/client/ui2018/search.ts @@ -128,8 +128,8 @@ export function searchBar(model: SearchModel, testId: TestId = noTestId) { find: () => { inputElem.focus(); inputElem.select(); }, // On Mac, Firefox has a default behaviour witch causes to close the search bar on Cmd+g and // Cmd+shirt+G. Returning false is a Mousetrap convenience which prevents that. - findNext: () => {model.findNext().catch(reportError); return false; }, - findPrev: () => {model.findPrev().catch(reportError); return false; }, + findNext: () => { model.findNext().catch(reportError); return false; }, + findPrev: () => { model.findPrev().catch(reportError); return false; }, }, null, true); const toggleMenu = debounce((_value?: boolean) => { diff --git a/app/client/widgets/AttachmentsEditor.ts b/app/client/widgets/AttachmentsEditor.ts index cc248e84..94f8ea28 100644 --- a/app/client/widgets/AttachmentsEditor.ts +++ b/app/client/widgets/AttachmentsEditor.ts @@ -105,7 +105,7 @@ export class AttachmentsEditor extends NewBaseEditor { }), // Close if clicking into the background. (The default modal's behavior for this isn't // triggered because our content covers the whole screen.) - dom.on('click', (ev, elem) => { if (ev.target === elem) { ctl.close(); }}), + dom.on('click', (ev, elem) => { if (ev.target === elem) { ctl.close(); } }), ...this._buildDom(ctl) ]; }, {noEscapeKey: true}); diff --git a/app/client/widgets/FieldBuilder.ts b/app/client/widgets/FieldBuilder.ts index 29b7bbb9..7f977f38 100644 --- a/app/client/widgets/FieldBuilder.ts +++ b/app/client/widgets/FieldBuilder.ts @@ -66,30 +66,30 @@ export class FieldBuilder extends Disposable { public readonly widgetImpl: ko.Computed; public readonly diffImpl: NewAbstractWidget; - private readonly availableTypes: Computed>>; - private readonly readOnlyPureType: ko.PureComputed; - private readonly isRightType: ko.PureComputed<(value: CellValue, options?: any) => boolean>; - private readonly refTableId: ko.Computed; - private readonly isRef: ko.Computed; + private readonly _availableTypes: Computed>>; + private readonly _readOnlyPureType: ko.PureComputed; + private readonly _isRightType: ko.PureComputed<(value: CellValue, options?: any) => boolean>; + private readonly _refTableId: ko.Computed; + private readonly _isRef: ko.Computed; private readonly _rowMap: Map; - private readonly isTransformingFormula: ko.Computed; - private readonly isTransformingType: ko.Computed; + private readonly _isTransformingFormula: ko.Computed; + private readonly _isTransformingType: ko.Computed; private readonly _fieldEditorHolder: Holder; - private readonly widgetCons: ko.Computed<{create: (...args: any[]) => NewAbstractWidget}>; - private readonly docModel: DocModel; + private readonly _widgetCons: ko.Computed<{create: (...args: any[]) => NewAbstractWidget}>; + private readonly _docModel: DocModel; public constructor(public readonly gristDoc: GristDoc, public readonly field: ViewFieldRec, private _cursor: Cursor) { super(); - this.docModel = gristDoc.docModel; + this._docModel = gristDoc.docModel; this.origColumn = field.column(); this.options = field.widgetOptionsJson; - this.readOnlyPureType = ko.pureComputed(() => this.field.column().pureType()); + this._readOnlyPureType = ko.pureComputed(() => this.field.column().pureType()); // Observable with a list of available types. - this.availableTypes = Computed.create(this, (use) => { + this._availableTypes = Computed.create(this, (use) => { const isFormula = use(this.origColumn.isFormula); const types: Array> = []; _.each(UserType.typeDefs, (def: any, key: string|number) => { @@ -108,17 +108,17 @@ export class FieldBuilder extends Disposable { }); // Observable which evaluates to a *function* that decides if a value is valid. - this.isRightType = ko.pureComputed(function() { - return gristTypes.isRightType(this.readOnlyPureType()) || _.constant(false); + this._isRightType = ko.pureComputed(function() { + return gristTypes.isRightType(this._readOnlyPureType()) || _.constant(false); }, this); // Returns a boolean indicating whether the column is type Reference. - this.isRef = this.autoDispose(ko.computed(() => { + this._isRef = this.autoDispose(ko.computed(() => { return gutil.startsWith(this.field.column().type(), 'Ref:'); })); // Gives the table ID to which the reference points. - this.refTableId = this.autoDispose(ko.computed({ + this._refTableId = this.autoDispose(ko.computed({ read: () => gutil.removePrefix(this.field.column().type(), "Ref:"), write: val => this._setType(`Ref:${val}`) })); @@ -148,11 +148,11 @@ export class FieldBuilder extends Disposable { this.columnTransform = null; // Returns a boolean indicating whether a formula transform is in progress. - this.isTransformingFormula = this.autoDispose(ko.computed(() => { + this._isTransformingFormula = this.autoDispose(ko.computed(() => { return this.field.column().isTransforming() && this.columnTransform instanceof FormulaTransform; })); // Returns a boolean indicating whether a type transform is in progress. - this.isTransformingType = this.autoDispose(ko.computed(() => { + this._isTransformingType = this.autoDispose(ko.computed(() => { return (this.field.column().isTransforming() || this.isCallPending()) && (this.columnTransform instanceof TypeTransform); })); @@ -165,14 +165,14 @@ export class FieldBuilder extends Disposable { this._rowMap = new Map(); // Returns the constructor for the widget, and only notifies subscribers on changes. - this.widgetCons = this.autoDispose(koUtil.withKoUtils(ko.computed(function() { + this._widgetCons = this.autoDispose(koUtil.withKoUtils(ko.computed(function() { return UserTypeImpl.getWidgetConstructor(this.options().widget, - this.readOnlyPureType()); + this._readOnlyPureType()); }, this)).onlyNotifyUnequal()); // Computed builder for the widget. this.widgetImpl = this.autoDispose(koUtil.computedBuilder(() => { - const cons = this.widgetCons(); + const cons = this._widgetCons(); // Must subscribe to `colId` so that field.colId is rechecked on transform. return cons.create.bind(cons, this.field, this.field.colId()); }, this).extend({ deferred: true })); @@ -180,11 +180,8 @@ export class FieldBuilder extends Disposable { this.diffImpl = this.autoDispose(DiffBox.create(this.field)); } -// dispose.makeDisposable(FieldBuilder); - - public buildSelectWidgetDom() { - return grainjsDom.maybe((use) => !use(this.isTransformingType) && use(this.readOnlyPureType), type => { + return grainjsDom.maybe((use) => !use(this._isTransformingType) && use(this._readOnlyPureType), type => { const typeWidgets = getTypeDefinition(type).widgets; const widgetOptions = Object.keys(typeWidgets).map(label => ({ label, @@ -206,32 +203,32 @@ export class FieldBuilder extends Disposable { * Build the type change dom. */ public buildSelectTypeDom() { - const selectType = Computed.create(null, (use) => use(fromKo(this.readOnlyPureType))); - selectType.onWrite(newType => newType === this.readOnlyPureType.peek() || this._setType(newType)); + const selectType = Computed.create(null, (use) => use(fromKo(this._readOnlyPureType))); + selectType.onWrite(newType => newType === this._readOnlyPureType.peek() || this._setType(newType)); const onDispose = () => (this.isDisposed() || selectType.set(this.field.column().pureType())); return [ cssRow( grainjsDom.autoDispose(selectType), - select(selectType, this.availableTypes, { - disabled: (use) => use(this.isTransformingFormula) || use(this.origColumn.disableModifyBase) || + select(selectType, this._availableTypes, { + disabled: (use) => use(this._isTransformingFormula) || use(this.origColumn.disableModifyBase) || use(this.isCallPending) }), testId('type-select') ), - grainjsDom.maybe((use) => use(this.isRef) && !use(this.isTransformingType), () => this._buildRefTableSelect()), - grainjsDom.maybe(this.isTransformingType, () => { + grainjsDom.maybe((use) => use(this._isRef) && !use(this._isTransformingType), () => this._buildRefTableSelect()), + grainjsDom.maybe(this._isTransformingType, () => { // Editor dom must be built before preparing transform. return dom('div.type_transform_prompt', kf.prompt( dom('div', - grainjsDom.maybe(this.isRef, () => this._buildRefTableSelect()), + grainjsDom.maybe(this._isRef, () => this._buildRefTableSelect()), grainjsDom.maybe((use) => use(this.field.column().isTransforming), () => this.columnTransform!.buildDom()) - ) + ) ), grainjsDom.onDispose(onDispose) - ); + ); }) ]; } @@ -242,7 +239,7 @@ export class FieldBuilder extends Disposable { // Do not type transform a new/empty column or a formula column. Just make a best guess for // the full type, and set it. const column = this.field.column(); - column.type.setAndSave(addColTypeSuffix(newType, column, this.docModel)).catch(reportError); + column.type.setAndSave(addColTypeSuffix(newType, column, this._docModel)).catch(reportError); } else if (!this.columnTransform) { this.columnTransform = TypeTransform.create(null, this.gristDoc, this); return this.columnTransform.prepare(newType); @@ -256,7 +253,7 @@ export class FieldBuilder extends Disposable { // Builds the reference type table selector. Built when the column is type reference. public _buildRefTableSelect() { const allTables = Computed.create(null, (use) => - use(this.docModel.allTableIds.getObservable()).map(tableId => ({ + use(this._docModel.allTableIds.getObservable()).map(tableId => ({ value: tableId, label: tableId, icon: 'FieldTable' as const @@ -266,7 +263,7 @@ export class FieldBuilder extends Disposable { cssLabel('DATA FROM TABLE'), cssRow( dom.autoDispose(allTables), - select(fromKo(this.refTableId), allTables), + select(fromKo(this._refTableId), allTables), testId('ref-table-select') ) ]; @@ -301,15 +298,15 @@ export class FieldBuilder extends Disposable { kf.checkButton(transformButton, dom('span.glyphicon.glyphicon-flash'), dom.testId("FieldBuilder_editTransform"), - kd.toggleClass('disabled', () => this.isTransformingType() || this.origColumn.isFormula() || + kd.toggleClass('disabled', () => this._isTransformingType() || this.origColumn.isFormula() || this.origColumn.disableModifyBase()) ) ) ), - kd.maybe(this.isTransformingFormula, () => { + kd.maybe(this._isTransformingFormula, () => { return this.columnTransform!.buildDom(); }) - ); + ); } /** @@ -319,7 +316,7 @@ export class FieldBuilder extends Disposable { // NOTE: adding a grainjsDom .maybe here causes the disposable order of the widgetImpl and // the dom created by the widgetImpl to get out of sync. return dom('div', - kd.maybe(() => !this.isTransformingType() && this.widgetImpl(), (widget: NewAbstractWidget) => + kd.maybe(() => !this._isTransformingType() && this.widgetImpl(), (widget: NewAbstractWidget) => dom('div', widget.buildConfigDom(), widget.buildColorConfigDom(), @@ -401,7 +398,7 @@ export class FieldBuilder extends Disposable { if (this.isDisposed()) { return null; } // Work around JS errors during field removal. const value = row.cells[this.field.colId()]; const cell = value && value(); - if (value && this.isRightType()(cell, this.options) || row._isAddRow.peek()) { + if (value && this._isRightType()(cell, this.options) || row._isAddRow.peek()) { return this.widgetImpl(); } else if (gristTypes.isVersions(cell)) { return this.diffImpl; @@ -462,7 +459,7 @@ export class FieldBuilder extends Disposable { return; } - const editorCtor = UserTypeImpl.getEditorConstructor(this.options().widget, this.readOnlyPureType()); + const editorCtor = UserTypeImpl.getEditorConstructor(this.options().widget, this._readOnlyPureType()); // constructor may be null for a read-only non-formula field, though not today. if (!editorCtor) { // Actually, we only expect buildEditorDom() to be called when isEditorActive() is false (i.e. diff --git a/app/client/widgets/FieldEditor.ts b/app/client/widgets/FieldEditor.ts index 290e52bc..7dc27138 100644 --- a/app/client/widgets/FieldEditor.ts +++ b/app/client/widgets/FieldEditor.ts @@ -47,10 +47,10 @@ export async function setAndSave(editRow: DataRowModel, field: ViewFieldRec, val } } -export type FieldEditorStateEvent = { - position : CellPosition, - currentState : any, - type: string +export interface FieldEditorStateEvent { + position: CellPosition; + currentState: any; + type: string; } export class FieldEditor extends Disposable { @@ -125,7 +125,7 @@ export class FieldEditor extends Disposable { unmakeFormula: () => this._unmakeFormula(), }; - const state : any = options.state; + const state: any = options.state; this.rebuildEditor(isFormula, editValue, Number.POSITIVE_INFINITY, state); @@ -141,7 +141,7 @@ export class FieldEditor extends Disposable { } // cursorPos refers to the position of the caret within the editor. - public rebuildEditor(isFormula: boolean, editValue: string|undefined, cursorPos: number, state? : any) { + public rebuildEditor(isFormula: boolean, editValue: string|undefined, cursorPos: number, state?: any) { const editorCtor: IEditorConstructor = isFormula ? FormulaEditor : this._editorCtor; const column = this._field.column(); @@ -168,11 +168,11 @@ export class FieldEditor extends Disposable { // if editor supports live changes, connect it to the change emitter if (editor.editorState) { editor.autoDispose(editor.editorState.addListener((currentState) => { - const event : FieldEditorStateEvent = { - position : this.cellPosition(), + const event: FieldEditorStateEvent = { + position: this._cellPosition(), currentState, - type : this._field.column.peek().pureType.peek() - } + type: this._field.column.peek().pureType.peek() + }; this.changeEmitter.emit(event); })); } @@ -181,7 +181,7 @@ export class FieldEditor extends Disposable { } // calculate current cell's absolute position - private cellPosition() { + private _cellPosition() { const rowId = this._editRow.getRowId(); const colRef = this._field.colRef.peek(); const sectionId = this._field.viewSection.peek().id.peek(); @@ -189,7 +189,7 @@ export class FieldEditor extends Disposable { rowId, colRef, sectionId - } + }; return position; } @@ -240,11 +240,11 @@ export class FieldEditor extends Disposable { // Cancels the edit private _cancelEdit() { - const event : FieldEditorStateEvent = { - position : this.cellPosition(), - currentState : this._editorHolder.get()?.editorState?.get(), - type : this._field.column.peek().pureType.peek() - } + const event: FieldEditorStateEvent = { + position: this._cellPosition(), + currentState: this._editorHolder.get()?.editorState?.get(), + type: this._field.column.peek().pureType.peek() + }; this.cancelEmitter.emit(event); this.dispose(); } @@ -296,11 +296,11 @@ export class FieldEditor extends Disposable { } } - const event : FieldEditorStateEvent = { - position : this.cellPosition(), - currentState : this._editorHolder.get()?.editorState?.get(), - type : this._field.column.peek().pureType.peek() - } + const event: FieldEditorStateEvent = { + position: this._cellPosition(), + currentState: this._editorHolder.get()?.editorState?.get(), + type: this._field.column.peek().pureType.peek() + }; this.saveEmitter.emit(event); const cursor = this._cursor; diff --git a/app/client/widgets/NTextEditor.ts b/app/client/widgets/NTextEditor.ts index 7bf17968..56fbf234 100644 --- a/app/client/widgets/NTextEditor.ts +++ b/app/client/widgets/NTextEditor.ts @@ -13,7 +13,7 @@ import {dom, Observable} from 'grainjs'; export class NTextEditor extends NewBaseEditor { // Observable with current editor state (used by drafts or latest edit/position component) - public readonly editorState : Observable; + public readonly editorState: Observable; protected cellEditorDiv: HTMLElement; protected textInput: HTMLTextAreaElement; @@ -29,7 +29,7 @@ export class NTextEditor extends NewBaseEditor { constructor(options: Options) { super(options); - const initialValue : string = undef( + const initialValue: string = undef( options.state as string | undefined, options.editValue, String(options.cellValue ?? "")); this.editorState = Observable.create(this, initialValue); @@ -96,10 +96,10 @@ export class NTextEditor extends NewBaseEditor { */ protected onInput() { // Resize the textbox whenever user types in it. - this.resizeInput() + this.resizeInput(); // notify about current state - this.editorState.set(String(this.getTextValue())) + this.editorState.set(String(this.getTextValue())); } /** diff --git a/app/client/widgets/NewBaseEditor.ts b/app/client/widgets/NewBaseEditor.ts index bc09dd41..b0552613 100644 --- a/app/client/widgets/NewBaseEditor.ts +++ b/app/client/widgets/NewBaseEditor.ts @@ -21,7 +21,7 @@ export interface Options { editValue?: string; cursorPos: number; commands: IEditorCommandGroup; - state? : any; + state?: any; } /** @@ -58,7 +58,7 @@ export abstract class NewBaseEditor extends Disposable { /** * Current state of the editor. Optional, not all editors will report theirs current state. */ - public editorState? : Observable; + public editorState?: Observable; constructor(protected options: Options) { super(); diff --git a/app/common/ACLPermissions.ts b/app/common/ACLPermissions.ts index 503a2596..008cfc83 100644 --- a/app/common/ACLPermissions.ts +++ b/app/common/ACLPermissions.ts @@ -171,7 +171,7 @@ export function summarizePermissionSet(pset: PartialPermissionSet): MixedPermiss for (const key of Object.keys(pset) as Array) { const pWithSome = pset[key]; // "Some" postfix is not significant for summarization. - const p = pWithSome === 'allowSome' ? 'allow' : (pWithSome === 'denySome' ? 'deny' : pWithSome) + const p = pWithSome === 'allowSome' ? 'allow' : (pWithSome === 'denySome' ? 'deny' : pWithSome); if (!p || p === sign) { continue; } if (!sign) { sign = p; diff --git a/app/common/ActionSummary.ts b/app/common/ActionSummary.ts index 8e6bbea6..8820a934 100644 --- a/app/common/ActionSummary.ts +++ b/app/common/ActionSummary.ts @@ -240,7 +240,7 @@ export function getAffectedTables(summary: ActionSummary): string[] { */ export function getTableIdBefore(renames: LabelDelta[], tableIdAfter: string|null): string|null { if (tableIdAfter === null) { return tableIdAfter; } - const rename = renames.find(rename => rename[1] === tableIdAfter); + const rename = renames.find(_rename => _rename[1] === tableIdAfter); return rename ? rename[0] : tableIdAfter; } @@ -250,7 +250,7 @@ export function getTableIdBefore(renames: LabelDelta[], tableIdAfter: string|nul */ export function getTableIdAfter(renames: LabelDelta[], tableIdBefore: string|null): string|null { if (tableIdBefore === null) { return tableIdBefore; } - const rename = renames.find(rename => rename[0] === tableIdBefore); + const rename = renames.find(_rename => _rename[0] === tableIdBefore); const tableIdAfter = rename ? rename[1] : tableIdBefore; if (tableIdAfter?.startsWith('-')) { return null; } return tableIdAfter; diff --git a/app/common/GranularAccessClause.ts b/app/common/GranularAccessClause.ts index 60a9b550..bc8a977c 100644 --- a/app/common/GranularAccessClause.ts +++ b/app/common/GranularAccessClause.ts @@ -78,7 +78,7 @@ export interface UserAttributeRule { * Check some key facts about the formula. */ export function getFormulaProperties(formula: ParsedAclFormula) { - const result: FormulaProperties = {} + const result: FormulaProperties = {}; if (usesRec(formula)) { result.hasRecOrNewRec = true; } const colIds = new Set(); collectRecColIds(formula, colIds); diff --git a/app/common/UserAPI.ts b/app/common/UserAPI.ts index ceb4ae4b..f229a80d 100644 --- a/app/common/UserAPI.ts +++ b/app/common/UserAPI.ts @@ -633,8 +633,8 @@ export class DocWorkerAPIImpl extends BaseAPI implements DocWorkerAPI { super(_options); } - public async importDocToWorkspace(uploadId: number, workspaceId: number, browserSettings?: BrowserSettings) - : Promise { + public async importDocToWorkspace(uploadId: number, workspaceId: number, browserSettings?: BrowserSettings): + Promise { return this.requestJson(`${this.url}/api/workspaces/${workspaceId}/import`, { method: 'POST', body: JSON.stringify({ uploadId, browserSettings }) diff --git a/app/common/gutil.ts b/app/common/gutil.ts index 7c2146eb..3f406a3a 100644 --- a/app/common/gutil.ts +++ b/app/common/gutil.ts @@ -121,9 +121,9 @@ type Undef = T extends [infer A, infer B, infer C, infer D] ? * Returns the first defined value from the list or unknown. * Use with typed result, so the typescript type checker can provide correct type. */ -export function undef>(...list : T): Undef { +export function undef>(...list: T): Undef { for(const value of list) { - if (value !== undefined) return value; + if (value !== undefined) { return value; } } return undefined as any; } @@ -853,7 +853,7 @@ export function isValidHex(val: string): boolean { */ export async function isLongerThan(promise: Promise, timeoutMsec: number): Promise { let isPending = true; - const done = () => {isPending = false; }; + const done = () => { isPending = false; }; await Promise.race([ promise.then(done, done), delay(timeoutMsec) diff --git a/app/common/marshal.ts b/app/common/marshal.ts index a54f4acd..9a95b959 100644 --- a/app/common/marshal.ts +++ b/app/common/marshal.ts @@ -126,34 +126,34 @@ export class WrappedObj { * communication with PyPy-based sandbox.) */ export class Marshaller { - private memBuf: MemBuffer; - private readonly floatCode: number; - private readonly stringCode: number; + private _memBuf: MemBuffer; + private readonly _floatCode: number; + private readonly _stringCode: number; constructor(options?: MarshalOptions) { - this.memBuf = new MemBuffer(undefined); - this.floatCode = options && options.version && options.version >= 2 ? marshalCodes.BFLOAT : marshalCodes.FLOAT; - this.stringCode = options && options.stringToBuffer ? marshalCodes.STRING : marshalCodes.UNICODE; + this._memBuf = new MemBuffer(undefined); + this._floatCode = options && options.version && options.version >= 2 ? marshalCodes.BFLOAT : marshalCodes.FLOAT; + this._stringCode = options && options.stringToBuffer ? marshalCodes.STRING : marshalCodes.UNICODE; } public dump(): Uint8Array { // asByteArray returns a view on the underlying data, and the constructor creates a new copy. // For some usages, we may want to avoid making the copy. - const bytes = new Uint8Array(this.memBuf.asByteArray()); - this.memBuf.clear(); + const bytes = new Uint8Array(this._memBuf.asByteArray()); + this._memBuf.clear(); return bytes; } public dumpAsBuffer(): Buffer { - const bytes = Buffer.from(this.memBuf.asByteArray()); - this.memBuf.clear(); + const bytes = Buffer.from(this._memBuf.asByteArray()); + this._memBuf.clear(); return bytes; } public getCode(value: any) { switch (typeof value) { - case 'number': return isInteger(value) ? marshalCodes.INT : this.floatCode; - case 'string': return this.stringCode; + case 'number': return isInteger(value) ? marshalCodes.INT : this._floatCode; + case 'string': return this._stringCode; case 'boolean': return value ? marshalCodes.TRUE : marshalCodes.FALSE; case 'undefined': return marshalCodes.NONE; case 'object': { @@ -181,16 +181,16 @@ export class Marshaller { if (value instanceof WrappedObj) { value = value.value; } - this.memBuf.writeUint8(code); + this._memBuf.writeUint8(code); switch (code) { case marshalCodes.NULL: return; case marshalCodes.NONE: return; case marshalCodes.FALSE: return; case marshalCodes.TRUE: return; - case marshalCodes.INT: return this.memBuf.writeInt32LE(value); + case marshalCodes.INT: return this._memBuf.writeInt32LE(value); case marshalCodes.INT64: return this._writeInt64(value); case marshalCodes.FLOAT: return this._writeStringFloat(value); - case marshalCodes.BFLOAT: return this.memBuf.writeFloat64LE(value); + case marshalCodes.BFLOAT: return this._memBuf.writeFloat64LE(value); case marshalCodes.STRING: return (value instanceof Uint8Array || Buffer.isBuffer(value) ? this._writeByteArray(value) : @@ -219,8 +219,8 @@ export class Marshaller { // TODO We could actually support 53 bits or so. throw new Error("Marshaller: int64 still only supports 32-bit ints for now: " + value); } - this.memBuf.writeInt32LE(value); - this.memBuf.writeInt32LE(value >= 0 ? 0 : -1); + this._memBuf.writeInt32LE(value); + this._memBuf.writeInt32LE(value >= 0 ? 0 : -1); } private _writeStringFloat(value: number) { @@ -230,28 +230,28 @@ export class Marshaller { if (bytes.byteLength >= 127) { throw new Error("Marshaller: Trying to write a float that takes " + bytes.byteLength + " bytes"); } - this.memBuf.writeUint8(bytes.byteLength); - this.memBuf.writeByteArray(bytes); + this._memBuf.writeUint8(bytes.byteLength); + this._memBuf.writeByteArray(bytes); } private _writeByteArray(value: Uint8Array|Buffer) { // This works for both Uint8Arrays and Node Buffers. - this.memBuf.writeInt32LE(value.length); - this.memBuf.writeByteArray(value); + this._memBuf.writeInt32LE(value.length); + this._memBuf.writeByteArray(value); } private _writeUtf8String(value: string) { - const offset = this.memBuf.size(); + const offset = this._memBuf.size(); // We don't know the length until we write the value. - this.memBuf.writeInt32LE(0); - this.memBuf.writeString(value); - const byteLength = this.memBuf.size() - offset - 4; + this._memBuf.writeInt32LE(0); + this._memBuf.writeString(value); + const byteLength = this._memBuf.size() - offset - 4; // Overwrite the 0 length we wrote earlier with the correct byte length. - this.memBuf.asDataView.setInt32(this.memBuf.startPos + offset, byteLength, true); + this._memBuf.asDataView.setInt32(this._memBuf.startPos + offset, byteLength, true); } private _writeList(array: unknown[]) { - this.memBuf.writeInt32LE(array.length); + this._memBuf.writeInt32LE(array.length); for (const item of array) { this.marshal(item); } @@ -264,7 +264,7 @@ export class Marshaller { this.marshal(key); this.marshal(obj[key]); } - this.memBuf.writeUint8(marshalCodes.NULL); + this._memBuf.writeUint8(marshalCodes.NULL); } } @@ -283,17 +283,17 @@ const TwoTo15 = 0x8000; // 2**15 */ export class Unmarshaller extends EventEmitter { public memBuf: MemBuffer; - private consumer: any = null; + private _consumer: any = null; private _lastCode: number|null = null; - private readonly bufferToString: boolean; - private emitter: (v: any) => boolean; - private stringTable: Array = []; + private readonly _bufferToString: boolean; + private _emitter: (v: any) => boolean; + private _stringTable: Array = []; constructor(options?: UnmarshalOptions) { super(); this.memBuf = new MemBuffer(undefined); - this.bufferToString = Boolean(options && options.bufferToString); - this.emitter = this.emit.bind(this, 'value'); + this._bufferToString = Boolean(options && options.bufferToString); + this._emitter = this.emit.bind(this, 'value'); } /** @@ -301,7 +301,7 @@ export class Unmarshaller extends EventEmitter { * @param {Uint8Array|Buffer} byteArray: Uint8Array or Node Buffer with bytes to parse. */ public push(byteArray: Uint8Array|Buffer) { - this.parse(byteArray, this.emitter); + this.parse(byteArray, this._emitter); } /** @@ -312,13 +312,13 @@ export class Unmarshaller extends EventEmitter { this.memBuf.writeByteArray(byteArray); try { while (this.memBuf.size() > 0) { - this.consumer = this.memBuf.makeConsumer(); + this._consumer = this.memBuf.makeConsumer(); // Have to reset stringTable for interned strings before each top-level parse call. - this.stringTable.length = 0; + this._stringTable.length = 0; const value = this._parse(); - this.memBuf.consume(this.consumer); + this.memBuf.consume(this._consumer); if (valueCB(value) === false) { return; } @@ -341,7 +341,7 @@ export class Unmarshaller extends EventEmitter { } private _parse(): unknown { - const code = this.memBuf.readUint8(this.consumer); + const code = this.memBuf.readUint8(this._consumer); this._lastCode = code; switch (code) { case marshalCodes.NULL: return null; @@ -374,12 +374,12 @@ export class Unmarshaller extends EventEmitter { } private _parseInt() { - return this.memBuf.readInt32LE(this.consumer); + return this.memBuf.readInt32LE(this._consumer); } private _parseInt64() { - const low = this.memBuf.readInt32LE(this.consumer); - const hi = this.memBuf.readInt32LE(this.consumer); + const low = this.memBuf.readInt32LE(this._consumer); + const hi = this.memBuf.readInt32LE(this._consumer); if ((hi === 0 && low >= 0) || (hi === -1 && low < 0)) { return low; } @@ -395,46 +395,46 @@ export class Unmarshaller extends EventEmitter { private _parseLong() { // The format is a 32-bit size whose sign is the sign of the result, followed by 16-bit digits // in base 2**15. - const size = this.memBuf.readInt32LE(this.consumer); + const size = this.memBuf.readInt32LE(this._consumer); const sign = size < 0 ? -1 : 1; const numDigits = size < 0 ? -size : size; const digits = []; for (let i = 0; i < numDigits; i++) { - digits.push(this.memBuf.readInt16LE(this.consumer)); + digits.push(this.memBuf.readInt16LE(this._consumer)); } return new BigInt(TwoTo15, digits, sign).toNative(); } private _parseStringFloat() { - const len = this.memBuf.readUint8(this.consumer); - const buf = this.memBuf.readString(this.consumer, len); + const len = this.memBuf.readUint8(this._consumer); + const buf = this.memBuf.readString(this._consumer, len); return parseFloat(buf); } private _parseBinaryFloat() { - return this.memBuf.readFloat64LE(this.consumer); + return this.memBuf.readFloat64LE(this._consumer); } private _parseByteString(): string|Uint8Array { - const len = this.memBuf.readInt32LE(this.consumer); - return (this.bufferToString ? - this.memBuf.readString(this.consumer, len) : - this.memBuf.readByteArray(this.consumer, len)); + const len = this.memBuf.readInt32LE(this._consumer); + return (this._bufferToString ? + this.memBuf.readString(this._consumer, len) : + this.memBuf.readByteArray(this._consumer, len)); } private _parseInterned() { const s = this._parseByteString(); - this.stringTable.push(s); + this._stringTable.push(s); return s; } private _parseStringRef() { const index = this._parseInt(); - return this.stringTable[index]; + return this._stringTable[index]; } private _parseList() { - const len = this.memBuf.readInt32LE(this.consumer); + const len = this.memBuf.readInt32LE(this._consumer); const value = []; for (let i = 0; i < len; i++) { value[i] = this._parse(); @@ -461,8 +461,8 @@ export class Unmarshaller extends EventEmitter { } private _parseUnicode() { - const len = this.memBuf.readInt32LE(this.consumer); - return this.memBuf.readString(this.consumer, len); + const len = this.memBuf.readInt32LE(this._consumer); + return this.memBuf.readString(this._consumer, len); } } diff --git a/app/gen-server/ApiServer.ts b/app/gen-server/ApiServer.ts index a8d982cf..67eab7e7 100644 --- a/app/gen-server/ApiServer.ts +++ b/app/gen-server/ApiServer.ts @@ -364,7 +364,7 @@ export class ApiServer { const userId = getAuthorizedUserId(req); await this._dbManager.connection.transaction(async manager => { const user = await manager.findOne(User, userId); - if (!user) {return handleDeletedUser(); } + if (!user) { return handleDeletedUser(); } user.apiKey = null; await manager.save(User, user); }); diff --git a/app/gen-server/lib/DocWorkerMap.ts b/app/gen-server/lib/DocWorkerMap.ts index a692d906..d2226781 100644 --- a/app/gen-server/lib/DocWorkerMap.ts +++ b/app/gen-server/lib/DocWorkerMap.ts @@ -337,9 +337,9 @@ export class DocWorkerMap implements IDocWorkerMap { if (docId === 'import') { const lock = await this._redlock.lock(`workers-lock`, LOCK_TIMEOUT); try { - const workerId = await this._client.srandmemberAsync(`workers-available-default`); - if (!workerId) { throw new Error('no doc worker available'); } - const docWorker = await this._client.hgetallAsync(`worker-${workerId}`) as DocWorkerInfo|null; + const _workerId = await this._client.srandmemberAsync(`workers-available-default`); + if (!_workerId) { throw new Error('no doc worker available'); } + const docWorker = await this._client.hgetallAsync(`worker-${_workerId}`) as DocWorkerInfo|null; if (!docWorker) { throw new Error('no doc worker contact info available'); } return { docMD5: null, diff --git a/app/plugin/grist-plugin-api.ts b/app/plugin/grist-plugin-api.ts index 1325631e..0812753c 100644 --- a/app/plugin/grist-plugin-api.ts +++ b/app/plugin/grist-plugin-api.ts @@ -172,7 +172,7 @@ if (typeof window !== 'undefined') { // running under mocha. For now, we only provide a disfunctional implementation. It allows // plugins to call methods like registerFunction() without failing, so that plugin code may be // imported, but the methods don't do anything useful. - rpc.setSendMessage((data) => {return; }); + rpc.setSendMessage((data) => { return; }); } function createRpcLogger(): IRpcLogger { diff --git a/app/server/lib/ExternalStorage.ts b/app/server/lib/ExternalStorage.ts index 87bd5157..7a399b9b 100644 --- a/app/server/lib/ExternalStorage.ts +++ b/app/server/lib/ExternalStorage.ts @@ -188,11 +188,13 @@ export class ChecksummedExternalStorage implements ExternalStorage { if (!snapshotIds) { await this._options.latestVersion.save(key, DELETED_TOKEN); await this._options.sharedHash.save(key, DELETED_TOKEN); - } else for (const snapshotId of snapshotIds) { - // Removing snapshots breaks their partial immutability, so we mark them - // as deleted in redis so that we don't get stale info from S3 if we check - // for their existence. Nothing currently depends on this in practice. - await this._options.sharedHash.save(this._keyWithSnapshot(key, snapshotId), DELETED_TOKEN); + } else { + for (const snapshotId of snapshotIds) { + // Removing snapshots breaks their partial immutability, so we mark them + // as deleted in redis so that we don't get stale info from S3 if we check + // for their existence. Nothing currently depends on this in practice. + await this._options.sharedHash.save(this._keyWithSnapshot(key, snapshotId), DELETED_TOKEN); + } } } catch (err) { log.error("ext %s delete: %s failure to remove, error %s", this.label, key, err.message); diff --git a/app/server/lib/FlexServer.ts b/app/server/lib/FlexServer.ts index 4c7e2038..8a852175 100644 --- a/app/server/lib/FlexServer.ts +++ b/app/server/lib/FlexServer.ts @@ -907,7 +907,7 @@ export class FlexServer implements GristServer { this.tagChecker.requireTag ]; - this.addSupportPaths(docAccessMiddleware); + this._addSupportPaths(docAccessMiddleware); if (!isSingleUserMode()) { addDocApiRoutes(this.app, docWorker, this._docWorkerMap, docManager, this.dbManager, this); @@ -1081,8 +1081,8 @@ export class FlexServer implements GristServer { ); const config = {errPage, errMessage: err.message || err}; await this._sendAppPage(req, resp, {path: 'error.html', status: err.status || 400, config}); - } catch (err) { - return next(err); + } catch (error) { + return next(error); } }); } @@ -1183,7 +1183,7 @@ export class FlexServer implements GristServer { } // Adds endpoints that support imports and exports. - private addSupportPaths(docAccessMiddleware: express.RequestHandler[]) { + private _addSupportPaths(docAccessMiddleware: express.RequestHandler[]) { if (!this._docWorker) { throw new Error("need DocWorker"); } this.app.get('/download', ...docAccessMiddleware, expressWrap(async (req, res) => { diff --git a/app/server/lib/GranularAccess.ts b/app/server/lib/GranularAccess.ts index 5c296069..7a03cde8 100644 --- a/app/server/lib/GranularAccess.ts +++ b/app/server/lib/GranularAccess.ts @@ -598,7 +598,7 @@ export class GranularAccess implements GranularAccessForBundle { const message = { actionGroup, docActions }; await this._docClients.broadcastDocMessage(client, 'docUserAction', message, - (docSession) => this._filterDocUpdate(docSession, message)); + (_docSession) => this._filterDocUpdate(_docSession, message)); } /** @@ -786,21 +786,21 @@ export class GranularAccess implements GranularAccessForBundle { // If the column is not row dependent, we have nothing to do. if (access.getColumnAccess(tableId, colId).perms.read !== 'mixed') { continue; } // Check column accessibility before and after. - const forbiddenBefores = new Set(await this._getForbiddenRows(cursor, rowsBefore, ids, colId)); - const forbiddenAfters = new Set(await this._getForbiddenRows(cursor, rowsAfter, ids, colId)); + const _forbiddenBefores = new Set(await this._getForbiddenRows(cursor, rowsBefore, ids, colId)); + const _forbiddenAfters = new Set(await this._getForbiddenRows(cursor, rowsAfter, ids, colId)); // For any column that is in a visible row and for which accessibility has changed, // pull it into the doc actions. We don't censor cells yet, that happens later // (if that's what needs doing). const changedIds = orderedIds.filter(id => !forceRemoves.has(id) && !removals.has(id) && - (forbiddenBefores.has(id) !== forbiddenAfters.has(id))); + (_forbiddenBefores.has(id) !== _forbiddenAfters.has(id))); if (changedIds.length > 0) { revisedDocActions.push(this._makeColumnUpdate(rowsAfter, colId, new Set(changedIds))); } } // Return the results, also applying any cell-level access control. - for (const action of revisedDocActions) { - await this._filterRowsAndCells({...cursor, action}, rowsAfter, rowsAfter, readAccessCheck); + for (const a of revisedDocActions) { + await this._filterRowsAndCells({...cursor, action: a}, rowsAfter, rowsAfter, readAccessCheck); } return revisedDocActions; } @@ -1656,7 +1656,7 @@ export const accessChecks = { const readAccessCheck = accessChecks.check.read; // This AccessCheck allows everything. -const dummyAccessCheck = { get() { return 'allow'; } } +const dummyAccessCheck = { get() { return 'allow'; } }; /** diff --git a/app/server/lib/HostedStorageManager.ts b/app/server/lib/HostedStorageManager.ts index 3c6e6222..cfe6fb0d 100644 --- a/app/server/lib/HostedStorageManager.ts +++ b/app/server/lib/HostedStorageManager.ts @@ -681,7 +681,7 @@ export class HostedStorageManager implements IDocStorageManager { lastModified: t, snapshotId: newSnapshotId, metadata - } + }; await this._inventory.add(docId, snapshot, prevSnapshotId); await this._onInventoryChange(docId); } finally { diff --git a/app/server/lib/PluginManager.ts b/app/server/lib/PluginManager.ts index bb78debb..c377306d 100644 --- a/app/server/lib/PluginManager.ts +++ b/app/server/lib/PluginManager.ts @@ -51,7 +51,7 @@ export class PluginManager { }; } - public dirs(): PluginDirectories {return this._dirs; } + public dirs(): PluginDirectories { return this._dirs; } /** * Create tmp dir and load plugins. diff --git a/app/server/lib/RowAccess.ts b/app/server/lib/RowAccess.ts index f743b323..92975504 100644 --- a/app/server/lib/RowAccess.ts +++ b/app/server/lib/RowAccess.ts @@ -27,7 +27,7 @@ export function getRelatedRows(docActions: DocAction[]): ReadonlyArray { const rebaseQueue: Deque = new Deque(); try { - this.createCheckpoint(); + this._createCheckpoint(); const actions: LocalActionBundle[] = await this._actionHistory.fetchAllLocal(); assert(actions.length > 0); - await this.doApplyUserActionBundle(this._createUndo(actions), null); + await this._doApplyUserActionBundle(this._createUndo(actions), null); rebaseQueue.push(...actions.map((a) => getUserActionBundle(a))); await this._actionHistory.clearLocalActions(); } catch (e) { log.error("Can't undo local actions; sharing is off"); - this.rollbackToCheckpoint(); + this._rollbackToCheckpoint(); // TODO this.disconnect(); // TODO errorState = true; return; @@ -178,34 +178,34 @@ export class Sharing { const action: UserActionBundle = rebaseQueue.shift()!; const adjusted: UserActionBundle = this._mergeAdjust(action); try { - await this.doApplyUserActionBundle(adjusted, null); + await this._doApplyUserActionBundle(adjusted, null); } catch (e) { log.warn("Unable to apply rebased action..."); rebaseFailures.push([action, adjusted]); } } if (rebaseFailures.length > 0) { - this.createBackupAtCheckpoint(); + this._createBackupAtCheckpoint(); // TODO we should notify the user too. log.error('Rebase failed to reapply some of your actions, backup of local at...'); } - this.releaseCheckpoint(); + this._releaseCheckpoint(); } // ====================================================================== - private doApplySharedActionBundle(action: ActionBundle): Promise { + private _doApplySharedActionBundle(action: ActionBundle): Promise { const userActions: UserAction[] = [ ['ApplyDocActions', action.stored.map(envContent => envContent[1])] ]; - return this.doApplyUserActions(action.info[1], userActions, Branch.Shared, null); + return this._doApplyUserActions(action.info[1], userActions, Branch.Shared, null); } - private doApplyUserActionBundle(action: UserActionBundle, docSession: OptDocSession|null): Promise { - return this.doApplyUserActions(action.info, action.userActions, Branch.Local, docSession); + private _doApplyUserActionBundle(action: UserActionBundle, docSession: OptDocSession|null): Promise { + return this._doApplyUserActions(action.info, action.userActions, Branch.Local, docSession); } - private async doApplyUserActions(info: ActionInfo, userActions: UserAction[], + private async _doApplyUserActions(info: ActionInfo, userActions: UserAction[], branch: Branch, docSession: OptDocSession|null): Promise { const client = docSession && docSession.client; @@ -245,7 +245,7 @@ export class Sharing { actionHash: null, // Gets set below by _actionHistory.recordNext... parentActionHash: null, // Gets set below by _actionHistory.recordNext... }; - this._logActionBundle(`doApplyUserActions (${Branch[branch]})`, localActionBundle); + this._logActionBundle(`_doApplyUserActions (${Branch[branch]})`, localActionBundle); // TODO Note that the sandbox may produce actions which are not addressed to us (e.g. when we // have EDIT permission without VIEW). These are not sent to the browser or the database. But @@ -332,10 +332,10 @@ export class Sharing { } // Our beautiful little checkpointing interface, used to handle errors during rebase. - private createCheckpoint() { /* TODO */ } - private releaseCheckpoint() { /* TODO */ } - private rollbackToCheckpoint() { /* TODO */ } - private createBackupAtCheckpoint() { /* TODO */ } + private _createCheckpoint() { /* TODO */ } + private _releaseCheckpoint() { /* TODO */ } + private _rollbackToCheckpoint() { /* TODO */ } + private _createBackupAtCheckpoint() { /* TODO */ } /** * Reduces a LocalActionBundle down to only those actions addressed to ourselves. diff --git a/app/server/lib/gristSessions.ts b/app/server/lib/gristSessions.ts index 7301cc0d..7fa11541 100644 --- a/app/server/lib/gristSessions.ts +++ b/app/server/lib/gristSessions.ts @@ -61,7 +61,7 @@ function createSessionStoreFactory(sessionsDB: string): () => SessionStore { // Doesn't actually close, just unrefs stream so node becomes close-able. store.client.unref(); }}); - } + }; } else { const SQLiteStore = require('@gristlabs/connect-sqlite3')(session); promisifyAll(SQLiteStore.prototype); @@ -72,7 +72,7 @@ function createSessionStoreFactory(sessionsDB: string): () => SessionStore { table: 'sessions' }); return assignIn(store, { async close() {}}); - } + }; } } diff --git a/app/server/lib/serverUtils.ts b/app/server/lib/serverUtils.ts index bbebc5b8..5e07173a 100644 --- a/app/server/lib/serverUtils.ts +++ b/app/server/lib/serverUtils.ts @@ -49,7 +49,7 @@ export function getAvailablePort(firstPort: number = 8000, optCount: number = 20 export function connect(options: { port: number, host?: string, localAddress?: string, localPort?: string, family?: number, allowHalfOpen?: boolean; }): Promise; export function connect(port: number, host?: string): Promise; -export function connect(path: string): Promise; // tslint:disable-line:unified-signatures +export function connect(sockPath: string): Promise; export function connect(arg: any, ...moreArgs: any[]): Promise { return new Promise((resolve, reject) => { const s = net.connect(arg, ...moreArgs, () => resolve(s)); diff --git a/test/nbrowser/gristUtils.ts b/test/nbrowser/gristUtils.ts index c9747f1c..b766979d 100644 --- a/test/nbrowser/gristUtils.ts +++ b/test/nbrowser/gristUtils.ts @@ -1333,8 +1333,9 @@ export class Session { const api = this.createHomeApi(); if (!noCleanup) { cleanup.addAfterEach(async () => { - if (doc.id) + if (doc.id) { await api.deleteDoc(doc.id).catch(noop); + } doc.id = ''; }); }