{"id":16429,"library":"lovefield","title":"Lovefield - Relational Database for Web Apps","description":"Lovefield is a relational database written entirely in JavaScript, designed for web applications. It provides a SQL-like query API, leveraging IndexedDB for persistent storage in the browser environment. Developed by Google, the package reached its last published version, 2.1.12, in February 2017. While the GitHub repository saw minor updates until January 2023, active feature development and official maintenance appear to have ceased significantly earlier, around 2015-2017, as indicated by project videos and publishing dates. Lovefield offers cross-browser compatibility (supporting older versions of Chrome, Firefox, IE, and Safari) but explicitly does not support Node.js due to its reliance on IndexedDB. Its key differentiators were bringing a relational model and SQL-like syntax to client-side data management before more modern alternatives emerged, offering atomic transactions and a query optimizer.","status":"abandoned","version":"2.1.12","language":"javascript","source_language":"en","source_url":"https://github.com/google/lovefield","tags":["javascript","lovefield"],"install":[{"cmd":"npm install lovefield","lang":"bash","label":"npm"},{"cmd":"yarn add lovefield","lang":"bash","label":"yarn"},{"cmd":"pnpm add lovefield","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Lovefield is primarily designed for browser environments and exposes a global `lf` object after script inclusion. It does not officially support module systems like CommonJS or ESM for Node.js.","symbol":"lf","correct":"<!-- In HTML -->\n<script src=\"path/to/lovefield.min.js\"></script>\n<script>\n  const schemaBuilder = lf.schema.create('my_db', 1);\n  // ... rest of your code using lf\n</script>"},{"note":"The `lf` global object is the entry point, with `schema` being a property on it. Direct named imports from a module are not the intended usage.","wrong":"import { schema } from 'lovefield'; // Incorrect for browser global\nconst schemaBuilder = schema.create('my_db', 1);","symbol":"lf.schema.create","correct":"const schemaBuilder = lf.schema.create('my_db', 1);"},{"note":"`lf.Type` provides constants for column types, accessed via the global `lf` object.","wrong":"import { Type } from 'lovefield';\naddColumn('id', Type.INTEGER);","symbol":"lf.Type","correct":"addColumn('id', lf.Type.INTEGER);"}],"quickstart":{"code":"<!-- In an HTML file -->\n<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\" />\n  <title>Lovefield Quick Start</title>\n  <script src=\"https://unpkg.com/lovefield@2.1.12/dist/lovefield.min.js\"></script>\n</head>\n<body>\n  <script>\n    // Define the database schema\n    const schemaBuilder = lf.schema.create('todoDb', 1);\n    schemaBuilder.createTable('Item')\n        .addColumn('id', lf.Type.INTEGER)\n        .addColumn('description', lf.Type.STRING)\n        .addColumn('deadline', lf.Type.DATE_TIME)\n        .addColumn('done', lf.Type.BOOLEAN)\n        .addPrimaryKey(['id'])\n        .addIndex('idxDeadline', ['deadline'], false, lf.Order.DESC);\n\n    let todoDb;\n    let itemTable;\n\n    // Connect to the database and perform operations\n    schemaBuilder.connect().then(function(db) {\n      todoDb = db;\n      itemTable = db.getSchema().table('Item');\n\n      // Create a new row\n      const row = itemTable.createRow({\n        'id': 1,\n        'description': 'Buy groceries',\n        'deadline': new Date(2026, 4, 25),\n        'done': false\n      });\n\n      // Insert the row into the database\n      return db.insertOrReplace().into(itemTable).values([row]).exec();\n    }).then(function() {\n      // Query data\n      return todoDb.select().from(itemTable).where(itemTable.done.eq(false)).exec();\n    }).then(function(results) {\n      // Process results\n      results.forEach(function(row) {\n        console.log(`Task: ${row['description']}, Due: ${row['deadline'].toLocaleDateString()}`);\n      });\n\n      // Example: Update an item\n      return todoDb.update(itemTable)\n                   .set(itemTable.done, true)\n                   .where(itemTable.id.eq(1))\n                   .exec();\n    }).then(() => {\n      console.log('Task ID 1 marked as done.');\n    }).catch(err => {\n      console.error('Lovefield operation failed:', err);\n    });\n  </script>\n</body>\n</html>","lang":"javascript","description":"This quickstart demonstrates how to define a database schema, connect to the database, insert data, and query data using Lovefield's SQL-like API in a browser environment, including a simple update operation."},"warnings":[{"fix":"Consider migrating to actively maintained client-side database solutions like IndexedDB directly, Dexie.js, PouchDB, or other state management libraries with persistence layers.","message":"Lovefield is an abandoned project. The last npm package was published in 2017 (v2.1.12), and active development by Google ceased significantly earlier. Use in new projects is strongly discouraged due to lack of security updates, bug fixes, or compatibility with modern browser APIs and JavaScript features.","severity":"breaking","affected_versions":">=2.1.12"},{"fix":"Do not attempt to use Lovefield in Node.js. For server-side or desktop applications, choose a different database solution.","message":"Lovefield explicitly does NOT support Node.js environments. It relies on the browser's IndexedDB API, which is not available in Node.js. Attempts to use it in Node.js will result in runtime errors.","severity":"breaking","affected_versions":"all"},{"fix":"Ensure your entire schema is fully defined before calling `schemaBuilder.connect()`. For schema changes in existing databases, implement the `onUpgrade` callback within `connect()` options, providing logic for data migration between versions.","message":"Once the `connect()` method is called on a `schemaBuilder`, the database schema cannot be altered. Any attempts to modify the schema after connection will fail or require a database upgrade path, which needs to be explicitly handled.","severity":"gotcha","affected_versions":"all"},{"fix":"If modifications are needed, clone the result objects explicitly or perform updates via Lovefield's `update()` API, which ensures data integrity and proper persistence.","message":"The results returned from `select` queries should be treated as read-only. Modifying these objects directly is not recommended and may lead to unexpected behavior or inconsistencies, as Lovefield does not actively clone/freeze objects from its internal cache for performance reasons.","severity":"gotcha","affected_versions":"all"},{"fix":"To achieve `HAVING` functionality, perform a `select` query with `groupBy`, then filter the results in JavaScript. For complex `GROUP BY` scenarios, multiple queries or client-side aggregation may be necessary.","message":"Lovefield's SQL-like API does not support the `HAVING` clause, which is common in standard SQL for filtering grouped results. Additionally, multi-column `ROLLUP` and `CUBE` are not supported for `GROUP BY` operations.","severity":"gotcha","affected_versions":"all"},{"fix":"Database deletion must be performed manually through browser developer tools (e.g., Application -> IndexedDB in Chrome DevTools) or by clearing site data, which will remove all IndexedDB databases for the origin.","message":"Lovefield does not provide an API for programmatically deleting a database instance. This can complicate cleanup during development or for end-users who need to reset application data.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `<script src=\"path/to/lovefield.min.js\"></script>` is correctly placed in your HTML, preferably before any inline scripts that use `lf`. Verify the path to `lovefield.min.js` is correct and accessible.","cause":"The Lovefield JavaScript file was not loaded, or the code attempting to use 'lf' is executing before the script has parsed.","error":"ReferenceError: lf is not defined"},{"fix":"Ensure `schemaBuilder.connect()` is called only once. Store the returned database instance (`db`) and reuse it for all subsequent operations. You might need a global or module-scoped variable to hold the database connection promise or instance.","cause":"The `schemaBuilder.connect()` method was called more than once for the same database instance. Lovefield assumes a single connection at a time.","error":"Error: This database is already connected, cannot connect again."},{"fix":"Double-check that `lf` is defined and accessible. This often happens if the `lovefield.min.js` script failed to load or a module system (e.g., CommonJS `require`) was incorrectly used in a browser context. Ensure `lf.schema.create()` is called to get a schema builder before attempting `schemaBuilder.connect()`.","cause":"The `lf.schema` object was not correctly accessed, or the global `lf` object was not available when trying to call `create()` or `connect()`.","error":"TypeError: Cannot read properties of undefined (reading 'connect')"}],"ecosystem":"npm"}