@warp-drive/legacy 5.9.0-alpha.21 → 5.9.0-alpha.22
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.
- package/dist/-private-DQ6Iap2t.js +193 -0
- package/dist/-private-DQ6Iap2t.js.map +1 -0
- package/dist/-private-DccRZQsm.js +904 -0
- package/dist/-private-DccRZQsm.js.map +1 -0
- package/dist/adapter/-private.d.ts +33 -0
- package/dist/adapter/-private.d.ts.map +1 -0
- package/dist/adapter/-private.js +3 -1
- package/dist/adapter/error.d.ts +2 -0
- package/dist/adapter/error.js +422 -453
- package/dist/adapter/error.js.map +1 -0
- package/{declarations → dist}/adapter/json-api.d.ts +30 -29
- package/dist/adapter/json-api.d.ts.map +1 -0
- package/dist/adapter/json-api.js +265 -143
- package/dist/adapter/json-api.js.map +1 -0
- package/dist/adapter/rest.d.ts +2 -0
- package/dist/adapter/rest.js +937 -1136
- package/dist/adapter/rest.js.map +1 -0
- package/dist/adapter-CARrK3-8.d.ts +784 -0
- package/dist/adapter-CARrK3-8.d.ts.map +1 -0
- package/dist/adapter-XgLAkYVs.js +1130 -0
- package/dist/adapter-XgLAkYVs.js.map +1 -0
- package/dist/adapter.d.ts +2 -0
- package/dist/adapter.js +1 -1248
- package/dist/compat/-private.d.ts +2 -0
- package/dist/compat/-private.js +3 -1
- package/dist/compat/builders.d.ts +169 -0
- package/dist/compat/builders.d.ts.map +1 -0
- package/dist/compat/builders.js +205 -245
- package/dist/compat/builders.js.map +1 -0
- package/dist/compat/extensions.d.ts +2 -0
- package/dist/compat/extensions.js +265 -304
- package/dist/compat/extensions.js.map +1 -0
- package/dist/compat/utils.d.ts +151 -0
- package/dist/compat/utils.d.ts.map +1 -0
- package/dist/compat/utils.js +187 -206
- package/dist/compat/utils.js.map +1 -0
- package/dist/compat-BbNNmTM-.d.ts +1386 -0
- package/dist/compat-BbNNmTM-.d.ts.map +1 -0
- package/dist/compat-g__Pfy2S.js +734 -0
- package/dist/compat-g__Pfy2S.js.map +1 -0
- package/dist/compat.d.ts +2 -0
- package/dist/compat.js +1 -1036
- package/dist/error-CzkyXr1Q.d.ts +435 -0
- package/dist/error-CzkyXr1Q.d.ts.map +1 -0
- package/dist/errors-LQhmDVdd.js +2134 -0
- package/dist/errors-LQhmDVdd.js.map +1 -0
- package/dist/extensions-DumNm4dA.d.ts +102 -0
- package/dist/extensions-DumNm4dA.d.ts.map +1 -0
- package/dist/index.d.ts +243 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +267 -339
- package/dist/index.js.map +1 -0
- package/dist/json-BXNPTlcH.js +1106 -0
- package/dist/json-BXNPTlcH.js.map +1 -0
- package/dist/model/-private.d.ts +3 -0
- package/dist/model/-private.js +3 -1
- package/dist/model/migration-support.d.ts +335 -0
- package/dist/model/migration-support.d.ts.map +1 -0
- package/dist/model/migration-support.js +504 -575
- package/dist/model/migration-support.js.map +1 -0
- package/dist/model-62hn5_PD.d.ts +3107 -0
- package/dist/model-62hn5_PD.d.ts.map +1 -0
- package/dist/model-BtIEHqYZ.js +683 -0
- package/dist/model-BtIEHqYZ.js.map +1 -0
- package/dist/model-fragments-Dpn9285r.js +334 -0
- package/dist/model-fragments-Dpn9285r.js.map +1 -0
- package/dist/model-fragments.d.ts +294 -0
- package/dist/model-fragments.d.ts.map +1 -0
- package/dist/model-fragments.js +2 -94
- package/dist/model.d.ts +404 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +3 -670
- package/{declarations/adapter/rest.d.ts → dist/rest-0NhtexIq.d.ts} +183 -173
- package/dist/rest-0NhtexIq.d.ts.map +1 -0
- package/dist/runtime-BPCpkOf1-BgO3Lyjx.js +53 -0
- package/dist/runtime-BPCpkOf1-BgO3Lyjx.js.map +1 -0
- package/dist/schema-provider-DsKuB5Wb.js +1929 -0
- package/dist/schema-provider-DsKuB5Wb.js.map +1 -0
- package/{declarations → dist}/serializer/json-api.d.ts +3 -0
- package/dist/serializer/json-api.d.ts.map +1 -0
- package/dist/serializer/json-api.js +527 -519
- package/dist/serializer/json-api.js.map +1 -0
- package/{declarations → dist}/serializer/json.d.ts +3 -0
- package/dist/serializer/json.d.ts.map +1 -0
- package/dist/serializer/json.js +3 -6
- package/{declarations/serializer/-private/embedded-records-mixin.d.ts → dist/serializer/rest.d.ts} +56 -1
- package/dist/serializer/rest.d.ts.map +1 -0
- package/dist/serializer/rest.js +958 -1199
- package/dist/serializer/rest.js.map +1 -0
- package/dist/serializer/transform.d.ts +313 -0
- package/dist/serializer/transform.d.ts.map +1 -0
- package/dist/serializer/transform.js +283 -308
- package/dist/serializer/transform.js.map +1 -0
- package/dist/serializer.d.ts +151 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +205 -205
- package/dist/serializer.js.map +1 -0
- package/dist/store-C4qYzXei.js +473 -0
- package/dist/store-C4qYzXei.js.map +1 -0
- package/dist/store.d.ts +13 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +1 -641
- package/dist/unpkg/dev/-private-CrEyBE-B.js +189 -0
- package/dist/unpkg/dev/-private-CrEyBE-B.js.map +1 -0
- package/dist/unpkg/dev/-private-vOhxVExH.js +896 -0
- package/dist/unpkg/dev/-private-vOhxVExH.js.map +1 -0
- package/dist/unpkg/dev/adapter/-private.js +3 -1
- package/dist/unpkg/dev/adapter/error.js +421 -452
- package/dist/unpkg/dev/adapter/error.js.map +1 -0
- package/dist/unpkg/dev/adapter/json-api.js +239 -257
- package/dist/unpkg/dev/adapter/json-api.js.map +1 -0
- package/dist/unpkg/dev/adapter/rest.js +935 -1134
- package/dist/unpkg/dev/adapter/rest.js.map +1 -0
- package/dist/unpkg/dev/adapter-Cw0uSl8d.js +1129 -0
- package/dist/unpkg/dev/adapter-Cw0uSl8d.js.map +1 -0
- package/dist/unpkg/dev/adapter.js +1 -1247
- package/dist/unpkg/dev/compat/-private.js +3 -1
- package/dist/unpkg/dev/compat/builders.js +204 -247
- package/dist/unpkg/dev/compat/builders.js.map +1 -0
- package/dist/unpkg/dev/compat/extensions.js +264 -303
- package/dist/unpkg/dev/compat/extensions.js.map +1 -0
- package/dist/unpkg/dev/compat/utils.js +186 -205
- package/dist/unpkg/dev/compat/utils.js.map +1 -0
- package/dist/unpkg/dev/compat-CeyxXB7K.js +825 -0
- package/dist/unpkg/dev/compat-CeyxXB7K.js.map +1 -0
- package/dist/unpkg/dev/compat.js +1 -1178
- package/dist/unpkg/dev/errors-1javxsPo.js +2127 -0
- package/dist/unpkg/dev/errors-1javxsPo.js.map +1 -0
- package/dist/unpkg/dev/index.js +266 -344
- package/dist/unpkg/dev/index.js.map +1 -0
- package/dist/unpkg/dev/json-DDJji3V3.js +1104 -0
- package/dist/unpkg/dev/json-DDJji3V3.js.map +1 -0
- package/dist/unpkg/dev/model/-private.js +3 -1
- package/dist/unpkg/dev/model/migration-support.js +481 -549
- package/dist/unpkg/dev/model/migration-support.js.map +1 -0
- package/dist/unpkg/dev/model-C9Xb1R1x.js +655 -0
- package/dist/unpkg/dev/model-C9Xb1R1x.js.map +1 -0
- package/dist/unpkg/dev/model-fragments-Dpn9285r.js +334 -0
- package/dist/unpkg/dev/model-fragments-Dpn9285r.js.map +1 -0
- package/dist/unpkg/dev/model-fragments.js +2 -94
- package/dist/unpkg/dev/model.js +3 -681
- package/dist/unpkg/dev/runtime-BPCpkOf1-BgO3Lyjx.js +53 -0
- package/dist/unpkg/dev/runtime-BPCpkOf1-BgO3Lyjx.js.map +1 -0
- package/dist/unpkg/dev/schema-provider-Dy6c1J5f.js +1834 -0
- package/dist/unpkg/dev/schema-provider-Dy6c1J5f.js.map +1 -0
- package/dist/unpkg/dev/serializer/json-api.js +514 -634
- package/dist/unpkg/dev/serializer/json-api.js.map +1 -0
- package/dist/unpkg/dev/serializer/json.js +3 -4
- package/dist/unpkg/dev/serializer/rest.js +954 -1196
- package/dist/unpkg/dev/serializer/rest.js.map +1 -0
- package/dist/unpkg/dev/serializer/transform.js +283 -308
- package/dist/unpkg/dev/serializer/transform.js.map +1 -0
- package/dist/unpkg/dev/serializer.js +205 -205
- package/dist/unpkg/dev/serializer.js.map +1 -0
- package/dist/unpkg/dev/store-D_V8-HQl.js +472 -0
- package/dist/unpkg/dev/store-D_V8-HQl.js.map +1 -0
- package/dist/unpkg/dev/store.js +1 -649
- package/dist/unpkg/dev/util-dSKEgQDp.js +12 -0
- package/dist/unpkg/dev/util-dSKEgQDp.js.map +1 -0
- package/dist/unpkg/dev/utils-DYC9utVJ.js +11 -0
- package/dist/unpkg/dev/utils-DYC9utVJ.js.map +1 -0
- package/dist/unpkg/dev-deprecated/-private-CrEyBE-B.js +189 -0
- package/dist/unpkg/dev-deprecated/-private-CrEyBE-B.js.map +1 -0
- package/dist/unpkg/dev-deprecated/-private-vOhxVExH.js +896 -0
- package/dist/unpkg/dev-deprecated/-private-vOhxVExH.js.map +1 -0
- package/dist/unpkg/dev-deprecated/adapter/-private.js +3 -1
- package/dist/unpkg/dev-deprecated/adapter/error.js +421 -452
- package/dist/unpkg/dev-deprecated/adapter/error.js.map +1 -0
- package/dist/unpkg/dev-deprecated/adapter/json-api.js +239 -257
- package/dist/unpkg/dev-deprecated/adapter/json-api.js.map +1 -0
- package/dist/unpkg/dev-deprecated/adapter/rest.js +935 -1134
- package/dist/unpkg/dev-deprecated/adapter/rest.js.map +1 -0
- package/dist/unpkg/dev-deprecated/adapter-Cw0uSl8d.js +1129 -0
- package/dist/unpkg/dev-deprecated/adapter-Cw0uSl8d.js.map +1 -0
- package/dist/unpkg/dev-deprecated/adapter.js +1 -1247
- package/dist/unpkg/dev-deprecated/compat/-private.js +3 -1
- package/dist/unpkg/dev-deprecated/compat/builders.js +204 -247
- package/dist/unpkg/dev-deprecated/compat/builders.js.map +1 -0
- package/dist/unpkg/dev-deprecated/compat/extensions.js +264 -303
- package/dist/unpkg/dev-deprecated/compat/extensions.js.map +1 -0
- package/dist/unpkg/dev-deprecated/compat/utils.js +186 -205
- package/dist/unpkg/dev-deprecated/compat/utils.js.map +1 -0
- package/dist/unpkg/dev-deprecated/compat-DmAgB2NS.js +825 -0
- package/dist/unpkg/dev-deprecated/compat-DmAgB2NS.js.map +1 -0
- package/dist/unpkg/dev-deprecated/compat.js +1 -1178
- package/dist/unpkg/dev-deprecated/errors-C4_aOhY5.js +2128 -0
- package/dist/unpkg/dev-deprecated/errors-C4_aOhY5.js.map +1 -0
- package/dist/unpkg/dev-deprecated/index.js +266 -343
- package/dist/unpkg/dev-deprecated/index.js.map +1 -0
- package/dist/unpkg/dev-deprecated/json-DDJji3V3.js +1104 -0
- package/dist/unpkg/dev-deprecated/json-DDJji3V3.js.map +1 -0
- package/dist/unpkg/dev-deprecated/model/-private.js +3 -1
- package/dist/unpkg/dev-deprecated/model/migration-support.js +492 -566
- package/dist/unpkg/dev-deprecated/model/migration-support.js.map +1 -0
- package/dist/unpkg/dev-deprecated/model-CvSMYkgs.js +660 -0
- package/dist/unpkg/dev-deprecated/model-CvSMYkgs.js.map +1 -0
- package/dist/unpkg/dev-deprecated/model-fragments-Dpn9285r.js +334 -0
- package/dist/unpkg/dev-deprecated/model-fragments-Dpn9285r.js.map +1 -0
- package/dist/unpkg/dev-deprecated/model-fragments.js +2 -94
- package/dist/unpkg/dev-deprecated/model.js +3 -685
- package/dist/unpkg/dev-deprecated/runtime-BPCpkOf1-BgO3Lyjx.js +53 -0
- package/dist/unpkg/dev-deprecated/runtime-BPCpkOf1-BgO3Lyjx.js.map +1 -0
- package/dist/unpkg/dev-deprecated/schema-provider-Cqttza94.js +1835 -0
- package/dist/unpkg/dev-deprecated/schema-provider-Cqttza94.js.map +1 -0
- package/dist/unpkg/dev-deprecated/serializer/json-api.js +514 -634
- package/dist/unpkg/dev-deprecated/serializer/json-api.js.map +1 -0
- package/dist/unpkg/dev-deprecated/serializer/json.js +3 -4
- package/dist/unpkg/dev-deprecated/serializer/rest.js +954 -1196
- package/dist/unpkg/dev-deprecated/serializer/rest.js.map +1 -0
- package/dist/unpkg/dev-deprecated/serializer/transform.js +283 -308
- package/dist/unpkg/dev-deprecated/serializer/transform.js.map +1 -0
- package/dist/unpkg/dev-deprecated/serializer.js +205 -205
- package/dist/unpkg/dev-deprecated/serializer.js.map +1 -0
- package/dist/unpkg/dev-deprecated/store-BX7GvXC_.js +472 -0
- package/dist/unpkg/dev-deprecated/store-BX7GvXC_.js.map +1 -0
- package/dist/unpkg/dev-deprecated/store.js +1 -649
- package/dist/unpkg/dev-deprecated/util-9mgEBJ3W.js +18 -0
- package/dist/unpkg/dev-deprecated/util-9mgEBJ3W.js.map +1 -0
- package/dist/unpkg/dev-deprecated/utils-Cl86-e7F.js +17 -0
- package/dist/unpkg/dev-deprecated/utils-Cl86-e7F.js.map +1 -0
- package/dist/unpkg/prod/-private-B4bxoTuK.js +160 -0
- package/dist/unpkg/prod/-private-B4bxoTuK.js.map +1 -0
- package/dist/unpkg/prod/-private-SfXkkHKd.js +745 -0
- package/dist/unpkg/prod/-private-SfXkkHKd.js.map +1 -0
- package/dist/unpkg/prod/adapter/-private.js +3 -1
- package/dist/unpkg/prod/adapter/error.js +418 -447
- package/dist/unpkg/prod/adapter/error.js.map +1 -0
- package/dist/unpkg/prod/adapter/json-api.js +236 -252
- package/dist/unpkg/prod/adapter/json-api.js.map +1 -0
- package/dist/unpkg/prod/adapter/rest.js +911 -1097
- package/dist/unpkg/prod/adapter/rest.js.map +1 -0
- package/dist/unpkg/prod/adapter-Wnk7jizX.js +1111 -0
- package/dist/unpkg/prod/adapter-Wnk7jizX.js.map +1 -0
- package/dist/unpkg/prod/adapter.js +1 -1214
- package/dist/unpkg/prod/compat/-private.js +3 -1
- package/dist/unpkg/prod/compat/builders.js +165 -182
- package/dist/unpkg/prod/compat/builders.js.map +1 -0
- package/dist/unpkg/prod/compat/extensions.js +252 -283
- package/dist/unpkg/prod/compat/extensions.js.map +1 -0
- package/dist/unpkg/prod/compat/utils.js +183 -200
- package/dist/unpkg/prod/compat/utils.js.map +1 -0
- package/dist/unpkg/prod/compat-CJ87MzDn.js +547 -0
- package/dist/unpkg/prod/compat-CJ87MzDn.js.map +1 -0
- package/dist/unpkg/prod/compat.js +1 -742
- package/dist/unpkg/prod/errors-Co7YWHoA.js +1977 -0
- package/dist/unpkg/prod/errors-Co7YWHoA.js.map +1 -0
- package/dist/unpkg/prod/index.js +245 -308
- package/dist/unpkg/prod/index.js.map +1 -0
- package/dist/unpkg/prod/json-BD1kRTfB.js +1080 -0
- package/dist/unpkg/prod/json-BD1kRTfB.js.map +1 -0
- package/dist/unpkg/prod/model/-private.js +3 -1
- package/dist/unpkg/prod/model/migration-support.js +477 -542
- package/dist/unpkg/prod/model/migration-support.js.map +1 -0
- package/dist/unpkg/prod/model-BzoOmtka.js +603 -0
- package/dist/unpkg/prod/model-BzoOmtka.js.map +1 -0
- package/dist/unpkg/prod/model-fragments-Dpn9285r.js +334 -0
- package/dist/unpkg/prod/model-fragments-Dpn9285r.js.map +1 -0
- package/dist/unpkg/prod/model-fragments.js +2 -94
- package/dist/unpkg/prod/model.js +3 -596
- package/dist/unpkg/prod/runtime-BPCpkOf1-BgO3Lyjx.js +53 -0
- package/dist/unpkg/prod/runtime-BPCpkOf1-BgO3Lyjx.js.map +1 -0
- package/dist/unpkg/prod/schema-provider-CKZcqWyP.js +1622 -0
- package/dist/unpkg/prod/schema-provider-CKZcqWyP.js.map +1 -0
- package/dist/unpkg/prod/serializer/json-api.js +497 -592
- package/dist/unpkg/prod/serializer/json-api.js.map +1 -0
- package/dist/unpkg/prod/serializer/json.js +3 -4
- package/dist/unpkg/prod/serializer/rest.js +938 -1166
- package/dist/unpkg/prod/serializer/rest.js.map +1 -0
- package/dist/unpkg/prod/serializer/transform.js +283 -308
- package/dist/unpkg/prod/serializer/transform.js.map +1 -0
- package/dist/unpkg/prod/serializer.js +205 -205
- package/dist/unpkg/prod/serializer.js.map +1 -0
- package/dist/unpkg/prod/store-RGGc1ilN.js +392 -0
- package/dist/unpkg/prod/store-RGGc1ilN.js.map +1 -0
- package/dist/unpkg/prod/store.js +1 -517
- package/dist/unpkg/prod/util-dSKEgQDp.js +12 -0
- package/dist/unpkg/prod/util-dSKEgQDp.js.map +1 -0
- package/dist/unpkg/prod/utils-DYC9utVJ.js +11 -0
- package/dist/unpkg/prod/utils-DYC9utVJ.js.map +1 -0
- package/dist/unpkg/prod-deprecated/-private-B4bxoTuK.js +160 -0
- package/dist/unpkg/prod-deprecated/-private-B4bxoTuK.js.map +1 -0
- package/dist/unpkg/prod-deprecated/-private-SfXkkHKd.js +745 -0
- package/dist/unpkg/prod-deprecated/-private-SfXkkHKd.js.map +1 -0
- package/dist/unpkg/prod-deprecated/adapter/-private.js +3 -1
- package/dist/unpkg/prod-deprecated/adapter/error.js +418 -447
- package/dist/unpkg/prod-deprecated/adapter/error.js.map +1 -0
- package/dist/unpkg/prod-deprecated/adapter/json-api.js +236 -252
- package/dist/unpkg/prod-deprecated/adapter/json-api.js.map +1 -0
- package/dist/unpkg/prod-deprecated/adapter/rest.js +911 -1097
- package/dist/unpkg/prod-deprecated/adapter/rest.js.map +1 -0
- package/{declarations/adapter.d.ts → dist/unpkg/prod-deprecated/adapter-Wnk7jizX.js} +445 -110
- package/dist/unpkg/prod-deprecated/adapter-Wnk7jizX.js.map +1 -0
- package/dist/unpkg/prod-deprecated/adapter.js +1 -1214
- package/dist/unpkg/prod-deprecated/compat/-private.js +3 -1
- package/dist/unpkg/prod-deprecated/compat/builders.js +165 -182
- package/dist/unpkg/prod-deprecated/compat/builders.js.map +1 -0
- package/dist/unpkg/prod-deprecated/compat/extensions.js +252 -283
- package/dist/unpkg/prod-deprecated/compat/extensions.js.map +1 -0
- package/dist/unpkg/prod-deprecated/compat/utils.js +183 -200
- package/dist/unpkg/prod-deprecated/compat/utils.js.map +1 -0
- package/dist/unpkg/prod-deprecated/compat-CJ87MzDn.js +547 -0
- package/dist/unpkg/prod-deprecated/compat-CJ87MzDn.js.map +1 -0
- package/dist/unpkg/prod-deprecated/compat.js +1 -742
- package/dist/unpkg/prod-deprecated/errors-C-opde61.js +1978 -0
- package/dist/unpkg/prod-deprecated/errors-C-opde61.js.map +1 -0
- package/dist/unpkg/prod-deprecated/index.js +245 -307
- package/dist/unpkg/prod-deprecated/index.js.map +1 -0
- package/dist/unpkg/prod-deprecated/json-BD1kRTfB.js +1080 -0
- package/dist/unpkg/prod-deprecated/json-BD1kRTfB.js.map +1 -0
- package/dist/unpkg/prod-deprecated/model/-private.js +3 -1
- package/dist/unpkg/prod-deprecated/model/migration-support.js +488 -559
- package/dist/unpkg/prod-deprecated/model/migration-support.js.map +1 -0
- package/dist/unpkg/prod-deprecated/model-C0bTXzGn.js +604 -0
- package/dist/unpkg/prod-deprecated/model-C0bTXzGn.js.map +1 -0
- package/dist/unpkg/prod-deprecated/model-fragments-Dpn9285r.js +334 -0
- package/dist/unpkg/prod-deprecated/model-fragments-Dpn9285r.js.map +1 -0
- package/dist/unpkg/prod-deprecated/model-fragments.js +2 -94
- package/dist/unpkg/prod-deprecated/model.js +3 -599
- package/dist/unpkg/prod-deprecated/runtime-BPCpkOf1-BgO3Lyjx.js +53 -0
- package/dist/unpkg/prod-deprecated/runtime-BPCpkOf1-BgO3Lyjx.js.map +1 -0
- package/dist/unpkg/prod-deprecated/schema-provider-lH3qP5tw.js +1635 -0
- package/dist/unpkg/prod-deprecated/schema-provider-lH3qP5tw.js.map +1 -0
- package/dist/unpkg/prod-deprecated/serializer/json-api.js +497 -592
- package/dist/unpkg/prod-deprecated/serializer/json-api.js.map +1 -0
- package/dist/unpkg/prod-deprecated/serializer/json.js +3 -4
- package/dist/unpkg/prod-deprecated/serializer/rest.js +938 -1166
- package/dist/unpkg/prod-deprecated/serializer/rest.js.map +1 -0
- package/dist/unpkg/prod-deprecated/serializer/transform.js +283 -308
- package/dist/unpkg/prod-deprecated/serializer/transform.js.map +1 -0
- package/dist/unpkg/prod-deprecated/serializer.js +205 -205
- package/dist/unpkg/prod-deprecated/serializer.js.map +1 -0
- package/dist/unpkg/prod-deprecated/store-0L2CkYzh.js +392 -0
- package/dist/unpkg/prod-deprecated/store-0L2CkYzh.js.map +1 -0
- package/dist/unpkg/prod-deprecated/store.js +1 -517
- package/dist/unpkg/prod-deprecated/util-CQQdHX3n.js +14 -0
- package/dist/unpkg/prod-deprecated/util-CQQdHX3n.js.map +1 -0
- package/dist/unpkg/prod-deprecated/utils-BMI_JwFP.js +13 -0
- package/dist/unpkg/prod-deprecated/utils-BMI_JwFP.js.map +1 -0
- package/dist/util-Bnx8nm-D.js +29 -0
- package/dist/util-Bnx8nm-D.js.map +1 -0
- package/dist/utils-ZAytYep8.js +28 -0
- package/dist/utils-ZAytYep8.js.map +1 -0
- package/package.json +13 -13
- package/declarations/adapter/-private/build-url-mixin.d.ts +0 -189
- package/declarations/adapter/-private/fastboot-interface.d.ts +0 -8
- package/declarations/adapter/-private/utils/continue-on-reject.d.ts +0 -1
- package/declarations/adapter/-private/utils/determine-body-promise.d.ts +0 -4
- package/declarations/adapter/-private/utils/fetch.d.ts +0 -8
- package/declarations/adapter/-private/utils/parse-response-headers.d.ts +0 -1
- package/declarations/adapter/-private/utils/serialize-into-hash.d.ts +0 -6
- package/declarations/adapter/-private/utils/serialize-query-params.d.ts +0 -5
- package/declarations/adapter/-private.d.ts +0 -5
- package/declarations/adapter/error.d.ts +0 -431
- package/declarations/compat/-private.d.ts +0 -13
- package/declarations/compat/builders/find-all.d.ts +0 -34
- package/declarations/compat/builders/find-record.d.ts +0 -56
- package/declarations/compat/builders/query.d.ts +0 -66
- package/declarations/compat/builders/save-record.d.ts +0 -34
- package/declarations/compat/builders/utils.d.ts +0 -3
- package/declarations/compat/builders.d.ts +0 -14
- package/declarations/compat/extensions.d.ts +0 -99
- package/declarations/compat/legacy-network-handler/fetch-manager.d.ts +0 -55
- package/declarations/compat/legacy-network-handler/identifier-has-id.d.ts +0 -2
- package/declarations/compat/legacy-network-handler/legacy-data-fetch.d.ts +0 -11
- package/declarations/compat/legacy-network-handler/legacy-data-utils.d.ts +0 -5
- package/declarations/compat/legacy-network-handler/legacy-network-handler.d.ts +0 -9
- package/declarations/compat/legacy-network-handler/minimum-adapter-interface.d.ts +0 -528
- package/declarations/compat/legacy-network-handler/minimum-serializer-interface.d.ts +0 -220
- package/declarations/compat/legacy-network-handler/serializer-response.d.ts +0 -6
- package/declarations/compat/legacy-network-handler/snapshot-record-array.d.ts +0 -110
- package/declarations/compat/legacy-network-handler/snapshot.d.ts +0 -255
- package/declarations/compat/utils.d.ts +0 -148
- package/declarations/compat.d.ts +0 -189
- package/declarations/index.d.ts +0 -244
- package/declarations/model/-private/attr.d.ts +0 -191
- package/declarations/model/-private/belongs-to.d.ts +0 -195
- package/declarations/model/-private/debug/assert-polymorphic-type.d.ts +0 -5
- package/declarations/model/-private/errors.d.ts +0 -289
- package/declarations/model/-private/has-many.d.ts +0 -162
- package/declarations/model/-private/hooks.d.ts +0 -36
- package/declarations/model/-private/legacy-relationships-support.d.ts +0 -47
- package/declarations/model/-private/model-for-mixin.d.ts +0 -3
- package/declarations/model/-private/model-methods.d.ts +0 -39
- package/declarations/model/-private/model.d.ts +0 -1279
- package/declarations/model/-private/notify-changes.d.ts +0 -4
- package/declarations/model/-private/promise-belongs-to.d.ts +0 -40
- package/declarations/model/-private/promise-many-array.d.ts +0 -130
- package/declarations/model/-private/record-state.d.ts +0 -58
- package/declarations/model/-private/references/belongs-to.d.ts +0 -488
- package/declarations/model/-private/references/has-many.d.ts +0 -498
- package/declarations/model/-private/schema-provider.d.ts +0 -66
- package/declarations/model/-private/type-utils.d.ts +0 -57
- package/declarations/model/-private/util.d.ts +0 -5
- package/declarations/model/-private.d.ts +0 -8
- package/declarations/model/migration-support.d.ts +0 -306
- package/declarations/model-fragments/extensions/fragment-array.d.ts +0 -54
- package/declarations/model-fragments/extensions/fragment.d.ts +0 -50
- package/declarations/model-fragments/hooks/model-for.d.ts +0 -27
- package/declarations/model-fragments/index.d.ts +0 -13
- package/declarations/model-fragments/instance-initializers/fragment-extensions.d.ts +0 -15
- package/declarations/model-fragments/utilities/with-array-defaults.d.ts +0 -56
- package/declarations/model-fragments/utilities/with-fragment-array-defaults.d.ts +0 -38
- package/declarations/model-fragments/utilities/with-fragment-defaults.d.ts +0 -34
- package/declarations/model-fragments/utilities/with-legacy.d.ts +0 -11
- package/declarations/model-fragments.d.ts +0 -9
- package/declarations/model.d.ts +0 -49
- package/declarations/serializer/-private/transforms/boolean.d.ts +0 -60
- package/declarations/serializer/-private/transforms/date.d.ts +0 -42
- package/declarations/serializer/-private/transforms/number.d.ts +0 -42
- package/declarations/serializer/-private/transforms/string.d.ts +0 -42
- package/declarations/serializer/-private/transforms/transform.d.ts +0 -118
- package/declarations/serializer/-private/utils.d.ts +0 -27
- package/declarations/serializer/rest.d.ts +0 -51
- package/declarations/serializer/transform.d.ts +0 -5
- package/declarations/serializer.d.ts +0 -252
- package/declarations/store/-private.d.ts +0 -223
- package/declarations/store.d.ts +0 -10
- package/dist/-private-BG3bMiKp.js +0 -1211
- package/dist/errors-DZKA206g.js +0 -2589
- package/dist/hooks-BvOqJBei.js +0 -105
- package/dist/json-DU8m1pGf.js +0 -1336
- package/dist/model-for-CXkJw59V.js +0 -297
- package/dist/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
- package/dist/schema-provider-DtPOp0d7.js +0 -2382
- package/dist/serialize-into-hash-DPZYoF-i.js +0 -261
- package/dist/unpkg/dev/-private-DtjBbEgy.js +0 -1206
- package/dist/unpkg/dev/errors-DngRU-If.js +0 -2585
- package/dist/unpkg/dev/hooks-UuiLxWxS.js +0 -104
- package/dist/unpkg/dev/json-K2Y9z6MN.js +0 -1333
- package/dist/unpkg/dev/model-for-CXkJw59V.js +0 -297
- package/dist/unpkg/dev/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
- package/dist/unpkg/dev/schema-provider-0D7f-QOn.js +0 -2272
- package/dist/unpkg/dev/serialize-into-hash-B2xDbuo5.js +0 -259
- package/dist/unpkg/dev/util-DvanW33H.js +0 -20
- package/dist/unpkg/dev/utils-BhvS1iTS.js +0 -8
- package/dist/unpkg/dev-deprecated/-private-DtjBbEgy.js +0 -1206
- package/dist/unpkg/dev-deprecated/errors-Bzidntpi.js +0 -2588
- package/dist/unpkg/dev-deprecated/hooks-DVXhMW14.js +0 -104
- package/dist/unpkg/dev-deprecated/json-K2Y9z6MN.js +0 -1333
- package/dist/unpkg/dev-deprecated/model-for-CXkJw59V.js +0 -297
- package/dist/unpkg/dev-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
- package/dist/unpkg/dev-deprecated/schema-provider-ZwO5_fZw.js +0 -2292
- package/dist/unpkg/dev-deprecated/serialize-into-hash-B2xDbuo5.js +0 -259
- package/dist/unpkg/dev-deprecated/util-CWr5WQOT.js +0 -24
- package/dist/unpkg/dev-deprecated/utils-C9PJehtL.js +0 -12
- package/dist/unpkg/prod/-private-BdyZaGEh.js +0 -971
- package/dist/unpkg/prod/errors-B-PWeYlW.js +0 -2337
- package/dist/unpkg/prod/hooks-Bx-zBziU.js +0 -72
- package/dist/unpkg/prod/json-Qewu-UN9.js +0 -1300
- package/dist/unpkg/prod/model-for-CXkJw59V.js +0 -297
- package/dist/unpkg/prod/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
- package/dist/unpkg/prod/schema-provider-BgRqk8i9.js +0 -1951
- package/dist/unpkg/prod/serialize-into-hash-DGlzQteF.js +0 -215
- package/dist/unpkg/prod/util-DvanW33H.js +0 -20
- package/dist/unpkg/prod/utils-BhvS1iTS.js +0 -8
- package/dist/unpkg/prod-deprecated/-private-BdyZaGEh.js +0 -971
- package/dist/unpkg/prod-deprecated/errors-Dl2J9d1D.js +0 -2340
- package/dist/unpkg/prod-deprecated/hooks-Cm60wWTf.js +0 -72
- package/dist/unpkg/prod-deprecated/json-Qewu-UN9.js +0 -1300
- package/dist/unpkg/prod-deprecated/model-for-CXkJw59V.js +0 -297
- package/dist/unpkg/prod-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
- package/dist/unpkg/prod-deprecated/schema-provider-Dh6tRqVI.js +0 -1980
- package/dist/unpkg/prod-deprecated/serialize-into-hash-DGlzQteF.js +0 -215
- package/dist/unpkg/prod-deprecated/util-B6cn-i93.js +0 -23
- package/dist/unpkg/prod-deprecated/utils-BUWwQwCh.js +0 -11
- package/dist/util-Dul6TZts.js +0 -35
- package/dist/utils-Cqw9eRj5.js +0 -23
|
@@ -0,0 +1,3107 @@
|
|
|
1
|
+
import { m as Snapshot } from "./compat-BbNNmTM-.js";
|
|
2
|
+
import { Store } from "@warp-drive/core";
|
|
3
|
+
import { LegacyManyArray, PrivateStore, RelatedCollection } from "@warp-drive/core/store/-private";
|
|
4
|
+
import EmberObject from "@ember/object";
|
|
5
|
+
import { RecordStore, Type } from "@warp-drive/core/types/symbols";
|
|
6
|
+
import PromiseProxyMixin from "@ember/object/promise-proxy-mixin";
|
|
7
|
+
import ObjectProxy from "@ember/object/proxy";
|
|
8
|
+
import { NativeArray } from "@ember/array";
|
|
9
|
+
import ArrayProxy from "@ember/array/proxy";
|
|
10
|
+
import { BaseFinderOptions, ModelSchema, ResourceKey } from "@warp-drive/core/types";
|
|
11
|
+
import { CollectionResourceDocument, CollectionResourceRelationship, ExistingResourceObject, Links, Meta, PaginationLinks, SingleResourceDocument, SingleResourceRelationship } from "@warp-drive/core/types/spec/json-api-raw";
|
|
12
|
+
import { ChangedAttributesHash } from "@warp-drive/core/types/cache";
|
|
13
|
+
import { ResourceKey as ResourceKey$1 } from "@warp-drive/core/types/identifier";
|
|
14
|
+
import { OpaqueRecordInstance, TypeFromInstance, TypeFromInstanceOrString, TypedRecordInstance } from "@warp-drive/core/types/record";
|
|
15
|
+
import { LegacyAttributeField, LegacyRelationshipField } from "@warp-drive/core/types/schema/fields";
|
|
16
|
+
import { CollectionEdge, Graph, ResourceEdge, UpgradedMeta } from "@warp-drive/core/graph/-private";
|
|
17
|
+
import { CollectionRelationship } from "@warp-drive/core/types/cache/relationship";
|
|
18
|
+
import { LocalRelationshipOperation } from "@warp-drive/core/types/graph";
|
|
19
|
+
//#region src/model/-private/belongs-to.d.ts
|
|
20
|
+
type IsUnknown<T> = unknown extends T ? true : false;
|
|
21
|
+
type RelationshipOptions<T, Async extends boolean> = {
|
|
22
|
+
async: Async;
|
|
23
|
+
inverse: null | (IsUnknown<T> extends true ? string : keyof NoNull<T> & string);
|
|
24
|
+
polymorphic?: boolean;
|
|
25
|
+
as?: string;
|
|
26
|
+
linksMode?: true;
|
|
27
|
+
resetOnRemoteUpdate?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The name of the field as returned by the API and inserted into the
|
|
30
|
+
* cache if it differs from the name of the decorated property.
|
|
31
|
+
*
|
|
32
|
+
* For instance, if the API returns:
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* {
|
|
36
|
+
* relationships: {
|
|
37
|
+
* 'best-friend': { data: { type: 'user', id: '1' } }
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* But the app desires to use `record.bestFriend`, then the property
|
|
43
|
+
* should be named `bestFriend` and `sourceKey` should be set to
|
|
44
|
+
* `'best-friend'`.
|
|
45
|
+
*
|
|
46
|
+
* This option is only needed when the value differs from the property name.
|
|
47
|
+
*/
|
|
48
|
+
sourceKey?: string;
|
|
49
|
+
};
|
|
50
|
+
type NoNull<T> = Exclude<T, null>;
|
|
51
|
+
type RelationshipDecorator<T> = <This>(target: This, key: string, desc?: PropertyDescriptor) => void;
|
|
52
|
+
/**
|
|
53
|
+
`belongsTo` is used to define One-To-One and One-To-Many, and One-To-None
|
|
54
|
+
relationships on a {@link Model}.
|
|
55
|
+
|
|
56
|
+
`belongsTo` takes a configuration hash as a second parameter, currently
|
|
57
|
+
supported options are:
|
|
58
|
+
|
|
59
|
+
- `async`: (*required*) A boolean value used to declare whether this is a sync (false) or async (true) relationship.
|
|
60
|
+
- `inverse`: (*required*) A string used to identify the inverse property on a related model, or `null`.
|
|
61
|
+
- `polymorphic`: (*optional*) A boolean value to mark the relationship as polymorphic
|
|
62
|
+
- `as`: (*optional*) A string used to declare the abstract type "this" record satisfies for polymorphism.
|
|
63
|
+
|
|
64
|
+
### Examples
|
|
65
|
+
|
|
66
|
+
To declare a **one-to-many** (or many-to-many) relationship, use
|
|
67
|
+
`belongsTo` in combination with `hasMany`:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
// app/models/comment.js
|
|
71
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
72
|
+
|
|
73
|
+
export default class Comment extends Model {
|
|
74
|
+
@belongsTo('post', { async: false, inverse: 'comments' }) post;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// app/models/post.js
|
|
78
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
79
|
+
|
|
80
|
+
export default class Post extends Model {
|
|
81
|
+
@hasMany('comment', { async: false, inverse: 'post' }) comments;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
To declare a **one-to-one** relationship with managed inverses, use `belongsTo` for both sides:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
// app/models/author.js
|
|
89
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
90
|
+
|
|
91
|
+
export default class Author extends Model {
|
|
92
|
+
@belongsTo('address', { async: true, inverse: 'owner' }) address;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// app/models/address.js
|
|
96
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
97
|
+
|
|
98
|
+
export default class Address extends Model {
|
|
99
|
+
@belongsTo('author', { async: true, inverse: 'address' }) owner;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
To declare a **one-to-one** relationship without managed inverses, use `belongsTo` for both sides
|
|
104
|
+
with `null` as the inverse:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
// app/models/author.js
|
|
108
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
109
|
+
|
|
110
|
+
export default class Author extends Model {
|
|
111
|
+
@belongsTo('address', { async: true, inverse: null }) address;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// app/models/address.js
|
|
115
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
116
|
+
|
|
117
|
+
export default class Address extends Model {
|
|
118
|
+
@belongsTo('author', { async: true, inverse: null }) owner;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To declare a one-to-none relationship between two models, use
|
|
123
|
+
`belongsTo` with inverse set to `null` on just one side::
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
// app/models/person.js
|
|
127
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
128
|
+
|
|
129
|
+
export default class Person extends Model {
|
|
130
|
+
@belongsTo('person', { async: false, inverse: null }) bestFriend;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Sync vs Async Relationships
|
|
135
|
+
|
|
136
|
+
WarpDrive fulfills relationships using resource data available in
|
|
137
|
+
the cache.
|
|
138
|
+
|
|
139
|
+
Sync relationships point directly to the known related resources.
|
|
140
|
+
|
|
141
|
+
When a relationship is declared as async, if any of the known related
|
|
142
|
+
resources have not been loaded, they will be fetched. The property
|
|
143
|
+
on the record when accessed provides a promise that resolves once
|
|
144
|
+
all resources are loaded.
|
|
145
|
+
|
|
146
|
+
Async relationships may take advantage of links. On access, if the related
|
|
147
|
+
link has not been loaded, or if any known resources are not available in
|
|
148
|
+
the cache, the fresh state will be fetched using the link.
|
|
149
|
+
|
|
150
|
+
In contrast to async relationship, accessing a sync relationship
|
|
151
|
+
will error on access when any of the known related resources have
|
|
152
|
+
not been loaded.
|
|
153
|
+
|
|
154
|
+
If you are using `links` with sync relationships, you have to use
|
|
155
|
+
the BelongsTo reference API to fetch or refresh related resources
|
|
156
|
+
that aren't loaded. For instance, for a `bestFriend` relationship:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
person.belongsTo('bestFriend').reload();
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Polymorphic Relationships
|
|
163
|
+
|
|
164
|
+
To declare a polymorphic relationship, use `hasMany` with the `polymorphic`
|
|
165
|
+
option set to `true`:
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
// app/models/comment.js
|
|
169
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
170
|
+
|
|
171
|
+
export default class Comment extends Model {
|
|
172
|
+
@belongsTo('commentable', { async: false, inverse: 'comments', polymorphic: true }) parent;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`'commentable'` here is referred to as the "abstract type" for the polymorphic
|
|
177
|
+
relationship.
|
|
178
|
+
|
|
179
|
+
Polymorphic relationships with `inverse: null` will accept any type of record as their content.
|
|
180
|
+
Polymorphic relationships with `inverse` set to a string will only accept records with a matching
|
|
181
|
+
inverse relationships declaring itself as satisfying the abstract type.
|
|
182
|
+
|
|
183
|
+
Below, 'as' is used to declare the that 'post' record satisfies the abstract type 'commentable'
|
|
184
|
+
for this relationship.
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
// app/models/post.js
|
|
188
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
189
|
+
|
|
190
|
+
export default class Post extends Model {
|
|
191
|
+
@hasMany('comment', { async: false, inverse: 'parent', as: 'commentable' }) comments;
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Note: every Model that declares an inverse to a polymorphic relationship must
|
|
196
|
+
declare itself exactly the same. This is because polymorphism is based on structural
|
|
197
|
+
traits.
|
|
198
|
+
|
|
199
|
+
Polymorphic to polymorphic relationships are supported. Both sides of the relationship
|
|
200
|
+
must be declared as polymorphic, and the `as` option must be used to declare the abstract
|
|
201
|
+
type each record satisfies on both sides.
|
|
202
|
+
|
|
203
|
+
@public
|
|
204
|
+
@param type the name of the related resource
|
|
205
|
+
@param options a hash of options
|
|
206
|
+
*/
|
|
207
|
+
declare function belongsTo$1(): never;
|
|
208
|
+
declare function belongsTo$1(type: string): never;
|
|
209
|
+
declare function belongsTo$1<T>(type: TypeFromInstance<NoNull<T>>, options: RelationshipOptions<T, boolean>): RelationshipDecorator<T>;
|
|
210
|
+
declare function belongsTo$1(type: string, options: RelationshipOptions<unknown, boolean>): RelationshipDecorator<unknown>;
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region src/model/-private/promise-many-array.d.ts
|
|
213
|
+
interface HasManyProxyCreateArgs<T = unknown> {
|
|
214
|
+
promise: Promise<RelatedCollection<T>>;
|
|
215
|
+
content?: RelatedCollection<T>;
|
|
216
|
+
}
|
|
217
|
+
interface PromiseManyArray<T> {
|
|
218
|
+
/**
|
|
219
|
+
* A property signifying that this object implements the classic Ember
|
|
220
|
+
* `PromiseProxyMixin`-like API. See {@link LegacyPromiseProxy}.
|
|
221
|
+
*/
|
|
222
|
+
[LegacyPromiseProxy]: true;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
This class is returned as the result of accessing an async hasMany relationship
|
|
226
|
+
on an instance of a Model extending from `@warp-drive/legacy/model`.
|
|
227
|
+
|
|
228
|
+
A PromiseManyArray is an iterable proxy that allows templates to consume related
|
|
229
|
+
ManyArrays and update once their contents are no longer pending.
|
|
230
|
+
|
|
231
|
+
In your JS code you should resolve the promise first.
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
const comments = await post.comments;
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
@public
|
|
238
|
+
*/
|
|
239
|
+
declare class PromiseManyArray<T = unknown> {
|
|
240
|
+
/**
|
|
241
|
+
* The promise for the relationship's content, or `null` once
|
|
242
|
+
* {@link PromiseManyArray.destroy | destroy} has been called.
|
|
243
|
+
*/
|
|
244
|
+
promise: Promise<RelatedCollection<T>> | null;
|
|
245
|
+
/**
|
|
246
|
+
* Whether {@link PromiseManyArray.destroy | destroy} has been called.
|
|
247
|
+
*/
|
|
248
|
+
isDestroyed: boolean;
|
|
249
|
+
/**
|
|
250
|
+
* The resolved `ManyArray` for the relationship, if the promise has
|
|
251
|
+
* resolved, else `null`.
|
|
252
|
+
*/
|
|
253
|
+
content: RelatedCollection<T> | null;
|
|
254
|
+
constructor(promise: Promise<RelatedCollection<T>>, content?: RelatedCollection<T>);
|
|
255
|
+
/**
|
|
256
|
+
* Retrieve the length of the content
|
|
257
|
+
* @public
|
|
258
|
+
*/
|
|
259
|
+
get length(): number;
|
|
260
|
+
/**
|
|
261
|
+
* @private
|
|
262
|
+
*/
|
|
263
|
+
get "[]"(): 0 | RelatedCollection<T> | undefined;
|
|
264
|
+
/**
|
|
265
|
+
* Iterate the proxied content. Called by the glimmer iterator in #each
|
|
266
|
+
* We do not guarantee that forEach will always be available. This
|
|
267
|
+
* may eventually be made to use Symbol.Iterator once glimmer supports it.
|
|
268
|
+
*
|
|
269
|
+
* @param cb
|
|
270
|
+
* @return
|
|
271
|
+
* @private
|
|
272
|
+
*/
|
|
273
|
+
forEach(cb: (item: T, index: number, array: T[]) => void): void;
|
|
274
|
+
/**
|
|
275
|
+
* Reload the relationship
|
|
276
|
+
* @public
|
|
277
|
+
*/
|
|
278
|
+
reload(options: Omit<BaseFinderOptions, "">): this;
|
|
279
|
+
/**
|
|
280
|
+
* Whether the loading promise is still pending
|
|
281
|
+
*
|
|
282
|
+
* @public
|
|
283
|
+
*/
|
|
284
|
+
isPending: boolean;
|
|
285
|
+
/**
|
|
286
|
+
* Whether the loading promise rejected
|
|
287
|
+
*
|
|
288
|
+
* @public
|
|
289
|
+
*/
|
|
290
|
+
isRejected: boolean;
|
|
291
|
+
/**
|
|
292
|
+
* Whether the loading promise succeeded
|
|
293
|
+
*
|
|
294
|
+
* @public
|
|
295
|
+
*/
|
|
296
|
+
isFulfilled: boolean;
|
|
297
|
+
/**
|
|
298
|
+
* Whether the loading promise completed (resolved or rejected)
|
|
299
|
+
*
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
isSettled: boolean;
|
|
303
|
+
/**
|
|
304
|
+
* chain this promise
|
|
305
|
+
*
|
|
306
|
+
* @public
|
|
307
|
+
*/
|
|
308
|
+
then(success: Parameters<Promise<RelatedCollection<T>>["then"]>[0], rejected?: Parameters<Promise<RelatedCollection<T>>["then"]>[1]): Promise<unknown>;
|
|
309
|
+
/**
|
|
310
|
+
* catch errors thrown by this promise
|
|
311
|
+
* @public
|
|
312
|
+
*/
|
|
313
|
+
catch(cb: Parameters<Promise<RelatedCollection<T>>["catch"]>[0]): Promise<unknown>;
|
|
314
|
+
/**
|
|
315
|
+
* run cleanup after this promise completes
|
|
316
|
+
*
|
|
317
|
+
* @public
|
|
318
|
+
*/
|
|
319
|
+
finally(cb: Parameters<Promise<RelatedCollection<T>>["finally"]>[0]): Promise<unknown>;
|
|
320
|
+
/**
|
|
321
|
+
* Tears down this proxy, releasing its {@link PromiseManyArray.content | content} and
|
|
322
|
+
* {@link PromiseManyArray.promise | promise} and marking it as {@link PromiseManyArray.isDestroyed | destroyed}.
|
|
323
|
+
*
|
|
324
|
+
* @public
|
|
325
|
+
*/
|
|
326
|
+
destroy(): void;
|
|
327
|
+
/**
|
|
328
|
+
* Retrieve the links for this relationship
|
|
329
|
+
* @public
|
|
330
|
+
*/
|
|
331
|
+
get links(): Links | null | undefined;
|
|
332
|
+
/**
|
|
333
|
+
* Retrieve the meta for this relationship
|
|
334
|
+
* @public
|
|
335
|
+
*/
|
|
336
|
+
get meta(): Record<string, unknown> | null | undefined;
|
|
337
|
+
/** @internal */
|
|
338
|
+
_update(promise: Promise<RelatedCollection<T>>, content?: RelatedCollection<T>): void;
|
|
339
|
+
static create<T>({ promise, content }: HasManyProxyCreateArgs<T>): PromiseManyArray<T>;
|
|
340
|
+
}
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/model/-private/references/has-many.d.ts
|
|
343
|
+
type ArrayItemType<T> = T extends (infer U)[] ? U : never;
|
|
344
|
+
/**
|
|
345
|
+
A `HasManyReference` is a low-level API that allows access
|
|
346
|
+
and manipulation of a hasMany relationship.
|
|
347
|
+
|
|
348
|
+
It is especially useful when you're dealing with `async` relationships
|
|
349
|
+
from `@warp-drive/legacy/model` as it allows synchronous access to
|
|
350
|
+
the relationship data if loaded, as well as APIs for loading, reloading
|
|
351
|
+
the data or accessing available information without triggering a load.
|
|
352
|
+
|
|
353
|
+
It may also be useful when using `sync` relationships with `@warp-drive/legacy/model`
|
|
354
|
+
that need to be loaded/reloaded with more precise timing than marking the
|
|
355
|
+
relationship as `async` and relying on autofetch would have allowed.
|
|
356
|
+
|
|
357
|
+
However,keep in mind that marking a relationship as `async: false` will introduce
|
|
358
|
+
bugs into your application if the data is not always guaranteed to be available
|
|
359
|
+
by the time the relationship is accessed. Ergo, it is recommended when using this
|
|
360
|
+
approach to utilize `links` for unloaded relationship state instead of identifiers.
|
|
361
|
+
|
|
362
|
+
Reference APIs are entangled with the relationship's underlying state,
|
|
363
|
+
thus any getters or cached properties that utilize these will properly
|
|
364
|
+
invalidate if the relationship state changes.
|
|
365
|
+
|
|
366
|
+
References are "stable", meaning that multiple calls to retrieve the reference
|
|
367
|
+
for a given relationship will always return the same HasManyReference.
|
|
368
|
+
|
|
369
|
+
@class HasManyReference
|
|
370
|
+
@public
|
|
371
|
+
*/
|
|
372
|
+
declare class HasManyReference<T = unknown, K extends string = IsUnknown<T> extends true ? string : MaybeHasManyFields<T>, Related = K extends keyof T ? ArrayItemType<Awaited<T[K]>> : unknown> {
|
|
373
|
+
graph: Graph;
|
|
374
|
+
store: Store;
|
|
375
|
+
hasManyRelationship: CollectionEdge;
|
|
376
|
+
/**
|
|
377
|
+
* The field name on the parent record for this has-many relationship.
|
|
378
|
+
*
|
|
379
|
+
* @property key
|
|
380
|
+
* @type {String}
|
|
381
|
+
* @public
|
|
382
|
+
*/
|
|
383
|
+
key: K;
|
|
384
|
+
/**
|
|
385
|
+
* The type of resource this relationship will contain.
|
|
386
|
+
*
|
|
387
|
+
* @property type
|
|
388
|
+
* @type {String}
|
|
389
|
+
* @public
|
|
390
|
+
*/
|
|
391
|
+
type: TypeFromInstanceOrString<Related>;
|
|
392
|
+
___token: object;
|
|
393
|
+
___identifier: ResourceKey$1<TypeFromInstanceOrString<T>>;
|
|
394
|
+
___relatedTokenMap: Map<ResourceKey$1, object>;
|
|
395
|
+
_ref: number;
|
|
396
|
+
constructor(store: Store, graph: Graph, parentIdentifier: ResourceKey$1<TypeFromInstanceOrString<T>>, hasManyRelationship: CollectionEdge, key: K);
|
|
397
|
+
/**
|
|
398
|
+
* This method should never be called by user code.
|
|
399
|
+
*
|
|
400
|
+
* @internal
|
|
401
|
+
*/
|
|
402
|
+
destroy(): void;
|
|
403
|
+
/**
|
|
404
|
+
* An array of identifiers for the records that this reference refers to.
|
|
405
|
+
*
|
|
406
|
+
* @property identifiers
|
|
407
|
+
* @type {ResourceKey[]}
|
|
408
|
+
* @public
|
|
409
|
+
*/
|
|
410
|
+
get identifiers(): ResourceKey$1<TypeFromInstanceOrString<Related>>[];
|
|
411
|
+
_resource(): CollectionResourceRelationship;
|
|
412
|
+
/**
|
|
413
|
+
This returns a string that represents how the reference will be
|
|
414
|
+
looked up when it is loaded. If the relationship has a link it will
|
|
415
|
+
use the "link" otherwise it defaults to "id".
|
|
416
|
+
|
|
417
|
+
Example
|
|
418
|
+
|
|
419
|
+
```js [app/models/post.js]
|
|
420
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
421
|
+
|
|
422
|
+
export default class PostModel extends Model {
|
|
423
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
```javascript
|
|
428
|
+
let post = store.push({
|
|
429
|
+
data: {
|
|
430
|
+
type: 'post',
|
|
431
|
+
id: 1,
|
|
432
|
+
relationships: {
|
|
433
|
+
comments: {
|
|
434
|
+
data: [{ type: 'comment', id: 1 }]
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
let commentsRef = post.hasMany('comments');
|
|
441
|
+
|
|
442
|
+
// get the identifier of the reference
|
|
443
|
+
if (commentsRef.remoteType() === "ids") {
|
|
444
|
+
let ids = commentsRef.ids();
|
|
445
|
+
} else if (commentsRef.remoteType() === "link") {
|
|
446
|
+
let link = commentsRef.link();
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
@public
|
|
451
|
+
@return The name of the remote type. This should either be `link` or `ids`
|
|
452
|
+
*/
|
|
453
|
+
remoteType(): "link" | "ids";
|
|
454
|
+
/**
|
|
455
|
+
`ids()` returns an array of the record IDs in this relationship.
|
|
456
|
+
|
|
457
|
+
Example
|
|
458
|
+
|
|
459
|
+
```js [app/models/post.js]
|
|
460
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
461
|
+
|
|
462
|
+
export default class PostModel extends Model {
|
|
463
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
```javascript
|
|
468
|
+
let post = store.push({
|
|
469
|
+
data: {
|
|
470
|
+
type: 'post',
|
|
471
|
+
id: 1,
|
|
472
|
+
relationships: {
|
|
473
|
+
comments: {
|
|
474
|
+
data: [{ type: 'comment', id: 1 }]
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
let commentsRef = post.hasMany('comments');
|
|
481
|
+
|
|
482
|
+
commentsRef.ids(); // ['1']
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
@public
|
|
486
|
+
@return The ids in this has-many relationship
|
|
487
|
+
*/
|
|
488
|
+
ids(): Array<string | null>;
|
|
489
|
+
/**
|
|
490
|
+
The link WarpDrive will use to fetch or reload this belongs-to
|
|
491
|
+
relationship. By default it uses only the "related" resource linkage.
|
|
492
|
+
|
|
493
|
+
Example
|
|
494
|
+
|
|
495
|
+
```javascript
|
|
496
|
+
// models/blog.js
|
|
497
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
498
|
+
export default Model.extend({
|
|
499
|
+
user: belongsTo('user', { async: true, inverse: null })
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
let blog = store.push({
|
|
503
|
+
data: {
|
|
504
|
+
type: 'blog',
|
|
505
|
+
id: 1,
|
|
506
|
+
relationships: {
|
|
507
|
+
user: {
|
|
508
|
+
links: {
|
|
509
|
+
related: '/articles/1/author'
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
let userRef = blog.belongsTo('user');
|
|
516
|
+
|
|
517
|
+
// get the identifier of the reference
|
|
518
|
+
if (userRef.remoteType() === "link") {
|
|
519
|
+
let link = userRef.link();
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
@public
|
|
524
|
+
@return The link WarpDrive will use to fetch or reload this belongs-to relationship.
|
|
525
|
+
*/
|
|
526
|
+
link(): string | null;
|
|
527
|
+
/**
|
|
528
|
+
* any links that have been received for this relationship
|
|
529
|
+
*
|
|
530
|
+
* @public
|
|
531
|
+
* @return
|
|
532
|
+
*/
|
|
533
|
+
links(): PaginationLinks | null;
|
|
534
|
+
/**
|
|
535
|
+
The meta data for the has-many relationship.
|
|
536
|
+
|
|
537
|
+
Example
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
// models/blog.js
|
|
541
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
542
|
+
export default Model.extend({
|
|
543
|
+
users: hasMany('user', { async: true, inverse: null })
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
let blog = store.push({
|
|
547
|
+
data: {
|
|
548
|
+
type: 'blog',
|
|
549
|
+
id: 1,
|
|
550
|
+
relationships: {
|
|
551
|
+
users: {
|
|
552
|
+
links: {
|
|
553
|
+
related: {
|
|
554
|
+
href: '/articles/1/authors'
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
meta: {
|
|
558
|
+
lastUpdated: 1458014400000
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
let usersRef = blog.hasMany('user');
|
|
566
|
+
|
|
567
|
+
usersRef.meta() // { lastUpdated: 1458014400000 }
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
@public
|
|
571
|
+
@return The meta information for the belongs-to relationship.
|
|
572
|
+
*/
|
|
573
|
+
meta(): Meta | null;
|
|
574
|
+
/**
|
|
575
|
+
`push` can be used to update the data in the relationship and WarpDrive
|
|
576
|
+
will treat the new data as the canonical value of this relationship on
|
|
577
|
+
the backend. An empty array will signify the canonical value should be
|
|
578
|
+
empty.
|
|
579
|
+
|
|
580
|
+
Example model
|
|
581
|
+
|
|
582
|
+
```js [app/models/post.js]
|
|
583
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
584
|
+
|
|
585
|
+
export default class PostModel extends Model {
|
|
586
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Setup some initial state, note we haven't loaded the comments yet:
|
|
591
|
+
|
|
592
|
+
```js
|
|
593
|
+
const post = store.push({
|
|
594
|
+
data: {
|
|
595
|
+
type: 'post',
|
|
596
|
+
id: '1',
|
|
597
|
+
relationships: {
|
|
598
|
+
comments: {
|
|
599
|
+
data: [{ type: 'comment', id: '1' }]
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
const commentsRef = post.hasMany('comments');
|
|
606
|
+
commentsRef.ids(); // ['1']
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Update the state using `push`, note we can do this even without
|
|
610
|
+
having loaded these comments yet by providing resource identifiers.
|
|
611
|
+
|
|
612
|
+
Both full resources and resource identifiers are supported.
|
|
613
|
+
|
|
614
|
+
```js
|
|
615
|
+
await commentsRef.push({
|
|
616
|
+
data: [
|
|
617
|
+
{ type: 'comment', id: '2' },
|
|
618
|
+
{ type: 'comment', id: '3' },
|
|
619
|
+
]
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
commentsRef.ids(); // ['2', '3']
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
For convenience, you can also pass in an array of resources or resource identifiers
|
|
626
|
+
without wrapping them in the `data` property:
|
|
627
|
+
|
|
628
|
+
```js
|
|
629
|
+
await commentsRef.push([
|
|
630
|
+
{ type: 'comment', id: '4' },
|
|
631
|
+
{ type: 'comment', id: '5' },
|
|
632
|
+
]);
|
|
633
|
+
|
|
634
|
+
commentsRef.ids(); // ['4', '5']
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
When using the `data` property, you may also include other resource data via included,
|
|
638
|
+
as well as provide new links and meta to the relationship.
|
|
639
|
+
|
|
640
|
+
```js
|
|
641
|
+
await commentsRef.push({
|
|
642
|
+
links: {
|
|
643
|
+
related: '/posts/1/comments'
|
|
644
|
+
},
|
|
645
|
+
meta: {
|
|
646
|
+
total: 2
|
|
647
|
+
},
|
|
648
|
+
data: [
|
|
649
|
+
{ type: 'comment', id: '4' },
|
|
650
|
+
{ type: 'comment', id: '5' },
|
|
651
|
+
],
|
|
652
|
+
included: [
|
|
653
|
+
{ type: 'other-thing', id: '1', attributes: { foo: 'bar' },
|
|
654
|
+
]
|
|
655
|
+
});
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
By default, the store will attempt to fetch any unloaded records before resolving
|
|
659
|
+
the returned promise with the ManyArray.
|
|
660
|
+
|
|
661
|
+
Alternatively, pass `true` as the second argument to avoid fetching unloaded records
|
|
662
|
+
and instead the promise will resolve with void without attempting to fetch. This is
|
|
663
|
+
particularly useful if you want to update the state of the relationship without
|
|
664
|
+
forcing the load of all of the associated records.
|
|
665
|
+
|
|
666
|
+
@public
|
|
667
|
+
@param doc a JSONAPI document object describing the new value of this relationship.
|
|
668
|
+
@param skipFetch [optional] if `true`, do not attempt to fetch unloaded records
|
|
669
|
+
*/
|
|
670
|
+
push(doc: ExistingResourceObject[] | CollectionResourceDocument, skipFetch?: boolean): Promise<RelatedCollection<Related> | void>;
|
|
671
|
+
_isLoaded(): boolean;
|
|
672
|
+
/**
|
|
673
|
+
`value()` synchronously returns the current value of the has-many
|
|
674
|
+
relationship. Unlike `record.relationshipName`, calling
|
|
675
|
+
`value()` on a reference does not trigger a fetch if the async
|
|
676
|
+
relationship is not yet loaded. If the relationship is not loaded
|
|
677
|
+
it will always return `null`.
|
|
678
|
+
|
|
679
|
+
Example
|
|
680
|
+
|
|
681
|
+
```js [app/models/post.js]
|
|
682
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
683
|
+
|
|
684
|
+
export default class PostModel extends Model {
|
|
685
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
686
|
+
}
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
```javascript
|
|
690
|
+
let post = store.push({
|
|
691
|
+
data: {
|
|
692
|
+
type: 'post',
|
|
693
|
+
id: 1,
|
|
694
|
+
relationships: {
|
|
695
|
+
comments: {
|
|
696
|
+
data: [{ type: 'comment', id: 1 }]
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
let commentsRef = post.hasMany('comments');
|
|
703
|
+
|
|
704
|
+
post.comments.then(function(comments) {
|
|
705
|
+
commentsRef.value() === comments
|
|
706
|
+
})
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
@public
|
|
710
|
+
*/
|
|
711
|
+
value(): RelatedCollection<Related> | null;
|
|
712
|
+
/**
|
|
713
|
+
Loads the relationship if it is not already loaded. If the
|
|
714
|
+
relationship is already loaded this method does not trigger a new
|
|
715
|
+
load. This causes a request to the specified
|
|
716
|
+
relationship link or reloads all items currently in the relationship.
|
|
717
|
+
|
|
718
|
+
Example
|
|
719
|
+
|
|
720
|
+
```js [app/models/post.js]
|
|
721
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
722
|
+
|
|
723
|
+
export default class PostModel extends Model {
|
|
724
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
```javascript
|
|
729
|
+
let post = store.push({
|
|
730
|
+
data: {
|
|
731
|
+
type: 'post',
|
|
732
|
+
id: 1,
|
|
733
|
+
relationships: {
|
|
734
|
+
comments: {
|
|
735
|
+
data: [{ type: 'comment', id: 1 }]
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
let commentsRef = post.hasMany('comments');
|
|
742
|
+
|
|
743
|
+
commentsRef.load().then(function(comments) {
|
|
744
|
+
//...
|
|
745
|
+
});
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
You may also pass in an options object whose properties will be
|
|
749
|
+
fed forward. This enables you to pass `adapterOptions` into the
|
|
750
|
+
request given to the adapter via the reference.
|
|
751
|
+
|
|
752
|
+
Example
|
|
753
|
+
|
|
754
|
+
```javascript
|
|
755
|
+
commentsRef.load({ adapterOptions: { isPrivate: true } })
|
|
756
|
+
.then(function(comments) {
|
|
757
|
+
//...
|
|
758
|
+
});
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
```js [app/adapters/comment.js]
|
|
762
|
+
export default ApplicationAdapter.extend({
|
|
763
|
+
findMany(store, type, id, snapshots) {
|
|
764
|
+
// In the adapter you will have access to adapterOptions.
|
|
765
|
+
let adapterOptions = snapshots[0].adapterOptions;
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
@public
|
|
771
|
+
@param options the options to pass in.
|
|
772
|
+
@return a promise that resolves with the ManyArray in
|
|
773
|
+
this has-many relationship.
|
|
774
|
+
*/
|
|
775
|
+
load(options?: BaseFinderOptions): Promise<RelatedCollection<Related>>;
|
|
776
|
+
/**
|
|
777
|
+
Reloads this has-many relationship. This causes a request to the specified
|
|
778
|
+
relationship link or reloads all items currently in the relationship.
|
|
779
|
+
|
|
780
|
+
Example
|
|
781
|
+
|
|
782
|
+
```js [app/models/post.js]
|
|
783
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
784
|
+
|
|
785
|
+
export default class PostModel extends Model {
|
|
786
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
787
|
+
}
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
```javascript
|
|
791
|
+
let post = store.push({
|
|
792
|
+
data: {
|
|
793
|
+
type: 'post',
|
|
794
|
+
id: 1,
|
|
795
|
+
relationships: {
|
|
796
|
+
comments: {
|
|
797
|
+
data: [{ type: 'comment', id: 1 }]
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
let commentsRef = post.hasMany('comments');
|
|
804
|
+
|
|
805
|
+
commentsRef.reload().then(function(comments) {
|
|
806
|
+
//...
|
|
807
|
+
});
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
You may also pass in an options object whose properties will be
|
|
811
|
+
fed forward. This enables you to pass `adapterOptions` into the
|
|
812
|
+
request given to the adapter via the reference. A full example
|
|
813
|
+
can be found in the `load` method.
|
|
814
|
+
|
|
815
|
+
Example
|
|
816
|
+
|
|
817
|
+
```javascript
|
|
818
|
+
commentsRef.reload({ adapterOptions: { isPrivate: true } })
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
@public
|
|
822
|
+
@param options the options to pass in.
|
|
823
|
+
@return a promise that resolves with the ManyArray in this has-many relationship.
|
|
824
|
+
*/
|
|
825
|
+
reload(options?: BaseFinderOptions): Promise<RelatedCollection<Related>>;
|
|
826
|
+
}
|
|
827
|
+
//#endregion
|
|
828
|
+
//#region src/model/-private/legacy-relationships-support.d.ts
|
|
829
|
+
declare const LEGACY_SUPPORT: Map<ResourceKey | MinimalLegacyRecord, LegacySupport>;
|
|
830
|
+
declare function lookupLegacySupport(record: MinimalLegacyRecord): LegacySupport;
|
|
831
|
+
/**
|
|
832
|
+
* @hideconstructor
|
|
833
|
+
*/
|
|
834
|
+
declare class LegacySupport {
|
|
835
|
+
/** @internal */
|
|
836
|
+
private record;
|
|
837
|
+
/** @internal */
|
|
838
|
+
store: PrivateStore;
|
|
839
|
+
/** @internal */
|
|
840
|
+
private graph;
|
|
841
|
+
/** @internal */
|
|
842
|
+
private cache;
|
|
843
|
+
/** @internal */
|
|
844
|
+
private references;
|
|
845
|
+
identifier: ResourceKey;
|
|
846
|
+
/** @internal */
|
|
847
|
+
_manyArrayCache: Record<string, LegacyManyArray>;
|
|
848
|
+
/** @internal */
|
|
849
|
+
_relationshipPromisesCache: Record<string, Promise<LegacyManyArray | OpaqueRecordInstance>>;
|
|
850
|
+
/** @internal */
|
|
851
|
+
_relationshipProxyCache: Record<string, PromiseManyArray | PromiseBelongsTo | undefined>;
|
|
852
|
+
/** @internal */
|
|
853
|
+
private _pending;
|
|
854
|
+
/** @internal */
|
|
855
|
+
private isDestroying;
|
|
856
|
+
/** @internal */
|
|
857
|
+
private isDestroyed;
|
|
858
|
+
constructor(record: MinimalLegacyRecord, identifier: ResourceKey);
|
|
859
|
+
/** @private */
|
|
860
|
+
_syncArray(array: LegacyManyArray): void;
|
|
861
|
+
mutate(mutation: LocalRelationshipOperation): void;
|
|
862
|
+
_findBelongsTo(key: string, resource: SingleResourceRelationship, relationship: ResourceEdge, options?: BaseFinderOptions): Promise<OpaqueRecordInstance | null>;
|
|
863
|
+
reloadBelongsTo(key: string, options?: BaseFinderOptions): Promise<OpaqueRecordInstance | null>;
|
|
864
|
+
getBelongsTo(key: string, options?: BaseFinderOptions): PromiseBelongsTo | OpaqueRecordInstance | null;
|
|
865
|
+
setDirtyBelongsTo(key: string, value: OpaqueRecordInstance | null): void;
|
|
866
|
+
_getCurrentState<T>(identifier: ResourceKey, field: string): [ResourceKey<TypeFromInstanceOrString<T>>[], CollectionRelationship];
|
|
867
|
+
getManyArray<T>(key: string, definition?: UpgradedMeta): LegacyManyArray<T>;
|
|
868
|
+
fetchAsyncHasMany(key: string, relationship: CollectionEdge, manyArray: LegacyManyArray, options?: BaseFinderOptions): Promise<LegacyManyArray>;
|
|
869
|
+
reloadHasMany<T>(key: string, options?: BaseFinderOptions): Promise<LegacyManyArray<T>> | PromiseManyArray<T>;
|
|
870
|
+
getHasMany(key: string, options?: BaseFinderOptions): PromiseManyArray | LegacyManyArray;
|
|
871
|
+
_updatePromiseProxyFor(kind: "hasMany", key: string, args: HasManyProxyCreateArgs): PromiseManyArray;
|
|
872
|
+
_updatePromiseProxyFor(kind: "belongsTo", key: string, args: BelongsToProxyCreateArgs): PromiseBelongsTo;
|
|
873
|
+
_updatePromiseProxyFor(kind: "belongsTo", key: string, args: {
|
|
874
|
+
promise: Promise<OpaqueRecordInstance | null>;
|
|
875
|
+
}): PromiseBelongsTo;
|
|
876
|
+
referenceFor(kind: "belongsTo", key: string): BelongsToReference;
|
|
877
|
+
referenceFor(kind: "hasMany", key: string): HasManyReference;
|
|
878
|
+
_findHasManyByJsonApiResource(resource: CollectionResourceRelationship, parentIdentifier: ResourceKey, relationship: CollectionEdge, options?: BaseFinderOptions): Promise<void | unknown[]> | void;
|
|
879
|
+
_findBelongsToByJsonApiResource(resource: SingleResourceRelationship, parentIdentifier: ResourceKey, relationship: ResourceEdge, options?: BaseFinderOptions): Promise<ResourceKey | null>;
|
|
880
|
+
destroy(): void;
|
|
881
|
+
}
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/model/-private/promise-belongs-to.d.ts
|
|
884
|
+
interface BelongsToProxyMeta<T = unknown> {
|
|
885
|
+
key: string;
|
|
886
|
+
store: Store;
|
|
887
|
+
legacySupport: LegacySupport;
|
|
888
|
+
modelName: TypeFromInstanceOrString<T>;
|
|
889
|
+
}
|
|
890
|
+
interface BelongsToProxyCreateArgs<T = unknown> {
|
|
891
|
+
promise: Promise<T | null>;
|
|
892
|
+
content?: T | null;
|
|
893
|
+
_belongsToState: BelongsToProxyMeta<T>;
|
|
894
|
+
}
|
|
895
|
+
declare const LegacyPromiseProxy: unique symbol;
|
|
896
|
+
interface PromiseObjectType<T> extends PromiseProxyMixin<T | null>, ObjectProxy<T> {
|
|
897
|
+
new <PT>(...args: unknown[]): PromiseObjectType<PT>;
|
|
898
|
+
}
|
|
899
|
+
declare class PromiseObjectType<T> {}
|
|
900
|
+
declare const Extended: PromiseObjectType<OpaqueRecordInstance>;
|
|
901
|
+
interface PromiseBelongsTo<T> {
|
|
902
|
+
[LegacyPromiseProxy]: true;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
A PromiseBelongsTo is a PromiseObject that also proxies certain method calls
|
|
906
|
+
to the underlying belongsTo model.
|
|
907
|
+
Right now we proxy:
|
|
908
|
+
* `reload()`
|
|
909
|
+
@class PromiseBelongsTo
|
|
910
|
+
@private
|
|
911
|
+
*/
|
|
912
|
+
declare class PromiseBelongsTo<T = unknown> extends Extended<T> {
|
|
913
|
+
_belongsToState: BelongsToProxyMeta<T>;
|
|
914
|
+
get id(): string | null;
|
|
915
|
+
get meta(): void;
|
|
916
|
+
reload(options: Record<string, unknown>): Promise<this>;
|
|
917
|
+
}
|
|
918
|
+
//#endregion
|
|
919
|
+
//#region src/model/-private/type-utils.d.ts
|
|
920
|
+
type ExcludeNull<T> = Exclude<T, null> extends never ? T : Exclude<T, null>;
|
|
921
|
+
type GetMappedKey<M, V> = { [K in keyof M]-?: ExcludeNull<M[K]> extends V ? K : never; }[keyof M] & string;
|
|
922
|
+
/**
|
|
923
|
+
* Get the keys of fields that are maybe defined as `belongsTo` relationships
|
|
924
|
+
*
|
|
925
|
+
* "Maybe" because getter/computed fields might be returning values that look
|
|
926
|
+
* like relationships, but are not.
|
|
927
|
+
*
|
|
928
|
+
*/
|
|
929
|
+
type MaybeBelongsToFields<ThisType> = _TrueKeys<ThisType> extends never ? string : _MaybeBelongsToFields<ThisType>;
|
|
930
|
+
type _MaybeBelongsToFields<ThisType> = GetMappedKey<ThisType, PromiseBelongsTo | TypedRecordInstance>;
|
|
931
|
+
/**
|
|
932
|
+
* Get the keys of fields that are maybe defined as `hasMany` relationships
|
|
933
|
+
*
|
|
934
|
+
* "Maybe" because getter/computed fields might be returning values that look
|
|
935
|
+
* like relationships, but are not.
|
|
936
|
+
*
|
|
937
|
+
*/
|
|
938
|
+
type MaybeHasManyFields<ThisType> = _TrueKeys<ThisType> extends never ? string : _MaybeHasManyFields<ThisType>;
|
|
939
|
+
type _MaybeHasManyFields<ThisType> = GetMappedKey<ThisType, RelatedCollection | PromiseManyArray>;
|
|
940
|
+
/**
|
|
941
|
+
* Get the keys of fields that are maybe defined as `attr` fields
|
|
942
|
+
*
|
|
943
|
+
* "Maybe" because getter/computed fields might be returning values that look
|
|
944
|
+
* like attributes, but are not.
|
|
945
|
+
*
|
|
946
|
+
* This is computed by excluding the keys that are defined as `belongsTo` or `hasMany`
|
|
947
|
+
* as well as the keys on EmberObject and the Model base class
|
|
948
|
+
*
|
|
949
|
+
*/
|
|
950
|
+
type MaybeAttrFields<ThisType> = Exclude<_TrueKeys<ThisType>, _MaybeBelongsToFields<ThisType> | _MaybeHasManyFields<ThisType>>;
|
|
951
|
+
/**
|
|
952
|
+
* Get the keys of fields that are maybe defined as relationships
|
|
953
|
+
*
|
|
954
|
+
* "Maybe" because getter/computed fields might be returning values that look
|
|
955
|
+
* like relationships, but are not.
|
|
956
|
+
*
|
|
957
|
+
*/
|
|
958
|
+
type MaybeRelationshipFields<ThisType> = _TrueKeys<ThisType> extends never ? string : _MaybeBelongsToFields<ThisType> | _MaybeHasManyFields<ThisType>;
|
|
959
|
+
type _TrueKeys<ThisType> = Exclude<keyof ThisType & string, (keyof Model & string) | typeof Type>;
|
|
960
|
+
type isSubClass<ThisType> = _TrueKeys<ThisType> extends never ? false : true;
|
|
961
|
+
//#endregion
|
|
962
|
+
//#region src/model/-private/references/belongs-to.d.ts
|
|
963
|
+
/**
|
|
964
|
+
A `BelongsToReference` is a low-level API that allows access
|
|
965
|
+
and manipulation of a belongsTo relationship.
|
|
966
|
+
|
|
967
|
+
It is especially useful when you're dealing with `async` relationships
|
|
968
|
+
from `@warp-drive/legacy/model` as it allows synchronous access to
|
|
969
|
+
the relationship data if loaded, as well as APIs for loading, reloading
|
|
970
|
+
the data or accessing available information without triggering a load.
|
|
971
|
+
|
|
972
|
+
It may also be useful when using `sync` relationships with `@warp-drive/legacy/model`
|
|
973
|
+
that need to be loaded/reloaded with more precise timing than marking the
|
|
974
|
+
relationship as `async` and relying on autofetch would have allowed.
|
|
975
|
+
|
|
976
|
+
However,keep in mind that marking a relationship as `async: false` will introduce
|
|
977
|
+
bugs into your application if the data is not always guaranteed to be available
|
|
978
|
+
by the time the relationship is accessed. Ergo, it is recommended when using this
|
|
979
|
+
approach to utilize `links` for unloaded relationship state instead of identifiers.
|
|
980
|
+
|
|
981
|
+
Reference APIs are entangled with the relationship's underlying state,
|
|
982
|
+
thus any getters or cached properties that utilize these will properly
|
|
983
|
+
invalidate if the relationship state changes.
|
|
984
|
+
|
|
985
|
+
References are "stable", meaning that multiple calls to retrieve the reference
|
|
986
|
+
for a given relationship will always return the same HasManyReference.
|
|
987
|
+
|
|
988
|
+
@public
|
|
989
|
+
*/
|
|
990
|
+
declare class BelongsToReference<T = unknown, K extends string = IsUnknown<T> extends true ? string : MaybeBelongsToFields<T>, Related = K extends keyof T ? Exclude<Awaited<T[K]>, null> : unknown> {
|
|
991
|
+
graph: Graph;
|
|
992
|
+
store: Store;
|
|
993
|
+
belongsToRelationship: ResourceEdge;
|
|
994
|
+
/**
|
|
995
|
+
* The field name on the parent record for this has-many relationship.
|
|
996
|
+
*
|
|
997
|
+
*/
|
|
998
|
+
key: K;
|
|
999
|
+
/**
|
|
1000
|
+
* The type of resource this relationship will contain.
|
|
1001
|
+
*
|
|
1002
|
+
*/
|
|
1003
|
+
type: TypeFromInstanceOrString<Related>;
|
|
1004
|
+
___token: object;
|
|
1005
|
+
___identifier: ResourceKey$1<TypeFromInstanceOrString<T>>;
|
|
1006
|
+
___relatedToken: object | null;
|
|
1007
|
+
_ref: number;
|
|
1008
|
+
constructor(store: Store, graph: Graph, parentIdentifier: ResourceKey$1<TypeFromInstanceOrString<T>>, belongsToRelationship: ResourceEdge, key: K);
|
|
1009
|
+
destroy(): void;
|
|
1010
|
+
/**
|
|
1011
|
+
* The identifier of the record that this reference refers to.
|
|
1012
|
+
* `null` if no related record is known.
|
|
1013
|
+
*
|
|
1014
|
+
*/
|
|
1015
|
+
get identifier(): ResourceKey$1<TypeFromInstanceOrString<Related>> | null;
|
|
1016
|
+
/**
|
|
1017
|
+
The `id` of the record that this reference refers to. Together, the
|
|
1018
|
+
`type()` and `id()` methods form a composite key for the identity
|
|
1019
|
+
map. This can be used to access the id of an async relationship
|
|
1020
|
+
without triggering a fetch that would normally happen if you
|
|
1021
|
+
attempted to use `record.relationship.id`.
|
|
1022
|
+
|
|
1023
|
+
Example
|
|
1024
|
+
|
|
1025
|
+
```javascript
|
|
1026
|
+
// models/blog.js
|
|
1027
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1028
|
+
|
|
1029
|
+
export default class BlogModel extends Model {
|
|
1030
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let blog = store.push({
|
|
1034
|
+
data: {
|
|
1035
|
+
type: 'blog',
|
|
1036
|
+
id: 1,
|
|
1037
|
+
relationships: {
|
|
1038
|
+
user: {
|
|
1039
|
+
data: { type: 'user', id: 1 }
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
let userRef = blog.belongsTo('user');
|
|
1045
|
+
|
|
1046
|
+
// get the identifier of the reference
|
|
1047
|
+
if (userRef.remoteType() === "id") {
|
|
1048
|
+
let id = userRef.id();
|
|
1049
|
+
}
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
@public
|
|
1053
|
+
@return The id of the record in this belongsTo relationship.
|
|
1054
|
+
*/
|
|
1055
|
+
id(): string | null;
|
|
1056
|
+
/**
|
|
1057
|
+
The link WarpDrive will use to fetch or reload this belongs-to
|
|
1058
|
+
relationship. By default it uses only the "related" resource linkage.
|
|
1059
|
+
|
|
1060
|
+
Example
|
|
1061
|
+
|
|
1062
|
+
```javascript
|
|
1063
|
+
// models/blog.js
|
|
1064
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1065
|
+
export default Model.extend({
|
|
1066
|
+
user: belongsTo('user', { async: true, inverse: null })
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
let blog = store.push({
|
|
1070
|
+
data: {
|
|
1071
|
+
type: 'blog',
|
|
1072
|
+
id: 1,
|
|
1073
|
+
relationships: {
|
|
1074
|
+
user: {
|
|
1075
|
+
links: {
|
|
1076
|
+
related: '/articles/1/author'
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
let userRef = blog.belongsTo('user');
|
|
1083
|
+
|
|
1084
|
+
// get the identifier of the reference
|
|
1085
|
+
if (userRef.remoteType() === "link") {
|
|
1086
|
+
let link = userRef.link();
|
|
1087
|
+
}
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
@public
|
|
1091
|
+
@return The link WarpDrive will use to fetch or reload this belongs-to relationship.
|
|
1092
|
+
*/
|
|
1093
|
+
link(): string | null;
|
|
1094
|
+
/**
|
|
1095
|
+
* any links that have been received for this relationship
|
|
1096
|
+
*
|
|
1097
|
+
* @public
|
|
1098
|
+
* @return
|
|
1099
|
+
*/
|
|
1100
|
+
links(): Links | null;
|
|
1101
|
+
/**
|
|
1102
|
+
The meta data for the belongs-to relationship.
|
|
1103
|
+
|
|
1104
|
+
Example
|
|
1105
|
+
|
|
1106
|
+
```javascript
|
|
1107
|
+
// models/blog.js
|
|
1108
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1109
|
+
export default Model.extend({
|
|
1110
|
+
user: belongsTo('user', { async: true, inverse: null })
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
let blog = store.push({
|
|
1114
|
+
data: {
|
|
1115
|
+
type: 'blog',
|
|
1116
|
+
id: 1,
|
|
1117
|
+
relationships: {
|
|
1118
|
+
user: {
|
|
1119
|
+
links: {
|
|
1120
|
+
related: {
|
|
1121
|
+
href: '/articles/1/author'
|
|
1122
|
+
},
|
|
1123
|
+
},
|
|
1124
|
+
meta: {
|
|
1125
|
+
lastUpdated: 1458014400000
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
let userRef = blog.belongsTo('user');
|
|
1133
|
+
|
|
1134
|
+
userRef.meta() // { lastUpdated: 1458014400000 }
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
@public
|
|
1138
|
+
@return The meta information for the belongs-to relationship.
|
|
1139
|
+
*/
|
|
1140
|
+
meta(): Meta | null;
|
|
1141
|
+
_resource(): SingleResourceRelationship<ResourceKey$1<TypeFromInstance<Related>>>;
|
|
1142
|
+
/**
|
|
1143
|
+
This returns a string that represents how the reference will be
|
|
1144
|
+
looked up when it is loaded. If the relationship has a link it will
|
|
1145
|
+
use the "link" otherwise it defaults to "id".
|
|
1146
|
+
|
|
1147
|
+
Example
|
|
1148
|
+
|
|
1149
|
+
```js [app/models/post.js]
|
|
1150
|
+
import Model, { hasMany } from '@warp-drive/legacy/model';
|
|
1151
|
+
|
|
1152
|
+
export default class PostModel extends Model {
|
|
1153
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
1154
|
+
}
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
```javascript
|
|
1158
|
+
let post = store.push({
|
|
1159
|
+
data: {
|
|
1160
|
+
type: 'post',
|
|
1161
|
+
id: 1,
|
|
1162
|
+
relationships: {
|
|
1163
|
+
comments: {
|
|
1164
|
+
data: [{ type: 'comment', id: 1 }]
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
|
|
1170
|
+
let commentsRef = post.hasMany('comments');
|
|
1171
|
+
|
|
1172
|
+
// get the identifier of the reference
|
|
1173
|
+
if (commentsRef.remoteType() === "ids") {
|
|
1174
|
+
let ids = commentsRef.ids();
|
|
1175
|
+
} else if (commentsRef.remoteType() === "link") {
|
|
1176
|
+
let link = commentsRef.link();
|
|
1177
|
+
}
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
@public
|
|
1181
|
+
@return The name of the remote type. This should either be `link` or `id`
|
|
1182
|
+
*/
|
|
1183
|
+
remoteType(): "link" | "id";
|
|
1184
|
+
/**
|
|
1185
|
+
`push` can be used to update the data in the relationship and WarpDrive
|
|
1186
|
+
will treat the new data as the canonical value of this relationship on
|
|
1187
|
+
the backend. A value of `null` (e.g. `{ data: null }`) can be passed to
|
|
1188
|
+
clear the relationship.
|
|
1189
|
+
|
|
1190
|
+
Example model
|
|
1191
|
+
|
|
1192
|
+
```js [app/models/blog.js]
|
|
1193
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1194
|
+
|
|
1195
|
+
export default class BlogModel extends Model {
|
|
1196
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
1197
|
+
}
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
Setup some initial state, note we haven't loaded the user yet:
|
|
1201
|
+
|
|
1202
|
+
```js
|
|
1203
|
+
const blog = store.push({
|
|
1204
|
+
data: {
|
|
1205
|
+
type: 'blog',
|
|
1206
|
+
id: '1',
|
|
1207
|
+
relationships: {
|
|
1208
|
+
user: {
|
|
1209
|
+
data: { type: 'user', id: '1' }
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
const userRef = blog.belongsTo('user');
|
|
1216
|
+
userRef.id(); // '1'
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
Update the state using `push`, note we can do this even without
|
|
1220
|
+
having loaded the user yet by providing a resource-identifier.
|
|
1221
|
+
|
|
1222
|
+
Both full a resource and a resource-identifier are supported.
|
|
1223
|
+
|
|
1224
|
+
```js
|
|
1225
|
+
await userRef.push({
|
|
1226
|
+
data: {
|
|
1227
|
+
type: 'user',
|
|
1228
|
+
id: '2',
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
userRef.id(); // '2'
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
You may also pass in links and meta fore the relationship, and sideload
|
|
1236
|
+
additional resources that might be required.
|
|
1237
|
+
|
|
1238
|
+
```js
|
|
1239
|
+
await userRef.push({
|
|
1240
|
+
data: {
|
|
1241
|
+
type: 'user',
|
|
1242
|
+
id: '2',
|
|
1243
|
+
},
|
|
1244
|
+
links: {
|
|
1245
|
+
related: '/articles/1/author'
|
|
1246
|
+
},
|
|
1247
|
+
meta: {
|
|
1248
|
+
lastUpdated: Date.now()
|
|
1249
|
+
},
|
|
1250
|
+
included: [
|
|
1251
|
+
{
|
|
1252
|
+
type: 'user-preview',
|
|
1253
|
+
id: '2',
|
|
1254
|
+
attributes: {
|
|
1255
|
+
username: '@runspired'
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
]
|
|
1259
|
+
});
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
By default, the store will attempt to fetch the record if it is not loaded or its
|
|
1263
|
+
resource data is not included in the call to `push` before resolving the returned
|
|
1264
|
+
promise with the new state..
|
|
1265
|
+
|
|
1266
|
+
Alternatively, pass `true` as the second argument to avoid fetching unloaded records
|
|
1267
|
+
and instead the promise will resolve with void without attempting to fetch. This is
|
|
1268
|
+
particularly useful if you want to update the state of the relationship without
|
|
1269
|
+
forcing the load of all of the associated record.
|
|
1270
|
+
|
|
1271
|
+
@public
|
|
1272
|
+
@param doc a JSONAPI document object describing the new value of this relationship.
|
|
1273
|
+
@param skipFetch [optional] if `true`, do not attempt to fetch unloaded records
|
|
1274
|
+
@return a promise that resolves with the record in this belongs-to relationship after the push has completed.
|
|
1275
|
+
*/
|
|
1276
|
+
push(doc: SingleResourceDocument, skipFetch?: boolean): Promise<Related | null | void>;
|
|
1277
|
+
/**
|
|
1278
|
+
`value()` synchronously returns the current value of the belongs-to
|
|
1279
|
+
relationship. Unlike `record.relationshipName`, calling
|
|
1280
|
+
`value()` on a reference does not trigger a fetch if the async
|
|
1281
|
+
relationship is not yet loaded. If the relationship is not loaded
|
|
1282
|
+
it will always return `null`.
|
|
1283
|
+
|
|
1284
|
+
Example
|
|
1285
|
+
|
|
1286
|
+
```javascript
|
|
1287
|
+
// models/blog.js
|
|
1288
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1289
|
+
|
|
1290
|
+
export default class BlogModel extends Model {
|
|
1291
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
let blog = store.push({
|
|
1295
|
+
data: {
|
|
1296
|
+
type: 'blog',
|
|
1297
|
+
id: 1,
|
|
1298
|
+
relationships: {
|
|
1299
|
+
user: {
|
|
1300
|
+
data: { type: 'user', id: 1 }
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
});
|
|
1305
|
+
let userRef = blog.belongsTo('user');
|
|
1306
|
+
|
|
1307
|
+
userRef.value(); // null
|
|
1308
|
+
|
|
1309
|
+
// provide data for reference
|
|
1310
|
+
userRef.push({
|
|
1311
|
+
data: {
|
|
1312
|
+
type: 'user',
|
|
1313
|
+
id: 1,
|
|
1314
|
+
attributes: {
|
|
1315
|
+
username: "@user"
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}).then(function(user) {
|
|
1319
|
+
userRef.value(); // user
|
|
1320
|
+
});
|
|
1321
|
+
```
|
|
1322
|
+
|
|
1323
|
+
@public
|
|
1324
|
+
@return the record in this relationship
|
|
1325
|
+
*/
|
|
1326
|
+
value(): Related | null;
|
|
1327
|
+
/**
|
|
1328
|
+
Loads a record in a belongs-to relationship if it is not already
|
|
1329
|
+
loaded. If the relationship is already loaded this method does not
|
|
1330
|
+
trigger a new load.
|
|
1331
|
+
|
|
1332
|
+
Example
|
|
1333
|
+
|
|
1334
|
+
```javascript
|
|
1335
|
+
// models/blog.js
|
|
1336
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1337
|
+
|
|
1338
|
+
export default class BlogModel extends Model {
|
|
1339
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
let blog = store.push({
|
|
1343
|
+
data: {
|
|
1344
|
+
type: 'blog',
|
|
1345
|
+
id: 1,
|
|
1346
|
+
relationships: {
|
|
1347
|
+
user: {
|
|
1348
|
+
data: { type: 'user', id: 1 }
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
let userRef = blog.belongsTo('user');
|
|
1354
|
+
|
|
1355
|
+
userRef.value(); // null
|
|
1356
|
+
|
|
1357
|
+
userRef.load().then(function(user) {
|
|
1358
|
+
userRef.value() === user
|
|
1359
|
+
});
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
You may also pass in an options object whose properties will be
|
|
1363
|
+
fed forward. This enables you to pass `adapterOptions` into the
|
|
1364
|
+
request given to the adapter via the reference.
|
|
1365
|
+
|
|
1366
|
+
Example
|
|
1367
|
+
|
|
1368
|
+
```javascript
|
|
1369
|
+
userRef.load({ adapterOptions: { isPrivate: true } }).then(function(user) {
|
|
1370
|
+
userRef.value() === user;
|
|
1371
|
+
});
|
|
1372
|
+
```
|
|
1373
|
+
```js [app/adapters/user.js]
|
|
1374
|
+
import Adapter from '@warp-drive/legacy/adapter';
|
|
1375
|
+
|
|
1376
|
+
export default class UserAdapter extends Adapter {
|
|
1377
|
+
findRecord(store, type, id, snapshot) {
|
|
1378
|
+
// In the adapter you will have access to adapterOptions.
|
|
1379
|
+
let adapterOptions = snapshot.adapterOptions;
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
```
|
|
1383
|
+
|
|
1384
|
+
@public
|
|
1385
|
+
@param options the options to pass in.
|
|
1386
|
+
@return a promise that resolves with the record in this belongs-to relationship.
|
|
1387
|
+
*/
|
|
1388
|
+
load(options?: Record<string, unknown>): Promise<Related | null>;
|
|
1389
|
+
/**
|
|
1390
|
+
Triggers a reload of the value in this relationship. If the
|
|
1391
|
+
remoteType is `"link"` WarpDrive will use the relationship link to
|
|
1392
|
+
reload the relationship. Otherwise it will reload the record by its
|
|
1393
|
+
id.
|
|
1394
|
+
|
|
1395
|
+
Example
|
|
1396
|
+
|
|
1397
|
+
```javascript
|
|
1398
|
+
// models/blog.js
|
|
1399
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
1400
|
+
|
|
1401
|
+
export default class BlogModel extends Model {
|
|
1402
|
+
@belongsTo('user', { async: true, inverse: null }) user;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
let blog = store.push({
|
|
1406
|
+
data: {
|
|
1407
|
+
type: 'blog',
|
|
1408
|
+
id: 1,
|
|
1409
|
+
relationships: {
|
|
1410
|
+
user: {
|
|
1411
|
+
data: { type: 'user', id: 1 }
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
let userRef = blog.belongsTo('user');
|
|
1417
|
+
|
|
1418
|
+
userRef.reload().then(function(user) {
|
|
1419
|
+
userRef.value() === user
|
|
1420
|
+
});
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
You may also pass in an options object whose properties will be
|
|
1424
|
+
fed forward. This enables you to pass `adapterOptions` into the
|
|
1425
|
+
request given to the adapter via the reference. A full example
|
|
1426
|
+
can be found in the `load` method.
|
|
1427
|
+
|
|
1428
|
+
Example
|
|
1429
|
+
|
|
1430
|
+
```javascript
|
|
1431
|
+
userRef.reload({ adapterOptions: { isPrivate: true } })
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
@public
|
|
1435
|
+
@param options the options to pass in.
|
|
1436
|
+
@return a promise that resolves with the record in this belongs-to relationship after the reload has completed.
|
|
1437
|
+
*/
|
|
1438
|
+
reload(options?: Record<string, unknown>): Promise<Related | null>;
|
|
1439
|
+
}
|
|
1440
|
+
//#endregion
|
|
1441
|
+
//#region src/model/-private/model-methods.d.ts
|
|
1442
|
+
interface MinimalLegacyRecord {
|
|
1443
|
+
errors: Errors;
|
|
1444
|
+
/** @internal */
|
|
1445
|
+
___recordState: RecordState;
|
|
1446
|
+
currentState: RecordState;
|
|
1447
|
+
isDestroyed: boolean;
|
|
1448
|
+
isDestroying: boolean;
|
|
1449
|
+
isReloading: boolean;
|
|
1450
|
+
isValid: boolean;
|
|
1451
|
+
/** @internal */
|
|
1452
|
+
[RecordStore]: Store;
|
|
1453
|
+
deleteRecord(): void;
|
|
1454
|
+
unloadRecord(): void;
|
|
1455
|
+
save<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): Promise<this>;
|
|
1456
|
+
destroyRecord<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): Promise<this>;
|
|
1457
|
+
}
|
|
1458
|
+
declare function belongsTo<T extends MinimalLegacyRecord, K extends MaybeBelongsToFields<T>>(this: T, prop: K): BelongsToReference<T, K>;
|
|
1459
|
+
declare function hasMany<T extends MinimalLegacyRecord, K extends MaybeHasManyFields<T>>(this: T, prop: K): HasManyReference<T, K>;
|
|
1460
|
+
//#endregion
|
|
1461
|
+
//#region src/model/-private/record-state.d.ts
|
|
1462
|
+
/**
|
|
1463
|
+
Historically WarpDrive managed a state machine
|
|
1464
|
+
for each record, the localState for which
|
|
1465
|
+
was reflected onto Model.
|
|
1466
|
+
|
|
1467
|
+
This implements the flags and stateName for backwards compat
|
|
1468
|
+
with the state tree that used to be possible (listed below).
|
|
1469
|
+
|
|
1470
|
+
stateName and dirtyType are candidates for deprecation.
|
|
1471
|
+
|
|
1472
|
+
root
|
|
1473
|
+
empty
|
|
1474
|
+
deleted // hidden from stateName
|
|
1475
|
+
preloaded // hidden from stateName
|
|
1476
|
+
|
|
1477
|
+
loading
|
|
1478
|
+
empty // hidden from stateName
|
|
1479
|
+
preloaded // hidden from stateName
|
|
1480
|
+
|
|
1481
|
+
loaded
|
|
1482
|
+
saved
|
|
1483
|
+
updated
|
|
1484
|
+
uncommitted
|
|
1485
|
+
invalid
|
|
1486
|
+
inFlight
|
|
1487
|
+
created
|
|
1488
|
+
uncommitted
|
|
1489
|
+
invalid
|
|
1490
|
+
inFlight
|
|
1491
|
+
|
|
1492
|
+
deleted
|
|
1493
|
+
saved
|
|
1494
|
+
new // hidden from stateName
|
|
1495
|
+
uncommitted
|
|
1496
|
+
invalid
|
|
1497
|
+
inFlight
|
|
1498
|
+
|
|
1499
|
+
@hideconstructor
|
|
1500
|
+
@private
|
|
1501
|
+
*/
|
|
1502
|
+
declare class RecordState {
|
|
1503
|
+
/** @internal */
|
|
1504
|
+
private store;
|
|
1505
|
+
/** @internal */
|
|
1506
|
+
private identifier;
|
|
1507
|
+
/** @internal */
|
|
1508
|
+
private record;
|
|
1509
|
+
/** @internal */
|
|
1510
|
+
private rs;
|
|
1511
|
+
/** @internal */
|
|
1512
|
+
private pendingCount;
|
|
1513
|
+
/** @internal */
|
|
1514
|
+
private fulfilledCount;
|
|
1515
|
+
/** @internal */
|
|
1516
|
+
private rejectedCount;
|
|
1517
|
+
/** @internal */
|
|
1518
|
+
private cache;
|
|
1519
|
+
/** @internal */
|
|
1520
|
+
private _errorRequests;
|
|
1521
|
+
/** @internal */
|
|
1522
|
+
private _lastError;
|
|
1523
|
+
/** @internal */
|
|
1524
|
+
private handler;
|
|
1525
|
+
constructor(record: MinimalLegacyRecord);
|
|
1526
|
+
/** @internal */
|
|
1527
|
+
destroy(): void;
|
|
1528
|
+
/** @internal */
|
|
1529
|
+
notify(key: keyof this & string): void;
|
|
1530
|
+
/** @internal */
|
|
1531
|
+
updateInvalidErrors(errors: Errors): void;
|
|
1532
|
+
/** @internal */
|
|
1533
|
+
cleanErrorRequests(): void;
|
|
1534
|
+
isSaving: boolean;
|
|
1535
|
+
get isLoading(): boolean;
|
|
1536
|
+
get isLoaded(): boolean;
|
|
1537
|
+
get isSaved(): boolean;
|
|
1538
|
+
get isEmpty(): boolean;
|
|
1539
|
+
get isNew(): boolean;
|
|
1540
|
+
get isDeleted(): boolean;
|
|
1541
|
+
get isValid(): boolean;
|
|
1542
|
+
get isDirty(): boolean;
|
|
1543
|
+
get isError(): boolean;
|
|
1544
|
+
get adapterError(): unknown;
|
|
1545
|
+
get isPreloaded(): boolean;
|
|
1546
|
+
get stateName(): "root.loading" | "root.empty" | "root.deleted.inFlight" | "root.deleted.saved" | "root.deleted.invalid" | "root.deleted.uncommitted" | "root.loaded.created.inFlight" | "root.loaded.created.invalid" | "root.loaded.created.uncommitted" | "root.loaded.updated.inFlight" | "root.loaded.updated.invalid" | "root.loaded.updated.uncommitted" | "root.loaded.saved";
|
|
1547
|
+
get dirtyType(): "" | "deleted" | "created" | "updated";
|
|
1548
|
+
}
|
|
1549
|
+
//#endregion
|
|
1550
|
+
//#region src/model/-private/errors.d.ts
|
|
1551
|
+
type ValidationError = {
|
|
1552
|
+
attribute: string;
|
|
1553
|
+
message: string;
|
|
1554
|
+
};
|
|
1555
|
+
interface ArrayProxyWithCustomOverrides<T> extends Omit<ArrayProxy<T>, "clear" | "content"> {
|
|
1556
|
+
content: NativeArray<T>;
|
|
1557
|
+
clear(): void;
|
|
1558
|
+
_has(name: string): boolean;
|
|
1559
|
+
}
|
|
1560
|
+
declare const ArrayProxyWithCustomOverrides: new <T>() => ArrayProxyWithCustomOverrides<T>;
|
|
1561
|
+
/**
|
|
1562
|
+
Holds validation errors for a given record, organized by attribute names.
|
|
1563
|
+
|
|
1564
|
+
This class is not directly instantiable.
|
|
1565
|
+
|
|
1566
|
+
Every `Model` has an `errors` property that is an instance of
|
|
1567
|
+
`Errors`. This can be used to display validation error
|
|
1568
|
+
messages returned from the server when a `record.save()` rejects.
|
|
1569
|
+
|
|
1570
|
+
For Example, if you had a `User` model that looked like this:
|
|
1571
|
+
|
|
1572
|
+
```js [app/models/user.js]
|
|
1573
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
1574
|
+
|
|
1575
|
+
export default class UserModel extends Model {
|
|
1576
|
+
@attr('string') username;
|
|
1577
|
+
@attr('string') email;
|
|
1578
|
+
}
|
|
1579
|
+
```
|
|
1580
|
+
And you attempted to save a record that did not validate on the backend:
|
|
1581
|
+
|
|
1582
|
+
```javascript
|
|
1583
|
+
let user = store.createRecord('user', {
|
|
1584
|
+
username: 'tomster',
|
|
1585
|
+
email: 'invalidEmail'
|
|
1586
|
+
});
|
|
1587
|
+
user.save();
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
Your backend would be expected to return an error response that described
|
|
1591
|
+
the problem, so that error messages can be generated on the app.
|
|
1592
|
+
|
|
1593
|
+
API responses will be translated into instances of `Errors` differently,
|
|
1594
|
+
depending on the specific combination of adapter and serializer used. You
|
|
1595
|
+
may want to check the documentation or the source code of the libraries
|
|
1596
|
+
that you are using, to know how they expect errors to be communicated.
|
|
1597
|
+
|
|
1598
|
+
Errors can be displayed to the user by accessing their property name
|
|
1599
|
+
to get an array of all the error objects for that property. Each
|
|
1600
|
+
error object is a JavaScript object with two keys:
|
|
1601
|
+
|
|
1602
|
+
- `message` A string containing the error message from the backend
|
|
1603
|
+
- `attribute` The name of the property associated with this error message
|
|
1604
|
+
|
|
1605
|
+
```handlebars
|
|
1606
|
+
<label>Username: <Input @value={{@model.username}} /> </label>
|
|
1607
|
+
{{#each @model.errors.username as |error|}}
|
|
1608
|
+
<div class="error">
|
|
1609
|
+
{{error.message}}
|
|
1610
|
+
</div>
|
|
1611
|
+
{{/each}}
|
|
1612
|
+
|
|
1613
|
+
<label>Email: <Input @value={{@model.email}} /> </label>
|
|
1614
|
+
{{#each @model.errors.email as |error|}}
|
|
1615
|
+
<div class="error">
|
|
1616
|
+
{{error.message}}
|
|
1617
|
+
</div>
|
|
1618
|
+
{{/each}}
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
You can also access the special `messages` property on the error
|
|
1622
|
+
object to get an array of all the error strings.
|
|
1623
|
+
|
|
1624
|
+
```handlebars
|
|
1625
|
+
{{#each @model.errors.messages as |message|}}
|
|
1626
|
+
<div class="error">
|
|
1627
|
+
{{message}}
|
|
1628
|
+
</div>
|
|
1629
|
+
{{/each}}
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
@class Errors
|
|
1633
|
+
@public
|
|
1634
|
+
*/
|
|
1635
|
+
declare class Errors extends ArrayProxyWithCustomOverrides<ValidationError> {
|
|
1636
|
+
__record: {
|
|
1637
|
+
currentState: RecordState;
|
|
1638
|
+
};
|
|
1639
|
+
/**
|
|
1640
|
+
@property errorsByAttributeName
|
|
1641
|
+
@type {MapWithDefault}
|
|
1642
|
+
@private
|
|
1643
|
+
*/
|
|
1644
|
+
get errorsByAttributeName(): Map<string, NativeArray<ValidationError>>;
|
|
1645
|
+
/**
|
|
1646
|
+
Returns errors for a given attribute
|
|
1647
|
+
|
|
1648
|
+
```javascript
|
|
1649
|
+
let user = store.createRecord('user', {
|
|
1650
|
+
username: 'tomster',
|
|
1651
|
+
email: 'invalidEmail'
|
|
1652
|
+
});
|
|
1653
|
+
user.save().catch(function(){
|
|
1654
|
+
user.errors.errorsFor('email'); // returns:
|
|
1655
|
+
// [{attribute: "email", message: "Doesn't look like a valid email."}]
|
|
1656
|
+
});
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
@public
|
|
1660
|
+
@param {String} attribute
|
|
1661
|
+
@return {Array}
|
|
1662
|
+
*/
|
|
1663
|
+
errorsFor(attribute: string): NativeArray<ValidationError>;
|
|
1664
|
+
/**
|
|
1665
|
+
An array containing all of the error messages for this
|
|
1666
|
+
record. This is useful for displaying all errors to the user.
|
|
1667
|
+
|
|
1668
|
+
```handlebars
|
|
1669
|
+
{{#each @model.errors.messages as |message|}}
|
|
1670
|
+
<div class="error">
|
|
1671
|
+
{{message}}
|
|
1672
|
+
</div>
|
|
1673
|
+
{{/each}}
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
@property messages
|
|
1677
|
+
@public
|
|
1678
|
+
@type {Array}
|
|
1679
|
+
*/
|
|
1680
|
+
messages: string[];
|
|
1681
|
+
/**
|
|
1682
|
+
@property content
|
|
1683
|
+
@type {Array}
|
|
1684
|
+
@private
|
|
1685
|
+
*/
|
|
1686
|
+
get content(): NativeArray<ValidationError>;
|
|
1687
|
+
/**
|
|
1688
|
+
@private
|
|
1689
|
+
*/
|
|
1690
|
+
unknownProperty(attribute: string): NativeArray<ValidationError> | undefined;
|
|
1691
|
+
/**
|
|
1692
|
+
Total number of errors.
|
|
1693
|
+
|
|
1694
|
+
@property length
|
|
1695
|
+
@type {Number}
|
|
1696
|
+
@public
|
|
1697
|
+
@readonly
|
|
1698
|
+
*/
|
|
1699
|
+
/**
|
|
1700
|
+
`true` if we have no errors.
|
|
1701
|
+
|
|
1702
|
+
@property isEmpty
|
|
1703
|
+
@type {Boolean}
|
|
1704
|
+
@public
|
|
1705
|
+
@readonly
|
|
1706
|
+
*/
|
|
1707
|
+
isEmpty: boolean;
|
|
1708
|
+
/**
|
|
1709
|
+
Manually adds errors to the record. This will trigger the `becameInvalid` event/ lifecycle method on
|
|
1710
|
+
the record and transition the record into an `invalid` state.
|
|
1711
|
+
|
|
1712
|
+
Example
|
|
1713
|
+
```javascript
|
|
1714
|
+
let errors = user.errors;
|
|
1715
|
+
|
|
1716
|
+
// add multiple errors
|
|
1717
|
+
errors.add('password', [
|
|
1718
|
+
'Must be at least 12 characters',
|
|
1719
|
+
'Must contain at least one symbol',
|
|
1720
|
+
'Cannot contain your name'
|
|
1721
|
+
]);
|
|
1722
|
+
|
|
1723
|
+
errors.errorsFor('password');
|
|
1724
|
+
// =>
|
|
1725
|
+
// [
|
|
1726
|
+
// { attribute: 'password', message: 'Must be at least 12 characters' },
|
|
1727
|
+
// { attribute: 'password', message: 'Must contain at least one symbol' },
|
|
1728
|
+
// { attribute: 'password', message: 'Cannot contain your name' },
|
|
1729
|
+
// ]
|
|
1730
|
+
|
|
1731
|
+
// add a single error
|
|
1732
|
+
errors.add('username', 'This field is required');
|
|
1733
|
+
|
|
1734
|
+
errors.errorsFor('username');
|
|
1735
|
+
// =>
|
|
1736
|
+
// [
|
|
1737
|
+
// { attribute: 'username', message: 'This field is required' },
|
|
1738
|
+
// ]
|
|
1739
|
+
```
|
|
1740
|
+
@public
|
|
1741
|
+
@param {String} attribute - the property name of an attribute or relationship
|
|
1742
|
+
@param {string[]|string} messages - an error message or array of error messages for the attribute
|
|
1743
|
+
*/
|
|
1744
|
+
add(attribute: string, messages: string[] | string): void;
|
|
1745
|
+
/**
|
|
1746
|
+
@private
|
|
1747
|
+
*/
|
|
1748
|
+
_findOrCreateMessages(attribute: string, messages: string | string[]): ValidationError[];
|
|
1749
|
+
/**
|
|
1750
|
+
Manually removes all errors for a given member from the record.
|
|
1751
|
+
This will transition the record into a `valid` state, and
|
|
1752
|
+
triggers the `becameValid` event and lifecycle method.
|
|
1753
|
+
|
|
1754
|
+
Example:
|
|
1755
|
+
|
|
1756
|
+
```javascript
|
|
1757
|
+
let errors = user.errors;
|
|
1758
|
+
errors.add('phone', ['error-1', 'error-2']);
|
|
1759
|
+
|
|
1760
|
+
errors.errorsFor('phone');
|
|
1761
|
+
// =>
|
|
1762
|
+
// [
|
|
1763
|
+
// { attribute: 'phone', message: 'error-1' },
|
|
1764
|
+
// { attribute: 'phone', message: 'error-2' },
|
|
1765
|
+
// ]
|
|
1766
|
+
|
|
1767
|
+
errors.remove('phone');
|
|
1768
|
+
|
|
1769
|
+
errors.errorsFor('phone');
|
|
1770
|
+
// => undefined
|
|
1771
|
+
```
|
|
1772
|
+
@public
|
|
1773
|
+
@param {String} member - the property name of an attribute or relationship
|
|
1774
|
+
*/
|
|
1775
|
+
remove(attribute: string): void;
|
|
1776
|
+
/**
|
|
1777
|
+
Manually clears all errors for the record.
|
|
1778
|
+
This will transition the record into a `valid` state, and
|
|
1779
|
+
will trigger the `becameValid` event and lifecycle method.
|
|
1780
|
+
|
|
1781
|
+
Example:
|
|
1782
|
+
|
|
1783
|
+
```javascript
|
|
1784
|
+
let errors = user.errors;
|
|
1785
|
+
errors.add('username', ['error-a']);
|
|
1786
|
+
errors.add('phone', ['error-1', 'error-2']);
|
|
1787
|
+
|
|
1788
|
+
errors.errorsFor('username');
|
|
1789
|
+
// =>
|
|
1790
|
+
// [
|
|
1791
|
+
// { attribute: 'username', message: 'error-a' },
|
|
1792
|
+
// ]
|
|
1793
|
+
|
|
1794
|
+
errors.errorsFor('phone');
|
|
1795
|
+
// =>
|
|
1796
|
+
// [
|
|
1797
|
+
// { attribute: 'phone', message: 'error-1' },
|
|
1798
|
+
// { attribute: 'phone', message: 'error-2' },
|
|
1799
|
+
// ]
|
|
1800
|
+
|
|
1801
|
+
errors.clear();
|
|
1802
|
+
|
|
1803
|
+
errors.errorsFor('username');
|
|
1804
|
+
// => undefined
|
|
1805
|
+
|
|
1806
|
+
errors.errorsFor('phone');
|
|
1807
|
+
// => undefined
|
|
1808
|
+
|
|
1809
|
+
errors.messages
|
|
1810
|
+
// => []
|
|
1811
|
+
```
|
|
1812
|
+
@public
|
|
1813
|
+
*/
|
|
1814
|
+
clear(): void;
|
|
1815
|
+
/**
|
|
1816
|
+
Checks if there are error messages for the given attribute.
|
|
1817
|
+
|
|
1818
|
+
```js [app/controllers/user/edit.js]
|
|
1819
|
+
export default class UserEditController extends Controller {
|
|
1820
|
+
@action
|
|
1821
|
+
save(user) {
|
|
1822
|
+
if (user.errors.has('email')) {
|
|
1823
|
+
return alert('Please update your email before attempting to save.');
|
|
1824
|
+
}
|
|
1825
|
+
user.save();
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
```
|
|
1829
|
+
|
|
1830
|
+
@public
|
|
1831
|
+
@param {String} attribute
|
|
1832
|
+
@return {Boolean} true if there some errors on given attribute
|
|
1833
|
+
*/
|
|
1834
|
+
has(attribute: string): boolean;
|
|
1835
|
+
}
|
|
1836
|
+
//#endregion
|
|
1837
|
+
//#region src/model/-private/model.d.ts
|
|
1838
|
+
type ModelCreateArgs = {
|
|
1839
|
+
_createProps: Record<string, unknown>;
|
|
1840
|
+
_secretInit: {
|
|
1841
|
+
identifier: ResourceKey;
|
|
1842
|
+
store: Store;
|
|
1843
|
+
cb: (record: Model, identifier: ResourceKey, store: Store) => void;
|
|
1844
|
+
};
|
|
1845
|
+
};
|
|
1846
|
+
type StaticModel = typeof Model & {
|
|
1847
|
+
create(options: ModelCreateArgs): Model;
|
|
1848
|
+
};
|
|
1849
|
+
type ModelFactory = {
|
|
1850
|
+
class: StaticModel;
|
|
1851
|
+
};
|
|
1852
|
+
type FactoryCache = Record<string, ModelFactory>;
|
|
1853
|
+
type ModelStore = Store & {
|
|
1854
|
+
_modelFactoryCache: FactoryCache;
|
|
1855
|
+
};
|
|
1856
|
+
interface Model {
|
|
1857
|
+
/**
|
|
1858
|
+
* The store service instance which created this record instance
|
|
1859
|
+
*/
|
|
1860
|
+
store: Store;
|
|
1861
|
+
/** @internal */
|
|
1862
|
+
___recordState: RecordState;
|
|
1863
|
+
/** @internal */
|
|
1864
|
+
___private_notifications: object;
|
|
1865
|
+
/** @internal */
|
|
1866
|
+
_isReloading: boolean;
|
|
1867
|
+
/** @internal */
|
|
1868
|
+
[RecordStore]: Store;
|
|
1869
|
+
/**
|
|
1870
|
+
Create a JSON representation of the record, using the serialization
|
|
1871
|
+
strategy of the store's adapter.
|
|
1872
|
+
|
|
1873
|
+
`serialize` takes an optional hash as a parameter, currently
|
|
1874
|
+
supported options are:
|
|
1875
|
+
|
|
1876
|
+
- `includeId`: `true` if the record's ID should be included in the
|
|
1877
|
+
JSON representation.
|
|
1878
|
+
|
|
1879
|
+
@public
|
|
1880
|
+
@param {Object} options
|
|
1881
|
+
@return {Object} an object whose values are primitive JSON values only
|
|
1882
|
+
*/
|
|
1883
|
+
serialize<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): unknown;
|
|
1884
|
+
/**
|
|
1885
|
+
Same as `deleteRecord`, but saves the record immediately.
|
|
1886
|
+
|
|
1887
|
+
Example
|
|
1888
|
+
|
|
1889
|
+
```js
|
|
1890
|
+
import Component from '@glimmer/component';
|
|
1891
|
+
|
|
1892
|
+
export default class extends Component {
|
|
1893
|
+
delete = () => {
|
|
1894
|
+
this.args.model.destroyRecord().then(function() {
|
|
1895
|
+
this.transitionToRoute('model.index');
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
```
|
|
1900
|
+
|
|
1901
|
+
If you pass an object on the `adapterOptions` property of the options
|
|
1902
|
+
argument it will be passed to your adapter via the snapshot
|
|
1903
|
+
|
|
1904
|
+
```js
|
|
1905
|
+
record.destroyRecord({ adapterOptions: { subscribe: false } });
|
|
1906
|
+
```
|
|
1907
|
+
|
|
1908
|
+
```js [app/adapters/post.js]
|
|
1909
|
+
import MyCustomAdapter from './custom-adapter';
|
|
1910
|
+
|
|
1911
|
+
export default class PostAdapter extends MyCustomAdapter {
|
|
1912
|
+
deleteRecord(store, type, snapshot) {
|
|
1913
|
+
if (snapshot.adapterOptions.subscribe) {
|
|
1914
|
+
// ...
|
|
1915
|
+
}
|
|
1916
|
+
// ...
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1921
|
+
@public
|
|
1922
|
+
@param options
|
|
1923
|
+
@return a promise that will be resolved when the adapter returns
|
|
1924
|
+
successfully or rejected if the adapter returns with an error.
|
|
1925
|
+
*/
|
|
1926
|
+
destroyRecord<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): Promise<this>;
|
|
1927
|
+
/**
|
|
1928
|
+
Unloads the record from the store. This will not send a delete request
|
|
1929
|
+
to your server, it just unloads the record from memory.
|
|
1930
|
+
|
|
1931
|
+
@public
|
|
1932
|
+
*/
|
|
1933
|
+
unloadRecord<T extends MinimalLegacyRecord>(this: T): void;
|
|
1934
|
+
/**
|
|
1935
|
+
Returns an object, whose keys are changed properties, and value is
|
|
1936
|
+
an [oldProp, newProp] array.
|
|
1937
|
+
|
|
1938
|
+
The array represents the diff of the canonical state with the local state
|
|
1939
|
+
of the model. Note: if the model is created locally, the canonical state is
|
|
1940
|
+
empty since the adapter hasn't acknowledged the attributes yet:
|
|
1941
|
+
|
|
1942
|
+
Example
|
|
1943
|
+
|
|
1944
|
+
```js [app/models/mascot.js]
|
|
1945
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
1946
|
+
|
|
1947
|
+
export default class MascotModel extends Model {
|
|
1948
|
+
@attr('string') name;
|
|
1949
|
+
@attr('boolean', {
|
|
1950
|
+
defaultValue: false
|
|
1951
|
+
})
|
|
1952
|
+
isAdmin;
|
|
1953
|
+
}
|
|
1954
|
+
```
|
|
1955
|
+
|
|
1956
|
+
```javascript
|
|
1957
|
+
let mascot = store.createRecord('mascot');
|
|
1958
|
+
|
|
1959
|
+
mascot.changedAttributes(); // {}
|
|
1960
|
+
|
|
1961
|
+
mascot.set('name', 'Tomster');
|
|
1962
|
+
mascot.changedAttributes(); // { name: [undefined, 'Tomster'] }
|
|
1963
|
+
|
|
1964
|
+
mascot.set('isAdmin', true);
|
|
1965
|
+
mascot.changedAttributes(); // { isAdmin: [undefined, true], name: [undefined, 'Tomster'] }
|
|
1966
|
+
|
|
1967
|
+
mascot.save().then(function() {
|
|
1968
|
+
mascot.changedAttributes(); // {}
|
|
1969
|
+
|
|
1970
|
+
mascot.set('isAdmin', false);
|
|
1971
|
+
mascot.changedAttributes(); // { isAdmin: [true, false] }
|
|
1972
|
+
});
|
|
1973
|
+
```
|
|
1974
|
+
|
|
1975
|
+
@public
|
|
1976
|
+
@return {Object} an object, whose keys are changed properties,
|
|
1977
|
+
and value is an [oldProp, newProp] array.
|
|
1978
|
+
*/
|
|
1979
|
+
changedAttributes<T extends MinimalLegacyRecord>(this: T): ChangedAttributesHash;
|
|
1980
|
+
/**
|
|
1981
|
+
If the model `hasDirtyAttributes` this function will discard any unsaved
|
|
1982
|
+
changes. If the model `isNew` it will be removed from the store.
|
|
1983
|
+
|
|
1984
|
+
Example
|
|
1985
|
+
|
|
1986
|
+
```javascript
|
|
1987
|
+
record.name; // 'Untitled Document'
|
|
1988
|
+
record.set('name', 'Doc 1');
|
|
1989
|
+
record.name; // 'Doc 1'
|
|
1990
|
+
record.rollbackAttributes();
|
|
1991
|
+
record.name; // 'Untitled Document'
|
|
1992
|
+
```
|
|
1993
|
+
|
|
1994
|
+
@since 1.13.0
|
|
1995
|
+
@public
|
|
1996
|
+
*/
|
|
1997
|
+
rollbackAttributes<T extends MinimalLegacyRecord>(this: T): void;
|
|
1998
|
+
/**
|
|
1999
|
+
@private
|
|
2000
|
+
*/
|
|
2001
|
+
_createSnapshot<T extends MinimalLegacyRecord>(this: T): Snapshot<T>;
|
|
2002
|
+
/**
|
|
2003
|
+
Save the record and persist any changes to the record to an
|
|
2004
|
+
external source via the adapter.
|
|
2005
|
+
|
|
2006
|
+
Example
|
|
2007
|
+
|
|
2008
|
+
```javascript
|
|
2009
|
+
record.set('name', 'Tomster');
|
|
2010
|
+
record.save().then(function() {
|
|
2011
|
+
// Success callback
|
|
2012
|
+
}, function() {
|
|
2013
|
+
// Error callback
|
|
2014
|
+
});
|
|
2015
|
+
```
|
|
2016
|
+
|
|
2017
|
+
If you pass an object using the `adapterOptions` property of the options
|
|
2018
|
+
argument it will be passed to your adapter via the snapshot.
|
|
2019
|
+
|
|
2020
|
+
```js
|
|
2021
|
+
record.save({ adapterOptions: { subscribe: false } });
|
|
2022
|
+
```
|
|
2023
|
+
|
|
2024
|
+
```js [app/adapters/post.js]
|
|
2025
|
+
import MyCustomAdapter from './custom-adapter';
|
|
2026
|
+
|
|
2027
|
+
export default class PostAdapter extends MyCustomAdapter {
|
|
2028
|
+
updateRecord(store, type, snapshot) {
|
|
2029
|
+
if (snapshot.adapterOptions.subscribe) {
|
|
2030
|
+
// ...
|
|
2031
|
+
}
|
|
2032
|
+
// ...
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
```
|
|
2036
|
+
|
|
2037
|
+
@deprecated use {@link Store.request} instead
|
|
2038
|
+
@public
|
|
2039
|
+
@return a promise that will be resolved when the adapter returns
|
|
2040
|
+
successfully or rejected if the adapter returns with an error.
|
|
2041
|
+
*/
|
|
2042
|
+
save<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): Promise<this>;
|
|
2043
|
+
/**
|
|
2044
|
+
Reload the record from the adapter.
|
|
2045
|
+
|
|
2046
|
+
This will only work if the record has already finished loading.
|
|
2047
|
+
|
|
2048
|
+
Example
|
|
2049
|
+
|
|
2050
|
+
```js
|
|
2051
|
+
import Component from '@glimmer/component';
|
|
2052
|
+
|
|
2053
|
+
export default class extends Component {
|
|
2054
|
+
async reload = () => {
|
|
2055
|
+
await this.args.model.reload();
|
|
2056
|
+
// do something with the reloaded model
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
```
|
|
2060
|
+
|
|
2061
|
+
@public
|
|
2062
|
+
@param {Object} options optional, may include `adapterOptions` hash which will be passed to adapter request
|
|
2063
|
+
|
|
2064
|
+
@return {Promise} a promise that will be resolved with the record when the
|
|
2065
|
+
adapter returns successfully or rejected if the adapter returns
|
|
2066
|
+
with an error.
|
|
2067
|
+
*/
|
|
2068
|
+
reload<T extends MinimalLegacyRecord>(this: T, options?: Record<string, unknown>): Promise<T>;
|
|
2069
|
+
/**
|
|
2070
|
+
Get the reference for the specified belongsTo relationship.
|
|
2071
|
+
|
|
2072
|
+
For instance, given the following model
|
|
2073
|
+
|
|
2074
|
+
```js [app/models/blog-post.js]
|
|
2075
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
2076
|
+
|
|
2077
|
+
export default class BlogPost extends Model {
|
|
2078
|
+
@belongsTo('user', { async: true, inverse: null }) author;
|
|
2079
|
+
}
|
|
2080
|
+
```
|
|
2081
|
+
|
|
2082
|
+
Then the reference for the author relationship would be
|
|
2083
|
+
retrieved from a record instance like so:
|
|
2084
|
+
|
|
2085
|
+
```js
|
|
2086
|
+
blogPost.belongsTo('author');
|
|
2087
|
+
```
|
|
2088
|
+
|
|
2089
|
+
A `BelongsToReference` is a low-level API that allows access
|
|
2090
|
+
and manipulation of a belongsTo relationship.
|
|
2091
|
+
|
|
2092
|
+
It is especially useful when you're dealing with `async` relationships
|
|
2093
|
+
as it allows synchronous access to the relationship data if loaded, as
|
|
2094
|
+
well as APIs for loading, reloading the data or accessing available
|
|
2095
|
+
information without triggering a load.
|
|
2096
|
+
|
|
2097
|
+
It may also be useful when using `sync` relationships that need to be
|
|
2098
|
+
loaded/reloaded with more precise timing than marking the
|
|
2099
|
+
relationship as `async` and relying on autofetch would have allowed.
|
|
2100
|
+
|
|
2101
|
+
However,keep in mind that marking a relationship as `async: false` will introduce
|
|
2102
|
+
bugs into your application if the data is not always guaranteed to be available
|
|
2103
|
+
by the time the relationship is accessed. Ergo, it is recommended when using this
|
|
2104
|
+
approach to utilize `links` for unloaded relationship state instead of identifiers.
|
|
2105
|
+
|
|
2106
|
+
Reference APIs are entangled with the relationship's underlying state,
|
|
2107
|
+
thus any getters or cached properties that utilize these will properly
|
|
2108
|
+
invalidate if the relationship state changes.
|
|
2109
|
+
|
|
2110
|
+
References are "stable", meaning that multiple calls to retrieve the reference
|
|
2111
|
+
for a given relationship will always return the same HasManyReference.
|
|
2112
|
+
|
|
2113
|
+
@public
|
|
2114
|
+
@param prop - the name of the relationship
|
|
2115
|
+
@since 2.5.0
|
|
2116
|
+
@return reference for this relationship
|
|
2117
|
+
*/
|
|
2118
|
+
belongsTo<T extends Model, K extends keyof T & string>(this: T, prop: K & (K extends _MaybeBelongsToFields<T> ? K : never)): BelongsToReference<T, K>;
|
|
2119
|
+
/**
|
|
2120
|
+
Get the reference for the specified hasMany relationship.
|
|
2121
|
+
|
|
2122
|
+
For instance, given the following model
|
|
2123
|
+
|
|
2124
|
+
```js [app/models/blog-post.js]
|
|
2125
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
2126
|
+
|
|
2127
|
+
export default class BlogPost extends Model {
|
|
2128
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
2129
|
+
}
|
|
2130
|
+
```
|
|
2131
|
+
|
|
2132
|
+
Then the reference for the comments relationship would be
|
|
2133
|
+
retrieved from a record instance like so:
|
|
2134
|
+
|
|
2135
|
+
```js
|
|
2136
|
+
blogPost.hasMany('comments');
|
|
2137
|
+
```
|
|
2138
|
+
|
|
2139
|
+
A `HasManyReference` is a low-level API that allows access
|
|
2140
|
+
and manipulation of a hasMany relationship.
|
|
2141
|
+
|
|
2142
|
+
It is especially useful when you are dealing with `async` relationships
|
|
2143
|
+
as it allows synchronous access to the relationship data if loaded, as
|
|
2144
|
+
well as APIs for loading, reloading the data or accessing available
|
|
2145
|
+
information without triggering a load.
|
|
2146
|
+
|
|
2147
|
+
It may also be useful when using `sync` relationships with `@ember-data/model`
|
|
2148
|
+
that need to be loaded/reloaded with more precise timing than marking the
|
|
2149
|
+
relationship as `async` and relying on autofetch would have allowed.
|
|
2150
|
+
|
|
2151
|
+
However,keep in mind that marking a relationship as `async: false` will introduce
|
|
2152
|
+
bugs into your application if the data is not always guaranteed to be available
|
|
2153
|
+
by the time the relationship is accessed. Ergo, it is recommended when using this
|
|
2154
|
+
approach to utilize `links` for unloaded relationship state instead of identifiers.
|
|
2155
|
+
|
|
2156
|
+
Reference APIs are entangled with the relationship's underlying state,
|
|
2157
|
+
thus any getters or cached properties that utilize these will properly
|
|
2158
|
+
invalidate if the relationship state changes.
|
|
2159
|
+
|
|
2160
|
+
References are "stable", meaning that multiple calls to retrieve the reference
|
|
2161
|
+
for a given relationship will always return the same HasManyReference.
|
|
2162
|
+
|
|
2163
|
+
@public
|
|
2164
|
+
@param prop - the name of the relationship
|
|
2165
|
+
@since 2.5.0
|
|
2166
|
+
@return reference for this relationship
|
|
2167
|
+
*/
|
|
2168
|
+
hasMany<T extends MinimalLegacyRecord, K extends MaybeHasManyFields<T>>(this: T, prop: K): HasManyReference<T, K>;
|
|
2169
|
+
/**
|
|
2170
|
+
Marks the record as deleted but does not save it. You must call
|
|
2171
|
+
`save` afterwards if you want to persist it. You might use this
|
|
2172
|
+
method if you want to allow the user to still `rollbackAttributes()`
|
|
2173
|
+
after a delete was made.
|
|
2174
|
+
|
|
2175
|
+
Example
|
|
2176
|
+
|
|
2177
|
+
```js
|
|
2178
|
+
import Component from '@glimmer/component';
|
|
2179
|
+
|
|
2180
|
+
export default class extends Component {
|
|
2181
|
+
softDelete = () => {
|
|
2182
|
+
this.args.model.deleteRecord();
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
confirm = () => {
|
|
2186
|
+
this.args.model.save();
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
undo = () => {
|
|
2190
|
+
this.args.model.rollbackAttributes();
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
```
|
|
2194
|
+
|
|
2195
|
+
@public
|
|
2196
|
+
*/
|
|
2197
|
+
deleteRecord<T extends MinimalLegacyRecord>(this: T): void;
|
|
2198
|
+
}
|
|
2199
|
+
/**
|
|
2200
|
+
* Base class from which Models can be defined.
|
|
2201
|
+
*
|
|
2202
|
+
* ::: code-group
|
|
2203
|
+
*
|
|
2204
|
+
* ```js [app/models/user.js]
|
|
2205
|
+
* import { Model, attr, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2206
|
+
*
|
|
2207
|
+
* export default class User extends Model {
|
|
2208
|
+
* @attr name;
|
|
2209
|
+
* @attr('number') age;
|
|
2210
|
+
* @hasMany('post', { async: true, inverse: null }) posts;
|
|
2211
|
+
* @belongsTo('group', { async: false, inverse: 'users' }) group;
|
|
2212
|
+
* }
|
|
2213
|
+
* ```
|
|
2214
|
+
*
|
|
2215
|
+
* ```ts [app/models/user.ts]
|
|
2216
|
+
* import { Model, attr, belongsTo, hasMany, type AsyncHasMany } from '@warp-drive/legacy/model';
|
|
2217
|
+
* import type { NumberTransform } from '@ember-data/serializer/transform';
|
|
2218
|
+
* import type Group from './group';
|
|
2219
|
+
* import type Post from './post';
|
|
2220
|
+
*
|
|
2221
|
+
* export default class User extends Model {
|
|
2222
|
+
* @attr declare name: string;
|
|
2223
|
+
*
|
|
2224
|
+
* @attr<NumberTransform>('number')
|
|
2225
|
+
* declare age: number;
|
|
2226
|
+
*
|
|
2227
|
+
* @hasMany('post', { async: true, inverse: null })
|
|
2228
|
+
* declare posts: AsyncHasMany<Post>;
|
|
2229
|
+
*
|
|
2230
|
+
* @belongsTo('group', { async: false, inverse: 'users' })
|
|
2231
|
+
* declare group: Group | null;
|
|
2232
|
+
* }
|
|
2233
|
+
* ```
|
|
2234
|
+
*
|
|
2235
|
+
* :::
|
|
2236
|
+
*
|
|
2237
|
+
* Models both define the schema for a resource type and provide
|
|
2238
|
+
* the class to use as the reactive object for data of resource
|
|
2239
|
+
* of that type.
|
|
2240
|
+
*
|
|
2241
|
+
* @public
|
|
2242
|
+
* @noInheritDoc
|
|
2243
|
+
* @hideconstructor
|
|
2244
|
+
* @legacy
|
|
2245
|
+
*/
|
|
2246
|
+
declare class Model extends EmberObject implements MinimalLegacyRecord {
|
|
2247
|
+
/** @internal */
|
|
2248
|
+
init(options: ModelCreateArgs): void;
|
|
2249
|
+
/** @private */
|
|
2250
|
+
destroy(): this;
|
|
2251
|
+
/**
|
|
2252
|
+
If this property is `true` the record is in the `empty`
|
|
2253
|
+
state. Empty is the first state all records enter after they have
|
|
2254
|
+
been created. Most records created by the store will quickly
|
|
2255
|
+
transition to the `loading` state if data needs to be fetched from
|
|
2256
|
+
the server or the `created` state if the record is created on the
|
|
2257
|
+
client. A record can also enter the empty state if the adapter is
|
|
2258
|
+
unable to locate the record.
|
|
2259
|
+
|
|
2260
|
+
@public
|
|
2261
|
+
*/
|
|
2262
|
+
get isEmpty(): boolean;
|
|
2263
|
+
/**
|
|
2264
|
+
If this property is `true` the record is in the `loading` state. A
|
|
2265
|
+
record enters this state when the store asks the adapter for its
|
|
2266
|
+
data. It remains in this state until the adapter provides the
|
|
2267
|
+
requested data.
|
|
2268
|
+
|
|
2269
|
+
@public
|
|
2270
|
+
*/
|
|
2271
|
+
get isLoading(): boolean;
|
|
2272
|
+
/**
|
|
2273
|
+
If this property is `true` the record is in the `loaded` state. A
|
|
2274
|
+
record enters this state when its data is populated. Most of a
|
|
2275
|
+
record's lifecycle is spent inside substates of the `loaded`
|
|
2276
|
+
state.
|
|
2277
|
+
|
|
2278
|
+
Example
|
|
2279
|
+
|
|
2280
|
+
```javascript
|
|
2281
|
+
let record = store.createRecord('model');
|
|
2282
|
+
record.isLoaded; // true
|
|
2283
|
+
|
|
2284
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
2285
|
+
model.isLoaded;
|
|
2286
|
+
```
|
|
2287
|
+
|
|
2288
|
+
@public
|
|
2289
|
+
*/
|
|
2290
|
+
get isLoaded(): boolean;
|
|
2291
|
+
/**
|
|
2292
|
+
If this property is `true` the record is in the `dirty` state. The
|
|
2293
|
+
record has local changes that have not yet been saved by the
|
|
2294
|
+
adapter. This includes records that have been created (but not yet
|
|
2295
|
+
saved) or deleted.
|
|
2296
|
+
|
|
2297
|
+
Example
|
|
2298
|
+
|
|
2299
|
+
```javascript
|
|
2300
|
+
let record = store.createRecord('model');
|
|
2301
|
+
record.hasDirtyAttributes; // true
|
|
2302
|
+
|
|
2303
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
2304
|
+
|
|
2305
|
+
model.hasDirtyAttributes; // false
|
|
2306
|
+
model.foo = 'some value';
|
|
2307
|
+
model.hasDirtyAttributes; // true
|
|
2308
|
+
```
|
|
2309
|
+
|
|
2310
|
+
@since 1.13.0
|
|
2311
|
+
@public
|
|
2312
|
+
*/
|
|
2313
|
+
get hasDirtyAttributes(): boolean;
|
|
2314
|
+
/**
|
|
2315
|
+
If this property is `true` the record is in the `saving` state. A
|
|
2316
|
+
record enters the saving state when `save` is called, but the
|
|
2317
|
+
adapter has not yet acknowledged that the changes have been
|
|
2318
|
+
persisted to the backend.
|
|
2319
|
+
|
|
2320
|
+
Example
|
|
2321
|
+
|
|
2322
|
+
```javascript
|
|
2323
|
+
let record = store.createRecord('model');
|
|
2324
|
+
record.isSaving; // false
|
|
2325
|
+
let promise = record.save();
|
|
2326
|
+
record.isSaving; // true
|
|
2327
|
+
promise.then(function() {
|
|
2328
|
+
record.isSaving; // false
|
|
2329
|
+
});
|
|
2330
|
+
```
|
|
2331
|
+
|
|
2332
|
+
@public
|
|
2333
|
+
*/
|
|
2334
|
+
get isSaving(): boolean;
|
|
2335
|
+
/**
|
|
2336
|
+
If this property is `true` the record is in the `deleted` state
|
|
2337
|
+
and has been marked for deletion. When `isDeleted` is true and
|
|
2338
|
+
`hasDirtyAttributes` is true, the record is deleted locally but the deletion
|
|
2339
|
+
was not yet persisted. When `isSaving` is true, the change is
|
|
2340
|
+
in-flight. When both `hasDirtyAttributes` and `isSaving` are false, the
|
|
2341
|
+
change has persisted.
|
|
2342
|
+
|
|
2343
|
+
Example
|
|
2344
|
+
|
|
2345
|
+
```javascript
|
|
2346
|
+
let record = store.createRecord('model');
|
|
2347
|
+
record.isDeleted; // false
|
|
2348
|
+
record.deleteRecord();
|
|
2349
|
+
|
|
2350
|
+
// Locally deleted
|
|
2351
|
+
record.isDeleted; // true
|
|
2352
|
+
record.hasDirtyAttributes; // true
|
|
2353
|
+
record.isSaving; // false
|
|
2354
|
+
|
|
2355
|
+
// Persisting the deletion
|
|
2356
|
+
let promise = record.save();
|
|
2357
|
+
record.isDeleted; // true
|
|
2358
|
+
record.isSaving; // true
|
|
2359
|
+
|
|
2360
|
+
// Deletion Persisted
|
|
2361
|
+
promise.then(function() {
|
|
2362
|
+
record.isDeleted; // true
|
|
2363
|
+
record.isSaving; // false
|
|
2364
|
+
record.hasDirtyAttributes; // false
|
|
2365
|
+
});
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
@public
|
|
2369
|
+
*/
|
|
2370
|
+
get isDeleted(): boolean;
|
|
2371
|
+
/**
|
|
2372
|
+
If this property is `true` the record is in the `new` state. A
|
|
2373
|
+
record will be in the `new` state when it has been created on the
|
|
2374
|
+
client and the adapter has not yet report that it was successfully
|
|
2375
|
+
saved.
|
|
2376
|
+
|
|
2377
|
+
Example
|
|
2378
|
+
|
|
2379
|
+
```javascript
|
|
2380
|
+
let record = store.createRecord('model');
|
|
2381
|
+
record.isNew; // true
|
|
2382
|
+
|
|
2383
|
+
record.save().then(function(model) {
|
|
2384
|
+
model.isNew; // false
|
|
2385
|
+
});
|
|
2386
|
+
```
|
|
2387
|
+
|
|
2388
|
+
@public
|
|
2389
|
+
*/
|
|
2390
|
+
get isNew(): boolean;
|
|
2391
|
+
/**
|
|
2392
|
+
If this property is `true` the record is in the `valid` state.
|
|
2393
|
+
|
|
2394
|
+
A record will be in the `valid` state when the adapter did not report any
|
|
2395
|
+
server-side validation failures.
|
|
2396
|
+
|
|
2397
|
+
@public
|
|
2398
|
+
*/
|
|
2399
|
+
get isValid(): boolean;
|
|
2400
|
+
/**
|
|
2401
|
+
If the record is in the dirty state this property will report what
|
|
2402
|
+
kind of change has caused it to move into the dirty
|
|
2403
|
+
state. Possible values are:
|
|
2404
|
+
|
|
2405
|
+
- `created` The record has been created by the client and not yet saved to the adapter.
|
|
2406
|
+
- `updated` The record has been updated by the client and not yet saved to the adapter.
|
|
2407
|
+
- `deleted` The record has been deleted by the client and not yet saved to the adapter.
|
|
2408
|
+
|
|
2409
|
+
Example
|
|
2410
|
+
|
|
2411
|
+
```javascript
|
|
2412
|
+
let record = store.createRecord('model');
|
|
2413
|
+
record.dirtyType; // 'created'
|
|
2414
|
+
```
|
|
2415
|
+
|
|
2416
|
+
@public
|
|
2417
|
+
*/
|
|
2418
|
+
get dirtyType(): "created" | "updated" | "deleted" | "";
|
|
2419
|
+
/**
|
|
2420
|
+
If `true` the adapter reported that it was unable to save local
|
|
2421
|
+
changes to the backend for any reason other than a server-side
|
|
2422
|
+
validation error.
|
|
2423
|
+
|
|
2424
|
+
Example
|
|
2425
|
+
|
|
2426
|
+
```javascript
|
|
2427
|
+
record.isError; // false
|
|
2428
|
+
record.set('foo', 'valid value');
|
|
2429
|
+
record.save().then(null, function() {
|
|
2430
|
+
record.isError; // true
|
|
2431
|
+
});
|
|
2432
|
+
```
|
|
2433
|
+
|
|
2434
|
+
@public
|
|
2435
|
+
*/
|
|
2436
|
+
get isError(): boolean;
|
|
2437
|
+
/**
|
|
2438
|
+
* `isError` is read-only and cannot be set directly.
|
|
2439
|
+
*/
|
|
2440
|
+
set isError(v: boolean);
|
|
2441
|
+
/**
|
|
2442
|
+
If `true` the store is attempting to reload the record from the adapter.
|
|
2443
|
+
|
|
2444
|
+
Example
|
|
2445
|
+
|
|
2446
|
+
```javascript
|
|
2447
|
+
record.isReloading; // false
|
|
2448
|
+
record.reload();
|
|
2449
|
+
record.isReloading; // true
|
|
2450
|
+
```
|
|
2451
|
+
|
|
2452
|
+
@public
|
|
2453
|
+
*/
|
|
2454
|
+
isReloading: boolean;
|
|
2455
|
+
/**
|
|
2456
|
+
All ember models have an id property. This is an identifier
|
|
2457
|
+
managed by an external source. These are always coerced to be
|
|
2458
|
+
strings before being used internally. Note when declaring the
|
|
2459
|
+
attributes for a model it is an error to declare an id
|
|
2460
|
+
attribute.
|
|
2461
|
+
|
|
2462
|
+
```javascript
|
|
2463
|
+
let record = store.createRecord('model');
|
|
2464
|
+
record.id; // null
|
|
2465
|
+
|
|
2466
|
+
const { content: { data: model } } = await store.request(findRecord({ type: 'model', id: '1' }));
|
|
2467
|
+
model.id; // '1'
|
|
2468
|
+
```
|
|
2469
|
+
|
|
2470
|
+
@public
|
|
2471
|
+
*/
|
|
2472
|
+
get id(): string | null;
|
|
2473
|
+
/**
|
|
2474
|
+
* Assigns the resource's primary key. Typically only used internally
|
|
2475
|
+
* when a client-created record is assigned an id upon being saved.
|
|
2476
|
+
*/
|
|
2477
|
+
set id(id: string | null);
|
|
2478
|
+
toString(): string;
|
|
2479
|
+
/**
|
|
2480
|
+
@private
|
|
2481
|
+
*/
|
|
2482
|
+
get currentState(): RecordState;
|
|
2483
|
+
/**
|
|
2484
|
+
* `currentState` is read-only and cannot be set directly.
|
|
2485
|
+
*/
|
|
2486
|
+
set currentState(_v: RecordState);
|
|
2487
|
+
/**
|
|
2488
|
+
The store service instance which created this record instance
|
|
2489
|
+
|
|
2490
|
+
@public
|
|
2491
|
+
*/
|
|
2492
|
+
store: Store;
|
|
2493
|
+
/**
|
|
2494
|
+
When the record is in the `invalid` state this object will contain
|
|
2495
|
+
any errors returned by the adapter. When present the errors hash
|
|
2496
|
+
contains keys corresponding to the invalid property names
|
|
2497
|
+
and values which are arrays of Javascript objects with two keys:
|
|
2498
|
+
|
|
2499
|
+
- `message` A string containing the error message from the backend
|
|
2500
|
+
- `attribute` The name of the property associated with this error message
|
|
2501
|
+
|
|
2502
|
+
```javascript
|
|
2503
|
+
record.errors.length; // 0
|
|
2504
|
+
record.set('foo', 'invalid value');
|
|
2505
|
+
record.save().catch(function() {
|
|
2506
|
+
record.errors.foo;
|
|
2507
|
+
// [{message: 'foo should be a number.', attribute: 'foo'}]
|
|
2508
|
+
});
|
|
2509
|
+
```
|
|
2510
|
+
|
|
2511
|
+
The `errors` property is useful for displaying error messages to
|
|
2512
|
+
the user.
|
|
2513
|
+
|
|
2514
|
+
```handlebars
|
|
2515
|
+
<label>Username: <Input @value={{@model.username}} /> </label>
|
|
2516
|
+
{{#each @model.errors.username as |error|}}
|
|
2517
|
+
<div class="error">
|
|
2518
|
+
{{error.message}}
|
|
2519
|
+
</div>
|
|
2520
|
+
{{/each}}
|
|
2521
|
+
<label>Email: <Input @value={{@model.email}} /> </label>
|
|
2522
|
+
{{#each @model.errors.email as |error|}}
|
|
2523
|
+
<div class="error">
|
|
2524
|
+
{{error.message}}
|
|
2525
|
+
</div>
|
|
2526
|
+
{{/each}}
|
|
2527
|
+
```
|
|
2528
|
+
|
|
2529
|
+
|
|
2530
|
+
You can also access the special `messages` property on the error
|
|
2531
|
+
object to get an array of all the error strings.
|
|
2532
|
+
|
|
2533
|
+
```handlebars
|
|
2534
|
+
{{#each @model.errors.messages as |message|}}
|
|
2535
|
+
<div class="error">
|
|
2536
|
+
{{message}}
|
|
2537
|
+
</div>
|
|
2538
|
+
{{/each}}
|
|
2539
|
+
```
|
|
2540
|
+
|
|
2541
|
+
@public
|
|
2542
|
+
*/
|
|
2543
|
+
get errors(): Errors;
|
|
2544
|
+
/**
|
|
2545
|
+
This property holds the `AdapterError` object with which
|
|
2546
|
+
last adapter operation was rejected.
|
|
2547
|
+
|
|
2548
|
+
@public
|
|
2549
|
+
*/
|
|
2550
|
+
get adapterError(): unknown;
|
|
2551
|
+
/**
|
|
2552
|
+
* `adapterError` is read-only and cannot be set directly.
|
|
2553
|
+
*/
|
|
2554
|
+
set adapterError(v: unknown);
|
|
2555
|
+
notifyPropertyChange(prop: string): this;
|
|
2556
|
+
/** @internal */
|
|
2557
|
+
attr(): void;
|
|
2558
|
+
/**
|
|
2559
|
+
Given a callback, iterates over each of the relationships in the model,
|
|
2560
|
+
invoking the callback with the name of each relationship and its relationship
|
|
2561
|
+
descriptor.
|
|
2562
|
+
|
|
2563
|
+
|
|
2564
|
+
The callback method you provide should have the following signature (all
|
|
2565
|
+
parameters are optional):
|
|
2566
|
+
|
|
2567
|
+
```javascript
|
|
2568
|
+
function(name, descriptor);
|
|
2569
|
+
```
|
|
2570
|
+
|
|
2571
|
+
- `name` the name of the current property in the iteration
|
|
2572
|
+
- `descriptor` the meta object that describes this relationship
|
|
2573
|
+
|
|
2574
|
+
The relationship descriptor argument is an object with the following properties.
|
|
2575
|
+
|
|
2576
|
+
- **name** <span class="type">String</span> the name of this relationship on the Model
|
|
2577
|
+
- **kind** <span class="type">String</span> "hasMany" or "belongsTo"
|
|
2578
|
+
- **options** <span class="type">Object</span> the original options hash passed when the relationship was declared
|
|
2579
|
+
- **parentType** <span class="type">Model</span> the type of the Model that owns this relationship
|
|
2580
|
+
- **type** <span class="type">String</span> the type name of the related Model
|
|
2581
|
+
|
|
2582
|
+
Note that in addition to a callback, you can also pass an optional target
|
|
2583
|
+
object that will be set as `this` on the context.
|
|
2584
|
+
|
|
2585
|
+
Example
|
|
2586
|
+
|
|
2587
|
+
```js [app/serializers/application.js]
|
|
2588
|
+
import JSONSerializer from '@ember-data/serializer/json';
|
|
2589
|
+
|
|
2590
|
+
export default class ApplicationSerializer extends JSONSerializer {
|
|
2591
|
+
serialize(record, options) {
|
|
2592
|
+
let json = {};
|
|
2593
|
+
|
|
2594
|
+
record.eachRelationship(function(name, descriptor) {
|
|
2595
|
+
if (descriptor.kind === 'hasMany') {
|
|
2596
|
+
let serializedHasManyName = name.toUpperCase() + '_IDS';
|
|
2597
|
+
json[serializedHasManyName] = record.get(name).map(r => r.id);
|
|
2598
|
+
}
|
|
2599
|
+
});
|
|
2600
|
+
|
|
2601
|
+
return json;
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
```
|
|
2605
|
+
|
|
2606
|
+
@public
|
|
2607
|
+
@param callback the callback to invoke
|
|
2608
|
+
@param binding the value to which the callback's `this` should be bound
|
|
2609
|
+
*/
|
|
2610
|
+
eachRelationship<T>(callback: (this: NoInfer<T> | undefined, key: MaybeRelationshipFields<this>, meta: LegacyRelationshipField) => void, binding?: T): void;
|
|
2611
|
+
/**
|
|
2612
|
+
* Returns the relationship schema for the given relationship name, if any.
|
|
2613
|
+
*/
|
|
2614
|
+
relationshipFor(name: string): LegacyRelationshipField | undefined;
|
|
2615
|
+
/**
|
|
2616
|
+
* Returns the inverse relationship schema for the given relationship
|
|
2617
|
+
* name, if one exists. See {@link Model.inverseFor | the static inverseFor}.
|
|
2618
|
+
*/
|
|
2619
|
+
inverseFor(name: string): LegacyRelationshipField | null;
|
|
2620
|
+
/**
|
|
2621
|
+
* Iterates over the attributes defined on this record's class, calling
|
|
2622
|
+
* `callback` for each one. See {@link Model.eachAttribute | the static eachAttribute}.
|
|
2623
|
+
*
|
|
2624
|
+
* @param callback the callback to invoke
|
|
2625
|
+
* @param binding the value to which the callback's `this` should be bound
|
|
2626
|
+
*/
|
|
2627
|
+
eachAttribute<T>(callback: (this: NoInfer<T> | undefined, key: isSubClass<this> extends true ? MaybeAttrFields<this> : string, meta: LegacyAttributeField) => void, binding?: T): void;
|
|
2628
|
+
/**
|
|
2629
|
+
* @internal
|
|
2630
|
+
*/
|
|
2631
|
+
static isModel: boolean;
|
|
2632
|
+
/**
|
|
2633
|
+
Represents the model's class name as a string. This can be used to look up the model's class name through
|
|
2634
|
+
`Store`'s modelFor method.
|
|
2635
|
+
|
|
2636
|
+
`modelName` is generated for you by WarpDrive. It will be a lowercased, dasherized string.
|
|
2637
|
+
For example:
|
|
2638
|
+
|
|
2639
|
+
```javascript
|
|
2640
|
+
store.modelFor('post').modelName; // 'post'
|
|
2641
|
+
store.modelFor('blog-post').modelName; // 'blog-post'
|
|
2642
|
+
```
|
|
2643
|
+
|
|
2644
|
+
The most common place you'll want to access `modelName` is in your serializer's `payloadKeyFromModelName` method. For example, to change payload
|
|
2645
|
+
keys to underscore (instead of dasherized), you might use the following code:
|
|
2646
|
+
|
|
2647
|
+
```javascript
|
|
2648
|
+
import RESTSerializer from '@ember-data/serializer/rest';
|
|
2649
|
+
import { underscore } from '<app-name>/utils/string-utils';
|
|
2650
|
+
|
|
2651
|
+
export default const PostSerializer = RESTSerializer.extend({
|
|
2652
|
+
payloadKeyFromModelName(modelName) {
|
|
2653
|
+
return underscore(modelName);
|
|
2654
|
+
}
|
|
2655
|
+
});
|
|
2656
|
+
```
|
|
2657
|
+
|
|
2658
|
+
@public
|
|
2659
|
+
*/
|
|
2660
|
+
static modelName: string;
|
|
2661
|
+
/**
|
|
2662
|
+
For a given relationship name, returns the model type of the relationship.
|
|
2663
|
+
|
|
2664
|
+
For example, if you define a model like this:
|
|
2665
|
+
|
|
2666
|
+
```js [app/models/post.js]
|
|
2667
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
2668
|
+
|
|
2669
|
+
export default class PostModel extends Model {
|
|
2670
|
+
@hasMany('comment') comments;
|
|
2671
|
+
}
|
|
2672
|
+
```
|
|
2673
|
+
|
|
2674
|
+
Calling `store.modelFor('post').typeForRelationship('comments', store)` will return `Comment`.
|
|
2675
|
+
|
|
2676
|
+
@public
|
|
2677
|
+
@param name the name of the relationship
|
|
2678
|
+
@param store an instance of Store
|
|
2679
|
+
@return the type of the relationship, or undefined
|
|
2680
|
+
*/
|
|
2681
|
+
static typeForRelationship(name: string, store: Store): ModelSchema | undefined;
|
|
2682
|
+
/**
|
|
2683
|
+
* A cache of resolved inverse relationships by name, populated lazily by
|
|
2684
|
+
* {@link Model.inverseFor | inverseFor}.
|
|
2685
|
+
*/
|
|
2686
|
+
static get inverseMap(): Record<string, LegacyRelationshipField | null>;
|
|
2687
|
+
/**
|
|
2688
|
+
Find the relationship which is the inverse of the one asked for.
|
|
2689
|
+
|
|
2690
|
+
For example, if you define models like this:
|
|
2691
|
+
|
|
2692
|
+
```js [app/models/post.js]
|
|
2693
|
+
import { Model, hasMany } from '@warp-drive/legacy/model';
|
|
2694
|
+
|
|
2695
|
+
export default class PostModel extends Model {
|
|
2696
|
+
@hasMany('message') comments;
|
|
2697
|
+
}
|
|
2698
|
+
```
|
|
2699
|
+
|
|
2700
|
+
```js [app/models/message.js]
|
|
2701
|
+
import { Model, belongsTo } from '@warp-drive/legacy/model';
|
|
2702
|
+
|
|
2703
|
+
export default class MessageModel extends Model {
|
|
2704
|
+
@belongsTo('post') owner;
|
|
2705
|
+
}
|
|
2706
|
+
```
|
|
2707
|
+
|
|
2708
|
+
``` js
|
|
2709
|
+
store.modelFor('post').inverseFor('comments', store) // { type: 'message', name: 'owner', kind: 'belongsTo' }
|
|
2710
|
+
store.modelFor('message').inverseFor('owner', store) // { type: 'post', name: 'comments', kind: 'hasMany' }
|
|
2711
|
+
```
|
|
2712
|
+
|
|
2713
|
+
@public
|
|
2714
|
+
@param name the name of the relationship
|
|
2715
|
+
@param store
|
|
2716
|
+
@return the inverse relationship, or null
|
|
2717
|
+
*/
|
|
2718
|
+
static inverseFor(name: string, store: Store): LegacyRelationshipField | null;
|
|
2719
|
+
/**
|
|
2720
|
+
* @private
|
|
2721
|
+
*/
|
|
2722
|
+
static _findInverseFor(name: string, store: Store): LegacyRelationshipField | null;
|
|
2723
|
+
/**
|
|
2724
|
+
The model's relationships as a map, keyed on the type of the
|
|
2725
|
+
relationship. The value of each entry is an array containing a descriptor
|
|
2726
|
+
for each relationship with that type, describing the name of the relationship
|
|
2727
|
+
as well as the type.
|
|
2728
|
+
|
|
2729
|
+
For example, given the following model definition:
|
|
2730
|
+
|
|
2731
|
+
```js [app/models/blog.js]
|
|
2732
|
+
import { Model, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2733
|
+
|
|
2734
|
+
export default class BlogModel extends Model {
|
|
2735
|
+
@hasMany('user') users;
|
|
2736
|
+
@belongsTo('user') owner;
|
|
2737
|
+
@hasMany('post') posts;
|
|
2738
|
+
}
|
|
2739
|
+
```
|
|
2740
|
+
|
|
2741
|
+
This computed property would return a map describing these
|
|
2742
|
+
relationships, like this:
|
|
2743
|
+
|
|
2744
|
+
```javascript
|
|
2745
|
+
import Blog from 'app/models/blog';
|
|
2746
|
+
import User from 'app/models/user';
|
|
2747
|
+
import Post from 'app/models/post';
|
|
2748
|
+
|
|
2749
|
+
let relationships = Blog.relationships;
|
|
2750
|
+
relationships.user;
|
|
2751
|
+
//=> [ { name: 'users', kind: 'hasMany' },
|
|
2752
|
+
// { name: 'owner', kind: 'belongsTo' } ]
|
|
2753
|
+
relationships.post;
|
|
2754
|
+
//=> [ { name: 'posts', kind: 'hasMany' } ]
|
|
2755
|
+
```
|
|
2756
|
+
|
|
2757
|
+
@public
|
|
2758
|
+
*/
|
|
2759
|
+
static get relationships(): Map<string, LegacyRelationshipField[]>;
|
|
2760
|
+
/**
|
|
2761
|
+
A hash containing lists of the model's relationships, grouped
|
|
2762
|
+
by the relationship kind. For example, given a model with this
|
|
2763
|
+
definition:
|
|
2764
|
+
|
|
2765
|
+
```js [app/models/blog.js]
|
|
2766
|
+
import { Model, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2767
|
+
|
|
2768
|
+
export default class BlogModel extends Model {
|
|
2769
|
+
@hasMany('user') users;
|
|
2770
|
+
@belongsTo('user') owner;
|
|
2771
|
+
|
|
2772
|
+
@hasMany('post') posts;
|
|
2773
|
+
}
|
|
2774
|
+
```
|
|
2775
|
+
|
|
2776
|
+
This property would contain the following:
|
|
2777
|
+
|
|
2778
|
+
```javascript
|
|
2779
|
+
import Blog from 'app/models/blog';
|
|
2780
|
+
|
|
2781
|
+
let relationshipNames = Blog.relationshipNames;
|
|
2782
|
+
relationshipNames.hasMany;
|
|
2783
|
+
//=> ['users', 'posts']
|
|
2784
|
+
relationshipNames.belongsTo;
|
|
2785
|
+
//=> ['owner']
|
|
2786
|
+
```
|
|
2787
|
+
|
|
2788
|
+
@public
|
|
2789
|
+
*/
|
|
2790
|
+
static get relationshipNames(): {
|
|
2791
|
+
/**
|
|
2792
|
+
* the names of the model's `hasMany` relationships
|
|
2793
|
+
*/
|
|
2794
|
+
hasMany: string[];
|
|
2795
|
+
/**
|
|
2796
|
+
* the names of the model's `belongsTo` relationships
|
|
2797
|
+
*/
|
|
2798
|
+
belongsTo: string[];
|
|
2799
|
+
};
|
|
2800
|
+
/**
|
|
2801
|
+
An array of types directly related to a model. Each type will be
|
|
2802
|
+
included once, regardless of the number of relationships it has with
|
|
2803
|
+
the model.
|
|
2804
|
+
|
|
2805
|
+
For example, given a model with this definition:
|
|
2806
|
+
|
|
2807
|
+
```js [app/models/blog.js]
|
|
2808
|
+
import { Model, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2809
|
+
|
|
2810
|
+
export default class BlogModel extends Model {
|
|
2811
|
+
@hasMany('user') users;
|
|
2812
|
+
@belongsTo('user') owner;
|
|
2813
|
+
|
|
2814
|
+
@hasMany('post') posts;
|
|
2815
|
+
}
|
|
2816
|
+
```
|
|
2817
|
+
|
|
2818
|
+
This property would contain the following:
|
|
2819
|
+
|
|
2820
|
+
```javascript
|
|
2821
|
+
import Blog from 'app/models/blog';
|
|
2822
|
+
|
|
2823
|
+
let relatedTypes = Blog.relatedTypes');
|
|
2824
|
+
//=> ['user', 'post']
|
|
2825
|
+
```
|
|
2826
|
+
|
|
2827
|
+
@public
|
|
2828
|
+
*/
|
|
2829
|
+
static get relatedTypes(): string[];
|
|
2830
|
+
/**
|
|
2831
|
+
A map whose keys are the relationships of a model and whose values are
|
|
2832
|
+
relationship descriptors.
|
|
2833
|
+
|
|
2834
|
+
For example, given a model with this
|
|
2835
|
+
definition:
|
|
2836
|
+
|
|
2837
|
+
```js [app/models/blog.js]
|
|
2838
|
+
import { Model, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2839
|
+
|
|
2840
|
+
export default class BlogModel extends Model {
|
|
2841
|
+
@hasMany('user') users;
|
|
2842
|
+
@belongsTo('user') owner;
|
|
2843
|
+
|
|
2844
|
+
@hasMany('post') posts;
|
|
2845
|
+
}
|
|
2846
|
+
```
|
|
2847
|
+
|
|
2848
|
+
This property would contain the following:
|
|
2849
|
+
|
|
2850
|
+
```javascript
|
|
2851
|
+
import Blog from 'app/models/blog';
|
|
2852
|
+
|
|
2853
|
+
let relationshipsByName = Blog.relationshipsByName;
|
|
2854
|
+
relationshipsByName.users;
|
|
2855
|
+
//=> { name: 'users', kind: 'hasMany', type: 'user', options: Object }
|
|
2856
|
+
relationshipsByName.owner;
|
|
2857
|
+
//=> { name: 'owner', kind: 'belongsTo', type: 'user', options: Object }
|
|
2858
|
+
```
|
|
2859
|
+
|
|
2860
|
+
@public
|
|
2861
|
+
*/
|
|
2862
|
+
static get relationshipsByName(): Map<string, LegacyRelationshipField>;
|
|
2863
|
+
/**
|
|
2864
|
+
* A hash of the model's relationship schemas keyed by relationship name.
|
|
2865
|
+
* See also {@link Model.relationshipsByName | relationshipsByName}, which
|
|
2866
|
+
* provides the same information as a `Map`.
|
|
2867
|
+
*/
|
|
2868
|
+
static get relationshipsObject(): Record<string, LegacyRelationshipField>;
|
|
2869
|
+
/**
|
|
2870
|
+
A map whose keys are the fields of the model and whose values are strings
|
|
2871
|
+
describing the kind of the field. A model's fields are the union of all of its
|
|
2872
|
+
attributes and relationships.
|
|
2873
|
+
|
|
2874
|
+
For example:
|
|
2875
|
+
|
|
2876
|
+
```js [app/models/blog.js]
|
|
2877
|
+
import { Model, attr, belongsTo, hasMany } from '@warp-drive/legacy/model';
|
|
2878
|
+
|
|
2879
|
+
export default class BlogModel extends Model {
|
|
2880
|
+
@hasMany('user') users;
|
|
2881
|
+
@belongsTo('user') owner;
|
|
2882
|
+
|
|
2883
|
+
@hasMany('post') posts;
|
|
2884
|
+
|
|
2885
|
+
@attr('string') title;
|
|
2886
|
+
}
|
|
2887
|
+
```
|
|
2888
|
+
|
|
2889
|
+
```js
|
|
2890
|
+
import Blog from 'app/models/blog'
|
|
2891
|
+
|
|
2892
|
+
let fields = Blog.fields;
|
|
2893
|
+
fields.forEach(function(kind, field) {
|
|
2894
|
+
// do thing
|
|
2895
|
+
});
|
|
2896
|
+
|
|
2897
|
+
// prints:
|
|
2898
|
+
// users, hasMany
|
|
2899
|
+
// owner, belongsTo
|
|
2900
|
+
// posts, hasMany
|
|
2901
|
+
// title, attribute
|
|
2902
|
+
```
|
|
2903
|
+
|
|
2904
|
+
@public
|
|
2905
|
+
*/
|
|
2906
|
+
static get fields(): Map<string, "attribute" | "belongsTo" | "hasMany">;
|
|
2907
|
+
/**
|
|
2908
|
+
Given a callback, iterates over each of the relationships in the model,
|
|
2909
|
+
invoking the callback with the name of each relationship and its relationship
|
|
2910
|
+
descriptor.
|
|
2911
|
+
|
|
2912
|
+
@public
|
|
2913
|
+
@param callback the callback to invoke
|
|
2914
|
+
@param binding the value to which the callback's `this` should be bound
|
|
2915
|
+
*/
|
|
2916
|
+
static eachRelationship<T, Schema extends Model>(callback: (this: T | undefined, key: MaybeRelationshipFields<Schema>, relationship: LegacyRelationshipField) => void, binding?: T): void;
|
|
2917
|
+
/**
|
|
2918
|
+
Given a callback, iterates over each of the types related to a model,
|
|
2919
|
+
invoking the callback with the related type's class. Each type will be
|
|
2920
|
+
returned just once, regardless of how many different relationships it has
|
|
2921
|
+
with a model.
|
|
2922
|
+
|
|
2923
|
+
@public
|
|
2924
|
+
@param callback the callback to invoke
|
|
2925
|
+
@param binding the value to which the callback's `this` should be bound
|
|
2926
|
+
*/
|
|
2927
|
+
static eachRelatedType<T>(callback: (this: T | undefined, type: string) => void, binding?: T): void;
|
|
2928
|
+
/**
|
|
2929
|
+
*
|
|
2930
|
+
* @private
|
|
2931
|
+
* @deprecated
|
|
2932
|
+
*/
|
|
2933
|
+
static determineRelationshipType(knownSide: LegacyRelationshipField, store: Store): "oneToOne" | "oneToMany" | "manyToOne" | "manyToMany" | "oneToNone" | "manyToNone";
|
|
2934
|
+
/**
|
|
2935
|
+
A map whose keys are the attributes of the model (properties
|
|
2936
|
+
described by attr) and whose values are the meta object for the
|
|
2937
|
+
property.
|
|
2938
|
+
|
|
2939
|
+
Example
|
|
2940
|
+
|
|
2941
|
+
```js [app/models/person.js]
|
|
2942
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
2943
|
+
|
|
2944
|
+
export default class PersonModel extends Model {
|
|
2945
|
+
@attr('string') firstName;
|
|
2946
|
+
@attr('string') lastName;
|
|
2947
|
+
@attr('date') birthday;
|
|
2948
|
+
}
|
|
2949
|
+
```
|
|
2950
|
+
|
|
2951
|
+
```javascript
|
|
2952
|
+
import Person from 'app/models/person'
|
|
2953
|
+
|
|
2954
|
+
let attributes = Person.attributes
|
|
2955
|
+
|
|
2956
|
+
attributes.forEach(function(meta, name) {
|
|
2957
|
+
// do thing
|
|
2958
|
+
});
|
|
2959
|
+
|
|
2960
|
+
// prints:
|
|
2961
|
+
// firstName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "firstName"}
|
|
2962
|
+
// lastName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "lastName"}
|
|
2963
|
+
// birthday {type: "date", kind: 'attribute', options: Object, parentType: function, name: "birthday"}
|
|
2964
|
+
```
|
|
2965
|
+
|
|
2966
|
+
@public
|
|
2967
|
+
*/
|
|
2968
|
+
static get attributes(): Map<string, LegacyAttributeField>;
|
|
2969
|
+
/**
|
|
2970
|
+
A map whose keys are the attributes of the model (properties
|
|
2971
|
+
described by attr) and whose values are type of transformation
|
|
2972
|
+
applied to each attribute. This map does not include any
|
|
2973
|
+
attributes that do not have an transformation type.
|
|
2974
|
+
|
|
2975
|
+
Example
|
|
2976
|
+
|
|
2977
|
+
```js [app/models/person.js]
|
|
2978
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
2979
|
+
|
|
2980
|
+
export default class PersonModel extends Model {
|
|
2981
|
+
@attr firstName;
|
|
2982
|
+
@attr('string') lastName;
|
|
2983
|
+
@attr('date') birthday;
|
|
2984
|
+
}
|
|
2985
|
+
```
|
|
2986
|
+
|
|
2987
|
+
```javascript
|
|
2988
|
+
import Person from 'app/models/person';
|
|
2989
|
+
|
|
2990
|
+
let transformedAttributes = Person.transformedAttributes
|
|
2991
|
+
|
|
2992
|
+
transformedAttributes.forEach(function(field, type) {
|
|
2993
|
+
// do thing
|
|
2994
|
+
});
|
|
2995
|
+
|
|
2996
|
+
// prints:
|
|
2997
|
+
// lastName string
|
|
2998
|
+
// birthday date
|
|
2999
|
+
```
|
|
3000
|
+
|
|
3001
|
+
@public
|
|
3002
|
+
*/
|
|
3003
|
+
static get transformedAttributes(): Map<string, string>;
|
|
3004
|
+
/**
|
|
3005
|
+
Iterates through the attributes of the model, calling the passed function on each
|
|
3006
|
+
attribute.
|
|
3007
|
+
|
|
3008
|
+
The callback method you provide should have the following signature (all
|
|
3009
|
+
parameters are optional):
|
|
3010
|
+
|
|
3011
|
+
```javascript
|
|
3012
|
+
function(name, meta);
|
|
3013
|
+
```
|
|
3014
|
+
|
|
3015
|
+
- `name` the name of the current property in the iteration
|
|
3016
|
+
- `meta` the meta object for the attribute property in the iteration
|
|
3017
|
+
|
|
3018
|
+
Note that in addition to a callback, you can also pass an optional target
|
|
3019
|
+
object that will be set as `this` on the context.
|
|
3020
|
+
|
|
3021
|
+
Example
|
|
3022
|
+
|
|
3023
|
+
```javascript
|
|
3024
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
3025
|
+
|
|
3026
|
+
class PersonModel extends Model {
|
|
3027
|
+
@attr('string') firstName;
|
|
3028
|
+
@attr('string') lastName;
|
|
3029
|
+
@attr('date') birthday;
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
PersonModel.eachAttribute(function(name, meta) {
|
|
3033
|
+
// do thing
|
|
3034
|
+
});
|
|
3035
|
+
|
|
3036
|
+
// prints:
|
|
3037
|
+
// firstName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "firstName"}
|
|
3038
|
+
// lastName {type: "string", kind: 'attribute', options: Object, parentType: function, name: "lastName"}
|
|
3039
|
+
// birthday {type: "date", kind: 'attribute', options: Object, parentType: function, name: "birthday"}
|
|
3040
|
+
```
|
|
3041
|
+
|
|
3042
|
+
@public
|
|
3043
|
+
@param callback The callback to execute
|
|
3044
|
+
@param binding [optional] the value to which the callback's `this` should be bound
|
|
3045
|
+
*/
|
|
3046
|
+
static eachAttribute<T, Schema extends Model>(callback: (this: T | undefined, key: MaybeAttrFields<Schema>, attribute: LegacyAttributeField) => void, binding?: T): void;
|
|
3047
|
+
/**
|
|
3048
|
+
Iterates through the transformedAttributes of the model, calling
|
|
3049
|
+
the passed function on each attribute. Note the callback will not be
|
|
3050
|
+
called for any attributes that do not have an transformation type.
|
|
3051
|
+
|
|
3052
|
+
The callback method you provide should have the following signature (all
|
|
3053
|
+
parameters are optional):
|
|
3054
|
+
|
|
3055
|
+
```javascript
|
|
3056
|
+
function(name, type);
|
|
3057
|
+
```
|
|
3058
|
+
|
|
3059
|
+
- `name` the name of the current property in the iteration
|
|
3060
|
+
- `type` a string containing the name of the type of transformed
|
|
3061
|
+
applied to the attribute
|
|
3062
|
+
|
|
3063
|
+
Note that in addition to a callback, you can also pass an optional target
|
|
3064
|
+
object that will be set as `this` on the context.
|
|
3065
|
+
|
|
3066
|
+
Example
|
|
3067
|
+
|
|
3068
|
+
```javascript
|
|
3069
|
+
import { Model, attr } from '@warp-drive/legacy/model';
|
|
3070
|
+
|
|
3071
|
+
let Person = Model.extend({
|
|
3072
|
+
firstName: attr(),
|
|
3073
|
+
lastName: attr('string'),
|
|
3074
|
+
birthday: attr('date')
|
|
3075
|
+
});
|
|
3076
|
+
|
|
3077
|
+
Person.eachTransformedAttribute(function(name, type) {
|
|
3078
|
+
// do thing
|
|
3079
|
+
});
|
|
3080
|
+
|
|
3081
|
+
// prints:
|
|
3082
|
+
// lastName string
|
|
3083
|
+
// birthday date
|
|
3084
|
+
```
|
|
3085
|
+
|
|
3086
|
+
@public
|
|
3087
|
+
@param callback The callback to execute
|
|
3088
|
+
@param binding [optional] the value to which the callback's `this` should be bound
|
|
3089
|
+
*/
|
|
3090
|
+
static eachTransformedAttribute<T, Schema extends Model>(callback: (this: T | undefined, key: Exclude<keyof Schema & string, keyof Model & string>, type: string) => void, binding?: T): void;
|
|
3091
|
+
/**
|
|
3092
|
+
Returns the name of the model class.
|
|
3093
|
+
|
|
3094
|
+
@public
|
|
3095
|
+
*/
|
|
3096
|
+
static toString(): string;
|
|
3097
|
+
}
|
|
3098
|
+
/**
|
|
3099
|
+
* Restores the pre-`RequestManager` implementations of `save`,
|
|
3100
|
+
* `destroyRecord`, and `reload` onto the given `Model` subclass, for
|
|
3101
|
+
* apps that have not yet migrated off of the deprecated
|
|
3102
|
+
* `ENABLE_LEGACY_REQUEST_METHODS` behaviors.
|
|
3103
|
+
*/
|
|
3104
|
+
declare function restoreDeprecatedModelRequestBehaviors(ModelKlass: typeof Model): void;
|
|
3105
|
+
//#endregion
|
|
3106
|
+
export { belongsTo$1 as S, HasManyReference as _, RecordState as a, RelationshipDecorator as b, hasMany as c, MaybeHasManyFields as d, MaybeRelationshipFields as f, lookupLegacySupport as g, LEGACY_SUPPORT as h, Errors as i, BelongsToReference as l, PromiseBelongsTo as m, ModelStore as n, MinimalLegacyRecord as o, _MaybeBelongsToFields as p, restoreDeprecatedModelRequestBehaviors as r, belongsTo as s, Model as t, MaybeBelongsToFields as u, PromiseManyArray as v, RelationshipOptions as x, NoNull as y };
|
|
3107
|
+
//# sourceMappingURL=model-62hn5_PD.d.ts.map
|