diff --git a/frontend/common/Binder.js b/frontend/common/Binder.js index 1e7a6bea6d..21c9842dd9 100644 --- a/frontend/common/Binder.js +++ b/frontend/common/Binder.js @@ -1,4 +1,4 @@ -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import { timeout_promise, ws_address_from_base } from "./PlutoConnection.js" import { with_query_params } from "./URLTools.js" @@ -95,7 +95,7 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) // view stats on https://stats.plutojl.org/ count_stat(`binder-start`) await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.backend_launch_phase = BackendLaunchPhase.requesting state.disable_ui = false // Clear the Status of the process that generated the HTML @@ -107,7 +107,7 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) const { binder_session_url, binder_session_token } = await request_binder(launch_params.binder_url.replace("mybinder.org/v2/", "mybinder.org/build/"), { on_log: (logs) => setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.backend_launch_logs = logs }) ), @@ -122,7 +122,7 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) } await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.backend_launch_phase = BackendLaunchPhase.created state.binder_session_url = binder_session_url state.binder_session_token = binder_session_token @@ -133,7 +133,7 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) await fetch(with_token(binder_session_url)) await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.backend_launch_phase = BackendLaunchPhase.responded }) ) @@ -197,7 +197,7 @@ export const start_binder = async ({ setStatePromise, connect, launch_params }) console.info("notebook_id:", new_notebook_id) await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.notebook.notebook_id = new_notebook_id state.backend_launch_phase = BackendLaunchPhase.notebook_running state.refresh_target = edit_url diff --git a/frontend/common/RunLocal.js b/frontend/common/RunLocal.js index 2acdb33f06..b43e8b90b5 100644 --- a/frontend/common/RunLocal.js +++ b/frontend/common/RunLocal.js @@ -1,4 +1,4 @@ -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import { BackendLaunchPhase } from "./Binder.js" import { timeout_promise } from "./PlutoConnection.js" import { with_query_params } from "./URLTools.js" @@ -18,7 +18,7 @@ export const start_local = async ({ setStatePromise, connect, launch_params }) = if (launch_params.pluto_server_url == null || launch_params.notebookfile == null) throw Error("Invalid launch parameters for starting locally.") await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.backend_launch_phase = BackendLaunchPhase.responded state.disable_ui = false // Clear the Status of the process that generated the HTML @@ -63,7 +63,7 @@ export const start_local = async ({ setStatePromise, connect, launch_params }) = window.history.replaceState({}, "", edit_url) await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { state.notebook.notebook_id = new_notebook_id state.backend_launch_phase = BackendLaunchPhase.notebook_running }) diff --git a/frontend/common/SliderServerClient.js b/frontend/common/SliderServerClient.js index a08f9f3815..40403a8cfa 100644 --- a/frontend/common/SliderServerClient.js +++ b/frontend/common/SliderServerClient.js @@ -1,7 +1,7 @@ import { trailingslash } from "./Binder.js" import { plutohash_arraybuffer, debounced_promises, base64url_arraybuffer } from "./PlutoHash.js" import { pack, unpack } from "./MsgPack.js" -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import _ from "../imports/lodash.js" const assert_response_ok = (/** @type {Response} */ r) => (r.ok ? r : Promise.reject(r)) @@ -39,19 +39,9 @@ export const nothing_actions = ({ actions }) => ]) ) -/** - * @param {{ - * setStatePromise: any, - * launch_params: import("../components/Editor.js").LaunchParameters, - * actions: any, - * get_original_state: () => import("../components/Editor.js").NotebookData, - * get_current_state: () => import("../components/Editor.js").NotebookData, - * apply_notebook_patches: (patches: import("../imports/immer.js").Patch[], old_state?: import("../components/Editor.js").NotebookData?, get_reverse_patches?: boolean) => Promise, - * }} props - */ export const slider_server_actions = ({ setStatePromise, launch_params, actions, get_original_state, get_current_state, apply_notebook_patches }) => { setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((state) => { state.slider_server.connecting = true }) ) @@ -72,7 +62,7 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, bond_connections.then((x) => { console.log("Bond connections:", x) setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((state) => { state.slider_server.connecting = false state.slider_server.interactive = Object.keys(x).length > 0 }) @@ -95,7 +85,7 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, const update_cells_running = async (running) => await setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((state) => { running_cells.forEach((cell_id) => (state.notebook.cell_results[cell_id][starts.has(cell_id) ? "running" : "queued"] = running)) }) ) @@ -138,12 +128,12 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, await apply_notebook_patches( patches, - produce(get_current_state(), (state) => { + immer((state) => { const original = get_original_state() ids_of_cells_that_ran.forEach((id) => { state.cell_results[id] = original.cell_results[id] }) - }) + })(get_current_state()) ) } catch (e) { console.error(unpacked, e) @@ -158,7 +148,7 @@ export const slider_server_actions = ({ setStatePromise, launch_params, actions, ...nothing_actions({ actions }), set_bond: async (symbol, value) => { setStatePromise( - produce((/** @type {import("../components/Editor.js").EditorState} */ state) => { + immer((state) => { state.notebook.bonds[symbol] = { value: value } }) ) diff --git a/frontend/components/Editor.js b/frontend/components/Editor.js index c063a1712f..b6cc050877 100644 --- a/frontend/components/Editor.js +++ b/frontend/components/Editor.js @@ -1,6 +1,6 @@ import { html, Component } from "../imports/Preact.js" import * as preact from "../imports/Preact.js" -import { produce, applyPatches, produceWithPatches } from "../imports/immer.js" +import immer, { applyPatches, produceWithPatches } from "../imports/immer.js" import _ from "../imports/lodash.js" import { empty_notebook_state, set_disable_ui_css } from "../editor.js" @@ -20,7 +20,7 @@ import { Scroller } from "./Scroller.js" import { ExportBanner } from "./ExportBanner.js" import { Popup } from "./Popup.js" -import { slice_utf8 } from "../common/UnicodeTools.js" +import { slice_utf8, length_utf8 } from "../common/UnicodeTools.js" import { has_ctrl_or_cmd_pressed, ctrl_or_cmd_name, @@ -297,10 +297,6 @@ export const url_logo_small = document.head.querySelector("link[rel='pluto-logo- * extended_components: any, * is_recording: boolean, * recording_waiting_to_start: boolean, - * slider_server: { - * connecting: boolean, - * interactive: boolean, - * }, * }} */ @@ -369,7 +365,7 @@ export class Editor extends Component { set_doc_query: (query) => this.setState({ desired_doc_query: query }), set_local_cell: (cell_id, new_val) => { return this.setStatePromise( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { state.cell_inputs_local[cell_id] = { code: new_val, } @@ -426,7 +422,7 @@ export class Editor extends Component { * See ** 1 ** */ this.setState( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { // Deselect everything first, to clean things up state.selected_cells = [] @@ -464,7 +460,7 @@ export class Editor extends Component { const new_code = `${block_start}\n\t${cell.code.replace(/\n/g, "\n\t")}\n${block_end}` await this.setStatePromise( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { state.cell_inputs_local[cell_id] = { code: new_code, } @@ -492,7 +488,7 @@ export class Editor extends Component { }) this.setState( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { for (let cell of cells_to_add) { state.cell_inputs_local[cell.cell_id] = cell } @@ -621,7 +617,7 @@ export class Editor extends Component { // This is a "dirty" trick, as this should actually be stored in some shared request_status => status state // But for now... this is fine 😼 await this.setStatePromise( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { for (let cell_id of cell_ids) { if (state.notebook.cell_results[cell_id] != null) { state.notebook.cell_results[cell_id].queued = this.is_process_ready() @@ -695,7 +691,7 @@ export class Editor extends Component { let _copy_of_patches, reverse_of_patches = [] this.setState( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { let new_notebook try { // To test this, uncomment the lines below: @@ -1181,7 +1177,7 @@ all patches: ${JSON.stringify(patches, null, 1)} window.plutoDesktop?.ipcRenderer.once("PLUTO-MOVE-NOTEBOOK", async (/** @type {string?} */ loc) => { if (!!loc) await this.setStatePromise( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { state.notebook.in_temp_dir = false state.notebook.path = loc }) @@ -1651,7 +1647,7 @@ The notebook file saves every time you run a cell.` apply_notebook_patches=${this.apply_notebook_patches} reset_notebook_state=${() => this.setStatePromise( - produce((/** @type {EditorState} */ state) => { + immer((/** @type {EditorState} */ state) => { state.notebook = this.props.initial_notebook_state }) )} diff --git a/frontend/components/Editor/LaunchBackendButton.js b/frontend/components/Editor/LaunchBackendButton.js index 51b03b84c5..e835a5e2eb 100644 --- a/frontend/components/Editor/LaunchBackendButton.js +++ b/frontend/components/Editor/LaunchBackendButton.js @@ -1,15 +1,15 @@ -import { html, useMemo } from "../../imports/Preact.js" +import { html, useMemo, useEffect } from "../../imports/Preact.js" import * as preact from "../../imports/Preact.js" import { RunLocalButton, BinderButton } from "../EditOrRunButton.js" import { start_local } from "../../common/RunLocal.js" import { BackendLaunchPhase, start_binder } from "../../common/Binder.js" -import { produce } from "../../imports/immer.js" +import immer, { applyPatches, produceWithPatches } from "../../imports/immer.js" export const EditorLaunchBackendButton = ({ editor, launch_params, status }) => { try { const EnvRun = useMemo( // @ts-ignore - () => window?.pluto_injected_environment?.environment?.({ client: editor.client, editor, imports: { immer: produce, preact } })?.custom_run_or_edit, + () => window?.pluto_injected_environment?.environment?.({ client: editor.client, editor, imports: { immer, preact } })?.custom_run_or_edit, [editor.client, editor] ) // @ts-ignore diff --git a/frontend/components/FrontmatterInput.js b/frontend/components/FrontmatterInput.js index c5ede6c610..e278036aa5 100644 --- a/frontend/components/FrontmatterInput.js +++ b/frontend/components/FrontmatterInput.js @@ -5,7 +5,7 @@ import _ from "../imports/lodash.js" import "https://cdn.jsdelivr.net/gh/fonsp/rebel-tag-input@1.0.6/lib/rebel-tag-input.mjs" //@ts-ignore -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import { useDialog } from "../common/useDialog.js" import { FeaturedCard } from "./welcome/FeaturedCard.js" import { useEventListener } from "../common/useEventListener.js" @@ -26,7 +26,7 @@ export const FrontMatterInput = ({ filename, remote_frontmatter, set_remote_fron const fm_setter = (key) => (value) => set_frontmatter( - produce((fm) => { + immer((fm) => { _.set(fm, key, value) }) ) @@ -87,7 +87,7 @@ export const FrontMatterInput = ({ filename, remote_frontmatter, set_remote_fron onClick=${() => { // TODO set_frontmatter( - produce((fm) => { + immer((fm) => { _.unset(fm, path) }) ) @@ -103,7 +103,7 @@ export const FrontMatterInput = ({ filename, remote_frontmatter, set_remote_fron const fieldname = prompt("Field name:") if (fieldname) { set_frontmatter( - produce((fm) => { + immer((fm) => { _.set(fm, `${base_path}${fieldname}`, null) }) ) diff --git a/frontend/components/LiveDocsTab.js b/frontend/components/LiveDocsTab.js index 4f985f48cc..96e41dc75c 100644 --- a/frontend/components/LiveDocsTab.js +++ b/frontend/components/LiveDocsTab.js @@ -1,5 +1,5 @@ import { html, useState, useRef, useLayoutEffect, useEffect, useMemo, useContext } from "../imports/Preact.js" -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import observablehq from "../common/SetupCellEnvironment.js" import { RawHTMLContainer, highlight } from "./CellOutput.js" @@ -26,7 +26,7 @@ export let LiveDocsTab = ({ focus_on_open, desired_doc_query, on_update_doc_quer body: `

Welcome to the Live docs! Keep this little window open while you work on the notebook, and you will get documentation of everything you type!

You can also type a query above.


Still stuck? Here are some tips.

`, loading: false, }) - let update_state = (mutation) => set_state(produce((state) => mutation(state))) + let update_state = (mutation) => set_state(immer((state) => mutation(state))) useEffect(() => { if (state.loading) { diff --git a/frontend/components/RecordingUI.js b/frontend/components/RecordingUI.js index 05d7502823..ebd170f7ba 100644 --- a/frontend/components/RecordingUI.js +++ b/frontend/components/RecordingUI.js @@ -2,7 +2,7 @@ import _ from "../imports/lodash.js" import { createSilentAudio, create_recorder } from "../common/AudioRecording.js" import { html, useEffect, useState, useRef, useCallback, useLayoutEffect, useMemo } from "../imports/Preact.js" import { AudioPlayer } from "./AudioPlayer.js" -import { produce } from "../imports/immer.js" +import immer from "../imports/immer.js" import { base64_arraybuffer, blob_url_to_data_url } from "../common/PlutoHash.js" import { pack, unpack } from "../common/MsgPack.js" diff --git a/frontend/imports/immer.d.ts b/frontend/imports/immer.d.ts index 9e2bc16de4..35884f8800 100644 --- a/frontend/imports/immer.d.ts +++ b/frontend/imports/immer.d.ts @@ -1,262 +1,19 @@ -/** - * The sentinel value returned by producers to replace the draft with undefined. - */ -declare const NOTHING: unique symbol; -/** - * To let Immer treat your class instances as plain immutable objects - * (albeit with a custom prototype), you must define either an instance property - * or a static property on each of your custom classes. - * - * Otherwise, your class instance will never be drafted, which means it won't be - * safe to mutate in a produce callback. - */ -declare const DRAFTABLE: unique symbol; - -type AnyFunc = (...args: any[]) => any; -type PrimitiveType = number | string | boolean; -/** Object types that should never be mapped */ -type AtomicObject = Function | Promise | Date | RegExp; -/** - * If the lib "ES2015.Collection" is not included in tsconfig.json, - * types like ReadonlyArray, WeakMap etc. fall back to `any` (specified nowhere) - * or `{}` (from the node types), in both cases entering an infinite recursion in - * pattern matching type mappings - * This type can be used to cast these types to `void` in these cases. - */ -type IfAvailable = true | false extends (T extends never ? true : false) ? Fallback : keyof T extends never ? Fallback : T; -/** - * These should also never be mapped but must be tested after regular Map and - * Set - */ -type WeakReferences = IfAvailable> | IfAvailable>; -type WritableDraft = { - -readonly [K in keyof T]: Draft; -}; -/** Convert a readonly type into a mutable type, if possible */ -type Draft = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap ? Map, Draft> : T extends ReadonlySet ? Set> : T extends WeakReferences ? T : T extends object ? WritableDraft : T; -/** Convert a mutable type into a readonly type */ -type Immutable = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap ? ReadonlyMap, Immutable> : T extends ReadonlySet ? ReadonlySet> : T extends WeakReferences ? T : T extends object ? { - readonly [K in keyof T]: Immutable; -} : T; -interface Patch { - op: "replace" | "remove" | "add"; - path: (string | number)[]; - value?: any; -} -type PatchListener = (patches: Patch[], inversePatches: Patch[]) => void; -/** - * Utility types - */ -type PatchesTuple = readonly [T, Patch[], Patch[]]; -type ValidRecipeReturnType = State | void | undefined | (State extends undefined ? typeof NOTHING : never); -type ReturnTypeWithPatchesIfNeeded = UsePatches extends true ? PatchesTuple : State; -/** - * Core Producer inference - */ -type InferRecipeFromCurried = Curried extends (base: infer State, ...rest: infer Args) => any ? ReturnType extends State ? (draft: Draft, ...rest: Args) => ValidRecipeReturnType> : never : never; -type InferInitialStateFromCurried = Curried extends (base: infer State, ...rest: any[]) => any ? State : never; -type InferCurriedFromRecipe = Recipe extends (draft: infer DraftState, ...args: infer RestArgs) => any ? ReturnType extends ValidRecipeReturnType ? (base: Immutable, ...args: RestArgs) => ReturnTypeWithPatchesIfNeeded : never : never; -type InferCurriedFromInitialStateAndRecipe = Recipe extends (draft: Draft, ...rest: infer RestArgs) => ValidRecipeReturnType ? (base?: State | undefined, ...args: RestArgs) => ReturnTypeWithPatchesIfNeeded : never; -/** - * The `produce` function takes a value and a "recipe function" (whose - * return value often depends on the base state). The recipe function is - * free to mutate its first argument however it wants. All mutations are - * only ever applied to a __copy__ of the base state. - * - * Pass only a function to create a "curried producer" which relieves you - * from passing the recipe function every time. - * - * Only plain objects and arrays are made mutable. All other objects are - * considered uncopyable. - * - * Note: This function is __bound__ to its `Immer` instance. - * - * @param {any} base - the initial state - * @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified - * @param {Function} patchListener - optional function that will be called with all the patches produced here - * @returns {any} a new state, or the initial state if nothing was modified - */ -interface IProduce { - /** Curried producer that infers the recipe from the curried output function (e.g. when passing to setState) */ - (recipe: InferRecipeFromCurried, initialState?: InferInitialStateFromCurried): Curried; - /** Curried producer that infers curried from the recipe */ - (recipe: Recipe): InferCurriedFromRecipe; - /** Curried producer that infers curried from the State generic, which is explicitly passed in. */ - (recipe: (state: Draft, initialState: State) => ValidRecipeReturnType): (state?: State) => State; - (recipe: (state: Draft, ...args: Args) => ValidRecipeReturnType, initialState: State): (state?: State, ...args: Args) => State; - (recipe: (state: Draft) => ValidRecipeReturnType): (state: State) => State; - (recipe: (state: Draft, ...args: Args) => ValidRecipeReturnType): (state: State, ...args: Args) => State; - /** Curried producer with initial state, infers recipe from initial state */ - (recipe: Recipe, initialState: State): InferCurriedFromInitialStateAndRecipe; - /** Normal producer */ - >(// By using a default inferred D, rather than Draft in the recipe, we can override it. - base: Base, recipe: (draft: D) => ValidRecipeReturnType, listener?: PatchListener): Base; +export type Patch = { + path: Array + op: "add" | "replace" | "remove" + value: any } -/** - * Like `produce`, but instead of just returning the new state, - * a tuple is returned with [nextState, patches, inversePatches] - * - * Like produce, this function supports currying - */ -interface IProduceWithPatches { - (recipe: Recipe): InferCurriedFromRecipe; - (recipe: Recipe, initialState: State): InferCurriedFromInitialStateAndRecipe; - >(base: Base, recipe: (draft: D) => ValidRecipeReturnType, listener?: PatchListener): PatchesTuple; -} -/** - * The type for `recipe function` - */ -type Producer = (draft: Draft) => ValidRecipeReturnType>; - -type Objectish = AnyObject | AnyArray | AnyMap | AnySet; -type AnyObject = { - [key: string]: any; -}; -type AnyArray = Array; -type AnySet = Set; -type AnyMap = Map; -/** Returns true if the given value is an Immer draft */ -declare function isDraft(value: any): boolean; -/** Returns true if the given value can be drafted by Immer */ -declare function isDraftable(value: any): boolean; -/** Get the underlying object that is represented by the given draft */ -declare function original(value: T): T | undefined; -/** - * Freezes draftable objects. Returns the original object. - * By default freezes shallowly, but if the second argument is `true` it will freeze recursively. - * - * @param obj - * @param deep - */ -declare function freeze(obj: T, deep?: boolean): T; - -interface ProducersFns { - produce: IProduce; - produceWithPatches: IProduceWithPatches; -} -type StrictMode = boolean | "class_only"; -declare class Immer implements ProducersFns { - autoFreeze_: boolean; - useStrictShallowCopy_: StrictMode; - constructor(config?: { - autoFreeze?: boolean; - useStrictShallowCopy?: StrictMode; - }); - /** - * The `produce` function takes a value and a "recipe function" (whose - * return value often depends on the base state). The recipe function is - * free to mutate its first argument however it wants. All mutations are - * only ever applied to a __copy__ of the base state. - * - * Pass only a function to create a "curried producer" which relieves you - * from passing the recipe function every time. - * - * Only plain objects and arrays are made mutable. All other objects are - * considered uncopyable. - * - * Note: This function is __bound__ to its `Immer` instance. - * - * @param {any} base - the initial state - * @param {Function} recipe - function that receives a proxy of the base state as first argument and which can be freely modified - * @param {Function} patchListener - optional function that will be called with all the patches produced here - * @returns {any} a new state, or the initial state if nothing was modified - */ - produce: IProduce; - produceWithPatches: IProduceWithPatches; - createDraft(base: T): Draft; - finishDraft>(draft: D, patchListener?: PatchListener): D extends Draft ? T : never; - /** - * Pass true to automatically freeze all copies created by Immer. - * - * By default, auto-freezing is enabled. - */ - setAutoFreeze(value: boolean): void; - /** - * Pass true to enable strict shallow copy. - * - * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties. - */ - setUseStrictShallowCopy(value: StrictMode): void; - applyPatches(base: T, patches: readonly Patch[]): T; -} +// type PatchesCallback = (patches: Array, inversePatch: Array) => void -/** Takes a snapshot of the current state of a draft and finalizes it (but without freezing). This is a great utility to print the current state during debugging (no Proxies in the way). The output of current can also be safely leaked outside the producer. */ -declare function current(value: T): T; +declare function produce(value: T, mutator: (draft: T) => void | T): T +declare function produce(mutator: (draft: T) => void | T): (value: T) => T -declare function enablePatches(): void; +export default produce -declare function enableMapSet(): void; +declare function applyPatches(value: T, patches: Array): T -/** - * The `produce` function takes a value and a "recipe function" (whose - * return value often depends on the base state). The recipe function is - * free to mutate its first argument however it wants. All mutations are - * only ever applied to a __copy__ of the base state. - * - * Pass only a function to create a "curried producer" which relieves you - * from passing the recipe function every time. - * - * Only plain objects and arrays are made mutable. All other objects are - * considered uncopyable. - * - * Note: This function is __bound__ to its `Immer` instance. - * - * @param {any} base - the initial state - * @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified - * @param {Function} patchListener - optional function that will be called with all the patches produced here - * @returns {any} a new state, or the initial state if nothing was modified - */ -declare const produce: IProduce; -/** - * Like `produce`, but `produceWithPatches` always returns a tuple - * [nextState, patches, inversePatches] (instead of just the next state) - */ -declare const produceWithPatches: IProduceWithPatches; -/** - * Pass true to automatically freeze all copies created by Immer. - * - * Always freeze by default, even in production mode - */ -declare const setAutoFreeze: (value: boolean) => void; -/** - * Pass true to enable strict shallow copy. - * - * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties. - */ -declare const setUseStrictShallowCopy: (value: StrictMode) => void; -/** - * Apply an array of Immer patches to the first argument. - * - * This function is a producer, which means copy-on-write is in effect. - */ -declare const applyPatches: (base: T, patches: readonly Patch[]) => T; -/** - * Create an Immer draft from the given base state, which may be a draft itself. - * The draft can be modified until you finalize it with the `finishDraft` function. - */ -declare const createDraft: (base: T) => Draft; -/** - * Finalize an Immer draft from a `createDraft` call, returning the base state - * (if no changes were made) or a modified copy. The draft must *not* be - * mutated afterwards. - * - * Pass a function as the 2nd argument to generate Immer patches based on the - * changes that were made. - */ -declare const finishDraft: (draft: D, patchListener?: PatchListener | undefined) => D extends Draft ? T : never; -/** - * This function is actually a no-op, but can be used to cast an immutable type - * to an draft type and make TypeScript happy - * - * @param value - */ -declare function castDraft(value: T): Draft; -/** - * This function is actually a no-op, but can be used to cast a mutable type - * to an immutable type and make TypeScript happy - * @param value - */ -declare function castImmutable(value: T): Immutable; +export { applyPatches } -export { Draft, Immer, Immutable, Objectish, Patch, PatchListener, Producer, StrictMode, WritableDraft, applyPatches, castDraft, castImmutable, createDraft, current, enableMapSet, enablePatches, finishDraft, freeze, DRAFTABLE as immerable, isDraft, isDraftable, NOTHING as nothing, original, produce, produceWithPatches, setAutoFreeze, setUseStrictShallowCopy }; \ No newline at end of file +declare function produceWithPatches(value: T, mutator: (draft: T) => void | T): [T, Array, Array] +export { produceWithPatches } diff --git a/frontend/imports/immer.js b/frontend/imports/immer.js index 0281a7f3d6..aec3b510ac 100644 --- a/frontend/imports/immer.js +++ b/frontend/imports/immer.js @@ -1,6 +1,8 @@ // @ts-nocheck -export { produce, produceWithPatches, applyPatches } from "https://cdn.jsdelivr.net/npm/immer@10.1.1/dist/immer.mjs" -import { enablePatches, setAutoFreeze } from "https://cdn.jsdelivr.net/npm/immer@10.1.1/dist/immer.mjs" +import immer, { produceWithPatches, applyPatches, enablePatches, setAutoFreeze } from "https://cdn.jsdelivr.net/npm/immer@8.0.0/dist/immer.esm.js" + +export { applyPatches, produceWithPatches } +export default immer enablePatches()