diff --git a/packages/base/package.json b/packages/base/package.json index 763cf027d7..c89c8fa673 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -18,6 +18,7 @@ "ember-concurrency": "^3.1.1", "ember-css-url": "^1.0.0", "ember-modifier": "^3.2.1", + "ember-resources": "^6.5.1", "ember-template-lint": "^5.11.2", "ethers": "^6.6.2", "matrix-js-sdk": "^31.0.0", diff --git a/packages/base/spec.gts b/packages/base/spec.gts index 504d033e39..b4e658364a 100644 --- a/packages/base/spec.gts +++ b/packages/base/spec.gts @@ -14,10 +14,8 @@ import StringField from './string'; import BooleanField from './boolean'; import CodeRef from './code-ref'; import MarkdownField from './markdown'; -import { restartableTask } from 'ember-concurrency'; import { FieldContainer, - LoadingIndicator, Pill, RealmIcon, BoxelInput, @@ -40,6 +38,8 @@ import StackIcon from '@cardstack/boxel-icons/stack'; import AppsIcon from '@cardstack/boxel-icons/apps'; import LayoutList from '@cardstack/boxel-icons/layout-list'; import Brain from '@cardstack/boxel-icons/brain'; +import { use, resource } from 'ember-resources'; +import { TrackedObject } from 'tracked-built-ins'; export type SpecType = 'card' | 'field' | 'app' | 'skill'; @@ -47,6 +47,720 @@ class SpecTypeField extends StringField { static displayName = 'Spec Type'; } +class Isolated extends Component { + get defaultIcon() { + return this.args.model.constructor?.icon; + } + + get icon() { + return this.loadCardIcon.value; + } + + @use private loadCardIcon = resource(() => { + let icon = new TrackedObject<{ value: CardOrFieldTypeIcon | undefined }>({ + value: undefined, + }); + (async () => { + try { + if (this.args.model.ref && this.args.model.id) { + let card = await loadCard(this.args.model.ref, { + loader: myLoader(), + relativeTo: new URL(this.args.model.id), + }); + icon.value = card.icon; + } + } catch (e) { + icon.value = undefined; + } + })(); + return icon; + }); + + get absoluteRef() { + if (!this.args.model.ref || !this.args.model.id) { + return undefined; + } + let url = new URL(this.args.model.id); + let ref = codeRefWithAbsoluteURL(this.args.model.ref, url); + if (!isResolvedCodeRef(ref)) { + throw new Error('ref is not a resolved code ref'); + } + return ref; + } + + private get realmInfo() { + return getCardMeta(this.args.model as CardDef, 'realmInfo'); + } + + +} + +class Fitted extends Component { + get defaultIcon() { + return this.args.model.constructor?.icon; + } + + get icon() { + return this.loadCardIcon.value; + } + + @use private loadCardIcon = resource(() => { + let icon = new TrackedObject<{ value: CardOrFieldTypeIcon | undefined }>({ + value: undefined, + }); + (async () => { + try { + if (this.args.model.ref && this.args.model.id) { + let card = await loadCard(this.args.model.ref, { + loader: myLoader(), + relativeTo: new URL(this.args.model.id), + }); + icon.value = card.icon; + } + } catch (e) { + icon.value = undefined; + } + })(); + return icon; + }); + + +} + +class Edit extends Component { + get defaultIcon() { + return this.args.model.constructor?.icon; + } + + get icon() { + return this.cardIconResource.value; + } + + @use private cardIconResource = resource(() => { + let icon = new TrackedObject<{ value: CardOrFieldTypeIcon | undefined }>({ + value: undefined, + }); + (async () => { + try { + if (this.args.model.ref && this.args.model.id) { + let card = await loadCard(this.args.model.ref, { + loader: myLoader(), + relativeTo: new URL(this.args.model.id), + }); + icon.value = card.icon; + } + } catch (e) { + icon.value = undefined; + } + })(); + return icon; + }); + + get absoluteRef() { + if (!this.args.model.ref || !this.args.model.id) { + return undefined; + } + let url = new URL(this.args.model.id); + let ref = codeRefWithAbsoluteURL(this.args.model.ref, url); + if (!isResolvedCodeRef(ref)) { + throw new Error('ref is not a resolved code ref'); + } + return ref; + } + + private get realmInfo() { + return getCardMeta(this.args.model as CardDef, 'realmInfo'); + } + + +} + class SpecTitleField extends StringField { static displayName = 'Spec Title'; @@ -149,229 +863,7 @@ export class Spec extends CardDef { @field title = contains(SpecTitleField); @field description = contains(SpecDescriptionField); - static isolated = class Isolated extends Component { - icon: CardOrFieldTypeIcon | undefined; - - get defaultIcon() { - return this.args.model.constructor?.icon; - } - constructor(owner: any, args: any) { - super(owner, args); - this.loadCardIcon.perform(); - } - - private loadCardIcon = restartableTask(async () => { - if (this.args.model.ref && this.args.model.id) { - let card = await loadCard(this.args.model.ref, { - loader: myLoader(), - relativeTo: new URL(this.args.model.id), - }); - this.icon = card.icon; - } - }); - - get absoluteRef() { - if (!this.args.model.ref || !this.args.model.id) { - return undefined; - } - let url = new URL(this.args.model.id); - let ref = codeRefWithAbsoluteURL(this.args.model.ref, url); - if (!isResolvedCodeRef(ref)) { - throw new Error('ref is not a resolved code ref'); - } - return ref; - } - - private get realmInfo() { - return getCardMeta(this.args.model as CardDef, 'realmInfo'); - } - - - }; + static isolated = Isolated; static embedded = class Embedded extends Component { get icon() { @@ -427,477 +919,9 @@ export class Spec extends CardDef { }; - static fitted = class Fitted extends Component { - icon: CardOrFieldTypeIcon | undefined; - - get defaultIcon() { - return this.args.model.constructor?.icon; - } - constructor(owner: any, args: any) { - super(owner, args); - this.loadCardIcon.perform(); - } - - private loadCardIcon = restartableTask(async () => { - if (this.args.model.ref && this.args.model.id) { - let card = await loadCard(this.args.model.ref, { - loader: myLoader(), - relativeTo: new URL(this.args.model.id), - }); - this.icon = card.icon; - } - }); - - - }; - - static edit = class Edit extends Component { - icon: CardOrFieldTypeIcon | undefined; + static fitted = Fitted; - get defaultIcon() { - return this.args.model.constructor?.icon; - } - constructor(owner: any, args: any) { - super(owner, args); - this.loadCardIcon.perform(); - } - - private loadCardIcon = restartableTask(async () => { - if (this.args.model.ref && this.args.model.id) { - let card = await loadCard(this.args.model.ref, { - loader: myLoader(), - relativeTo: new URL(this.args.model.id), - }); - this.icon = card.icon; - } - }); - - get absoluteRef() { - if (!this.args.model.ref || !this.args.model.id) { - return undefined; - } - let url = new URL(this.args.model.id); - let ref = codeRefWithAbsoluteURL(this.args.model.ref, url); - if (!isResolvedCodeRef(ref)) { - throw new Error('ref is not a resolved code ref'); - } - return ref; - } - - private get realmInfo() { - return getCardMeta(this.args.model as CardDef, 'realmInfo'); - } - - - }; + static edit = Edit; } interface SpecTagSignature { diff --git a/packages/realm-server/lib/externals.ts b/packages/realm-server/lib/externals.ts index b0ad821f65..ab1fcf29e7 100644 --- a/packages/realm-server/lib/externals.ts +++ b/packages/realm-server/lib/externals.ts @@ -126,7 +126,11 @@ export function shimExternals(virtualNetwork: VirtualNetwork) { }); virtualNetwork.shimModule('lodash', lodash); virtualNetwork.shimModule('date-fns', dateFns); - virtualNetwork.shimModule('ember-resources', { Resource: class {} }); + virtualNetwork.shimModule('ember-resources', { + Resource: class {}, + use() {}, + resource() {}, + }); virtualNetwork.shimModule('@ember/destroyable', {}); virtualNetwork.shimModule('marked', { marked: () => {} }); virtualNetwork.shimModule('ethers', ethers); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 447f78ef03..c262e06dfe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -79,7 +79,7 @@ importers: version: 6.3.0 ember-resources: specifier: ^6.5.1 - version: 6.5.1(@ember/test-waiters@3.0.2)(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-concurrency@3.1.1)(ember-source@5.4.1) + version: 6.5.1(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-source@5.4.1) ember-source: specifier: ~5.4.0 version: 5.4.1(patch_hash=oko46qetwhgpor6xgs7vahyney)(@babel/core@7.24.3)(@glimmer/component@1.1.2)(@glint/template@1.3.0)(rsvp@4.8.5)(webpack@5.89.0) @@ -232,6 +232,9 @@ importers: ember-modifier: specifier: ^4.1.0 version: 4.1.0(ember-source@5.4.1) + ember-resources: + specifier: ^6.5.1 + version: 6.5.1(@ember/test-waiters@3.0.2)(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-concurrency@3.1.1)(ember-source@5.4.1) ember-template-lint: specifier: ^5.11.2 version: 5.11.2 @@ -696,7 +699,7 @@ importers: version: 11.0.1(ember-source@5.4.1) ember-resources: specifier: ^6.5.1 - version: 6.5.1(@ember/test-waiters@3.0.2)(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-concurrency@3.1.1)(ember-source@5.4.1) + version: 6.5.1(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-source@5.4.1) ember-source: specifier: ^5.4.0 version: 5.4.1(patch_hash=oko46qetwhgpor6xgs7vahyney)(@babel/core@7.24.3)(@glimmer/component@1.1.2)(@glint/template@1.3.0)(rsvp@4.8.5)(webpack@5.89.0) @@ -1124,7 +1127,7 @@ importers: version: 11.0.1(ember-source@5.4.1) ember-resources: specifier: ^6.5.1 - version: 6.5.1(@ember/test-waiters@3.0.2)(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-concurrency@3.1.1)(ember-source@5.4.1) + version: 6.5.1(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-source@5.4.1) ember-source: specifier: ^5.4.0 version: 5.4.1(patch_hash=oko46qetwhgpor6xgs7vahyney)(@babel/core@7.24.3)(@glimmer/component@1.1.2)(@glint/template@1.3.0)(rsvp@4.8.5)(webpack@5.89.0) @@ -14408,7 +14411,7 @@ packages: '@babel/runtime': 7.22.11 '@ember/test-waiters': 3.0.2 '@embroider/addon-shim': 1.8.9 - '@embroider/macros': 1.16.5(@glint/template@1.3.0) + '@embroider/macros': 1.16.9(@glint/template@1.3.0) '@glimmer/component': 1.1.2(@babel/core@7.24.3) '@glimmer/tracking': 1.1.2 '@glint/template': 1.3.0 @@ -14419,6 +14422,35 @@ packages: - supports-color dev: true + /ember-resources@6.5.1(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(@glint/template@1.3.0)(ember-source@5.4.1): + resolution: {integrity: sha512-8eEdbSE0sioqjpB2CWw/dKF4Ftfe9tbebuSUfMDBmP3xxTIvxTDbvDnbd8A0IbQ0z/iQt6Va+/5cadzvkbMZtg==} + peerDependencies: + '@ember/test-waiters': ^3.0.0 + '@glimmer/component': ^1.1.2 + '@glimmer/tracking': ^1.1.2 + '@glint/template': ^1.0.0-beta.3 || ^1.0.0 + ember-concurrency: ^2.0.0 || ^3.0.0 + ember-source: ^3.28.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + '@ember/test-waiters': + optional: true + '@glimmer/component': + optional: true + ember-concurrency: + optional: true + dependencies: + '@babel/runtime': 7.22.11 + '@embroider/addon-shim': 1.8.9 + '@embroider/macros': 1.16.5(@glint/template@1.3.0) + '@glimmer/component': 1.1.2(@babel/core@7.24.3) + '@glimmer/tracking': 1.1.2 + '@glint/template': 1.3.0 + ember-async-data: 1.0.3(ember-source@5.4.1) + ember-source: 5.4.1(patch_hash=oko46qetwhgpor6xgs7vahyney)(@babel/core@7.24.3)(@glimmer/component@1.1.2)(@glint/template@1.3.0)(rsvp@4.8.5)(webpack@5.89.0) + transitivePeerDependencies: + - supports-color + dev: true + /ember-rfc176-data@0.3.18: resolution: {integrity: sha512-JtuLoYGSjay1W3MQAxt3eINWXNYYQliK90tLwtb8aeCuQK8zKGCRbBodVIrkcTqshULMnRuTOS6t1P7oQk3g6Q==}