{"id":16310,"library":"can-local-store","title":"Can-Local-Store","description":"can-local-store is a client-side data persistence library for the CanJS framework, providing a localStorage-backed database for `can/Map` and `can/List` instances. It enables developers to automatically serialize and deserialize data to and from the browser's `localStorage` API, making it easy to store and retrieve application state or user data directly in the browser. The current stable version is 1.0.1, last released in October 2017. Due to its age and lack of updates since then, the package is considered abandoned, with no ongoing development or maintenance. Its key differentiator was its deep integration with CanJS's observable data structures, allowing seamless persistence without boilerplate. However, modern CanJS applications or new projects would typically opt for more actively maintained state management solutions or direct `localStorage` wrappers.","status":"abandoned","version":"1.0.1","language":"javascript","source_language":"en","source_url":"git://github.com/canjs/can-local-store","tags":["javascript","canjs","donejs","donejs-plugin"],"install":[{"cmd":"npm install can-local-store","lang":"bash","label":"npm"},{"cmd":"yarn add can-local-store","lang":"bash","label":"yarn"},{"cmd":"pnpm add can-local-store","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency required for defining observable maps and lists.","package":"can-define","optional":false},{"reason":"Peer dependency for observable tracking within CanJS.","package":"can-observation","optional":false},{"reason":"Peer dependency for meta programming and reflection utilities in CanJS.","package":"can-reflect","optional":false}],"imports":[{"note":"Imports a `can/Map` extended with localStorage persistence. This is the primary way to define models.","wrong":"import { Map } from 'can-local-store'; // Incorrect named import from root\nimport Map from 'can-local-store'; // Root default import usually refers to the main 'Map' store, but subpath is clearer","symbol":"Map","correct":"import Map from 'can-local-store/map';"},{"note":"Imports a `can/List` extended with localStorage persistence. Used for collections of models.","wrong":"import { List } from 'can-local-store'; // Incorrect named import from root","symbol":"List","correct":"import List from 'can-local-store/list';"},{"note":"The root import often re-exports the `Map` variant or a factory function. The documentation primarily guides towards subpath imports for clarity. The d.ts indicates the default export is `can-local-store/map`.","wrong":"const localStore = require('can-local-store');","symbol":"localStore","correct":"import localStore from 'can-local-store'; // Or import Store from 'can-local-store';"}],"quickstart":{"code":"import Map from 'can-local-store/map';\n\n// Define a Todo model that uses can-local-store/map\ninterface TodoAttributes {\n  id?: number;\n  name: string;\n  completed: boolean;\n}\n\nconst Todo = Map.extend<TodoAttributes>('todo', {\n  // `todo` is the localStorage key for this model's data\n  seal: false, // Recommended for can-define-stream compatibility\n  init: function(this: any) {\n    if (!this.id) {\n      // Simple ID generation for example purposes\n      this.id = Date.now();\n    }\n  }\n});\n\nasync function runExample() {\n  console.log('--- can-local-store example ---');\n\n  // Create a new todo item\n  const newTodo = new Todo({ name: 'Learn can-local-store', completed: false });\n  await newTodo.save(); // Saves to localStorage under the key 'todo'\n  console.log('Created todo:', newTodo.serialize());\n  console.log('localStorage content (key \"todo\"):', localStorage.getItem('todo'));\n\n  // Find all todos (loads from localStorage)\n  const todos = await Todo.findAll({});\n  console.log('All todos after creation:', todos.serialize());\n\n  // Update an existing todo\n  const firstTodo = todos.get(0);\n  if (firstTodo) {\n    firstTodo.completed = true;\n    await firstTodo.save(); // Updates in localStorage\n    console.log('Updated todo:', firstTodo.serialize());\n    console.log('localStorage content (key \"todo\"):', localStorage.getItem('todo'));\n  }\n\n  // Find a specific todo by ID\n  const foundTodo = await Todo.findOne({ id: newTodo.id });\n  console.log('Found todo by ID:', foundTodo?.serialize());\n\n  // Delete a todo\n  if (foundTodo) {\n    await foundTodo.destroy(); // Removes from localStorage\n    console.log('Deleted todo:', foundTodo.serialize());\n    console.log('localStorage content (key \"todo\"):', localStorage.getItem('todo'));\n  }\n\n  // Verify deletion by fetching all remaining todos\n  const remainingTodos = await Todo.findAll({});\n  console.log('Remaining todos:', remainingTodos.serialize());\n\n  // Clean up localStorage completely for this example\n  localStorage.removeItem('todo');\n  console.log('localStorage \"todo\" key cleared.');\n}\n\nrunExample().catch(console.error);","lang":"typescript","description":"Demonstrates defining a CanJS Map-based model with `can-local-store`, then performing CRUD (Create, Read, Update, Delete) operations that persist data in the browser's `localStorage`."},"warnings":[{"fix":"Consider migrating to a more actively maintained client-side storage solution or a direct `localStorage` wrapper if starting a new project or updating an existing one.","message":"The package is considered abandoned, with its last release in October 2017. It is unlikely to receive updates for newer browser features, JavaScript standards, or security patches, and may have compatibility issues with modern CanJS versions (beyond those specified in its peer dependencies) or other contemporary libraries.","severity":"breaking","affected_versions":">=1.0.1"},{"fix":"Implement robust error handling around `localStorage` operations and consider alternative storage solutions (e.g., IndexedDB) for larger datasets. Monitor storage usage and prune old data.","message":"`localStorage` has a limited storage capacity (typically 5-10 MB per origin). Attempting to store too much data will result in a `QuotaExceededError` or data loss, without graceful degradation unless explicitly handled.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For performance-critical applications or large data sets, use asynchronous storage solutions like IndexedDB or a web worker to offload synchronous `localStorage` operations.","message":"`localStorage` operations are synchronous and can block the main thread. Storing or retrieving large amounts of data can lead to UI freezes and a poor user experience, especially on slower devices.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Avoid storing sensitive information. For secure client-side storage, consider using HTTP-only cookies for authentication tokens or server-side storage for critical data.","message":"Data stored in `localStorage` is not secure and can be accessed or modified by any JavaScript code running on the same origin (e.g., via Cross-Site Scripting). Sensitive user information, authentication tokens, or highly confidential data should never be stored here.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure all data intended for storage is JSON-serializable. Manually serialize/deserialize complex types to and from their JSON-compatible representations before interacting with the store.","message":"can-local-store automatically serializes data using `JSON.stringify` and deserializes using `JSON.parse`. This means only JSON-serializable data types (strings, numbers, booleans, null, arrays, plain objects) can be reliably stored. Custom classes, Dates, RegExps, or functions will lose their type or information upon serialization.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Reduce the amount of data being stored, implement a caching strategy to only store essential data, or migrate to a different storage mechanism like IndexedDB for larger datasets. Ensure `localStorage.removeItem()` or `localStorage.clear()` is used for cleanup when data is no longer needed.","cause":"Attempting to write more data to localStorage than the browser's allocated limit (typically 5-10 MB per origin) allows.","error":"DOMException: QuotaExceededError: The quota has been exceeded."},{"fix":"Before saving, ensure that any data passed to `can-local-store` (via `Map` or `List` instances) does not contain circular references. Manually transform the data to a non-circular structure if necessary.","cause":"`can-local-store` uses `JSON.stringify` internally, which cannot handle objects with circular references (where an object directly or indirectly refers back to itself).","error":"TypeError: Converting circular structure to JSON"},{"fix":"Verify that `can-define` and other peer dependencies are installed and compatible with `can-local-store@1.0.1`. Ensure the `Map` is correctly extended with `can-local-store/map` and that the instance methods like `save()` are available on the created model instance.","cause":"This usually indicates an issue with how the CanJS `Map` is defined or how `can-local-store/map` is integrated, possibly due to incorrect peer dependency versions or an outdated CanJS setup.","error":"Property 'save' does not exist on type 'Map<T>'"}],"ecosystem":"npm"}