Skip to content

Ember.js

Configure Reactivity

  1. Ensure @warp-drive/ember is installed with the proper version
  2. In the main entry point for your app add the following side-effect import
app/app.ts
ts
import '@warp-drive/ember/install';
  1. If you have tests, such as unit tests, which make use of WarpDrive directly and not via an app container you may also need to add the side-effect import to tests/test-helper.{js,ts}

  2. If it is installed, remove the package @ember-data/tracking.

  3. Change any usage of untracked

ts
import { untracked } from '@ember-data/tracking'; 
import { untrack as untracked } from '@glimmer/validator'; 

💡 @glimmer/validator is a virtual dep

You do not need to add a dependency on @glimmer/validator, this is a virtual package provided by ember-source.

  1. Remove the deprecation for use of @ember-data/tracking by setting the deprecation to false in your build config:
ember-cli-build.js
ts
'use strict';
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const { compatBuild } = require('@embroider/compat');

module.exports = async function (defaults) {
  const { setConfig } = await import('@warp-drive/build-config');
  const { buildOnce } = await import('@embroider/vite');
  const app = new EmberApp(defaults, {});

  setConfig(app, __dirname, {
    // this should be the most recent <major>.<minor> version for
    // which all deprecations have been fully resolved
    // and should be updated when that changes
    compatWith: '4.12'
    deprecations: { 
      DEPRECATE_TRACKING_PACKAGE: false 
    }
  });

  return compatBuild(app, buildOnce);
};

Setup Legacy Support

This guide presumes you've already gone through the setup steps that apply to all applications

"Legacy" is a term that applies to a fairly broad set of patterns that WarpDrive/EmberData is migrating away from. The previous guide showed how to configure schemas and reactivity to work with the legacy Model approach. You may also wish to configure legacy support for Adapters and Serializers.

Reasons to configure this legacy support include:

  • You have an existing application that has not migrated all requests away from this pattern
  • You are creating a new application and LinksMode is not sufficient
  1. Ensure @ember-data/legacy-compat is installed with the proper version
  2. Add desired hooks to the store. The below example builds from the Model example in the prior guide.
app/services/store.ts
ts
import Store, { CacheHandler } from '@ember-data/store';
import type { CacheCapabilitiesManager, ModelSchema, SchemaService } from '@ember-data/store/types';

import RequestManager from '@ember-data/request';
import Fetch from '@ember-data/request/fetch';
import { CachePolicy } from '@ember-data/request-utils';

import JSONAPICache from '@ember-data/json-api';

import type { ResourceKey } from '@warp-drive/core-types';
import type { TypeFromInstance } from '@warp-drive/core-types/record';

import type Model from '@ember-data/model';
import {
  buildSchema,
  instantiateRecord,
  modelFor,
  teardownRecord
} from '@ember-data/model/hooks';
import { 
  adapterFor,
  cleanup,
  LegacyNetworkHandler,
  normalize,
  pushPayload,
  serializeRecord,
  serializerFor,
} from '@ember-data/legacy-compat';

export default class AppStore extends Store {

  requestManager = new RequestManager()
    .use([LegacyNetworkHandler, Fetch]) 
    .useCache(CacheHandler);

  lifetimes = new CachePolicy({
    apiHardExpires: 15 * 60 * 1000, // 15 minutes
    apiSoftExpires: 1 * 30 * 1000, // 30 seconds
    constraints: {
      'X-WarpDrive-Expires': true,
      'Cache-Control': true,
      'Expires': true,
    }
  });

  createSchemaService(): SchemaService {
    return buildSchema(this);
  }

  createCache(capabilities: CacheCapabilitiesManager) {
    return new JSONAPICache(capabilities);
  }

  instantiateRecord(identifier: ResourceKey, createRecordArgs: Record<string, unknown>) {
    return instantiateRecord.call(this, identifier, createRecordArgs);
  }

  teardownRecord(record: unknown): void {
    return teardownRecord.call(this, record as Model);
  }

  modelFor<T>(type: TypeFromInstance<T>): ModelSchema<T>;
  modelFor(type: string): ModelSchema;
  modelFor(type: string): ModelSchema {
    return (modelFor.call(this, type) as ModelSchema) || super.modelFor(type);
  }

  adapterFor = adapterFor; 
  serializerFor = serializerFor;
  pushPayload = pushPayload;
  normalize = normalize;
  serializeRecord = serializeRecord;

  destroy() {  
    cleanup.call(this);
    super.destroy();
  }
}

Released under the MIT License.