Skip to content

Configuration ​

Breeze needs no configuration for a Breeze .NET server:

ts
import { EntityManager } from 'breeze-client';

const em = new EntityManager('/breeze/NorthwindIBModel');

Every setting has a default, listed below. Change the ones you need at startup, before you create any MetadataStore or EntityManager: stores and managers take the defaults in force when they are created.

What you can import ​

breeze-client holds everything a normal application needs. The rest are separate entry points so that a bundler leaves out what you do not import. The optional extensions among them — save queuing, entity graphs, RxJS and the Angular HttpClient bridge — are described together in Optional extensions.

Import fromWhat it is
breeze-clientEntityManager, EntityQuery, MetadataStore, Predicate, Validator, configureBreeze — the library
breeze-client/mixin-save-queuingenableSaveQueuing — queue a save made while another is in flight, and keep edits made during it. See Save queuing
breeze-client/mixin-get-entity-graphmixinEntityGraph, HasEntityGraph — adds em.getEntityGraph(roots, expand). See Entity graphs
breeze-client/rxjshasChanges$, entityChanged$ and the rest — Breeze events as RxJS observables. Needs rxjs, which you install yourself. See RxJS
breeze-client/adapter-angular-httpclienthttpClientFetch — sends Breeze's requests through Angular's HttpClient, so its interceptors see them. Needs @angular/common. See Angular HttpClient
breeze-client/adapter-model-library-backing-storeThe default model library adapter
breeze-client/adapter-data-service-webapiThe default data service adapter
breeze-client/adapter-uri-builder-jsonThe default URI builder
breeze-client/adapter-ajax-fetchThe deprecated ajax adapter — see Supplying your own transport
breeze-client/adapter-ajax-postSends queries as POST, for queries too long for a URL

The four adapter subpaths are the defaults, so you only import one to subclass it or to register it explicitly. The two mixins are opt-in: nothing pulls them in unless you import them.

Defaults ​

Adapters and transport ​

Breeze delegates three jobs to adapters, and makes its HTTP requests through a fetch function.

InterfaceJobDefaultTo replace it
modelLibraryhow entities track changesModelLibraryBackingStoreAdapter ('backingStore')configureBreeze({ modelLibrary })
dataServicehow to talk to the serverDataServiceWebApiAdapter ('webApi')configureBreeze({ dataService }) — see DataServiceAdapter
uriBuilderhow a query becomes a URLUriBuilderJsonAdapter ('json')configureBreeze({ uriBuilder })
HTTPmakes the requestno ajax adapter: config.fetch, which defaults to globalThis.fetchconfigureBreeze({ fetch }) — see Supplying your own transport

Breeze registers a default adapter the first time it needs it, and only for an interface that nothing has been registered for. Nothing is registered when you import Breeze, and anything you register takes precedence. A DataService resolves its adapters once, the first time it is used, and keeps them.

Global settings ​

SettingDefaultTo change it
Naming conventionNamingConvention.camelCase: CompanyName on the server is companyName on the clientconfigureBreeze({ namingConvention }), or NamingConvention.none.setAsDefault(). See Naming conventions
Local string comparisonLocalQueryComparisonOptions.caseInsensitiveSQL: case-insensitive, and == / != ignore leading and trailing spacesnew LocalQueryComparisonOptions({ ... }).setAsDefault(). See Querying the cache
Query optionsfetchStrategy: FetchStrategy.FromServer, mergeStrategy: MergeStrategy.PreserveChanges, includeDeleted: falsenew QueryOptions({ ... }).setAsDefault(); per manager with queryOptions; per query with EntityQuery.using(...)
Save optionsallowConcurrentSaves: false; saves go to SaveChanges on the manager's servicenew SaveOptions({ ... }).setAsDefault(); per manager with saveOptions; per save as the second argument to saveChanges
Validation optionsvalidateOnAttach: true, validateOnSave: true, validateOnQuery: false, validateOnPropertyChange: truenew ValidationOptions({ ... }).setAsDefault(); per manager with validationOptions
Transportconfig.fetch is unset, so requests use globalThis.fetchconfigureBreeze({ fetch }), or assign config.fetch

setAsDefault() changes the default for everything created afterwards. It does not change stores and managers that already exist.

EntityManager ​

new EntityManager(serviceName), or new EntityManager({ ... }) with any of:

OptionDefault
serviceNamenone
dataServicethe MetadataStore's DataService for serviceName, if it has one; otherwise a new DataService for that name
metadataStorea new MetadataStore, with the default naming convention and comparison options
queryOptions, saveOptions, validationOptionsthe defaults in force when the manager is created
keyGeneratorCtorKeyGenerator

DataService ​

OptionDefault
serviceNamerequired
hasServerMetadatatrue: metadata is fetched from {serviceName}/Metadata before the first query
adapterNamethe default data service adapter ('webApi')
uriBuilderNamethe default URI builder ('json')
jsonResultsAdapterthe data service adapter's own
useJsonpfalse. Deprecated: no effect on Breeze’s own transport

MetadataStore ​

OptionDefault
namingConventionthe default naming convention when the store is created. An empty store that imports metadata naming a convention adopts that one
localQueryComparisonOptionsthe default comparison options when the store is created. An empty store adopts the ones named in imported metadata, unless the store was given options of its own

configureBreeze ​

configureBreeze is optional. Use it to replace a default adapter, supply your own fetch, or set the naming convention:

ts
import { configureBreeze } from 'breeze-client';
import { MyWebApiAdapter } from './my-web-api-adapter';   // a subclass of DataServiceWebApiAdapter

configureBreeze({
  dataService: MyWebApiAdapter,
  fetch: authFetch,
});

The standard adapters are still exported, from breeze-client/adapter-model-library-backing-store, breeze-client/adapter-uri-builder-json and breeze-client/adapter-data-service-webapi, so that you can subclass them or register them explicitly. Passing one to configureBreeze does no harm, but it is not needed.

Options ​

OptionTypeNotes
modelLibraryadapter classreplaces the default, ModelLibraryBackingStoreAdapter
uriBuilderadapter classreplaces the default, UriBuilderJsonAdapter
ajaxadapter classdeprecated — see below
dataServiceadapter classreplaces the default, DataServiceWebApiAdapter
fetchBreezeFetchthe function every HTTP request goes through; defaults to globalThis.fetch. See Supplying your own transport
namingConventionNamingConventionsets the default, which is initially NamingConvention.camelCase
configBreezeConfigtarget a non-global config; rarely needed

You can call it more than once and pass only what you want to change:

ts
configureBreeze({ namingConvention: NamingConvention.none });

Registration order does not matter ​

Instead of passing an adapter to configureBreeze, you can call its static register(). Adapters can be registered in any order:

ts
import { DataServiceWebApiAdapter } from 'breeze-client/adapter-data-service-webapi';
import { UriBuilderJsonAdapter } from 'breeze-client/adapter-uri-builder-json';

// Either order works. So does leaving both out: these are the defaults.
UriBuilderJsonAdapter.register();
DataServiceWebApiAdapter.register();

What does matter is registering before you create an EntityManager — see Default adapters.

Importing does not register ​

In 2.x, importing an adapter module registered it as a side effect:

ts
// 2.x — the import alone was enough
import 'breeze-client/adapter-ajax-fetch';

Breeze 3 modules do not touch global state when imported. An adapter is registered only when you pass it to configureBreeze or call its register(), or when Breeze falls back to a default.

This makes import order irrelevant and lets bundlers reason about the package properly. It rarely matters otherwise: the adapters 2.x registered on import are the defaults, and need no registration at all. See Migrating from 2.x.

The older API still works ​

ts
config.registerAdapter('dataService', DataServiceWebApiAdapter);
config.initializeAdapterInstance('dataService', 'webApi', true);

registerAdapter, initializeAdapterInstance and initializeAdapterInstances are all still there and still work. They are marked @deprecated because configureBreeze is better — a misspelled adapter name is a compile error rather than a runtime one — but they are not scheduled for removal.

You don't need registerAdapter before initializing a default adapter by name. The names 'backingStore', 'json' and 'webApi', and the ajax adapter's 'fetch', resolve to the defaults, so 2.x startup code that relied on the import side effect runs as-is:

ts
config.initializeAdapterInstance('dataService', 'webApi', true);
config.initializeAdapterInstance('ajax', 'fetch', true);
// or
config.initializeAdapterInstances({ dataService: 'webApi', ajax: 'fetch' });

'fetch' gives an AjaxFetchAdapter that sends its requests through config.fetch. A name that is neither registered nor a default still throws Unregistered adapter.

Choosing adapters ​

modelLibrary ​

ModelLibraryBackingStoreAdapter is the default and the only one shipped, and the right choice for plain JavaScript and TypeScript models. The Knockout adapter was removed in 3.0.

dataService ​

DataServiceWebApiAdapter, the default, talks to a Breeze .NET server, or anything using the same JSON shape. To target a different backend, subclass AbstractDataServiceAdapter and register it — see DataServiceAdapter.

The OData data service adapter was removed in 3.0.

uriBuilder ​

UriBuilderJsonAdapter, the default, encodes the query as Breeze JSON in the query string. It is the only one shipped; the OData URI builder was removed in 3.0.

ajax (deprecated) ​

Breeze 3 does not need an ajax adapter. Every request goes through config.fetch, which defaults to globalThis.fetch. To add auth headers, retry or logging, supply your own fetch — see Supplying your own transport.

AjaxFetchAdapter and the ajax option are kept so that 2.x startup code keeps working. If you register an ajax adapter, Breeze uses it instead of config.fetch. There is no reason to in new code.

Naming conventions ​

A NamingConvention translates between server and client property names. The default is NamingConvention.camelCase.

  • NamingConvention.camelCase — CompanyName ⟷ companyName. The default, and what a .NET server needs.
  • NamingConvention.none — names pass through unchanged. Use it when the server already sends the names the client should use:
ts
configureBreeze({ namingConvention: NamingConvention.none });
// or
NamingConvention.none.setAsDefault();

Metadata that names a naming convention sets it when imported into an empty MetadataStore. See Naming conventions for custom conventions.

Content Security Policy ​

Breeze needs no Content Security Policy exception. It never evaluates a string - no eval, no new Function - so a policy without 'unsafe-eval' runs it without complaint and without CSP violation reports.

Released under the MIT License.