andsala / svelte-persistent-store

Persist your svelte store in localStorage or sessionStorage
MIT License
86 stars 6 forks source link

"svelte-persistent-store/dist/local" not found #15

Open beebase opened 3 years ago

beebase commented 3 years ago

I'm getting this error using snowpack

Dependency Install Error: Package "svelte-persistent-store/dist/local" not found. Have you installed it?

Package was installed correctly with npm. Any ideas?

NetOpWibby commented 3 years ago

I'm having this same issue, just using Rollup. However, I did try to convert to Snowpack last week but reverted. Also, for some reason Rollup is trying to find this module via a double/nested /dist directory (~/<project>/node_modules/svelte-persistent-store/dist/dist/local).

beebase commented 3 years ago

Yes, I also noticed the double dist path with snowpack. Couldn't reproduce consistently though.

NetOpWibby commented 3 years ago

I added all the non-test root files in /src into my project and a few @ts-ignores later I was able to continue development as usual.

nye commented 3 years ago

I'm having the same issue: svelte-persistent-store/dist/dist/local with the double dist path. I'm using Rollup and this happened after updating rollup-plugin-svelte to 7.1.0

lhapaipai commented 3 years ago

I had the same issue with rollup and resolve this with

import { writable } from "svelte-persistent-store/local.js";
lhapaipai commented 3 years ago

I'm having the same issue: svelte-persistent-store/dist/dist/local with the double dist path. I'm using Rollup and this happened after updating rollup-plugin-svelte to 7.1.0

this is due to the path mapping given by the exports field of the package.json.

  "exports": {
    ".": "./dist/index.js",
    "./": "./dist/"
  },

any import with "svelte-persistent-store/[something]" is rewritten into "./node-modules/svelte-persistent-store/dist/[something]". the documentation is not up to date.

this exports is necessary ? so I will propose to update the documentation and to rewrite it like this :

  "exports": {
    ".": "./dist/index.js",
    "./*": "./dist/*"
  },

subpath folder mappings is deprecated so you can import your file with

import { writable } from "svelte-persistent-store/local.mjs";

or exports field is it necessary? if we remove we can import file respecting the file path (which is more intuitive):

import { writable } from "svelte-persistent-store/dist/local.mjs";
Spenhouet commented 3 years ago

I'm trying to run this with SvelteKit and run into the same issue.

import { writable, readable, derived } from 'svelte-persistent-store/dist/local';
 [vite] Internal server error: Failed to resolve import "svelte-persistent-store/dist/local" from "src/lib/authstore.ts". Does the file exist?
  Plugin: vite:import-analysis
  File: /home/spen/svelte-app-mui/src/lib/authstore.ts
  1  |  import { writable } from "svelte-persistent-store/dist/local";
     |                            ^
  2  |  export const jwt = writable("jwt", "");
  3  |  
      at formatError (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:50738:46)
      at TransformContext.error (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:50734:19)
      at normalizeUrl (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:74223:26)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)
      at async TransformContext.transform (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:74356:57)
      at async Object.transform (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:50939:30)
      at async transformRequest (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:66763:29)
      at async viteTransformMiddleware (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:66904:32)
import { local } from 'svelte-persistent-store';
const { writable, readable, derived } = local;
[vite] Error when evaluating SSR module /src/lib/authstore.ts:
TypeError: Cannot destructure property 'writable' of '__vite_ssr_import_0__.local' as it is undefined.
    at /home/spen/svelte-app-mui/src/lib/authstore.ts:19:18
    at instantiateModule (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:73464:166)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
Cannot destructure property 'writable' of '__vite_ssr_import_0__.local' as it is undefined.
TypeError: Cannot destructure property 'writable' of '__vite_ssr_import_0__.local' as it is undefined.
    at /home/spen/svelte-app-mui/src/lib/authstore.ts:19:18
    at instantiateModule (/home/spen/svelte-app-mui/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:73464:166)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)

I'm new to Svelte and have no clue how to solve this. The workaround proposed by @lhapaipai does not work for me (nothing of what he wrote).

Spenhouet commented 3 years ago

Okay, so the issue for me seems to be the SSR of SvelteKit. See the section How do I use a client-side only library that depends on document or window? in https://kit.svelte.dev/faq.

I tried to figure out a solution with the standard writable and came up with the following. See also my answer on StackOverflow.

As a bonus this solution also updates the writable if the localStorage changes (e.g. in a different tab). So this solution works across tabs. See the Window: storage event

Put this into a typescript file e.g. $lib/store.ts:

import { browser } from '$app/env';
import type { Writable } from 'svelte/store';
import { writable, get } from 'svelte/store'

const storage = <T>(key: string, initValue: T): Writable<T> => {
    const store = writable(initValue);
    if (!browser) return store;

    const storedValueStr = localStorage.getItem(key);
    if (storedValueStr != null) store.set(JSON.parse(storedValueStr));

    store.subscribe((val) => {
        if ([null, undefined].includes(val)) {
            localStorage.removeItem(key)
        } else {
            localStorage.setItem(key, JSON.stringify(val))
        }
    })

    window.addEventListener('storage', () => {
        const storedValueStr = localStorage.getItem(key);
        if (storedValueStr == null) return;

        const localValue: T = JSON.parse(storedValueStr)
        if (localValue !== get(store)) store.set(localValue);
    });

    return store;
}

export default storage

This can be used like this:

import storage from '$lib/store'

interface Auth {
    jwt: string
}

export const auth = storage<Auth>("auth", { jwt: "" })

Maybe this package could be updated to also work around the SSR.