Export (#213)
* initial Signed-off-by: Jess Frazelle <github@jessfraz.com> update Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * start of tauri Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * better Signed-off-by: Jess Frazelle <github@jessfraz.com> * set the default type Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * add comments Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * dialog for save tauri Signed-off-by: Jess Frazelle <github@jessfraz.com> * partial tsc fix * bump kittycad lib * Update src/lib/exportSave.ts Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch> * updates; Signed-off-by: Jess Frazelle <github@jessfraz.com> * default coords Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
		@ -8,7 +8,7 @@
 | 
			
		||||
    "@fortawesome/free-solid-svg-icons": "^6.4.0",
 | 
			
		||||
    "@fortawesome/react-fontawesome": "^0.2.0",
 | 
			
		||||
    "@headlessui/react": "^1.7.13",
 | 
			
		||||
    "@kittycad/lib": "^0.0.22",
 | 
			
		||||
    "@kittycad/lib": "^0.0.24",
 | 
			
		||||
    "@react-hook/resize-observer": "^1.2.6",
 | 
			
		||||
    "@tauri-apps/api": "^1.3.0",
 | 
			
		||||
    "@testing-library/jest-dom": "^5.14.1",
 | 
			
		||||
@ -21,12 +21,14 @@
 | 
			
		||||
    "@uiw/react-codemirror": "^4.15.1",
 | 
			
		||||
    "allotment": "^1.17.0",
 | 
			
		||||
    "crypto-js": "^4.1.1",
 | 
			
		||||
    "formik": "^2.4.3",
 | 
			
		||||
    "http-server": "^14.1.1",
 | 
			
		||||
    "react": "^18.2.0",
 | 
			
		||||
    "react-dom": "^18.2.0",
 | 
			
		||||
    "react-hot-toast": "^2.4.1",
 | 
			
		||||
    "react-hotkeys-hook": "^4.4.1",
 | 
			
		||||
    "react-json-view": "^1.21.3",
 | 
			
		||||
    "react-modal": "^3.16.1",
 | 
			
		||||
    "react-modal-promise": "^1.0.2",
 | 
			
		||||
    "react-router-dom": "^6.14.2",
 | 
			
		||||
    "sketch-helpers": "^0.0.4",
 | 
			
		||||
@ -82,7 +84,9 @@
 | 
			
		||||
    "@tauri-apps/cli": "^1.3.1",
 | 
			
		||||
    "@types/crypto-js": "^4.1.1",
 | 
			
		||||
    "@types/isomorphic-fetch": "^0.0.36",
 | 
			
		||||
    "@types/react-modal": "^3.16.0",
 | 
			
		||||
    "@types/uuid": "^9.0.1",
 | 
			
		||||
    "@types/wicg-file-system-access": "^2020.9.6",
 | 
			
		||||
    "@types/ws": "^8.5.5",
 | 
			
		||||
    "@vitejs/plugin-react": "^4.0.3",
 | 
			
		||||
    "autoprefixer": "^10.4.13",
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ import { SetAngleLength } from './components/Toolbar/setAngleLength'
 | 
			
		||||
import { ConvertToVariable } from './components/Toolbar/ConvertVariable'
 | 
			
		||||
import { SetAbsDistance } from './components/Toolbar/SetAbsDistance'
 | 
			
		||||
import { SetAngleBetween } from './components/Toolbar/SetAngleBetween'
 | 
			
		||||
import { ExportButton } from './components/ExportButton'
 | 
			
		||||
 | 
			
		||||
export const Toolbar = () => {
 | 
			
		||||
  const {
 | 
			
		||||
@ -31,6 +32,7 @@ export const Toolbar = () => {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <ExportButton />
 | 
			
		||||
      {guiMode.mode === 'default' && (
 | 
			
		||||
        <button
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										185
									
								
								src/components/ExportButton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								src/components/ExportButton.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,185 @@
 | 
			
		||||
import { v4 as uuidv4 } from 'uuid'
 | 
			
		||||
import { useStore } from '../useStore'
 | 
			
		||||
import { faXmark } from '@fortawesome/free-solid-svg-icons'
 | 
			
		||||
import { ActionButton } from './ActionButton'
 | 
			
		||||
import Modal from 'react-modal'
 | 
			
		||||
import React from 'react'
 | 
			
		||||
import { useFormik } from 'formik'
 | 
			
		||||
import { Models } from '@kittycad/lib'
 | 
			
		||||
 | 
			
		||||
type OutputFormat = Models['OutputFormat_type']
 | 
			
		||||
 | 
			
		||||
export const ExportButton = () => {
 | 
			
		||||
  const { engineCommandManager } = useStore((s) => ({
 | 
			
		||||
    engineCommandManager: s.engineCommandManager,
 | 
			
		||||
  }))
 | 
			
		||||
 | 
			
		||||
  const [modalIsOpen, setIsOpen] = React.useState(false)
 | 
			
		||||
 | 
			
		||||
  const defaultType = 'gltf'
 | 
			
		||||
  const [type, setType] = React.useState(defaultType)
 | 
			
		||||
 | 
			
		||||
  const customModalStyles = {
 | 
			
		||||
    content: {
 | 
			
		||||
      top: '50%',
 | 
			
		||||
      left: '50%',
 | 
			
		||||
      right: 'auto',
 | 
			
		||||
      bottom: 'auto',
 | 
			
		||||
      marginRight: '-50%',
 | 
			
		||||
      transform: 'translate(-50%, -50%)',
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function openModal() {
 | 
			
		||||
    setIsOpen(true)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function closeModal() {
 | 
			
		||||
    setIsOpen(false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Default to gltf and embedded.
 | 
			
		||||
  const initialValues: OutputFormat = {
 | 
			
		||||
    type: defaultType,
 | 
			
		||||
    storage: 'embedded',
 | 
			
		||||
  }
 | 
			
		||||
  const formik = useFormik({
 | 
			
		||||
    initialValues,
 | 
			
		||||
    onSubmit: (values: OutputFormat) => {
 | 
			
		||||
      // Set the default coords.
 | 
			
		||||
      if (
 | 
			
		||||
        values.type === 'obj' ||
 | 
			
		||||
        values.type === 'ply' ||
 | 
			
		||||
        values.type === 'step' ||
 | 
			
		||||
        values.type === 'stl'
 | 
			
		||||
      ) {
 | 
			
		||||
        // Set the default coords.
 | 
			
		||||
        // In the future we can make this configurable.
 | 
			
		||||
        // But for now, its probably best to keep it consistent with the
 | 
			
		||||
        // UI.
 | 
			
		||||
        values.coords = {
 | 
			
		||||
          forward: {
 | 
			
		||||
            axis: 'y',
 | 
			
		||||
            direction: 'negative',
 | 
			
		||||
          },
 | 
			
		||||
          up: {
 | 
			
		||||
            axis: 'z',
 | 
			
		||||
            direction: 'positive',
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      engineCommandManager?.sendSceneCommand({
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'export',
 | 
			
		||||
          // By default let's leave this blank to export the whole scene.
 | 
			
		||||
          // In the future we might want to let the user choose which entities
 | 
			
		||||
          // in the scene to export. In that case, you'd pass the IDs thru here.
 | 
			
		||||
          entity_ids: [],
 | 
			
		||||
          format: values,
 | 
			
		||||
        },
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        file_id: uuidv4(),
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      closeModal()
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <button onClick={openModal}>Export</button>
 | 
			
		||||
      <Modal
 | 
			
		||||
        isOpen={modalIsOpen}
 | 
			
		||||
        onRequestClose={closeModal}
 | 
			
		||||
        contentLabel="Export"
 | 
			
		||||
        style={customModalStyles}
 | 
			
		||||
      >
 | 
			
		||||
        <div className="text-black">
 | 
			
		||||
          <h1 className="text-2xl font-bold">Export your design</h1>
 | 
			
		||||
          <form onSubmit={formik.handleSubmit}>
 | 
			
		||||
            <p>
 | 
			
		||||
              <label htmlFor="type">Type</label>
 | 
			
		||||
            </p>
 | 
			
		||||
            <p>
 | 
			
		||||
              <select
 | 
			
		||||
                id="type"
 | 
			
		||||
                name="type"
 | 
			
		||||
                onChange={(e) => {
 | 
			
		||||
                  setType(e.target.value)
 | 
			
		||||
                  formik.handleChange(e)
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                <option value="gltf">gltf</option>
 | 
			
		||||
                <option value="obj">obj</option>
 | 
			
		||||
                <option value="ply">ply</option>
 | 
			
		||||
                <option value="step">step</option>
 | 
			
		||||
                <option value="stl">stl</option>
 | 
			
		||||
              </select>
 | 
			
		||||
            </p>
 | 
			
		||||
 | 
			
		||||
            {(type === 'gltf' || type === 'ply' || type === 'stl') && (
 | 
			
		||||
              <>
 | 
			
		||||
                <p>
 | 
			
		||||
                  {' '}
 | 
			
		||||
                  <label htmlFor="storage">Storage</label>
 | 
			
		||||
                </p>
 | 
			
		||||
                <p>
 | 
			
		||||
                  <select
 | 
			
		||||
                    id="storage"
 | 
			
		||||
                    name="storage"
 | 
			
		||||
                    onChange={formik.handleChange}
 | 
			
		||||
                    value={formik.values.storage}
 | 
			
		||||
                  >
 | 
			
		||||
                    {type === 'gltf' && (
 | 
			
		||||
                      <>
 | 
			
		||||
                        <option value="embedded">embedded</option>
 | 
			
		||||
                        <option value="binary">binary</option>
 | 
			
		||||
                        <option value="standard">standard</option>
 | 
			
		||||
                      </>
 | 
			
		||||
                    )}
 | 
			
		||||
                    {type === 'ply' && (
 | 
			
		||||
                      <>
 | 
			
		||||
                        <option value="ascii">ascii</option>
 | 
			
		||||
                        <option value="binary">binary</option>
 | 
			
		||||
                      </>
 | 
			
		||||
                    )}
 | 
			
		||||
                    {type === 'stl' && (
 | 
			
		||||
                      <>
 | 
			
		||||
                        <option value="ascii">ascii</option>
 | 
			
		||||
                        <option value="binary_little_endian">
 | 
			
		||||
                          binary_little_endian
 | 
			
		||||
                        </option>
 | 
			
		||||
                        <option value="binary_big_endian">
 | 
			
		||||
                          binary_big_endian
 | 
			
		||||
                        </option>
 | 
			
		||||
                      </>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </select>
 | 
			
		||||
                </p>
 | 
			
		||||
              </>
 | 
			
		||||
            )}
 | 
			
		||||
 | 
			
		||||
            <div className="flex justify-between mt-6">
 | 
			
		||||
              <button type="submit">Submit</button>
 | 
			
		||||
            </div>
 | 
			
		||||
          </form>
 | 
			
		||||
          <div className="flex justify-between mt-6">
 | 
			
		||||
            <ActionButton
 | 
			
		||||
              onClick={closeModal}
 | 
			
		||||
              icon={{
 | 
			
		||||
                icon: faXmark,
 | 
			
		||||
                bgClassName: 'bg-destroy-80',
 | 
			
		||||
                iconClassName:
 | 
			
		||||
                  'text-destroy-20 group-hover:text-destroy-10 hover:text-destroy-10',
 | 
			
		||||
              }}
 | 
			
		||||
              className="hover:border-destroy-40"
 | 
			
		||||
            >
 | 
			
		||||
              Close
 | 
			
		||||
            </ActionButton>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </Modal>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@ -2,6 +2,7 @@ import { SourceRange } from '../executor'
 | 
			
		||||
import { Selections } from '../../useStore'
 | 
			
		||||
import { VITE_KC_API_WS_MODELING_URL } from '../../env'
 | 
			
		||||
import { Models } from '@kittycad/lib'
 | 
			
		||||
import { exportSave } from '../../lib/exportSave'
 | 
			
		||||
 | 
			
		||||
interface ResultCommand {
 | 
			
		||||
  type: 'result'
 | 
			
		||||
@ -65,6 +66,10 @@ export class EngineCommandManager {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    this.socket = new WebSocket(VITE_KC_API_WS_MODELING_URL, [])
 | 
			
		||||
 | 
			
		||||
    // Change binary type from "blob" to "arraybuffer"
 | 
			
		||||
    this.socket.binaryType = 'arraybuffer'
 | 
			
		||||
 | 
			
		||||
    this.pc = new RTCPeerConnection()
 | 
			
		||||
    this.pc.createDataChannel('unreliable_modeling_cmds')
 | 
			
		||||
    this.socket.addEventListener('open', (event) => {
 | 
			
		||||
@ -87,15 +92,13 @@ export class EngineCommandManager {
 | 
			
		||||
    this?.socket?.addEventListener('message', (event) => {
 | 
			
		||||
      if (!this.socket || !this.pc) return
 | 
			
		||||
 | 
			
		||||
      //console.log('Message from server ', event.data);
 | 
			
		||||
      if (event.data instanceof Blob) {
 | 
			
		||||
        const reader = new FileReader()
 | 
			
		||||
 | 
			
		||||
        reader.onload = () => {
 | 
			
		||||
          //console.log("Result: " + reader.result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        reader.readAsText(event.data)
 | 
			
		||||
      // console.log('Message from server ', event.data);
 | 
			
		||||
      if (event.data instanceof ArrayBuffer) {
 | 
			
		||||
        // If the data is an ArrayBuffer, it's  the result of an export command,
 | 
			
		||||
        // because in all other cases we send JSON strings. But in the case of
 | 
			
		||||
        // export we send a binary blob.
 | 
			
		||||
        // Pass this to our export function.
 | 
			
		||||
        exportSave(event.data)
 | 
			
		||||
      } else if (
 | 
			
		||||
        typeof event.data === 'string' &&
 | 
			
		||||
        event.data.toLocaleLowerCase().startsWith('error')
 | 
			
		||||
@ -211,6 +214,7 @@ export class EngineCommandManager {
 | 
			
		||||
        } else if (message.type === 'click') {
 | 
			
		||||
          this.onClickCallback(message)
 | 
			
		||||
        } else {
 | 
			
		||||
          console.log('received message', message)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
@ -272,6 +276,7 @@ export class EngineCommandManager {
 | 
			
		||||
      this.lossyDataChannel.send(JSON.stringify(command))
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    console.log('sending command', command)
 | 
			
		||||
    this.socket?.send(JSON.stringify(command))
 | 
			
		||||
  }
 | 
			
		||||
  sendModellingCommand({
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										53
									
								
								src/lib/browserSaveFile.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/lib/browserSaveFile.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
/// The method below uses the File System Access API when it's supported and
 | 
			
		||||
// else falls back to the classic approach. In both cases the function saves
 | 
			
		||||
// the file, but in case of where the File System Access API is supported, the
 | 
			
		||||
// user will get a file save dialog where they can choose where the file should be saved.
 | 
			
		||||
export const browserSaveFile = async (blob: Blob, suggestedName: string) => {
 | 
			
		||||
  // Feature detection. The API needs to be supported
 | 
			
		||||
  // and the app not run in an iframe.
 | 
			
		||||
  const supportsFileSystemAccess =
 | 
			
		||||
    'showSaveFilePicker' in window &&
 | 
			
		||||
    (() => {
 | 
			
		||||
      try {
 | 
			
		||||
        return window.self === window.top
 | 
			
		||||
      } catch {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
    })()
 | 
			
		||||
  // If the File System Access API is supported…
 | 
			
		||||
  if (supportsFileSystemAccess && window.showSaveFilePicker) {
 | 
			
		||||
    try {
 | 
			
		||||
      // Show the file save dialog.
 | 
			
		||||
      const handle = await window.showSaveFilePicker({
 | 
			
		||||
        suggestedName,
 | 
			
		||||
      })
 | 
			
		||||
      // Write the blob to the file.
 | 
			
		||||
      const writable = await handle.createWritable()
 | 
			
		||||
      await writable.write(blob)
 | 
			
		||||
      await writable.close()
 | 
			
		||||
      return
 | 
			
		||||
    } catch (err: any) {
 | 
			
		||||
      // Fail silently if the user has simply canceled the dialog.
 | 
			
		||||
      if (err.name !== 'AbortError') {
 | 
			
		||||
        console.error(err.name, err.message)
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // Fallback if the File System Access API is not supported…
 | 
			
		||||
  // Create the blob URL.
 | 
			
		||||
  const blobURL = URL.createObjectURL(blob)
 | 
			
		||||
  // Create the `<a download>` element and append it invisibly.
 | 
			
		||||
  const a = document.createElement('a')
 | 
			
		||||
  a.href = blobURL
 | 
			
		||||
  a.download = suggestedName
 | 
			
		||||
  a.style.display = 'none'
 | 
			
		||||
  document.body.append(a)
 | 
			
		||||
  // Programmatically click the element.
 | 
			
		||||
  a.click()
 | 
			
		||||
  // Revoke the blob URL and remove the element.
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    URL.revokeObjectURL(blobURL)
 | 
			
		||||
    a.remove()
 | 
			
		||||
  }, 1000)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								src/lib/exportSave.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/lib/exportSave.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
import { isTauri } from './isTauri'
 | 
			
		||||
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
 | 
			
		||||
import { browserSaveFile } from './browserSaveFile'
 | 
			
		||||
import { save } from '@tauri-apps/api/dialog'
 | 
			
		||||
import { writeBinaryFile } from '@tauri-apps/api/fs'
 | 
			
		||||
 | 
			
		||||
// Saves files locally from an export call.
 | 
			
		||||
export async function exportSave(data: ArrayBuffer) {
 | 
			
		||||
  // This converts the ArrayBuffer to a Rust equivalent Vec<u8>.
 | 
			
		||||
  let uintArray = new Uint8Array(data)
 | 
			
		||||
  try {
 | 
			
		||||
    const files: { contents: number[]; name: string }[] =
 | 
			
		||||
      deserialize_files(uintArray)
 | 
			
		||||
    for (const file of files) {
 | 
			
		||||
      if (isTauri()) {
 | 
			
		||||
        // Open a dialog to save the file.
 | 
			
		||||
        const filePath = await save({
 | 
			
		||||
          defaultPath: file.name,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (filePath === null) {
 | 
			
		||||
          // The user canceled the save.
 | 
			
		||||
          // Return early.
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Write the file.
 | 
			
		||||
        await writeBinaryFile(filePath, uintArray)
 | 
			
		||||
      } else {
 | 
			
		||||
        // Download the file to the user's computer.
 | 
			
		||||
        // Now we need to download the files to the user's downloads folder.
 | 
			
		||||
        // Or the destination they choose.
 | 
			
		||||
        // Iterate over the files.
 | 
			
		||||
        // Create a new blob.
 | 
			
		||||
        const blob = new Blob([new Uint8Array(file.contents)])
 | 
			
		||||
        // Save the file.
 | 
			
		||||
        browserSaveFile(blob, file.name)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    // TODO: do something real with the error.
 | 
			
		||||
    console.log(e)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								src/wasm-lib/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -11,6 +11,15 @@ dependencies = [
 | 
			
		||||
 "memchr",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bincode"
 | 
			
		||||
version = "1.3.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "serde",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bumpalo"
 | 
			
		||||
version = "3.12.0"
 | 
			
		||||
@ -241,6 +250,7 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
 | 
			
		||||
name = "wasm-lib"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bincode",
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "regex",
 | 
			
		||||
 "serde",
 | 
			
		||||
 | 
			
		||||
@ -8,9 +8,10 @@ edition = "2021"
 | 
			
		||||
crate-type = ["cdylib"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
bincode = "1.3.3"
 | 
			
		||||
lazy_static = "1.4.0"
 | 
			
		||||
regex = "1.7.1"
 | 
			
		||||
serde = {version = "1.0.152", features = ["derive"] }
 | 
			
		||||
serde-wasm-bindgen = "0.3.1"
 | 
			
		||||
serde_json = "1.0.93"
 | 
			
		||||
wasm-bindgen = "0.2.78"
 | 
			
		||||
serde-wasm-bindgen = "0.3.1"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								src/wasm-lib/src/export.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/wasm-lib/src/export.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
//! Functions for exported files from the server.
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use wasm_bindgen::prelude::*;
 | 
			
		||||
 | 
			
		||||
/// A file that has been exported from the server.
 | 
			
		||||
#[derive(Debug, Deserialize, Serialize)]
 | 
			
		||||
pub struct File {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub contents: Vec<u8>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
pub fn deserialize_files(data: Vec<u8>) -> Result<JsValue, JsError> {
 | 
			
		||||
    let files: Vec<File> = bincode::deserialize(&data)?;
 | 
			
		||||
 | 
			
		||||
    Ok(serde_wasm_bindgen::to_value(&files)?)
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
mod abstract_syntax_tree;
 | 
			
		||||
mod export;
 | 
			
		||||
mod recast;
 | 
			
		||||
mod tokeniser;
 | 
			
		||||
 | 
			
		||||
@ -240,8 +240,7 @@ fn recast_pipe_expression(expression: PipeExpression) -> String {
 | 
			
		||||
            let mut maybe_line_break = "\n".to_string();
 | 
			
		||||
            let mut str = recast_value(statement.clone(), indentation.clone(), true);
 | 
			
		||||
            let non_code_meta = expression.non_code_meta.clone();
 | 
			
		||||
            if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index)
 | 
			
		||||
            {
 | 
			
		||||
            if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index) {
 | 
			
		||||
                if non_code_meta_value.value != " " {
 | 
			
		||||
                    str += non_code_meta_value.value.as_str();
 | 
			
		||||
                    indentation = "".to_string();
 | 
			
		||||
@ -325,10 +324,8 @@ pub fn recast(ast: Program, indentation: String, is_with_block: bool) -> String
 | 
			
		||||
 | 
			
		||||
            // determine the value of startString
 | 
			
		||||
            let last_white_space_or_comment = if index > 0 {
 | 
			
		||||
                let tmp = if let Some(non_code_node) = ast
 | 
			
		||||
                    .non_code_meta
 | 
			
		||||
                    .none_code_nodes
 | 
			
		||||
                    .get(&(index - 1))
 | 
			
		||||
                let tmp = if let Some(non_code_node) =
 | 
			
		||||
                    ast.non_code_meta.none_code_nodes.get(&(index - 1))
 | 
			
		||||
                {
 | 
			
		||||
                    non_code_node.value.clone()
 | 
			
		||||
                } else {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "types": ["vite/client"],
 | 
			
		||||
    "types": ["vite/client", "@types/wicg-file-system-access"],
 | 
			
		||||
    "target": "esnext",
 | 
			
		||||
    "lib": [
 | 
			
		||||
      "dom",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								yarn.lock
									
									
									
									
									
								
							@ -1710,10 +1710,10 @@
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
 | 
			
		||||
  integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
 | 
			
		||||
 | 
			
		||||
"@kittycad/lib@^0.0.22":
 | 
			
		||||
  version "0.0.22"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.22.tgz#3d9b063c6cfe6593cdf7b61d3ffb5c1251262401"
 | 
			
		||||
  integrity sha512-H9AS3/8Ag2fJRZqNNkbOjy/08kEqeOxWEWsmQIzJ/dNGYRD0B7Fm+UM6T8eSEkPP2+KKrIhoHMYEfGd9KjY1uQ==
 | 
			
		||||
"@kittycad/lib@^0.0.24":
 | 
			
		||||
  version "0.0.24"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.24.tgz#afc2f0baf8b742344e86332a60e89e85804b4b30"
 | 
			
		||||
  integrity sha512-RT3EThq0s7DQFT9+8HQ9yRgIb5+Q2xwYFYl/aNel5DdkfAya3WGlwhjv2YOtMXsy981JVpabo0HXD3tLfm/9QA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    node-fetch "3.3.2"
 | 
			
		||||
    openapi-types "^12.0.0"
 | 
			
		||||
@ -2113,6 +2113,13 @@
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/react" "*"
 | 
			
		||||
 | 
			
		||||
"@types/react-modal@^3.16.0":
 | 
			
		||||
  version "3.16.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/react-modal/-/react-modal-3.16.0.tgz#b8d6be10de894139a2ea9f4a2505b1b5d02023df"
 | 
			
		||||
  integrity sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/react" "*"
 | 
			
		||||
 | 
			
		||||
"@types/react@*", "@types/react@^18.0.0":
 | 
			
		||||
  version "18.2.18"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.18.tgz#c8b233919eef1bdc294f6f34b37f9727ad677516"
 | 
			
		||||
@ -2154,6 +2161,11 @@
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b"
 | 
			
		||||
  integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==
 | 
			
		||||
 | 
			
		||||
"@types/wicg-file-system-access@^2020.9.6":
 | 
			
		||||
  version "2020.9.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.6.tgz#da34476b1e29451c8b7aa1a6db86b185647cd970"
 | 
			
		||||
  integrity sha512-6hogE75Hl2Ov/jgp8ZhDaGmIF/q3J07GtXf8nCJCwKTHq7971po5+DId7grft09zG7plBwpF6ZU0yx9Du4/e1A==
 | 
			
		||||
 | 
			
		||||
"@types/ws@^8.5.5":
 | 
			
		||||
  version "8.5.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
 | 
			
		||||
@ -3116,6 +3128,11 @@ deep-is@^0.1.3:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
 | 
			
		||||
  integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
 | 
			
		||||
 | 
			
		||||
deepmerge@^2.1.1:
 | 
			
		||||
  version "2.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
 | 
			
		||||
  integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
 | 
			
		||||
 | 
			
		||||
deepmerge@^4.2.2:
 | 
			
		||||
  version "4.3.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
 | 
			
		||||
@ -3198,9 +3215,9 @@ domexception@^4.0.0:
 | 
			
		||||
    webidl-conversions "^7.0.0"
 | 
			
		||||
 | 
			
		||||
electron-to-chromium@^1.4.477:
 | 
			
		||||
  version "1.4.478"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.478.tgz#687198cfcef9b854a79a229feaa6cd8961206290"
 | 
			
		||||
  integrity sha512-qjTA8djMXd+ruoODDFGnRCRBpID+AAfYWCyGtYTNhsuwxI19s8q19gbjKTwRS5z/LyVf5wICaIiPQGLekmbJbA==
 | 
			
		||||
  version "1.4.480"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.480.tgz#40e32849ca50bc23ce29c1516c5adb3fddac919d"
 | 
			
		||||
  integrity sha512-IXTgg+bITkQv/FLP9FjX6f9KFCs5hQWeh5uNSKxB9mqYj/JXhHDbu+ekS43LVvbkL3eW6/oZy4+r9Om6lan1Uw==
 | 
			
		||||
 | 
			
		||||
emittery@^0.13.1:
 | 
			
		||||
  version "0.13.1"
 | 
			
		||||
@ -3653,6 +3670,11 @@ execa@^5.0.0:
 | 
			
		||||
    signal-exit "^3.0.3"
 | 
			
		||||
    strip-final-newline "^2.0.0"
 | 
			
		||||
 | 
			
		||||
exenv@^1.2.0:
 | 
			
		||||
  version "1.2.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
 | 
			
		||||
  integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==
 | 
			
		||||
 | 
			
		||||
exit@^0.1.2:
 | 
			
		||||
  version "0.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
 | 
			
		||||
@ -3822,6 +3844,19 @@ formdata-polyfill@^4.0.10:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    fetch-blob "^3.1.2"
 | 
			
		||||
 | 
			
		||||
formik@^2.4.3:
 | 
			
		||||
  version "2.4.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/formik/-/formik-2.4.3.tgz#6020e85eb3e3e8415b3b19d6f4f65793ab754b24"
 | 
			
		||||
  integrity sha512-2Dy79Szw3zlXmZiokUdKsn+n1ow4G8hRrC/n92cOWHNTWXCRpQXlyvz6HcjW7aSQZrldytvDOavYjhfmDnUq8Q==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    deepmerge "^2.1.1"
 | 
			
		||||
    hoist-non-react-statics "^3.3.0"
 | 
			
		||||
    lodash "^4.17.21"
 | 
			
		||||
    lodash-es "^4.17.21"
 | 
			
		||||
    react-fast-compare "^2.0.1"
 | 
			
		||||
    tiny-warning "^1.0.2"
 | 
			
		||||
    tslib "^2.0.0"
 | 
			
		||||
 | 
			
		||||
fraction.js@^4.2.0:
 | 
			
		||||
  version "4.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
 | 
			
		||||
@ -4056,6 +4091,13 @@ he@^1.2.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
 | 
			
		||||
  integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
 | 
			
		||||
 | 
			
		||||
hoist-non-react-statics@^3.3.0:
 | 
			
		||||
  version "3.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
 | 
			
		||||
  integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    react-is "^16.7.0"
 | 
			
		||||
 | 
			
		||||
html-encoding-sniffer@^3.0.0:
 | 
			
		||||
  version "3.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9"
 | 
			
		||||
@ -4963,6 +5005,11 @@ locate-path@^6.0.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    p-locate "^5.0.0"
 | 
			
		||||
 | 
			
		||||
lodash-es@^4.17.21:
 | 
			
		||||
  version "4.17.21"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
 | 
			
		||||
  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
 | 
			
		||||
 | 
			
		||||
lodash.clamp@^4.0.0:
 | 
			
		||||
  version "4.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz#5c24bedeeeef0753560dc2b4cb4671f90a6ddfaa"
 | 
			
		||||
@ -5557,7 +5604,7 @@ prompts@^2.0.1:
 | 
			
		||||
    kleur "^3.0.3"
 | 
			
		||||
    sisteransi "^1.0.5"
 | 
			
		||||
 | 
			
		||||
prop-types@^15.8.1:
 | 
			
		||||
prop-types@^15.7.2, prop-types@^15.8.1:
 | 
			
		||||
  version "15.8.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
 | 
			
		||||
  integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
 | 
			
		||||
@ -5621,6 +5668,11 @@ react-dom@^18.2.0:
 | 
			
		||||
    loose-envify "^1.1.0"
 | 
			
		||||
    scheduler "^0.23.0"
 | 
			
		||||
 | 
			
		||||
react-fast-compare@^2.0.1:
 | 
			
		||||
  version "2.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
 | 
			
		||||
  integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
 | 
			
		||||
 | 
			
		||||
react-hot-toast@^2.4.1:
 | 
			
		||||
  version "2.4.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
 | 
			
		||||
@ -5633,7 +5685,7 @@ react-hotkeys-hook@^4.4.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-4.4.1.tgz#1f7a7a1c9c21d4fa3280bf340fcca8fd77d81994"
 | 
			
		||||
  integrity sha512-sClBMBioFEgFGYLTWWRKvhxcCx1DRznd+wkFHwQZspnRBkHTgruKIHptlK/U/2DPX8BhHoRGzpMVWUXMmdZlmw==
 | 
			
		||||
 | 
			
		||||
react-is@^16.13.1:
 | 
			
		||||
react-is@^16.13.1, react-is@^16.7.0:
 | 
			
		||||
  version "16.13.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
 | 
			
		||||
  integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 | 
			
		||||
@ -5658,7 +5710,7 @@ react-json-view@^1.21.3:
 | 
			
		||||
    react-lifecycles-compat "^3.0.4"
 | 
			
		||||
    react-textarea-autosize "^8.3.2"
 | 
			
		||||
 | 
			
		||||
react-lifecycles-compat@^3.0.4:
 | 
			
		||||
react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
 | 
			
		||||
  version "3.0.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
 | 
			
		||||
  integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
 | 
			
		||||
@ -5668,6 +5720,16 @@ react-modal-promise@^1.0.2:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-modal-promise/-/react-modal-promise-1.0.2.tgz#122620b7f19eec73683affadfa77c543d88edc40"
 | 
			
		||||
  integrity sha512-dqT618ROhG8qh1+O6EZkia5ELw3zaZWGpMX2YfEH4bgwYENPuFonqKw1W70LFx3K/SCZvVBcD6UYEI12yzYXzg==
 | 
			
		||||
 | 
			
		||||
react-modal@^3.16.1:
 | 
			
		||||
  version "3.16.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b"
 | 
			
		||||
  integrity sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    exenv "^1.2.0"
 | 
			
		||||
    prop-types "^15.7.2"
 | 
			
		||||
    react-lifecycles-compat "^3.0.0"
 | 
			
		||||
    warning "^4.0.3"
 | 
			
		||||
 | 
			
		||||
react-refresh@^0.14.0:
 | 
			
		||||
  version "0.14.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
 | 
			
		||||
@ -6234,6 +6296,11 @@ thenify-all@^1.0.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    any-promise "^1.0.0"
 | 
			
		||||
 | 
			
		||||
tiny-warning@^1.0.2:
 | 
			
		||||
  version "1.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
 | 
			
		||||
  integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
 | 
			
		||||
 | 
			
		||||
tmpl@1.0.5:
 | 
			
		||||
  version "1.0.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
 | 
			
		||||
@ -6336,6 +6403,11 @@ tslib@^1.8.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
 | 
			
		||||
  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 | 
			
		||||
 | 
			
		||||
tslib@^2.0.0:
 | 
			
		||||
  version "2.6.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
 | 
			
		||||
  integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
 | 
			
		||||
 | 
			
		||||
tslib@~2.4:
 | 
			
		||||
  version "2.4.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
 | 
			
		||||
@ -6575,9 +6647,9 @@ vite-tsconfig-paths@^4.2.0:
 | 
			
		||||
    tsconfck "^2.1.0"
 | 
			
		||||
 | 
			
		||||
vite@^4.4.3:
 | 
			
		||||
  version "4.4.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.7.tgz#71b8a37abaf8d50561aca084dbb77fa342824154"
 | 
			
		||||
  integrity sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==
 | 
			
		||||
  version "4.4.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.8.tgz#31e4a438f8748695c68bd57ffd262ba93540fdf7"
 | 
			
		||||
  integrity sha512-LONawOUUjxQridNWGQlNizfKH89qPigK36XhMI7COMGztz8KNY0JHim7/xDd71CZwGT4HtSRgI7Hy+RlhG0Gvg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    esbuild "^0.18.10"
 | 
			
		||||
    postcss "^8.4.26"
 | 
			
		||||
@ -6604,6 +6676,13 @@ walker@^1.0.8:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    makeerror "1.0.12"
 | 
			
		||||
 | 
			
		||||
warning@^4.0.3:
 | 
			
		||||
  version "4.0.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
 | 
			
		||||
  integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    loose-envify "^1.0.0"
 | 
			
		||||
 | 
			
		||||
wasm-pack@^0.12.1:
 | 
			
		||||
  version "0.12.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/wasm-pack/-/wasm-pack-0.12.1.tgz#974c1fbbf5b65c9e135e0d1fba3a97de1a21a489"
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user