Getting started
Install
npm install breeze-clientOne package, one tag. If you are used to choosing between breeze-client, breeze-client@cjs and breeze-client@mjs, that is gone — there is only latest.
Requirements: Node 20+ for server-side or test use, and any browser with native fetch. Breeze 3 ships ES modules only, so you will be using a bundler (Vite, webpack, esbuild, Rollup) or native import. There is no UMD bundle and no <script> tag build.
TypeScript 4.1 or later. The typings use template literal types, which arrived in 4.1; an older compiler cannot parse them at all.
A bundler that reads ES2022. The published JavaScript uses class fields, so the parser has to understand them: webpack 5, Vite, Rollup and esbuild all do. webpack 4 does not, which in practice means Angular 11 and earlier cannot bundle Breeze 3 without transpiling the package down a level first.
Configure
With a Breeze .NET server there is nothing to configure. Go straight to creating an EntityManager.
There are no adapters to import or register. Unless you say otherwise, Breeze talks to a Breeze .NET server, encodes queries as Breeze JSON, tracks changes with plain properties, makes its HTTP requests with the platform's fetch, and camel-cases property names: CompanyName on the server is companyName on the client. To replace any of those, see Configuration; to add auth headers or logging, see Supplying your own transport.
If your server already sends the property names the client should use — a Node server, say, or one whose names are already camelCase — turn the translation off. Do it once, at startup, before you create any EntityManager:
import { configureBreeze, NamingConvention } from 'breeze-client';
configureBreeze({ namingConvention: NamingConvention.none });NamingConvention.none.setAsDefault() does the same thing. See Naming conventions.
Create an EntityManager
An EntityManager is a cache plus a connection to one service. Most applications have one.
import { EntityManager } from 'breeze-client';
const em = new EntityManager('/breeze/NorthwindIBModel');The string is the service root. Breeze fetches metadata from /breeze/NorthwindIBModel/Metadata the first time you query, and uses it to build entity types, keys and relationships.
Give Breeze your entity classes
Optional, but it is what makes everything below type-checked, so it is worth two lines now. Write a class per entity type and register it:
import { EntityBase } from 'breeze-client';
// EntityBase declares the members Breeze supplies: entityAspect, entityType and the rest.
export class Customer extends EntityBase {
declare customerID: string;
declare companyName: string;
declare orders: Order[];
}
em.metadataStore.registerEntityTypeCtor('Customer', Customer);You don't have to write these by hand — Breeze ships a generator that produces one file per type from your service's metadata. See Generating entity classes, and Typed entities for what registering them buys you.
Skip this and everything still works; you reach properties through getProperty('companyName') instead, and results come back as any. The rest of this page shows both.
Query
import { EntityQuery } from 'breeze-client';
const query = EntityQuery
.from(Customer) // resource name comes from the metadata
.where('companyName', 'startsWith', 'B')
.orderBy('companyName')
.take(10);
const { results } = await em.executeQuery(query); // results: Customer[]
results.forEach(c => console.log(c.companyName));Without classes, name the resource and reach for properties by name:
const query = EntityQuery.from(Customer).where('companyName', 'startsWith', 'B');
const { results } = await em.executeQuery(query); // results: any[]
results.forEach(c => console.log(c.getProperty('companyName')));Results are entities, not plain objects: they are in the cache, they track their own changes, and their navigation properties are wired to other cached entities.
See Querying for the full query surface.
Change and save
const customer = results[0];
customer.companyName = 'Bravo Foods'; // or customer.setProperty('companyName', …)
console.log(customer.entityAspect.entityState.name); // "Modified"
const saveResult = await em.saveChanges();
console.log(`${saveResult.entities.length} entities saved`);saveChanges() sends every pending change in one request, and the server applies them in one transaction. You can also save a subset — see Saving changes.
Create a new entity
const order = em.createEntity(Order, {
customerID: customer.customerID,
orderDate: new Date(),
});
await em.saveChanges();createEntity gives the new entity a temporary key, adds it to the cache, and marks it Added. On save, the server assigns the real key and Breeze fixes up every reference to it.
Where next
- Configuration — the default adapters, replacing them, and supplying your own HTTP transport
- Querying — predicates, projections,
expand, querying the cache - Inside the entity —
entityAspect, entity state, original values - Migrating from 2.x — if you have an existing application