ember-tribe 3.0.5 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,7 +34,8 @@ function camelize(str) {
34
34
  * 'blogPost' | 'blog-post' | 'blog_post' → canonical snake_case 'blog_post'
35
35
  */
36
36
  function normalizeType(type) {
37
- return underscore(type.replace(/-/g, '_'));
37
+ if (!type) return '';
38
+ return underscore(String(type).replace(/-/g, '_'));
38
39
  }
39
40
 
40
41
  /**
@@ -445,11 +446,49 @@ export default class StoreService extends Service {
445
446
 
446
447
  /**
447
448
  * Normalise a JSON:API document and push all resources into the cache.
448
- * Returns { data: Record | [Record], meta }.
449
+ * Also handles raw (non-JSON:API) responses from the Tribe API by wrapping
450
+ * them into a JSON:API resource on the fly.
451
+ *
452
+ * @param {Object} payload The parsed JSON body from the server.
453
+ * @param {string} [contextType] The model type the caller requested (used
454
+ * to wrap raw responses that lack a `data` key).
455
+ * @param {string} [contextId] The id the caller requested.
456
+ * @returns {{ data: Record|Record[]|null, meta: Object }}
449
457
  */
450
- _normalizeAndPush(payload) {
458
+ _normalizeAndPush(payload, contextType, contextId) {
451
459
  if (!payload) return { data: null, meta: {} };
452
460
 
461
+ // -------------------------------------------------------------------
462
+ // Detect whether this is a JSON:API envelope or a raw Tribe response.
463
+ // JSON:API always has a top-level `data` key (object or array).
464
+ // If it's missing, treat the entire payload as a single raw resource.
465
+ // -------------------------------------------------------------------
466
+ if (!('data' in payload)) {
467
+ // Raw response — wrap it into JSON:API shape.
468
+ // `contextType` tells us what type was requested.
469
+ if (!contextType) {
470
+ // If we truly don't know the type, return the raw object as attributes
471
+ // on a best-effort basis.
472
+ return { data: payload, meta: payload.meta || {} };
473
+ }
474
+
475
+ const id = contextId ?? payload.id ?? payload.slug ?? '0';
476
+ const { id: _discardId, meta, ...attrs } = payload;
477
+
478
+ const wrapped = {
479
+ data: {
480
+ id: String(id),
481
+ type: normalizeType(contextType),
482
+ attributes: attrs,
483
+ },
484
+ meta: meta || {},
485
+ };
486
+ return this._normalizeAndPush(wrapped, contextType, contextId);
487
+ }
488
+
489
+ // -------------------------------------------------------------------
490
+ // Standard JSON:API path
491
+ // -------------------------------------------------------------------
453
492
  const meta = payload.meta || {};
454
493
 
455
494
  // Side-load included resources first
@@ -459,8 +498,15 @@ export default class StoreService extends Service {
459
498
 
460
499
  let data;
461
500
  if (Array.isArray(payload.data)) {
462
- data = payload.data.map((r) => this._pushResource(r));
463
- } else if (payload.data) {
501
+ data = payload.data
502
+ .filter((r) => r && r.type) // skip malformed entries
503
+ .map((r) => this._pushResource(r));
504
+ } else if (payload.data && payload.data.type) {
505
+ data = this._pushResource(payload.data);
506
+ } else if (payload.data && contextType) {
507
+ // `data` exists but has no `type` — inject it from context
508
+ payload.data.type = normalizeType(contextType);
509
+ if (!payload.data.id && contextId != null) payload.data.id = String(contextId);
464
510
  data = this._pushResource(payload.data);
465
511
  } else {
466
512
  data = null;
@@ -602,7 +648,7 @@ export default class StoreService extends Service {
602
648
  const payload = this._serialise(record);
603
649
  const json = await this._fetch(url, { method: 'POST', body: JSON.stringify(payload) });
604
650
  if (json) {
605
- const { data } = this._normalizeAndPush(json);
651
+ const { data } = this._normalizeAndPush(json, record._type);
606
652
  // The server may assign an id
607
653
  if (data && data._id) {
608
654
  // Re-key in cache
@@ -621,7 +667,7 @@ export default class StoreService extends Service {
621
667
  const url = this._urlForRecord(record._type, record._id);
622
668
  const payload = this._serialise(record);
623
669
  const json = await this._fetch(url, { method: 'PATCH', body: JSON.stringify(payload) });
624
- if (json) this._normalizeAndPush(json);
670
+ if (json) this._normalizeAndPush(json, record._type, record._id);
625
671
  }
626
672
 
627
673
  async _deleteRemote(record) {
@@ -642,7 +688,7 @@ export default class StoreService extends Service {
642
688
  const params = this._buildQueryParams(options);
643
689
  if (params) url += `?${params}`;
644
690
  const json = await this._fetch(url);
645
- const { data, meta } = this._normalizeAndPush(json);
691
+ const { data, meta } = this._normalizeAndPush(json, type, id);
646
692
  if (meta) this._meta.set(normalizeType(type), meta);
647
693
  return data;
648
694
  }
@@ -663,7 +709,7 @@ export default class StoreService extends Service {
663
709
  const params = this._buildQueryParams(options);
664
710
  if (params) url += `?${params}`;
665
711
  const json = await this._fetch(url);
666
- const { data, meta } = this._normalizeAndPush(json);
712
+ const { data, meta } = this._normalizeAndPush(json, type);
667
713
  const records = Array.isArray(data) ? data : data ? [data] : [];
668
714
  // Update or create live array
669
715
  const nType = normalizeType(type);
@@ -698,7 +744,7 @@ export default class StoreService extends Service {
698
744
  const qs = this._buildQueryParams(params);
699
745
  if (qs) url += `?${qs}`;
700
746
  const json = await this._fetch(url);
701
- const { data, meta } = this._normalizeAndPush(json);
747
+ const { data, meta } = this._normalizeAndPush(json, type);
702
748
  const records = Array.isArray(data) ? data : data ? [data] : [];
703
749
  return new RecordArray(records, meta);
704
750
  }
@@ -711,7 +757,7 @@ export default class StoreService extends Service {
711
757
  const qs = this._buildQueryParams(params);
712
758
  if (qs) url += `?${qs}`;
713
759
  const json = await this._fetch(url);
714
- const { data, meta } = this._normalizeAndPush(json);
760
+ const { data, meta } = this._normalizeAndPush(json, type);
715
761
  if (Array.isArray(data)) return data[0] || null;
716
762
  return data;
717
763
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-tribe",
3
- "version": "3.0.5",
3
+ "version": "3.0.6",
4
4
  "description": "The default blueprint for ember-cli addons.",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -1,6 +0,0 @@
1
- import Model, { attr } from '@ember-data/model';
2
-
3
- export default class WebappModel extends Model {
4
- @attr slug;
5
- @attr modules;
6
- }