Compare commits

...

1241 Commits

Author SHA1 Message Date
renovate[bot] 58585c1526 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-20 10:42:46 +00:00
renovate[bot] 7abd2ecddc chore: update actions/checkout action to v4.1.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-17 07:52:10 +00:00
dhmlau 819e1845c7 5.0.9
* chore: update dependency loopback-connector to ^6.1.5 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update actions/checkout action to v4.1.5 (renovate[bot])
 * chore: update actions/checkout action to v4.1.4 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^19.3.0 (renovate[bot])
 * chore: update actions/checkout action to v4.1.3 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.4.3 (renovate[bot])
 * chore: update dependency node to v17.9.1 (renovate[bot])
 * chore: update dependency node to v16.20.2 (renovate[bot])
 * chore: update dependency node to v14.21.3 (renovate[bot])
 * chore: update dependency node to v12.22.12 (renovate[bot])
 * chore: update dependency node to v10.24.1 (renovate[bot])
 * chore: update commitlint monorepo to ^19.2.2 (renovate[bot])
 * chore: update dependency qs to ^6.12.1 (renovate[bot])
 * chore: update dependency typescript to ^5.4.5 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.4.2 (renovate[bot])
 * chore: update dependency traverse to ^0.6.9 (renovate[bot])
 * chore: update dependency typescript to ^5.4.4 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.1.4 (renovate[bot])
2024-05-14 10:24:58 -04:00
renovate[bot] 394d16a96f chore: update dependency loopback-connector to ^6.1.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-13 15:32:23 +00:00
renovate[bot] 29f45692e9 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-13 04:04:17 +00:00
renovate[bot] 01d8584a7f chore: update actions/checkout action to v4.1.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-08 21:35:57 +00:00
renovate[bot] 7fce7dd559 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-06 04:54:51 +00:00
renovate[bot] 331cca66dd chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 06:43:45 +00:00
renovate[bot] a25e2da920 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 03:23:07 +00:00
renovate[bot] 84618aead6 chore: update actions/checkout action to v4.1.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-25 18:39:45 +00:00
renovate[bot] 3f910f9d2b chore: update dependency @commitlint/cli to ^19.3.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-23 07:51:04 +00:00
renovate[bot] 2f4ff8b6a9 chore: update actions/checkout action to v4.1.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-22 18:32:00 +00:00
renovate[bot] 7bc1d917dd chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-22 07:52:17 +00:00
renovate[bot] 99cd30a7a4 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-22 03:06:16 +00:00
renovate[bot] de40642e89 chore: update dependency eslint-plugin-mocha to ^10.4.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-19 12:30:03 +00:00
renovate[bot] 8233e2abed chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-15 07:09:58 +00:00
renovate[bot] 685d1da15c chore: update dependency node to v17.9.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-15 04:03:26 +00:00
renovate[bot] 163499308f chore: update dependency node to v16.20.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-15 02:40:53 +00:00
renovate[bot] c92e5862d0 chore: update dependency node to v14.21.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-14 21:05:50 +00:00
renovate[bot] dd40c27e8a chore: update dependency node to v12.22.12
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-14 19:05:59 +00:00
renovate[bot] c2c892b071 chore: update dependency node to v10.24.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-14 16:00:31 +00:00
renovate[bot] 260acdd898 chore: update commitlint monorepo to ^19.2.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-14 14:04:30 +00:00
renovate[bot] 9ae71251ae chore: update dependency qs to ^6.12.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-13 01:30:32 +00:00
renovate[bot] d35149e2b7 chore: update dependency typescript to ^5.4.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-10 22:42:19 +00:00
renovate[bot] 034cb0048b chore: update dependency eslint-plugin-mocha to ^10.4.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-10 15:52:41 +00:00
renovate[bot] ca091d0342 chore: update dependency traverse to ^0.6.9
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-09 04:05:42 +00:00
renovate[bot] a84721b8d8 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-08 04:12:35 +00:00
renovate[bot] 602602f69a chore: update dependency typescript to ^5.4.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-04 14:59:13 -04:00
renovate[bot] 26d4b30634 chore: update dependency loopback-connector to ^6.1.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-04 14:12:14 -04:00
dhmlau b7a7963223 5.0.8
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency minimatch to ^9.0.4 (renovate[bot])
 * fix: add error handling in case of unvailable cache server (Muhammad Aaqil)
 * chore: update dependency mocha to ^10.4.0 (renovate[bot])
 * chore: update dependency typescript to ^5.4.3 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^19.2.1 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^19.2.0 (renovate[bot])
 * chore: update commitlint monorepo to ^19.1.0 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.4.1 (renovate[bot])
2024-04-04 13:53:26 -04:00
renovate[bot] 12ebf9c5e6 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-01 04:36:25 +00:00
renovate[bot] 23b7ca8cff chore: update dependency minimatch to ^9.0.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-29 01:31:42 +00:00
Muhammad Aaqil feaecba71c fix: add error handling in case of unvailable cache server
Signed-off-by: Muhammad Aaqil <aaqilcs102@gmail.com>
2024-03-27 16:59:33 +05:30
renovate[bot] a206198e31 chore: update dependency mocha to ^10.4.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 21:47:30 +00:00
renovate[bot] 13f2ce6b98 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-25 04:38:11 +00:00
renovate[bot] 68bff40ba7 chore: update dependency typescript to ^5.4.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-21 00:29:48 +00:00
renovate[bot] 79a06a587c chore: update dependency @commitlint/cli to ^19.2.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-19 07:36:42 +00:00
renovate[bot] b83f9e68e9 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-18 04:12:23 +00:00
renovate[bot] a7efa3576b chore: update dependency @commitlint/cli to ^19.2.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-15 07:58:16 +00:00
renovate[bot] edbdf8520b chore: update commitlint monorepo to ^19.1.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-12 10:20:04 +00:00
renovate[bot] 1f5a4cd072 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 06:10:34 +00:00
renovate[bot] 365f27b911 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 03:10:05 +00:00
renovate[bot] 99ff788169 chore: update dependency eslint-plugin-mocha to ^10.4.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-08 13:22:32 +00:00
dhmlau 8de60b558e 5.0.7
* chore: update dependency eslint-plugin-mocha to ^10.4.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.1.3 (renovate[bot])
 * chore: update dependency typescript to ^5.4.2 (renovate[bot])
 * chore: update dependency qs to ^6.12.0 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update commitlint monorepo to ^19.0.3 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^19.0.1 (renovate[bot])
 * chore: update commitlint monorepo to v19 (renovate[bot])
 * chore: update dependency eslint to ^8.57.0 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.3.0 (renovate[bot])
 * chore: update dependency @commitlint/config-conventional to ^18.6.2 (renovate[bot])
 * chore: update commitlint monorepo to ^18.6.1 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.1.2 (renovate[bot])
2024-03-07 07:47:08 -05:00
renovate[bot] 5bd2b4a863 chore: update dependency eslint-plugin-mocha to ^10.4.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-07 07:40:44 -05:00
renovate[bot] 5bdf70874f chore: update dependency loopback-connector to ^6.1.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-07 07:11:38 +00:00
renovate[bot] ba8b93e692 chore: update dependency typescript to ^5.4.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 20:46:58 -05:00
renovate[bot] b6b240afc9 chore: update dependency qs to ^6.12.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 23:18:27 +00:00
renovate[bot] c4fac50863 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 06:32:16 +00:00
renovate[bot] d7083ec8f2 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 03:05:44 +00:00
renovate[bot] 911f29e8df chore: update commitlint monorepo to ^19.0.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-28 16:47:14 +00:00
renovate[bot] 5673cbd52b chore: update dependency @commitlint/cli to ^19.0.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-27 22:49:13 +00:00
renovate[bot] 714dc55ccd chore: update commitlint monorepo to v19
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-27 21:57:40 +08:00
renovate[bot] 838905877f chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 04:20:11 +00:00
renovate[bot] 138cd90d6c chore: update dependency eslint to ^8.57.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-24 01:45:16 +00:00
renovate[bot] 52cd087aff chore: update dependency eslint-plugin-mocha to ^10.3.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-16 16:53:52 +00:00
renovate[bot] ed7cabb668 chore: update dependency @commitlint/config-conventional to ^18.6.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-14 17:07:08 +00:00
renovate[bot] dee64a9b4c chore: update commitlint monorepo to ^18.6.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-13 12:41:55 +00:00
renovate[bot] a35e8d18c2 chore: update dependency loopback-connector to ^6.1.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-13 00:21:02 +00:00
dhmlau 33d06b5c71 5.0.6
* fix: return generated: false if the connector doesnot return it (Muhammad Aaqil)
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency mocha to ^10.3.0 (renovate[bot])
 * chore: update actions/setup-node action to v4.0.2 (renovate[bot])
 * chore: update commitlint monorepo to ^18.6.0 (renovate[bot])
 * chore: update commitlint monorepo to ^18.5.0 (renovate[bot])
 * chore: update dependency inflection to v3 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.1.1 (renovate[bot])
2024-02-12 10:32:59 -05:00
Muhammad Aaqil 748fe22bcb fix: return generated: false if the connector doesnot return it
Signed-off-by: Muhammad Aaqil <aaqilcs102@gmail.com>
2024-02-12 14:25:58 +05:30
renovate[bot] 901486f0d3 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-12 04:14:20 +00:00
renovate[bot] 60959e36c3 chore: update dependency mocha to ^10.3.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 18:23:35 +00:00
renovate[bot] b603283dc0 chore: update actions/setup-node action to v4.0.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-07 10:47:50 +00:00
renovate[bot] 9d47253316 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 06:55:13 +00:00
renovate[bot] 03c1683a83 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 03:03:02 +00:00
renovate[bot] 07d3e1bbf7 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-29 07:23:09 +00:00
renovate[bot] e9af46e836 chore: update commitlint monorepo to ^18.6.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-25 16:12:38 +00:00
renovate[bot] 3a50b1356e chore: update commitlint monorepo to ^18.5.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-22 13:45:06 +00:00
renovate[bot] 726476f8e0 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-22 04:27:04 +00:00
renovate[bot] 5c9e59845f chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-15 04:13:10 +00:00
renovate[bot] 3be58c9446 chore: update dependency inflection to v3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-11 14:47:37 -05:00
renovate[bot] df89ae59e3 chore: update dependency loopback-connector to ^6.1.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-09 21:33:18 +00:00
dhmlau f191c8a5dd 5.0.5
* chore: lock file maintenance (renovate[bot])
 * chore: update github/codeql-action action to v3 (renovate[bot])
 * chore: update commitlint monorepo to ^18.4.4 (renovate[bot])
 * chore: update dependency traverse to ^0.6.8 (renovate[bot])
 * chore: update actions/setup-node action to v4.0.1 (renovate[bot])
 * chore: update dependency eslint to ^8.56.0 (renovate[bot])
2024-01-09 10:59:06 -05:00
renovate[bot] 3268b036d5 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 04:36:46 +00:00
renovate[bot] 9b96f69098 chore: update github/codeql-action action to v3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-07 17:28:50 -05:00
renovate[bot] 14abfbd6dc chore: update commitlint monorepo to ^18.4.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-04 19:26:44 +00:00
renovate[bot] 8e642d7686 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-01 08:59:43 +00:00
renovate[bot] be3faa1ee2 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-25 06:30:42 +00:00
renovate[bot] fbd4b63b24 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-25 03:56:20 +00:00
renovate[bot] 0c9aca3b36 chore: update dependency traverse to ^0.6.8
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 03:39:20 +00:00
renovate[bot] da0863edf0 chore: update actions/setup-node action to v4.0.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-18 13:31:08 +00:00
renovate[bot] 70520a7812 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-18 07:57:02 +00:00
renovate[bot] b4c23eb6d1 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-18 03:35:38 +00:00
renovate[bot] ad8b95b2eb chore: update dependency eslint to ^8.56.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-16 04:05:10 +00:00
renovate[bot] e24936078c chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-11 08:04:18 +00:00
renovate[bot] 4f8af05cdf chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-11 03:42:43 +00:00
dhmlau 7a847a04d1 5.0.4
* chore: update dependency loopback-connector to ^6.1.0 (renovate[bot])
 * chore: update dependency typescript to ^5.3.3 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.55.0 (renovate[bot])
 * chore: update commitlint monorepo to ^18.4.3 (renovate[bot])
 * chore: update dependency typescript to ^5.3.2 (renovate[bot])
 * chore: update dependency eslint to ^8.54.0 (renovate[bot])
 * chore: update commitlint monorepo to ^18.4.2 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.0.4 (renovate[bot])
2023-12-07 13:31:13 -05:00
renovate[bot] da54829f83 chore: update dependency loopback-connector to ^6.1.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-07 18:25:41 +00:00
renovate[bot] 2eae64f3cc chore: update dependency typescript to ^5.3.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-07 00:20:28 +00:00
renovate[bot] 4557e2e10f chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-04 08:32:21 +00:00
renovate[bot] 469d4802bb chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-04 03:57:09 +00:00
renovate[bot] 76fe5ad1c7 chore: update dependency eslint to ^8.55.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-02 00:54:09 +00:00
renovate[bot] f80a351225 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 04:53:26 +00:00
renovate[bot] 82247a34ae chore: update commitlint monorepo to ^18.4.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-21 08:34:01 +00:00
renovate[bot] 9fa099484f chore: update dependency typescript to ^5.3.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-20 21:59:03 +00:00
renovate[bot] 15a9e785a7 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-20 07:03:15 +00:00
renovate[bot] 01a942cae0 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-20 03:05:02 +00:00
renovate[bot] 3ab268dc3c chore: update dependency eslint to ^8.54.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-17 20:11:52 -05:00
renovate[bot] 1dd3546c3f chore: update commitlint monorepo to ^18.4.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-16 11:30:53 +00:00
renovate[bot] 2137f28948 chore: update dependency loopback-connector to ^6.0.4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-13 19:44:29 +00:00
dhmlau 244ec17e60 5.0.3
* chore: update commitlint monorepo to v18 (renovate[bot])
 * chore: update actions/setup-node action to v4 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency nanoid to ^3.3.7 (renovate[bot])
 * chore: update dependency eslint to ^8.53.0 (renovate[bot])
 * chore: update dependency async to ^3.2.5 (renovate[bot])
 * chore: update actions/setup-node action to v3.8.2 (renovate[bot])
 * chore: update dependency eslint to ^8.52.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.8.1 (renovate[bot])
 * chore: update actions/checkout action to v4.1.1 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.0.3 (renovate[bot])
2023-11-13 09:10:07 -05:00
renovate[bot] ea84ff4314 chore: update commitlint monorepo to v18
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-13 09:08:06 -05:00
renovate[bot] f937e63d25 chore: update actions/setup-node action to v4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-13 09:07:56 -05:00
renovate[bot] b6f88b6a2a chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-13 06:49:17 +00:00
renovate[bot] 603ebced82 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-13 03:49:21 +00:00
renovate[bot] 75482a9acc chore: update dependency nanoid to ^3.3.7
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-06 10:17:58 +00:00
renovate[bot] d6f6910980 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-06 08:10:07 +00:00
renovate[bot] 8a3880289d chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-06 03:40:46 +00:00
renovate[bot] ae8597883a chore: update dependency eslint to ^8.53.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-04 06:54:06 +00:00
renovate[bot] d584420397 chore: update dependency async to ^3.2.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-04 04:41:27 +00:00
renovate[bot] ae9695fe3c chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-30 06:16:16 +00:00
renovate[bot] 92c26b4100 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-30 03:31:39 +00:00
renovate[bot] ef397c07e9 chore: update actions/setup-node action to v3.8.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-23 17:34:46 +00:00
renovate[bot] 7454c4a150 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-23 04:32:08 +00:00
renovate[bot] dac2d47312 chore: update dependency eslint to ^8.52.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-21 00:21:36 +00:00
renovate[bot] 23e1a4a4c2 chore: update commitlint monorepo to ^17.8.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-20 15:04:54 +00:00
renovate[bot] cdec276338 chore: update actions/checkout action to v4.1.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-17 18:28:52 +00:00
renovate[bot] a2bae7dabf chore: update dependency loopback-connector to ^6.0.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-16 18:57:06 +00:00
dhmlau b7e9f4d00a 5.0.2
* chore: lock file maintenance (renovate[bot])
 * chore: update commitlint monorepo to ^17.8.0 (renovate[bot])
 * chore: update dependency eslint to ^8.51.0 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^17.7.2 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.2.0 (renovate[bot])
 * chore: update dependency eslint to ^8.50.0 (renovate[bot])
 * chore: update actions/checkout action to v4.1.0 (renovate[bot])
2023-10-16 08:15:23 -04:00
renovate[bot] 5f1161a8ab chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-16 08:01:33 +00:00
renovate[bot] 584a5ccb82 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-16 03:18:36 +00:00
renovate[bot] 28d4007fdc chore: update commitlint monorepo to ^17.8.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-14 15:56:30 +00:00
renovate[bot] 2667d3b7d9 chore: update dependency eslint to ^8.51.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-07 02:11:36 +00:00
renovate[bot] 7926b52480 chore: update dependency @commitlint/cli to ^17.7.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-28 22:44:52 +00:00
renovate[bot] da06e6ea60 chore: update dependency eslint-plugin-mocha to ^10.2.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-25 17:33:35 +00:00
renovate[bot] 30751df17d chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-25 06:40:08 +00:00
renovate[bot] bbd63ce67e chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-25 03:39:27 +00:00
renovate[bot] 9846fceaa6 chore: update dependency eslint to ^8.50.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-23 01:28:21 +00:00
renovate[bot] ef210ef56a chore: update actions/checkout action to v4.1.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-22 22:22:51 +00:00
renovate[bot] f2b02920ba chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-18 06:42:18 +00:00
renovate[bot] 42430be43b chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-18 03:41:50 +00:00
dhmlau 8562200853 5.0.1 2023-09-13 09:19:28 -04:00
dhmlau 3469bded5a 5.0.0
* chore: drop Node.js 16 support BREAKING CHANGE: drop Node.js 16 support (dhmlau)
 * chore: update dependency typescript to v5 (renovate[bot])
 * chore: update actions/checkout action to v4 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.49.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^6.0.2 (renovate[bot])
 * chore: update dependency uuid to ^9.0.1 (renovate[bot])
 * fix(ci): fix GH actions versions (dhmlau)
 * chore: update dependency minimatch to v9 (renovate[bot])
 * chore: update dependency eslint to ^8.48.0 (renovate[bot])
 * chore: update dependency strong-globalize to ^6.0.6 (renovate[bot])
 * chore: drop Node.js 14 and lower (dhmlau)
2023-09-12 13:29:10 -04:00
dhmlau 8b6cad7d66 chore: drop Node.js 16 support
BREAKING CHANGE: drop Node.js 16 support

Signed-off-by: dhmlau <dhmlau@ca.ibm.com>
2023-09-12 13:27:56 -04:00
renovate[bot] 40bb3c0b79 chore: update dependency typescript to v5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 13:27:46 -04:00
renovate[bot] 757f48a539 chore: update actions/checkout action to v4
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 08:46:07 -04:00
renovate[bot] 1ea6ceb0d1 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 08:13:22 -04:00
renovate[bot] ac34f8141e chore: update dependency eslint to ^8.49.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 08:13:06 -04:00
renovate[bot] ea3cdb1a71 chore: update dependency loopback-connector to ^6.0.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 08:12:49 -04:00
renovate[bot] 90564e3100 chore: update dependency uuid to ^9.0.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-12 08:12:35 -04:00
dhmlau 90e1485d8c fix(ci): fix GH actions versions
Signed-off-by: dhmlau <dhmlau@ca.ibm.com>
2023-09-12 07:59:30 -04:00
renovate[bot] 19e9d633bc chore: update dependency minimatch to v9
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-11 10:00:40 -04:00
renovate[bot] 9d5899cab2 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-28 05:02:42 +00:00
renovate[bot] 1a4a6ae780 chore: update dependency eslint to ^8.48.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-26 00:32:22 +00:00
renovate[bot] 7cbc8a86ee chore: update dependency strong-globalize to ^6.0.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-24 22:36:48 +00:00
dhmlau 8306749436 chore: drop Node.js 14 and lower
BREAKING CHANGE: drop support for Node.js 14 version and lower

Signed-off-by: dhmlau <dhmlau@ca.ibm.com>
2023-08-24 15:24:48 -04:00
renovate[bot] 518e3ca1ca chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-23 09:37:55 +00:00
dhmlau 415dfda681 4.28.9
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.47.0 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^17.7.1 (renovate[bot])
 * chore: update commitlint monorepo to ^17.7.0 (renovate[bot])
 * chore: update dependency eslint to ^8.46.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.7 (renovate[bot])
 * chore: update dependency eslint to ^8.45.0 (renovate[bot])
2023-08-14 09:59:00 -04:00
renovate[bot] 8f43d9b659 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-14 05:03:29 +00:00
renovate[bot] 354235247b chore: update dependency eslint to ^8.47.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-11 18:19:13 +00:00
renovate[bot] 861cc5c448 chore: update dependency @commitlint/cli to ^17.7.1
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-10 10:54:22 +00:00
renovate[bot] 8716469dc2 chore: update commitlint monorepo to ^17.7.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-09 12:07:54 +00:00
renovate[bot] fa18610f96 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-07 04:22:50 +00:00
renovate[bot] f7ded61ad5 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-31 06:35:57 +00:00
renovate[bot] bab4c90553 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-31 03:53:09 +00:00
renovate[bot] 3bd71ff26f chore: update dependency eslint to ^8.46.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-28 19:14:28 +00:00
renovate[bot] 0d58339bb8 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-24 07:39:06 +00:00
renovate[bot] 23e76f905e chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-24 03:50:34 +00:00
renovate[bot] 363bdcea5d chore: update commitlint monorepo to ^17.6.7
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-19 09:03:35 +00:00
renovate[bot] 6959b9c620 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-17 04:56:52 +00:00
renovate[bot] 3b121482cf chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-16 22:09:37 -04:00
renovate[bot] 76cdc59461 chore: update dependency eslint to ^8.45.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-14 21:04:13 +00:00
dhmlau 1c197d8b17 4.28.8
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.44.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.3.3 (renovate[bot])
2023-07-11 12:31:32 -04:00
renovate[bot] 2f7ea50341 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-10 07:20:21 +00:00
renovate[bot] 6729c8a0ec chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-10 03:41:43 +00:00
renovate[bot] cdfc71ec77 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-03 08:02:44 +00:00
renovate[bot] 15da93ef83 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-03 03:53:41 +00:00
renovate[bot] 7184fb054a chore: update dependency eslint to ^8.44.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 13:01:52 +00:00
renovate[bot] b6cd522d44 chore: update dependency loopback-connector to ^5.3.3
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-27 19:17:39 +00:00
dhmlau 07333dfe8b 4.28.7
* fix: set nullable under jsonSchema in property to true in case of nullable property (Muhammad Aaqil)
 * chore: lock file maintenance (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.6 (renovate[bot])
 * fix: null value not persisted for properties of type JSON, Any, or Object (Siim Sams)
 * chore: update dependency eslint to ^8.43.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.3.2 (renovate[bot])
2023-06-27 09:11:43 -04:00
Muhammad Aaqil f14ae8af4b fix: set nullable under jsonSchema in property to true in case of nullable property
Signed-off-by: Muhammad Aaqil <aaqilniz@yahoo.com>
2023-06-26 22:12:47 +05:00
renovate[bot] 025b22a9af chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-26 07:03:27 +00:00
renovate[bot] 4908768c02 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-26 03:09:32 +00:00
renovate[bot] 3dea22d63e chore: update commitlint monorepo to ^17.6.6
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-24 13:26:07 +00:00
Siim Sams ae3cf25e77 fix: null value not persisted for properties of type JSON, Any, or Object
Signed-off-by: Siim Sams <siim.sams@katanamrp.com>
2023-06-20 16:09:07 -04:00
renovate[bot] c905f025df chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-19 06:30:09 +00:00
renovate[bot] 1977e5470b chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-19 03:38:10 +00:00
renovate[bot] ab90d50eff chore: update dependency eslint to ^8.43.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 01:32:41 +00:00
renovate[bot] fb725e9ff0 chore: update dependency loopback-connector to ^5.3.2
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-14 12:28:23 +05:30
dhmlau 8a126f623d 4.28.6
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.42.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.5 (renovate[bot])
 * chore: update dependency eslint to ^8.41.0 (renovate[bot])
 * chore: update dependency qs to ^6.11.2 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.3.1 (renovate[bot])
2023-06-13 20:28:30 -04:00
renovate[bot] 8b29d8db01 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 07:06:04 +00:00
renovate[bot] d395dbb24d chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 03:39:06 +00:00
renovate[bot] 52c6532add chore: update dependency eslint to ^8.42.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-03 03:34:19 +00:00
renovate[bot] 0b9cee7f3b chore: update commitlint monorepo to ^17.6.5
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-30 11:37:00 +00:00
renovate[bot] efc5d1d6f8 chore: lock file maintenance
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-29 03:12:44 +00:00
renovate[bot] 28debb4c75 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-22 06:20:47 +00:00
renovate[bot] a927649bc8 chore: update dependency eslint to ^8.41.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-20 04:24:40 +00:00
renovate[bot] 521bfba219 chore: update dependency qs to ^6.11.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-15 20:58:02 +00:00
renovate[bot] dfa614e025 chore: update dependency loopback-connector to ^5.3.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-15 17:45:37 +00:00
dhmlau ff623d6a0d 4.28.5
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.40.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.3 (renovate[bot])
 * chore: update dependency eslint to ^8.39.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.1 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.3.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.6.0 (renovate[bot])
2023-05-15 09:26:21 -04:00
renovate[bot] f6b2508dfd chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-15 07:18:06 +00:00
renovate[bot] 2f6dd870a6 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-08 04:34:37 +00:00
renovate[bot] 46aaa540bd chore: update dependency eslint to ^8.40.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-06 04:15:03 +00:00
renovate[bot] 9e928208d0 chore: update commitlint monorepo to ^17.6.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-04 13:39:12 +00:00
renovate[bot] 9cf7686a36 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-05-01 06:54:01 +00:00
renovate[bot] d72ced71e0 chore: update dependency eslint to ^8.39.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-22 05:16:12 +00:00
renovate[bot] 04b84b5e1b chore: update commitlint monorepo to ^17.6.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-19 03:33:00 +00:00
renovate[bot] 9b66ad190e chore: update dependency loopback-connector to ^5.3.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-13 19:41:57 -04:00
renovate[bot] 4fb97fcd04 chore: update commitlint monorepo to ^17.6.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-13 21:14:30 +00:00
dhmlau 66abcebe8a 4.28.4
* chore: update dependency eslint to ^8.38.0 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.37.0 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^17.5.1 (renovate[bot])
 * chore: update dependency nanoid to ^3.3.6 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^17.5.0 (renovate[bot])
 * chore: update dependency eslint to ^8.36.0 (renovate[bot])
 * chore: update dependency eslint to ^8.35.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.2.2 (renovate[bot])
 * chore: update dependency qs to ^6.11.1 (renovate[bot])
2023-04-13 10:16:42 -04:00
renovate[bot] abf82d7eca chore: update dependency eslint to ^8.38.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-08 05:33:26 +00:00
renovate[bot] 58c59cad72 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-04-03 08:41:21 +00:00
renovate[bot] 2b4ad689ad chore: update dependency eslint to ^8.37.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-29 11:41:25 +00:00
renovate[bot] a229a7ac58 chore: update dependency @commitlint/cli to ^17.5.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-28 22:14:19 +00:00
renovate[bot] 888e66bf6a chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-27 05:52:56 +00:00
renovate[bot] 2a233c7274 chore: update dependency nanoid to ^3.3.6
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-26 16:57:28 +00:00
renovate[bot] b7e8f5ff66 chore: update dependency @commitlint/cli to ^17.5.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-22 17:51:04 +00:00
renovate[bot] 59b61d5627 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-20 04:09:18 +00:00
renovate[bot] 07958c4076 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-13 04:59:40 +00:00
renovate[bot] 80e2b2112d chore: update dependency eslint to ^8.36.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-11 02:43:29 +00:00
renovate[bot] d274a48192 chore: update dependency eslint to ^8.35.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-09 23:26:30 +00:00
renovate[bot] d2b09ebf94 chore: update dependency loopback-connector to ^5.2.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-09 20:44:48 +00:00
renovate[bot] c61a47e88e chore: update dependency qs to ^6.11.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-03-08 20:31:09 +00:00
dhmlau 66af10f401 4.28.3
* fix: isolate context for each createAll call (akshatdubeysf)
 * chore: update dependency uuid to v9 (renovate[bot])
 * chore: update commitlint monorepo to ^17.4.4 (renovate[bot])
 * chore: update commitlint monorepo to ^17.4.3 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.34.0 (renovate[bot])
 * chore: update dependency typescript to ^4.9.5 (renovate[bot])
2023-03-08 11:33:10 -05:00
akshatdubeysf 69f010e4ca fix: isolate context for each createAll call
Signed-off-by: akshatdubeysf <akshat.dubey@sourcefuse.com>
2023-03-07 10:20:01 +05:30
renovate[bot] 8e8fe00564 chore: update dependency uuid to v9
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-02-25 20:07:29 -05:00
renovate[bot] 15f1a85fdc chore: update commitlint monorepo to ^17.4.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-02-17 22:10:28 +00:00
renovate[bot] c5eeb88a93 chore: update commitlint monorepo to ^17.4.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-02-13 15:04:39 +00:00
renovate[bot] 253ecfcbfb chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-02-13 05:24:05 +00:00
renovate[bot] 9df18e2a75 chore: update dependency eslint to ^8.34.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-02-11 04:36:05 +00:00
renovate[bot] 8dce904fc6 chore: update dependency typescript to ^4.9.5
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-31 05:31:31 +00:00
dhmlau d31b9d8b97 4.28.2
* chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.33.0 (renovate[bot])
 * fix: return correct model instance in createAll (Samarpan  Bhattacharya)
 * chore: update dependency minimatch to ^5.1.6 (renovate[bot])
 * chore: update dependency minimatch to ^5.1.4 (renovate[bot])
 * chore: update dependency eslint to ^8.32.0 (renovate[bot])
 * chore: update commitlint monorepo to ^17.4.2 (renovate[bot])
 * chore: update dependency bson to ^4.7.2 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.2.1 (renovate[bot])
2023-01-30 11:53:36 -05:00
renovate[bot] 2f993718f0 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-30 05:52:17 +00:00
renovate[bot] e20550b680 chore: update dependency eslint to ^8.33.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-29 02:57:06 +00:00
Samarpan Bhattacharya 316ebce660 fix: return correct model instance in createAll
Signed-off-by: Samarpan Bhattacharya <this.is.samy@gmail.com>
2023-01-24 21:48:44 +05:30
renovate[bot] c03b0a0440 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-23 04:56:25 +00:00
renovate[bot] e486faf93a chore: update dependency minimatch to ^5.1.6
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-18 02:29:38 +00:00
renovate[bot] a883c06bbc chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-16 06:19:10 +00:00
renovate[bot] 9e34360aae chore: update dependency minimatch to ^5.1.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-15 13:22:25 +00:00
renovate[bot] e8a401c347 chore: update dependency eslint to ^8.32.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-15 09:13:09 +00:00
renovate[bot] a97aed958c chore: update commitlint monorepo to ^17.4.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-12 20:06:31 +00:00
renovate[bot] 936be6bbff chore: update dependency bson to ^4.7.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-11 00:32:54 +00:00
renovate[bot] 236df1d649 chore: update dependency loopback-connector to ^5.2.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-10 04:50:48 +00:00
dhmlau dde1101793 4.28.1
* chore: update dependency @commitlint/cli to ^17.4.1 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency bson to ^4.7.1 (renovate[bot])
 * chore: update commitlint monorepo to ^17.4.0 (renovate[bot])
 * chore: update dependency eslint to ^8.31.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.2.0 (renovate[bot])
 * chore: update dependency minimatch to ^5.1.2 (renovate[bot])
 * chore: update dependency eslint to ^8.30.0 (renovate[bot])
 * chore: update dependency typescript to ^4.9.4 (renovate[bot])
 * chore: update dependency typescript to ^4.9.3 (renovate[bot])
 * chore: update commitlint monorepo to ^17.3.0 (renovate[bot])
 * chore: update dependency minimatch to ^5.1.1 (renovate[bot])
 * chore: update dependency eslint to ^8.29.0 (renovate[bot])
 * chore: update dependency eslint to ^8.27.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.1.1 (renovate[bot])
2023-01-09 14:49:37 -05:00
renovate[bot] 86ef5a48a9 chore: update dependency @commitlint/cli to ^17.4.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-09 12:47:26 -05:00
renovate[bot] 69cb28ade1 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-09 04:50:16 +00:00
renovate[bot] 3b59084cd0 chore: update dependency bson to ^4.7.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-05 21:09:46 +00:00
renovate[bot] 340db473ed chore: update commitlint monorepo to ^17.4.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-04 15:22:09 +00:00
renovate[bot] 492d569903 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2023-01-02 04:47:54 +00:00
renovate[bot] 99d56bba79 chore: update dependency eslint to ^8.31.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-31 11:09:58 +00:00
renovate[bot] 8b8fc962c7 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-26 03:45:04 +00:00
renovate[bot] df78022886 chore: update dependency loopback-connector to ^5.2.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-21 19:31:41 +00:00
renovate[bot] abf7bbaa1e chore: update dependency minimatch to ^5.1.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-20 22:24:11 +00:00
renovate[bot] b50cbb3cfd chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-19 04:29:21 +00:00
renovate[bot] 713a2775f2 chore: update dependency eslint to ^8.30.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-17 04:49:50 +00:00
renovate[bot] 21870e41ce chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-12 05:44:48 +00:00
renovate[bot] b4441976eb chore: update dependency typescript to ^4.9.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-08 06:58:10 +00:00
renovate[bot] 37ae2919e2 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-05 16:33:29 +00:00
renovate[bot] bc2f0fd705 chore: update dependency typescript to ^4.9.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-05 13:44:32 +00:00
renovate[bot] 8cd336407c chore: update commitlint monorepo to ^17.3.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-05 10:35:05 +00:00
renovate[bot] e34b63ea79 chore: update dependency minimatch to ^5.1.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-05 06:23:58 +00:00
renovate[bot] cbf3fe162d chore: update dependency eslint to ^8.29.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-12-05 03:28:50 +00:00
renovate[bot] 00b9903fac chore: update dependency eslint to ^8.27.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-11-07 23:41:26 +00:00
renovate[bot] 0e519f7559 chore: update dependency loopback-connector to ^5.1.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-11-07 19:09:14 +00:00
dhmlau 0f759fe0aa 4.28.0
* chore: update github/codeql-action action to v2 (Renovate Bot)
 * fix: add missing property in model generated (Muhammad Aaqil)
 * feat: add capability for insert multiple rows in single query (Samarpan Bhattacharya)
 * chore: update commitlint monorepo to ^17.2.0 (renovate[bot])
 * chore: lock file maintenance (renovate[bot])
 * chore: update dependency eslint to ^8.26.0 (renovate[bot])
 * chore: update dependency traverse to ^0.6.7 (renovate[bot])
 * chore: update dependency eslint to ^8.25.0 (renovate[bot])
 * chore: update dependency loopback-connector to ^5.1.0 (renovate[bot])
 * chore: update dependency typescript to ^4.8.4 (renovate[bot])
 * chore: update dependency eslint to ^8.24.0 (renovate[bot])
 * chore: update dependency inflection to ^1.13.4 (renovate[bot])
 * chore: update dependency eslint to ^8.23.1 (renovate[bot])
 * chore: update dependency typescript to ^4.8.3 (renovate[bot])
 * chore: update dependency @commitlint/cli to ^17.1.2 (renovate[bot])
 * chore: update commitlint monorepo (renovate[bot])
 * chore: update dependency eslint to ^8.23.0 (renovate[bot])
 * chore: update dependency typescript to ^4.8.2 (renovate[bot])
 * fix: missing serialisation for `Connector.update` (Rifa Achrinza)
 * chore: update dependency bson to ^4.7.0 (renovate[bot])
 * chore: update dependency eslint to ^8.22.0 (renovate[bot])
 * chore: update dependency eslint to ^8.21.0 (renovate[bot])
 * chore: update dependency eslint-plugin-mocha to ^10.1.0 (renovate[bot])
 * chore: update dependency eslint to ^8.20.0 (renovate[bot])
 * chore: update dependency eslint to ^8.19.0 (renovate[bot])
 * chore: update dependency bson to ^4.6.5 (renovate[bot])
 * chore: update dependency eslint to ^8.18.0 (renovate[bot])
 * chore: update dependency typescript to ^4.7.4 (renovate[bot])
 * chore: update dependency qs to ^6.10.5 (renovate[bot])
 * chore: update dependency async to ^3.2.4 (renovate[bot])
 * chore: update commitlint monorepo to ^17.0.3 (renovate[bot])
 * chore: update lint packages (Renovate Bot)
 * chore: update dependency typescript to ^4.7.2 (Renovate Bot)
 * chore: update commitlint monorepo to v17 (Renovate Bot)
 * chore: update dependency minimatch to ^5.1.0 (Renovate Bot)
 * chore: update dependency nanoid to ^3.3.4 (Renovate Bot)
 * chore: lock file maintenance (Renovate Bot)
 * chore: update dependency bson to ^4.6.4 (Renovate Bot)
 * chore: update commitlint monorepo (Renovate Bot)
 * chore: update dependency bson to ^4.6.3 (Renovate Bot)
 * chore: update dependency nanoid to ^3.3.3 (Renovate Bot)
 * chore: update dependency minimatch to v5 (Renovate Bot)
 * chore: update dependency typescript to ^4.6.3 (Renovate Bot)
 * chore: update dependency nanoid to 3.1.31 [security] (Renovate Bot)
 * chore: update dependency nanoid to ^3.3.2 (Renovate Bot)
 * chore: update actions/setup-node action to v3 (Renovate Bot)
 * chore: update actions/checkout action to v3 (Renovate Bot)
 * chore: update dependency minimatch to ^3.1.2 (Renovate Bot)
 * chore: update dependency bson to ^4.6.2 (Renovate Bot)
 * chore: update dependency qs to ^6.10.3 (Renovate Bot)
 * chore: update dependency loopback-connector to ^5.0.1 (Renovate Bot)
 * docs: add SECURITY.md (Diana Lau)
 * chore: update dependency uuid to ^8.3.2 (Renovate Bot)
 * chore: update dependency lodash to ^4.17.21 (Renovate Bot)
 * chore: update dependency inflection to ^1.13.2 (Renovate Bot)
 * chore: update dependency debug to ^4.3.4 (Renovate Bot)
 * chore: update dependency change-case to ^4.1.2 (Renovate Bot)
 * chore: update dependency async to ^3.2.3 (Renovate Bot)
 * ci: use shared renovate config (Rifa Achrinza)
 * ci: add renovate config (Rifa Achrinza)
 * docs: update coc (Diana Lau)
 * docs: add code of conduct (Diana Lau)
2022-11-07 10:38:52 -05:00
Renovate Bot 6ede40fee4 chore: update github/codeql-action action to v2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-11-04 09:22:26 -04:00
Muhammad Aaqil 6ffad9f7d6 fix: add missing property in model generated
Signed-off-by: Muhammad Aaqil <aaqilniz@yahoo.com>

Update lib/datasource.js

Co-authored-by: Samarpan Bhattacharya <this.is.samy@gmail.com>
2022-11-04 09:20:07 -04:00
Samarpan Bhattacharya d29bec72a8 feat: add capability for insert multiple rows in single query
Signed-off-by: Samarpan Bhattacharya <this.is.samy@gmail.com>
2022-11-01 15:47:02 -04:00
renovate[bot] cb20ae6575 chore: update commitlint monorepo to ^17.2.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-31 18:39:17 +00:00
renovate[bot] 31ea05783a chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-24 04:03:54 +00:00
renovate[bot] 2789a92899 chore: update dependency eslint to ^8.26.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-22 01:14:52 +00:00
renovate[bot] 1d0f914867 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-17 03:53:20 +00:00
renovate[bot] e6da14dcd1 chore: update dependency traverse to ^0.6.7
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-13 11:08:15 +00:00
renovate[bot] 7b4b0d3140 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-10 03:07:35 +00:00
renovate[bot] ac49c3ecd2 chore: update dependency eslint to ^8.25.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-10-08 02:56:55 +00:00
renovate[bot] 3e6a6367cc chore: update dependency loopback-connector to ^5.1.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-29 22:52:49 +00:00
renovate[bot] 91e255d850 chore: update dependency typescript to ^4.8.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-28 01:37:30 +00:00
renovate[bot] 1d2d6cb4e1 chore: update dependency eslint to ^8.24.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-24 03:25:20 +00:00
renovate[bot] b97a28db7b chore: update dependency inflection to ^1.13.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-18 12:01:43 +00:00
renovate[bot] 3a1dca1e87 chore: update dependency eslint to ^8.23.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-12 12:52:25 +00:00
renovate[bot] 70e859fa66 chore: update dependency typescript to ^4.8.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-09-09 02:28:36 +00:00
renovate[bot] ed951a6a61 chore: update dependency @commitlint/cli to ^17.1.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-29 16:26:32 +00:00
renovate[bot] e9b42dcd74 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-29 02:58:06 +00:00
renovate[bot] f45c92c1f8 chore: update commitlint monorepo
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-27 13:18:35 +00:00
renovate[bot] 82f11f0235 chore: update dependency eslint to ^8.23.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-27 05:44:39 +00:00
renovate[bot] 49cb048a45 chore: update dependency typescript to ^4.8.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-26 04:57:11 +00:00
Rifa Achrinza 837240b7f9 fix: missing serialisation for `Connector.update`
closes https://github.com/loopbackio/loopback-datasource-juggler/issues/1971

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-08-22 08:08:58 +00:00
renovate[bot] 12a502b097 chore: update dependency bson to ^4.7.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-18 22:37:25 +00:00
renovate[bot] 30d27f00c4 chore: update dependency eslint to ^8.22.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-15 06:26:55 +00:00
renovate[bot] 00a0693db0 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-15 03:32:08 +00:00
renovate[bot] a0659aefa0 chore: update dependency eslint to ^8.21.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-08 11:52:02 +00:00
renovate[bot] 5f1888b41a chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-08 05:21:22 +00:00
renovate[bot] 4bc39fdec1 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-08-01 03:39:53 +00:00
renovate[bot] caea97e3f5 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-25 04:23:10 +00:00
renovate[bot] 15b1335250 chore: update dependency eslint-plugin-mocha to ^10.1.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-20 12:47:19 +00:00
renovate[bot] 9b8123a14c chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-18 04:17:50 +00:00
renovate[bot] ed1c5079f6 chore: update dependency eslint to ^8.20.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-16 23:13:17 +00:00
renovate[bot] 53942e621a chore: update dependency eslint to ^8.19.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-11 23:02:20 +00:00
renovate[bot] a1321b9ecb chore: update dependency bson to ^4.6.5
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-11 17:07:57 -04:00
renovate[bot] b84c5201b1 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-07-11 16:58:13 -04:00
renovate[bot] f8d7ca9474 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 10:37:37 +00:00
renovate[bot] 53767a6995 chore: update dependency eslint to ^8.18.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 03:49:55 +00:00
renovate[bot] bc9c4defd1 chore: update dependency typescript to ^4.7.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 03:02:38 +00:00
renovate[bot] 615b95dde9 chore: update dependency qs to ^6.10.5
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 03:02:23 +00:00
renovate[bot] 5dbc0cab83 chore: update dependency async to ^3.2.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 03:02:11 +00:00
renovate[bot] 775cbbf2b9 chore: update commitlint monorepo to ^17.0.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-06-26 02:05:53 +00:00
Renovate Bot a4eb2f0377 chore: update lint packages
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-28 14:36:38 +00:00
Renovate Bot c021fc9abf chore: update dependency typescript to ^4.7.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-28 07:38:13 +00:00
Renovate Bot d9eac14926 chore: update commitlint monorepo to v17
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-27 20:45:24 -04:00
Renovate Bot 2db05f56e1 chore: update dependency minimatch to ^5.1.0
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-27 20:44:11 -04:00
Renovate Bot ba09182cea chore: update dependency nanoid to ^3.3.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-21 16:57:56 +00:00
Renovate Bot be09d5774e chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-20 20:30:37 +00:00
Renovate Bot 21ea203a58 chore: update dependency bson to ^4.6.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-20 07:38:46 +00:00
Renovate Bot 2fcbb1bd77 chore: update lint packages
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-19 12:48:41 +00:00
Renovate Bot b4c5e22403 chore: update commitlint monorepo
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-05-19 06:05:22 +00:00
Renovate Bot 3f39054504 chore: update dependency bson to ^4.6.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-20 16:08:25 +00:00
Renovate Bot 9a6d0d83ca chore: update dependency nanoid to ^3.3.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-18 14:49:20 +00:00
Renovate Bot f30fd1819c chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-18 06:30:04 +00:00
Renovate Bot 6aef060d52 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-11 17:22:12 +00:00
Renovate Bot b3b5dc2cd5 chore: update dependency minimatch to v5
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 17:18:45 +00:00
Renovate Bot 5665ff69d5 chore: lock file maintenance
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 08:01:15 +00:00
Renovate Bot bb577e61b5 chore: update dependency typescript to ^4.6.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-04-01 08:32:00 +00:00
Renovate Bot 6dfa9b859c chore: update dependency nanoid to 3.1.31 [security]
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 05:30:24 +00:00
Renovate Bot bc50aa7c4d chore: update dependency nanoid to ^3.3.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 02:33:18 +00:00
Renovate Bot b810bd88ca chore: update commitlint monorepo
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 02:16:39 +00:00
Renovate Bot 3ebf47c4ea chore: update lint packages
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 01:55:50 +00:00
Renovate Bot 5f6a5d5201 chore: update actions/setup-node action to v3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 23:03:34 +00:00
Renovate Bot e647559995 chore: update actions/checkout action to v3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 23:03:17 +00:00
Renovate Bot de008c40e3 chore: update dependency minimatch to ^3.1.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 16:31:08 +00:00
Renovate Bot c748ad1d26 chore: update dependency bson to ^4.6.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 16:13:35 +00:00
Renovate Bot a935fabcd1 chore: update commitlint monorepo
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 15:48:22 +00:00
Renovate Bot 2f95d901bd chore: update dependency qs to ^6.10.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 15:33:13 +00:00
Renovate Bot 6186b57659 chore: update dependency loopback-connector to ^5.0.1
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 15:31:48 +00:00
Diana Lau d7554634fc docs: add SECURITY.md
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2022-03-29 11:29:49 -04:00
Renovate Bot e3addf9f93 chore: update dependency uuid to ^8.3.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 14:58:27 +00:00
Renovate Bot e30c2c8dbd chore: update dependency lodash to ^4.17.21
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 14:45:47 +00:00
Renovate Bot 8d4de43c8a chore: update dependency inflection to ^1.13.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 10:35:25 +00:00
Renovate Bot 3b92a09e41 chore: update dependency debug to ^4.3.4
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 10:09:39 +00:00
Renovate Bot 26bd2225f1 chore: update dependency change-case to ^4.1.2
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 10:00:04 +00:00
Renovate Bot f60d4b0cca chore: update dependency async to ^3.2.3
Signed-off-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 09:53:07 +00:00
Rifa Achrinza 2cd612c4c3 ci: use shared renovate config
see: https://github.com/loopbackio/cicd/issues/15

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-03-29 09:42:56 +00:00
Rifa Achrinza 07cc90e40f ci: add renovate config
Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-03-27 15:14:30 +00:00
Diana Lau d04a6c13d1 docs: update coc
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2022-03-25 15:43:02 -04:00
Diana Lau 2be3b8be62 docs: add code of conduct
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2022-03-23 16:07:21 -04:00
Rifa Achrinza 92e05e6537
v4.27.1
* fix: remove `geo.d.ts` (Rifa Achrinza)

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-02-22 17:23:54 +08:00
Rifa Achrinza 2691470504 fix: remove `geo.d.ts`
Use of Template Literal Types broke support for older LB4 projects.

Temporarily removing it would have minimal impact as:

1. It was only introduced in the last release
2. It was not usable as-is due to wrong export location

fixes: https://github.com/loopbackio/loopback-datasource-juggler/issues/1909

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-02-22 09:14:38 +00:00
Rifa Achrinza 74d429d52d
v4.27.0
* ci: enable Node.js v17 testing (Rifa Achrinza)
 * feat: add built-in model property types typdef (Rifa Achrinza)
 * chore: replace shortid with nanoid (Mario Estrada)
 * ci: restrict GITHUB_TOKEN permissions (Rifa Achrinza)
 * ci: update pipelines (Rifa Achrinza)
 * chore: update 3.x LTS to End-of-Life (#1888) (Rifa Achrinza)
 * chore: sync v4 EOL withh Node.js v14 EOL (#1876) (Rifa Achrinza)

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2022-02-19 01:40:20 +08:00
Rifa Achrinza fe82f6ac79 ci: enable Node.js v17 testing
Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2021-11-24 18:22:20 +08:00
Rifa Achrinza 816b948ab0 feat: add built-in model property types typdef
Added typdef for:
- Any
- JSON
- Text
- GeoPoint
- DateString

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2021-09-22 19:32:13 +08:00
Mario Estrada e3448fad03 chore: replace shortid with nanoid
Signed-off-by: Mario Estrada <marioestradarosa@yahoo.com>
2021-09-12 18:14:03 +08:00
Rifa Achrinza 9a58695740 ci: restrict GITHUB_TOKEN permissions
Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2021-09-11 14:11:39 +08:00
Rifa Achrinza 5aa2d71a23 ci: update pipelines
Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2021-09-04 04:15:31 +08:00
Rifa Achrinza cc5557bd11
chore: update 3.x LTS to End-of-Life (#1888)
see https://github.com/strongloop/loopback-next/issues/6957

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2021-01-23 10:37:54 -05:00
Rifa Achrinza a0de6bc760
chore: sync v4 EOL withh Node.js v14 EOL (#1876)
see https://github.com/strongloop/loopback-next/issues/6709

Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
2020-11-06 13:00:51 -05:00
Raymond Feng 06428247ad 4.26.0
* Fix value equality test to avoid toString (Raymond Feng)
2020-11-02 09:38:59 -08:00
Raymond Feng 05898ed9f6
Merge pull request #1874 from strongloop/mem-connector-fix
Fix value equality test to avoid toString
2020-11-02 09:36:36 -08:00
Raymond Feng 454fd0f1b2 Fix value equality test to avoid toString
- The where statement can be something like {toString: 'not a function'}
- Avoid object string comparison

Signed-off-by: Raymond Feng <enjoyjava@gmail.com>
2020-10-30 09:15:39 -07:00
Miroslav Bajtoš 1e9ac69f2c
4.25.0
* Update dev dependencies to latest (Miroslav Bajtoš)
 * Update dependencies to latest (Miroslav Bajtoš)
2020-10-19 10:55:12 +02:00
Miroslav Bajtoš d2a594fc08
Merge pull request #1870 from strongloop/update-deps
Update dependencies to latest
2020-10-19 10:53:44 +02:00
Miroslav Bajtoš 8487ee1bc0
Update dev dependencies to latest
- `eslint` to `^7.11.0`
- `mocha` to `^8.1.3`
- `typescript` to `^4.0.3`

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-10-12 09:32:38 +02:00
Miroslav Bajtoš 8c95930cd6
Update dependencies to latest
- `loopback-connector` to  `^5.0.0`
- `strong-globalize` to `^6.0.5`
- `uuid` to `^8.3.1`

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-10-12 09:30:23 +02:00
jannyHou 8031e54fb4 4.20.1
* chore: add test for atomic upsertWithWhere (#1864) (Matteo Padovano)
 * chore: update PR template (#1863) (Diana Lau)
 * update PR template to include DCO (#1859) (Diana Lau)
 * chore: add contributing section to readme (#1858) (Diana Lau)
2020-09-25 12:14:33 -04:00
Matteo Padovano 76acf333fd
chore: add test for atomic upsertWithWhere (#1864)
Introduce the new property atomicUpsertWithWhere for
connector that implement specific method.
See https://github.com/strongloop/loopback-connector-mongodb/pull/563
for mongodb implementation.

Signed-off-by: Matteo Padovano <mrbatista@users.noreply.github.com>
2020-09-25 10:22:03 -04:00
Diana Lau 261dd1c865
chore: update PR template (#1863)
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2020-08-18 12:03:23 -04:00
Diana Lau c80aa9abe8
update PR template to include DCO (#1859)
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2020-08-06 14:25:51 -04:00
Diana Lau 35e032d1df
chore: add contributing section to readme (#1858)
Signed-off-by: Diana Lau <dhmlau@ca.ibm.com>
2020-08-06 09:35:07 -04:00
Miroslav Bajtoš a0f1d4a979
4.24.0
* Update .travis.yml (#1841) (karanssj4)
 * Add more `dataSource.execute()` flavors (Miroslav Bajtoš)
2020-08-04 16:35:43 +02:00
Miroslav Bajtoš dd23a14b24
Merge pull request #1857 from strongloop/feat/execute-db-command
feat: improve `dataSource.execute` to support more flavors
2020-08-04 16:34:49 +02:00
karanssj4 7835a43cce
Update .travis.yml (#1841)
drop v13 ad and add node v14
2020-08-03 22:21:36 -04:00
Miroslav Bajtoš c884c62b3b
Add more `dataSource.execute()` flavors
Implement support for the following variants:

- `execute(collection, command, ...params, options)` (MongoDB)
- `execute(...params)` (forward-compatibility & other databases)

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-08-03 15:00:30 +02:00
Miroslav Bajtoš c24e498191
4.23.0
* types: support no-SQL styles of `ds.execute` (Miroslav Bajtoš)
2020-07-28 10:40:49 +02:00
Miroslav Bajtoš 6e6a3df9f0
Merge pull request #1855 from strongloop/types/execute-nosql
types: support non-SQL styles of `ds.execute`
2020-07-28 10:39:50 +02:00
Miroslav Bajtoš f13d50ea3f
types: support no-SQL styles of `ds.execute`
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-07-28 10:01:34 +02:00
Miroslav Bajtoš 0ba09a1c4f
4.22.0
* types: add `DataSource.definitions` property (khlilturki97@gmail.com)
2020-07-27 11:02:15 +02:00
Miroslav Bajtoš b9929b83fe
Merge pull request #1844 from khlilturki97/add_attribute_to_datasource
Add definition attribute to datasource
2020-07-27 10:08:54 +02:00
khlilturki97@gmail.com b1cd7eff5c
types: add `DataSource.definitions` property 2020-07-27 09:50:33 +02:00
Miroslav Bajtoš 8d1690e9b2
4.21.2
* types: allow no `models` argument for automigrate (Miroslav Bajtoš)
2020-05-12 16:43:59 +02:00
Miroslav Bajtoš 259c0b9cc6
Merge pull request #1839 from strongloop/fix-types/datasource-migrate
types: allow no `models` argument for automigrate
2020-05-12 16:43:34 +02:00
Miroslav Bajtoš 4c53abad32
types: allow no `models` argument for automigrate
Fix type definitions to allow zero-argument invocation of
the following database migration methods:
  - `DataSource.automigrate()`
  - `DataSource.autoupdate()`

Implementation-wise, when no model names are specified, then ALL models
attached to the datasource are migrated.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-05-12 15:39:47 +02:00
Miroslav Bajtoš 429d13e537
4.21.1
* types: make DataSource.stop compatible with LB4 (Miroslav Bajtoš)
2020-04-28 09:04:42 +02:00
Miroslav Bajtoš a25df6ac36
Merge pull request #1838 from strongloop/fix/stop-typings
types: make DataSource.stop compatible with LB4
2020-04-28 09:04:02 +02:00
Miroslav Bajtoš 7292d206e5
types: make DataSource.stop compatible with LB4
Change the return value of `DataSource.stop()` from `Promise<void>`
to `void | PromiseLike<void>` to avoid breaking existing LoopBack 4
applications, where DataSource subclasses are scaffolded with
`stop(): ValueOrPromise<void>`.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-28 08:27:49 +02:00
Miroslav Bajtoš 4c665cd6f7
4.21.0
* feat: implement DataSource.stop() (Miroslav Bajtoš)
 * Add __parent reference to embedded models (Dimitris Xalatsis)
2020-04-27 13:43:49 +02:00
Miroslav Bajtoš 74c6776575
Merge pull request #1835 from strongloop/feat/datasource-stop
feat: implement DataSource.stop()
2020-04-27 13:42:58 +02:00
Miroslav Bajtoš c83f82d5a0
feat: implement DataSource.stop()
Implement `stop` as an alias for `disconnect`. This way LB4 applications
don't have to include custom `stop` implementation in every datasource
file.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-23 16:20:44 +02:00
Miroslav Bajtoš e026b4c4af
Merge pull request #1834 from strongloop/embedded-parent2
Add __parent reference to embedded models
2020-04-17 13:58:56 +02:00
Dimitris Xalatsis 095ddd654e
Add __parent reference to embedded models
Add a new hidden property `__parent` that's automatically set on all
instances of embedded models.

For backwards compatibility, this feature is not enabled by default.
You can turn it on by adding the following line to `server/server.js`
file:

    app.registry.modelBuilder.settings.parentRef = true;
2020-04-17 13:35:42 +02:00
Miroslav Bajtoš 9bcf42488d
4.20.0
* Add mocharc, remove mocha.opts (Miroslav Bajtoš)
 * Update dev dependencies (Miroslav Bajtoš)
 * Drop support for Node 8.x (Miroslav Bajtoš)
 * Add support for Node.js 13.x (Miroslav Bajtoš)
 * mark idColumnName as a deprecated function (Agnes Lin)
 * Move List.prototype.toItem out of inner init (#1828) (Dimitris Halatsis)
 * deps: update uuid to v7 (Miroslav Bajtoš)
2020-04-17 09:43:24 +02:00
Miroslav Bajtoš 280228960a
Merge pull request #1832 from strongloop/update-deps
Update dev dependencies + rework Mocha config
2020-04-06 08:53:36 +02:00
Miroslav Bajtoš 04336a60cf
Add mocharc, remove mocha.opts
Mocha has deprecated `mocha.opts` in favour of RC files. See also
https://mochajs.org/#configuring-mocha-nodejs

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-06 08:21:47 +02:00
Miroslav Bajtoš b1766518a8
Update dev dependencies
- mocha to 7.x
- nyc to 15.x

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-06 08:21:47 +02:00
Miroslav Bajtoš f1f7bf2031
Merge pull request #1831 from strongloop/update-node-versions
Update node versions
2020-04-06 08:20:48 +02:00
Miroslav Bajtoš 6d65afc35f
Drop support for Node 8.x
Node 8.x is no longer maintained by Node.js project.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-03 09:38:13 +02:00
Miroslav Bajtoš c6e8779a06
Add support for Node.js 13.x
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-04-03 09:37:28 +02:00
Agnes Lin df1c8dc00e
Merge pull request #1830 from strongloop/deprecated-idcol
mark idColumnName as deprecated
2020-03-25 16:41:13 -04:00
Agnes Lin 9fe64d412c mark idColumnName as a deprecated function 2020-03-25 15:18:34 -04:00
Dimitris Halatsis 8919115439
Move List.prototype.toItem out of inner init (#1828) 2020-03-18 12:52:35 -04:00
Miroslav Bajtoš df394a613b
Merge pull request #1821 from strongloop/update-uuid
deps: update uuid to v7
2020-03-09 16:17:09 +01:00
Miroslav Bajtoš 670a328bc3
deps: update uuid to v7
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-09 13:41:16 +01:00
Miroslav Bajtoš bf931b50c2
4.19.2
* README: move 3.x to Maintenance LTS (Miroslav Bajtoš)
 * README: extend 4.x LTS to match Node.js 12.x (Miroslav Bajtoš)
2020-03-05 16:46:57 +01:00
Miroslav Bajtoš d94327a8f4
Merge pull request #1827 from strongloop/update-lts-status
Update LTS status
2020-03-05 16:46:30 +01:00
Miroslav Bajtoš 376315b7a4
4.19.1
* chore: improve Listener signature (Hage Yaapa)
2020-03-05 10:01:53 +01:00
Hage Yaapa 2946c5b489 chore: improve Listener signature
Improved Listener signature so it can accept callback or promise.
2020-03-05 14:30:24 +05:30
Miroslav Bajtoš 39daef79d8
README: move 3.x to Maintenance LTS
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-05 09:57:33 +01:00
Miroslav Bajtoš cdbe715acc
README: extend 4.x LTS to match Node.js 12.x
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-05 09:56:56 +01:00
Miroslav Bajtoš a50b3db6e9
4.19.0
* fixup! improve comment for `this` & static members (Miroslav Bajtoš)
 * Add ObserverMixin members to ModelBase typings (Miroslav Bajtoš)
 * Add default generic arg value to `Listener` type (Miroslav Bajtoš)
 * feat: add OperationHookContext interface (Hage Yaapa)
2020-03-05 09:54:48 +01:00
Miroslav Bajtoš 33884062f4
Merge pull request #1823 from strongloop/feat/fix-observer-api
Add ObserverMixin to ModelBase typings
2020-03-02 15:10:03 +01:00
Miroslav Bajtoš b01cd74b19
fixup! improve comment for `this` & static members
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-02 13:04:01 +01:00
Miroslav Bajtoš c7b88e9b8e
Add ObserverMixin members to ModelBase typings
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-02 11:54:48 +01:00
Miroslav Bajtoš 65a358656f
Merge pull request #1825 from strongloop/fix/listener-type
Add default generic arg value to `Listener` type
2020-03-02 11:49:18 +01:00
Miroslav Bajtoš 92654f646b
Add default generic arg value to `Listener` type
The changes introduced by dcfda58 may break existing consumers
of our typings. This commit fixes this problem by adding a default
value to the recently introduced generic argument of `Listener` type.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2020-03-02 11:26:01 +01:00
Hage Yaapa dcfda58fda feat: add OperationHookContext interface
Added OperationHookContext interface.

Signed-off-by: Hage Yaapa <hage.yaapa@in.ibm.com>
2020-02-28 21:47:27 +05:30
Diana Lau 36303b3b63 4.18.1
* allows diff db cols naming conventions 4 discover (Agnes Lin)
2020-01-29 14:25:12 -05:00
Agnes Lin f4ec02b316
Merge pull request #1819 from strongloop/discover-naming
feat: allows different naming conventions for db  columns for discover
2020-01-29 13:57:44 -05:00
Agnes Lin baeb76e911 allows diff db cols naming conventions 4 discover 2020-01-29 13:26:16 -05:00
Diana Lau 3a08b9d9ae 4.18.0
* Update copyright year and CODEOWNERS (#1818) (Diana Lau)
 * add warning strict cannot be false with SQL dbs (Agnes Lin)
 * feat: add persistDefaultValues (#1813) (Hage Yaapa)
2020-01-21 13:14:25 -05:00
Diana Lau 251ced811b
Update copyright year and CODEOWNERS (#1818)
* chore: update CODEOWNERS

* chore: update copyright years
2020-01-21 13:12:14 -05:00
Agnes Lin d2b4d567d9
Merge pull request #1817 from strongloop/relational-strict
fix: warn about strict cannot be false with relational dbs
2020-01-21 11:17:10 -05:00
Agnes Lin ad3e1e8d8a add warning strict cannot be false with SQL dbs
this is only for LB4
2020-01-21 09:02:47 -05:00
Hage Yaapa b6f9e92ef8 feat: add persistDefaultValues (#1813)
Ignores value if it matches default value.
2019-12-17 10:52:15 -05:00
Miroslav Bajtoš d19e189fd7
4.17.0
* Fix typo introduced by 19048cd7 (Miroslav Bajtoš)
 * [BUGFIX] Fix issue with with array constructor (Jeremy Nagel)
 * Fix Promise/Callback variants in datasource types (Miroslav Bajtoš)
 * chore: update async to v3.x (Miroslav Bajtoš)
 * chore: update strong-globalize to 5.x (Miroslav Bajtoš)
 * chore: update eslint to 6.x (Miroslav Bajtoš)
 * return failed promise on error (Dimitris Xalatsis)
2019-12-06 14:00:50 +01:00
Miroslav Bajtoš a456700ea2
Merge tag 'v4.16.0'
Merge v4.16.0 release that was accidentally not merged to master
at publishing time.
2019-12-06 13:56:47 +01:00
Miroslav Bajtoš af4f4dfa87
Merge pull request #1808 from strongloop/fix/typo
Fix typo introduced by 19048cd7
2019-12-06 13:41:36 +01:00
Miroslav Bajtoš abdd5675b0
Fix typo introduced by 19048cd7
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-12-06 10:35:19 +01:00
Miroslav Bajtoš 002137dd5d
Merge pull request #1799 from jeznag/fix-issue-with-new-array
Fix issue with broken compatibility with array constructor
2019-12-06 10:18:17 +01:00
Jeremy Nagel b328934b6c [BUGFIX] Fix issue with with array constructor
- You can do new Array(4) to generate an array with 4 empty items
- Doing the same with list caused an error
- This broke lodash.deepclone
- This PR restores compatibility with the array constructor

Fixes #1798
2019-12-06 10:13:27 +11:00
Miroslav Bajtoš c555dedfeb
Merge pull request #1807 from strongloop/fix/datasource-typings
Fix Promise/Callback variants in datasource types
2019-12-05 17:03:55 +01:00
Miroslav Bajtoš 19048cd716
Fix Promise/Callback variants in datasource types
Remove usage of `PromiseOrVoid`, it makes it difficult to consume
the API via `await`. For each async method, define multiple variants
to correctly describe what's returned when a callback arg was provided
(`void`) and what's returned when called with no callback
(`Promise<T>`).

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-12-05 16:30:22 +01:00
Miroslav Bajtoš 2f867576b6
Merge pull request #1804 from strongloop/update-deps
Update strong-globalize and async to their latest versions
2019-12-03 16:13:52 +01:00
Miroslav Bajtoš 606880bf79
Merge pull request #1803 from strongloop/update-eslint
chore: update eslint to 6.x
2019-12-03 16:13:31 +01:00
Miroslav Bajtoš a9611a0430
chore: update async to v3.x
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-12-03 10:12:32 +01:00
Miroslav Bajtoš 1d4ad278c9
chore: update strong-globalize to 5.x
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-12-03 10:12:10 +01:00
Miroslav Bajtoš 1b7858a857
chore: update eslint to 6.x
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-12-03 10:09:16 +01:00
Miroslav Bajtoš 770f11b3a6
Merge pull request #1790 from mitsos1os/return-promise-on-error
Convert error thrown by a property setter to a rejected promise
2019-11-29 10:15:52 +01:00
Hage Yaapa 89503bb233 4.16.0
* feat: applyDefaultOnWrites in nested properties (Hage Yaapa)
 * chore: disable security issue reporting (Nora)
2019-11-28 14:13:49 +05:30
Hage Yaapa 89a964e919 feat: applyDefaultOnWrites in nested properties
Adds support for `applyDefaultOnWrites` in nested properties.
2019-11-28 13:59:47 +05:30
Dimitris Xalatsis b30fbf8c1e return failed promise on error 2019-11-22 19:38:43 +02:00
Nora d54d769477
Merge pull request #1792 from strongloop/chore/improve-issue-templates
chore: disable security issue reporting
2019-11-19 01:17:05 -05:00
Miroslav Bajtoš f921a4f630
4.15.0
* Fix generated string id's (Francisco Buceta)
 * Remove loopback-connector-ibmi from downstream (Miroslav Bajtoš)
2019-11-18 08:34:56 +01:00
Miroslav Bajtoš 5578ab4ea7
Merge pull request #1783 from frbuceta/fix/lb4-issue-3602
Fix issue with lb4 id different to int
2019-11-18 08:34:06 +01:00
Nora a1817a40e6 chore: disable security issue reporting 2019-11-15 20:50:45 -05:00
Francisco Buceta b9f0284a28
Fix generated string id's
Co-authored-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-11-15 16:15:38 +01:00
Miroslav Bajtoš b07bdfc71a
Merge pull request #1791 from strongloop/ci/skip-ibmi-downstream
chore: remove loopback-connector-ibmi from downstream list
2019-11-05 17:32:38 +01:00
Miroslav Bajtoš 28d457d357
Remove loopback-connector-ibmi from downstream
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-11-05 17:22:34 +01:00
Diana Lau 8b75767daf 4.14.0
* fix #1781 (#1782) (Dimitris Halatsis)
 * Introduce issue templates for bugs, features, etc. (Miroslav Bajtoš)
 * Improve PULL_REQUEST_TEMPLATE (Miroslav Bajtoš)
2019-10-21 13:13:03 -04:00
Dimitris Halatsis ab11205fa0 fix #1781 (#1782) 2019-10-21 12:55:14 -04:00
Miroslav Bajtoš 23949703b0
Merge pull request #1779 from strongloop/improve/github-templates
Improve issue & pull-request templates
2019-10-08 08:17:40 +02:00
Miroslav Bajtoš 063e0f173f
Introduce issue templates for bugs, features, etc.
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-10-07 10:58:14 +02:00
Miroslav Bajtoš 071f93762c
Improve PULL_REQUEST_TEMPLATE
Make it easier for contributors to mix the text provided by GitHub
from the commit messages with the template content.

Rework the checklist to follow the style we use in loopback-next.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-10-07 10:58:07 +02:00
Raymond Feng 15251880a1 4.13.0
* Fix typescript typing for DataSource.getModel (Raymond Feng)
2019-09-19 13:08:16 -07:00
Raymond Feng 8946516614
Merge pull request #1778 from strongloop/fix-datasource-getmodel-typing
Fix typescript typing for DataSource.prototype.getModel()
2019-09-19 13:05:50 -07:00
Raymond Feng 1e8b8a041b Fix typescript typing for DataSource.getModel
See https://github.com/strongloop/loopback-next/pull/3722
2019-09-19 09:25:24 -07:00
Diana Lau ad1777fcd3 4.12.1
* chore: reduce identifier length (Hage Yaapa)
2019-09-04 11:55:36 -04:00
Hage Yaapa 6f491dc756 chore: reduce identifier length
Existing identifier length exceeds Oracle DB's limit
2019-09-03 20:46:08 +05:30
Diana Lau fa7c38cad8 4.12.0
* feat: add applyDefaultOnWrites property (Hage Yaapa)
 * Fix polymorphic hasMany inverse relation (#1621) (Ayeni Olusegun)
2019-08-19 12:13:47 -04:00
Hage Yaapa 464610ef0a feat: add applyDefaultOnWrites property
Adds the ability to ignore writing default values to the database.
2019-08-19 17:11:27 +05:30
Ayeni Olusegun 814c55c7cd Fix polymorphic hasMany inverse relation (#1621)
* Polymorphic hasMany inverse relation

* rename test suit to eslint error
2019-08-12 15:30:28 -04:00
Diana Lau ac955826f5 4.11.0
* fix: prevent max listeners warning (Dominique Emond)
2019-08-09 13:23:25 -04:00
Nora a90dc0eac4
Merge pull request #1767 from strongloop/dremond_migrate_errors
fix: prevent max listeners warning
2019-08-09 09:18:38 -04:00
Dominique Emond bca631518b fix: prevent max listeners warning
If establishing a database connection is slow
and database migration runs and there are many
models, sql operations are queued up and this
leads to the node.js max emitters exceeded
warning.

A default value for max emitters has now
been introduced, and it can also be configured
in datasources.json.

Co-authored-by: Dominique Emond <dremond@ca.ibm.com>
2019-08-09 09:03:51 -04:00
Miroslav Bajtoš ad4edc6a15
4.10.1
* Fix coercion of PK value in `replaceById` method (Miroslav Bajtoš)
 * Fix autoupdate queueing automigrate instead (#1762) (darthmaim)
2019-07-26 09:22:59 +02:00
Miroslav Bajtoš 74c43ca358
Merge pull request #1763 from strongloop/fix/PK-coercion-in-replaceById
Fix coercion of PK value in `replaceById` method
2019-07-26 09:22:27 +02:00
Miroslav Bajtoš f1fa976f50
Fix coercion of PK value in `replaceById` method
Before this change, when both the PK value (`id`) and the `data` object
were provided as plain-data values (e.g. as received in a JSON request),
and the connector was using a complex PK type (e.g. `ObjectID`
in MongoDB), then `replaceById` operation was printing confusing
warnings:

    WARNING: id property cannot be changed from 5d39775a59f5f541513c5e05
        to 5d39775a59f5f541513c5e05 for model:Post
        in 'before save' operation hook

    WARNING: id property cannot be changed from 5d39775a59f5f541513c5e05
        to 5d39775a59f5f541513c5e05 for model:Post
        in 'loaded' operation hook

This commit fixes the problem by applying the same type coercion on the
PK value (`id`) as has been applied by the model constructor on the PK
property (`data.id`).

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-07-26 09:02:52 +02:00
darthmaim dd7167b533 Fix autoupdate queueing automigrate instead (#1762)
Fixes #1761
2019-07-25 14:17:34 -04:00
Miroslav Bajtoš ca4ede014e
4.10.0
* fix: use only promises for beginTransaction (Biniam Admikew)
 * feat: add DataSource.deleteAllModels() API (Miroslav Bajtoš)
2019-07-23 16:48:45 +02:00
Biniam Admikew 6b83b6f4d1
Merge pull request #1760 from strongloop/fix/begintransaction-api
fix: use only promises for beginTransaction
2019-07-19 11:11:58 -04:00
Biniam Admikew e3c276720f fix: use only promises for beginTransaction
Co-authored-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-07-19 10:30:10 -04:00
Miroslav Bajtoš 6478c73dde
Merge pull request #1759 from strongloop/feat/reset-datasource
feat: add DataSource.deleteAllModels() API
2019-07-18 18:22:37 +02:00
Miroslav Bajtoš 78c5b12740
feat: add DataSource.deleteAllModels() API
When writing tests, for performance reasons we often want to reuse
the same data-source instance for many tests suites. At the same time,
we want to keep such test suites independent and allow them to reuse
the same model name for different model classes.

Juggler does support redefinition of a model with the same name.

This change is adding a new API called that allows tests to remove all
old models before creating new ones. This API would be typically
called from a `before` hook.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-07-18 17:56:41 +02:00
Biniam Admikew 6aea50ad27 4.9.0
* fix: report errors from automigrate/autoupdate (Miroslav Bajtoš)
 * feat: add beginTransaction API on datasource (Biniam Admikew)
 * Revert "chore: expose beginTransaction API" (Biniam Admikew)
2019-07-15 17:27:53 -04:00
Miroslav Bajtoš 0c2bb81dac
Merge pull request #1756 from strongloop/fix/migrate-errors
fix: report errors from automigrate/autoupdate
2019-07-04 13:51:36 +02:00
Miroslav Bajtoš 40286fcd28
fix: report errors from automigrate/autoupdate
Defer automigrate/autoupdate until we are connected, so that connection
errors can be reported back to callers.

Fix postInit handler to not report connection error to console.log
and via dataSource "error" event in case there is already an operation
queued. When this happens, we want the error to be handled by the
queued operation and reported to its caller.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-07-04 12:36:50 +02:00
Biniam Admikew c3103a2077
Merge pull request #1753 from strongloop/feat/ds-begintransaction
add `beginTransaction` method to DataSource class
which calls `begin` method from the Transaction class
which in turn invokes the connector's `beginTransaction`
method if it supports transactions.
2019-06-28 15:06:49 -04:00
Biniam Admikew 1ed385e393 feat: add beginTransaction API on datasource
add beginTransaction method which calls begin
method from the Transaction class which in turn
calls the connector's beginTransaction method if
it supports transactions.

Co-Authored-By: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-06-28 12:58:50 -04:00
Biniam Admikew 39555a010a Revert "chore: expose beginTransaction API"
This reverts commit 313925a5e7.
2019-06-25 09:08:11 -04:00
Biniam Admikew 85a29caaa5 4.8.2
* chore: expose beginTransaction API (Biniam Admikew)
 * update LTS in README (#1751) (Diana Lau)
2019-06-24 22:48:21 -04:00
Biniam Admikew 5539ef7ac6
Merge pull request #1752 from strongloop/update/ds-declaration-file
chore: add beginTransaction API to declaration file
2019-06-24 18:06:46 -04:00
Biniam Admikew 313925a5e7 chore: expose beginTransaction API 2019-06-24 17:16:31 -04:00
Diana Lau 612cf05fdf
update LTS in README (#1751) 2019-06-21 21:15:56 -04:00
jannyHou 19e7a47489 4.8.1
* test: add property index to support cloudant (#1750) (Janny)
2019-06-20 11:43:46 -04:00
Janny 58b3c4f148
test: add property index to support cloudant (#1750) 2019-06-19 14:36:48 -04:00
Miroslav Bajtoš d49774c590
4.8.0
* Fix types to describe native Promise (Miroslav Bajtoš)
 * feat: after operation hook in case of errors (spurreiter)
 * Fix for #1724 - Added options to attribute updates (#1725) (Bill Matson)
2019-06-13 15:38:11 +02:00
Miroslav Bajtoš 5fcad43aab
Merge pull request #1749 from strongloop/fix/typings
Fix types to describe native Promise
2019-06-13 15:37:40 +02:00
Miroslav Bajtoš df4d89279a
Fix types to describe native Promise
In version 4.0.0, we switched from Bluebird to native Promises.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-06-13 15:24:01 +02:00
Miroslav Bajtoš acb667b73d
Merge pull request #1694 from spurreiter/operation-hook-error
feat: call after operation hook in case of errors
2019-06-01 11:33:53 +02:00
spurreiter 5b44c08f7a feat: after operation hook in case of errors
fix: move error into context

review: add debug statement; rename fns

fix: call next instead of ctx.end
2019-05-31 17:12:42 +02:00
Bill Matson 04523260c2 Fix for #1724 - Added options to attribute updates (#1725)
* Fix for #1724 - Added options to attribute updates

* Fix for #1724 - Added unit tests for options
2019-05-27 09:49:46 -04:00
Miroslav Bajtoš a5ba7408ff
4.7.1
* Fix "access" hook for unoptimized "near" queries (Miroslav Bajtoš)
 * Fix "loaded" hook for unoptimized "near" queries (Miroslav Bajtoš)
 * Test "near" queries executed in memory (Miroslav Bajtoš)
 * Fix DateString ctor to accept DateString instances (Miroslav Bajtoš)
 * datasource: copy settings object in constructor (Miroslav Bajtoš)
 * chore: update copyrights years (#1737) (Agnes Lin)
 * chore: update LTS status (#1734) (Diana Lau)
2019-05-14 09:48:27 +02:00
Miroslav Bajtoš 413f31631e
Merge pull request #1739 from strongloop/fix/hooks-with-near-queries
Fix implementation of Operation Hooks for "near" (geo) queries
2019-05-14 09:26:16 +02:00
Miroslav Bajtoš aa20180c4f
Fix "access" hook for unoptimized "near" queries
Before this change, when an "access" hook modified the "query" object,
the "near" condition from the original "query" object were still
applied. As a result, the query can end up being more restrictive and
return only a subset of models that should have matched the conditions.

With this change in place, after "access" hook observers are invoked,
we update the "near" condition using the "query" object provided by
hook observers.

Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-05-14 09:17:54 +02:00
Miroslav Bajtoš 344441d48d
Fix "loaded" hook for unoptimized "near" queries
Before this change, two "loaded" events were emitted for every model
instance found. This commit fixes the problem and restores the intended
behavior.

The bug was probably introduced by 5e0c73bec7.
2019-05-14 09:17:54 +02:00
Miroslav Bajtoš caf9d09274
Test "near" queries executed in memory
Rework setup of the Operation Hooks test suite for memory connector
so that the "unoptimized" variant disables not only atomic CRUD
operations, but also geo queries.

This way we can test both "near" querying implementations:
 - When the connectors supports "near" queries natively.
 - When "near" queries are executed at LoopBack side in-memory.
2019-05-14 09:14:10 +02:00
Miroslav Bajtoš 853a41641b
Merge pull request #1740 from strongloop/fix/datestring-ctor
Fix DateString constructor to accept DateString instances
2019-05-13 16:07:40 +02:00
Miroslav Bajtoš 5369cf3d54
Fix DateString ctor to accept DateString instances
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
2019-05-13 15:21:00 +02:00
Miroslav Bajtoš 91ab3e9162
Merge pull request #1738 from strongloop/fix/modification-of-datasource-config
datasource: copy settings object in constructor
2019-05-10 16:01:39 +02:00
Miroslav Bajtoš ef0257e338
datasource: copy settings object in constructor
Fix DataSource constructor to create a shallow copy of the settings
object provided by the caller. This prevents surprising behavior
where changes made to `ds.settings` were picked up by the provided
config object, as observed e.g. in tests of our MongoDB connector.
2019-05-10 14:56:02 +02:00
Agnes Lin de4718d5b8 chore: update copyrights years (#1737) 2019-05-08 11:45:37 -04:00
Diana Lau 98eb783a80
chore: update LTS status (#1734) 2019-05-06 13:27:52 -04:00
biniam 2aa4d20394 4.7.0
* fix: allow coercion of nested properties (biniam)
2019-05-03 19:15:10 -04:00
Biniam Admikew 0b871d1de1
Merge pull request #1727 from strongloop/fix/nested-property-coercion-4x
fix: allow coercion of nested properties

Handle model definitions with nested property
definitions for coercion of primitive values.
2019-05-03 19:08:53 -04:00
biniam 9c94b9344b fix: allow coercion of nested properties
Handle model definitions with nested property
definitions for coercion of primitive values.
2019-05-03 18:45:39 -04:00
Miroslav Bajtoš 3fba79e725
4.6.4
* Fix tests for empty/default values to pass on SQL (Miroslav Bajtoš)
 * Update nyc to 14.0.0 (Miroslav Bajtoš)
 * test: define models in before hooks (biniam)
 * Update `should` to `13.2.3` (Miroslav Bajtoš)
 * Update `mocha` to `6.1.4` (Miroslav Bajtoš)
2019-05-03 09:04:42 +02:00
Miroslav Bajtoš 78c4bfbc2d
Merge pull request #1733 from strongloop/fix/postgresql
Fix tests for empty vs. default values to pass on SQL
2019-05-03 09:04:08 +02:00
Miroslav Bajtoš b0e3de1083
Fix tests for empty/default values to pass on SQL 2019-05-03 08:57:48 +02:00
Miroslav Bajtoš 08e8725ba5
Merge pull request #1732 from strongloop/update-nyc
Update nyc to 14.0.0
2019-05-02 13:24:58 +02:00
Miroslav Bajtoš 837c74d08e
Update nyc to 14.0.0 2019-05-02 13:01:10 +02:00
Biniam Admikew 6677c58cff
Merge pull request #1721 from strongloop/fix/failing-tests
test: define models properly
2019-04-30 11:50:10 -04:00
biniam eff6458a2a test: define models in before hooks
Re-work tests from #1702 based on the failures observed in #1719
and cherry-pick those commits back to master using ES6 syntax.
2019-04-30 11:15:23 -04:00
Miroslav Bajtoš 0bba44ee29
Merge pull request #1730 from strongloop/update-deps
Update `mocha` and `should` to latest
2019-04-30 12:10:34 +02:00
Miroslav Bajtoš 76673a8ed8
Update `should` to `13.2.3` 2019-04-30 11:44:08 +02:00
Miroslav Bajtoš 511c4763d3
Update `mocha` to `6.1.4` 2019-04-30 11:44:00 +02:00
Miroslav Bajtoš 88312422d8
4.6.3
* Add support for Node.js 12.x (Miroslav Bajtoš)
 * fix: coerce primitive properties on update (biniam)
 * fix: coerce date array properties (biniam)
 * fix: normalize include with boolean or number (spurreiter)
2019-04-30 10:52:46 +02:00
Miroslav Bajtoš 6793be20ca
Merge pull request #1728 from strongloop/chore/add-node-12
Add support for Node.js 12.x
2019-04-30 09:09:37 +02:00
Miroslav Bajtoš 5c3405eceb
Add support for Node.js 12.x
- Fix code to pass all tests on Node.js 12
- Add Node.js 12 to the list of Travis CI platforms
2019-04-29 09:46:57 +02:00
Biniam Admikew 47addd943a
Merge pull request #1702 from strongloop/fix/nested-property-resolution
fix: primitive data type coercion
2019-04-16 12:00:24 -04:00
biniam 48af738ec4 fix: coerce primitive properties on update 2019-04-16 10:51:44 -04:00
biniam 1534392c62 fix: coerce date array properties 2019-04-16 10:50:54 -04:00
Miroslav Bajtoš fe83f3cfd1
Merge pull request #1581 from spurreiter/include-crashes
fix: normalize include with boolean or number
2019-04-12 17:05:02 +02:00
jannyHou b3945fcd33 4.6.2
* chore: update CODEOWNERS (#1712) (Diana Lau)
 * fix: ignore git file (#1714) (Janny)
 * remove kv-extreme-scale ctor from downstream test (#1710) (Diana Lau)
2019-04-10 11:59:45 -04:00
Diana Lau 11f9c1f23a
chore: update CODEOWNERS (#1712) 2019-04-10 11:07:55 -04:00
Janny b4d89fc7c5
fix: ignore git file (#1714) 2019-04-10 10:51:21 -04:00
Diana Lau 7288277e87
remove kv-extreme-scale ctor from downstream test (#1710) 2019-04-10 10:20:38 -04:00
Miroslav Bajtoš 095fe62fa6
4.6.1
* Improve tests for empty vs. default values (Miroslav Bajtoš)
 * Do not apply default values on data from database (Miroslav Bajtoš)
 * Update datasource-connector.md (#1703) (Jam Risser)
 * feat: support array within array (Hage Yaapa)
 * fix: update lodash (#1696) (Janny)
2019-04-09 18:20:02 +02:00
Miroslav Bajtoš a8d0d78913
Merge pull request #1707 from strongloop/test/fix-default-values
Improve tests for empty vs. default values
2019-04-09 18:12:40 +02:00
Miroslav Bajtoš 7d69bdab70
Improve tests for empty vs. default values 2019-04-09 15:54:52 +02:00
spurreiter 55b10a43c4 fix: normalize include with boolean or number
- On include = true or include = 1 the lib crashes with
  "TypeError: includes.forEach is not a function".
- checking for boolean and number type and return empty array.
- fix: include symbol and function in normalization
- fix: review changes; adding debug stmt + early exit for tests
2019-04-05 19:02:57 +02:00
Miroslav Bajtoš 84eee5a69e
Merge pull request #1704 from strongloop/fix/default-value-in-response
fix: do not apply default values on data from database
2019-04-04 10:10:23 +02:00
Miroslav Bajtoš e45292de08
Do not apply default values on data from database
Before this change, when a property was configured with a default value
at LoopBack side and the database was returned a record with a missing
value for such property, then we would supply use the configured
default.

This behavior is problematic for reasons explained in #1692.

In this commit, we are fixing DAO operations like `find` and
`findOrCreate` so that they do NOT apply default property values on
data returned by the database (connector).

Please note that most of the other CRUD methods were already not
applying default values on database data as long as the connector
provided native implementation of the operation.
2019-04-04 09:47:31 +02:00
Jam Risser ff5a3fa8bf Update datasource-connector.md (#1703)
Corrected typo in docs
2019-03-28 16:34:35 -04:00
Hage Yaapa 3f9448f5d2
Merge pull request #1699 from strongloop/fix/list-format
feat: support array within array
2019-03-19 19:06:08 +05:30
Hage Yaapa 80d8fcd8b1 feat: support array within array 2019-03-07 15:58:26 +05:30
Janny 5a7c0326ab
fix: update lodash (#1696) 2019-03-01 14:29:56 -05:00
Diana Lau ce7194ff6a 4.6.0
* feat: Support "type" key in sub-properties (Hage Yaapa)
 * fix: use correct callback for geo find queries (biniam)
 * fix: update typescript declarations (biniam)
2019-02-26 14:27:50 -05:00
biniam 75a8c6a309 4.5.4
* fix: use correct callback for geo find queries (biniam)
 * fix: update typescript declarations (biniam)
2019-02-26 14:22:13 -05:00
Hage Yaapa 01df3705d1
Merge pull request #1693 from strongloop/feat/type-sub-property
feat: Support "type" key in sub-properties
2019-02-26 20:49:52 +05:30
Hage Yaapa a391c83a2c feat: Support "type" key in sub-properties 2019-02-21 13:58:34 +05:30
Biniam Admikew 70b3bb6aae
Merge pull request #1690 from strongloop/fix/near-filter-cb
Fix callback for find queries with near filters
2019-02-15 11:00:30 -05:00
biniam 5e0c73bec7 fix: use correct callback for geo find queries 2019-02-14 15:45:13 -05:00
Biniam Admikew c7d23d18d0
Merge pull request #1654 from strongloop/fix/types
fix: update typescript declarations
2019-01-31 00:33:19 -05:00
biniam 4b705b127c fix: update typescript declarations 2019-01-31 00:29:35 -05:00
Miroslav Bajtoš 4d288813e2
4.5.3
* Support nested properties with class type (Miroslav Bajtoš)
2019-01-29 15:51:58 +01:00
Miroslav Bajtoš c0a778eeab
Merge pull request #1670 from up-group/master
Enable to target ES6
2019-01-29 15:50:56 +01:00
Miroslav Bajtoš fd99c6dc6e
Support nested properties with class type
When converting plain-data object values into model instances,
correctly handle the case where the constructor functions is a class
constructor and must be invoked via `new`.
2019-01-25 10:05:36 +01:00
Miroslav Bajtoš 4c69781504
4.5.2
* Improve Model type definitions (Miroslav Bajtoš)
 * fix: use existing field in exclude test (biniam)
2019-01-24 16:55:49 +01:00
Miroslav Bajtoš 928747f795
Merge pull request #1685 from strongloop/fix/type-defs
Improve Model type definitions
2019-01-24 16:54:37 +01:00
Miroslav Bajtoš 81fc722b72
Improve Model type definitions
Define two new types: ModelSettings and ModelProperties to describe the
objects describing model properties and settings.

Add static property `base` and static method `extend` to the definition
of `ModelBase` class.

Add property `defaultModelBaseClass` to `ModelBuilder` class definition.

Fix `PropertyDefinition` interface: remove `name`, add optional `id`.
2019-01-24 16:27:40 +01:00
Biniam Admikew 0ec951ee11
Merge pull request #1682 from strongloop/fix/include-test
fix: use existing field in exclude test
2019-01-16 14:33:55 -05:00
biniam 0b81425a13 fix: use existing field in exclude test
Co-authored-by: Raymond Feng <rfeng@us.ibm.com>
2019-01-16 13:24:27 -05:00
Diana Lau d3f63a8ecd 4.5.0
* Revert "5.0.0". It was released accidentally. (Diana Lau)
 * Upgrade eslint-config-loopback to latest (Miroslav Bajtoš)
 * manually fix remaining problems (Miroslav Bajtoš)
 * autofix eslint errors (Miroslav Bajtoš)
 * eslint: enable no-var and prefer-const rules (Miroslav Bajtoš)
 * Update eslint-config-loopback to latest (Miroslav Bajtoš)
 * Update dependencies to latest versions (Miroslav Bajtoš)
 * Upgrade bson to 4.x (latest) (Miroslav Bajtoš)
 * feat: dataSource.execute(cmd, args, opts, cb) (Miroslav Bajtoš)
 * eslint: enable ES2017 (async functions) (Miroslav Bajtoš)
2018-12-14 08:49:17 -05:00
Diana Lau 92499aa152 Revert "5.0.0". It was released accidentally.
This reverts commit caa36a21da.
2018-12-14 08:47:15 -05:00
Diana Lau caa36a21da 5.0.0
* Upgrade eslint-config-loopback to latest (Miroslav Bajtoš)
 * manually fix remaining problems (Miroslav Bajtoš)
 * autofix eslint errors (Miroslav Bajtoš)
 * eslint: enable no-var and prefer-const rules (Miroslav Bajtoš)
 * Update eslint-config-loopback to latest (Miroslav Bajtoš)
 * Update dependencies to latest versions (Miroslav Bajtoš)
 * Upgrade bson to 4.x (latest) (Miroslav Bajtoš)
 * feat: dataSource.execute(cmd, args, opts, cb) (Miroslav Bajtoš)
 * eslint: enable ES2017 (async functions) (Miroslav Bajtoš)
2018-12-14 08:29:22 -05:00
Miroslav Bajtoš 47ef38e9f1
Merge pull request #1675 from strongloop/upgrade-eslint-config
Upgrade eslint-config-loopback to latest
2018-12-07 17:15:44 +01:00
Miroslav Bajtoš 09e2208062
Upgrade eslint-config-loopback to latest 2018-12-07 17:09:10 +01:00
Miroslav Bajtoš bd5fd07d27
Merge pull request #1674 from strongloop/eslint/use-const-not-var
Refactor: migrate from "var" to "const"
2018-12-07 16:56:45 +01:00
Miroslav Bajtoš 9e0f624ad5
manually fix remaining problems 2018-12-07 16:46:15 +01:00
Miroslav Bajtoš 422ec9ad4f
autofix eslint errors 2018-12-07 16:46:15 +01:00
Miroslav Bajtoš 261ca1f092
eslint: enable no-var and prefer-const rules 2018-12-07 16:40:03 +01:00
Miroslav Bajtoš 8684df62a6
Merge pull request #1673 from strongloop/upgrade-deps
Upgrade dependencies to their latest versions
2018-12-07 16:31:17 +01:00
Miroslav Bajtoš 84322d07a9
Update eslint-config-loopback to latest 2018-12-07 16:22:59 +01:00
Miroslav Bajtoš e513c0d355
Update dependencies to latest versions
Skip update of shouldjs to avoid breaking tests in connectors.
2018-12-07 16:22:59 +01:00
Miroslav Bajtoš e834368502
Upgrade bson to 4.x (latest) 2018-12-07 16:22:59 +01:00
Miroslav Bajtoš 0cf0fa95ff
Merge pull request #1671 from strongloop/feat/execute
feat: dataSource.execute(cmd, args, opts, cb)
2018-12-07 16:21:15 +01:00
Miroslav Bajtoš fda332d60b
feat: dataSource.execute(cmd, args, opts, cb)
Implement a new helper API for calling connector's "execute" method
in a promise-friendly way.
2018-12-07 14:51:14 +01:00
Miroslav Bajtoš 3c2669ed7d
eslint: enable ES2017 (async functions) 2018-12-07 14:48:07 +01:00
Raymond Feng 5f713f0319 4.4.0
* Use options from request for settings (Raymond Feng)
2018-11-15 08:21:10 -08:00
Raymond Feng b2cbf99e73
Merge pull request #1662 from strongloop/set-default-remote-options
Use options.remotingContext for conditional settings
2018-11-15 08:19:21 -08:00
Raymond Feng f9131aa18f Use options from request for settings 2018-11-13 12:32:55 -08:00
Raymond Feng 49330322ef 4.3.0
* Allow flags to be passed via options (Raymond Feng)
 * chore: update file list for apidocs (biniam)
2018-11-12 11:35:49 -08:00
Raymond Feng 8f095520f4
Merge pull request #1661 from strongloop/allow-flags-in-options
Allow flags to be passed via options
2018-11-12 11:33:54 -08:00
Biniam Admikew 916d80c36d
Merge pull request #1660 from strongloop/fix/update-apidocs-file-list
chore: update file list for apidocs
2018-11-09 14:30:22 -05:00
Raymond Feng f6e1df87be Allow flags to be passed via options 2018-11-09 09:33:05 -08:00
biniam cc276643a2 chore: update file list for apidocs 2018-11-09 11:59:22 -05:00
Raymond Feng a39cbebf94 4.2.1
* [ BUGFIX ] maxDepthOfQuery config (leon3s)
2018-11-07 12:52:03 -08:00
Raymond Feng 0f0b391f67
Merge pull request #1658 from leon3s/fix-maxDepthOfQuery-config
[ BUGFIX ] maxDepthOfQuery config
2018-11-07 12:50:42 -08:00
leon3s 65548b6fe0 [ BUGFIX ] maxDepthOfQuery config 2018-11-06 17:29:14 +01:00
Raymond Feng f0a6bd146b 4.2.0
* Allow configuration of maxDepthOfQuery (Raymond Feng)
2018-10-31 09:11:58 -07:00
Raymond Feng 35f61c4aa4
Merge pull request #1652 from strongloop/fix-1651
Allow configuration of maxDepthOfQuery
2018-10-31 09:10:03 -07:00
Raymond Feng eb85b3e3a6 Allow configuration of maxDepthOfQuery
https://github.com/strongloop/loopback-datasource-juggler/issues/1651
2018-10-31 08:45:16 -07:00
Raymond Feng 3348d501e8 4.1.2
* Check composite keys containing hidden props (Raymond Feng)
 * Improve hidden/protected property checks (Raymond Feng)
2018-10-29 13:10:37 -07:00
Raymond Feng 7609585dc3
Merge pull request #1649 from strongloop/fix-1645
Improve hidden/protected property checks
2018-10-29 13:09:33 -07:00
Raymond Feng dbe25f282d Check composite keys containing hidden props 2018-10-29 07:57:55 -07:00
Raymond Feng 8fa7c94605 Improve hidden/protected property checks
- Fixes #1645
  - do not apply hidden property check for data
- Fixes #1648
  - allow prohibitHiddenPropertiesInQuery to be set in model/ds
2018-10-28 10:03:12 -07:00
Raymond Feng 8ebb734a31 4.1.1
* Allow hidden/protected props as an object (Raymond Feng)
2018-10-27 07:54:38 -07:00
Raymond Feng 726c6978fc
Merge pull request #1647 from strongloop/fix-1646
Allow hidden/protected props as an object
2018-10-27 07:53:42 -07:00
Raymond Feng 2af2599a7d Allow hidden/protected props as an object
Fixes #1646
2018-10-27 07:51:34 -07:00
Raymond Feng 708826cc49 4.1.0
* Ren handleUndefined to normalizeUndefinedInQuery (Raymond Feng)
 * Report circular or deep query objects (Raymond Feng)
 * Hide offending properties from the error object (Raymond Feng)
 * Tidy up extended operator check (Raymond Feng)
 * Prevent hidden/protected props from being searched (Raymond Feng)
 * Report errors for missing id props for include (Raymond Feng)
 * fix: add test coverage, correct typo that exposed (Matthew Gabeler-Lee)
 * fix: accelerate unique id checking (Matthew Gabeler-Lee)
 * remove null in embedded doc properties updates (Dimitris)
2018-10-26 09:25:30 -07:00
Raymond Feng 104b861747
Merge pull request #1638 from strongloop/exclude-hidden-properties-from-where
Report errors if where clause contains hidden properties
2018-10-26 09:14:08 -07:00
Raymond Feng a391762771 Ren handleUndefined to normalizeUndefinedInQuery 2018-10-26 09:09:50 -07:00
Raymond Feng 0ce3f4ead9 Report circular or deep query objects 2018-10-25 15:14:20 -07:00
Raymond Feng 39ff54d392 Hide offending properties from the error object 2018-10-25 15:14:20 -07:00
Raymond Feng a761e0d114 Tidy up extended operator check 2018-10-25 15:14:14 -07:00
Raymond Feng f2e718639a Prevent hidden/protected props from being searched
- report errors if where contains hidden properties
- report errors if incldue scope contains hidden or protected properties
2018-10-19 09:25:47 -07:00
Raymond Feng f1f535846e
Merge pull request #1642 from strongloop/fix-4028
Report errors for missing id properties for include
2018-10-19 09:21:07 -07:00
Raymond Feng 60e16298f2 Report errors for missing id props for include
https://github.com/strongloop/loopback/issues/4028
2018-10-19 09:20:12 -07:00
Raymond Feng f7036b2837
Merge pull request #1629 from mgabeler-lee-6rs/fix/fast-id-unique-check
fix: accelerate unique id checking
2018-10-14 07:58:35 -07:00
Miroslav Bajtoš abaf29f74d
Merge pull request #1623 from mitsos1os/issue-1622
Fix patchAttributes for embedded document properties in MongoDB
2018-10-09 14:55:56 +02:00
Miroslav Bajtoš c95a969af7
4.0.0
* Update LTS versions in README (Miroslav Bajtoš)
 * Switch from Bluebird to native Promise (Miroslav Bajtoš)
 * Start 4.0 development, drop support for Node 6 (Miroslav Bajtoš)
2018-10-08 08:34:03 +02:00
Miroslav Bajtoš 6e90ec6dcc
Merge pull request #1633 from strongloop/update-lts
Update LTS versions in README
2018-10-08 08:33:08 +02:00
Miroslav Bajtoš 22764a095a
Update LTS versions in README 2018-10-08 08:20:12 +02:00
Miroslav Bajtoš b285737382
Merge pull request #1631 from strongloop/drop-bluebird
[SEMVER-MAJOR] Switch from Bluebird to native Promise
2018-10-08 07:59:48 +02:00
Miroslav Bajtoš b6a43dd65a
Switch from Bluebird to native Promise
This is a breaking change. Juggler methods are no longer returning
instances of Bluebird Promise, but return a native Promise instead.

As a result, API consumers can no longer use sugar APIs provided by
Bluebird, e.g. `spread`, `delay`, etc.

Migration guide: rewrite your code from `.then()` style into `async`
functions using `await` statements.
2018-10-05 09:30:02 +02:00
Miroslav Bajtoš 5eb81aa47f
Merge pull request #1630 from strongloop/start-4.0
[SEMVER-MAJOR] Start 4.0 development, drop support for Node 6
2018-10-04 16:47:12 +02:00
Miroslav Bajtoš 64eddf5d26
Start 4.0 development, drop support for Node 6 2018-10-04 12:07:19 +02:00
Matthew Gabeler-Lee 1ddac5bddb
fix: add test coverage, correct typo that exposed 2018-10-03 18:56:57 -04:00
Matthew Gabeler-Lee 248d57da4e
fix: accelerate unique id checking 2018-10-03 18:40:42 -04:00
Dimitris eb921ed9d5 remove null in embedded doc properties updates
calling patchAttributes without all embedded properties inits to null
2018-09-24 10:04:09 +03:00
Raymond Feng fcac276955 3.24.0
* Add IBM copyright and MIT license headers (Raymond Feng)
 * Allow List to take items as instances of a class (Raymond Feng)
 * fix: ignore extra properties when strict=filter (#1423) (Tom Kirkpatrick)
 * Add EventEmitter type info to DataSource type (shimks)
2018-09-17 09:03:33 -07:00
Raymond Feng 242fd1bb56
Merge pull request #1625 from strongloop/fix-list-of-class-instances
Allow List to take items as instances of a class
2018-09-17 09:02:16 -07:00
Raymond Feng 7c7bd56b2e Add IBM copyright and MIT license headers 2018-09-17 09:00:12 -07:00
Raymond Feng 7eec7e4e34 Allow List to take items as instances of a class 2018-09-17 08:22:21 -07:00
Tom Kirkpatrick 251798c711 fix: ignore extra properties when strict=filter (#1423)
Fix for #1422
2018-08-29 22:57:37 -04:00
Kyusung Shim 2b8b6719a7
Merge pull request #1611 from strongloop/datasource-event-type
Add EventEmitter type information to DataSource type
2018-07-25 16:15:07 -04:00
shimks 1e59918c11 Add EventEmitter type info to DataSource type 2018-07-25 15:13:54 -04:00
Raymond Feng 4d14c1473f 3.23.0
* fix: update TypeScript declaration for KV (Raymond Feng)
 * Upgrade eslint-config-loopback + fix formatting (Miroslav Bajtoš)
 * Hide nyc coverage from test output (Miroslav Bajtoš)
 * Configure Mocha to use dot reporter (Miroslav Bajtoš)
2018-07-16 11:15:14 -07:00
Raymond Feng 06284be673 Merge branch 'kv-types' 2018-07-16 11:11:32 -07:00
Raymond Feng 76b87ade93 fix: update TypeScript declaration for KV 2018-07-16 11:09:29 -07:00
Raymond Feng 9717e512b4
Merge pull request #1608 from strongloop/kv-types
fix: update TypeScript declaration for KV
2018-07-16 10:43:03 -07:00
Raymond Feng 535b000195 fix: update TypeScript declaration for KV 2018-07-16 10:11:54 -07:00
Miroslav Bajtoš 3e5c805418
Merge pull request #1609 from strongloop/update-eslint-config
Upgrade eslint-config-loopback + fix formatting
2018-07-16 17:55:24 +02:00
Miroslav Bajtoš 7d50f6130b
Upgrade eslint-config-loopback + fix formatting
The new version of our config enabled function-paren-newline rule,
this commit fixes the codebase to use more consistent handling
of newlines when calling functions.
2018-07-16 08:46:25 +02:00
Miroslav Bajtoš be7d97c885
Merge pull request #1605 from strongloop/make-test-output-concise
Make test output concise
2018-07-10 12:24:55 +02:00
Miroslav Bajtoš bc2689f58d
Hide nyc coverage from test output
Configure nyc/istanbul to generate an HTML report that can be inspected
in a browser instead of printing a long table after each test run.
2018-07-10 12:11:46 +02:00
Miroslav Bajtoš 38d5b5b4fa
Configure Mocha to use dot reporter
With 1965 tests, printing names of all tests is no longer useful.

This commit switches to "dot" reporter which prints a single dot per
test.
2018-07-10 12:11:46 +02:00
virkt25 7ae64edf3d 3.22.2
* assertation of undefined could be null (shenghu)
 * fix: regression on Operation Hooks (virkt25)
2018-07-09 16:51:30 -04:00
shenghu bc16692d9b assertation of undefined could be null 2018-07-09 11:53:27 -04:00
Miroslav Bajtoš 2f263898c6
Merge pull request #1602 from strongloop/juggler-fix
Fix regression in Operation Hooks
2018-07-09 17:04:54 +02:00
virkt25 9bd7f8d02f
fix: regression on Operation Hooks
Fix the regression introduced by 9af79cf51a where updateAttributes
and replaceAttributes was incorrectly handling the response returned
by the database.

This commit restores the old behaviour where `context.data` is updated
only by a connector-provided function and reverts an incorrect change
of a test file made as part of the faulty fix.

Besides the fixes, this patch also renames `data` to `dbResponse` and
add comments explaining the structure of the response object for more
clarity.
2018-07-09 16:41:56 +02:00
Miroslav Bajtoš da728b8d70
3.22.1
* [WebFM] cs/pl/ru translation (#1600) (tangyinb)
 * fixup! address code review comments (Miroslav Bajtoš)
 * Fix type definitions for PersistedModel API (Miroslav Bajtoš)
 * Fix Operation Hooks to propagate data changes (Miroslav Bajtoš)
 * Fix stalebot config to ignore "good first issue" (Miroslav Bajtoš)
2018-07-02 09:02:00 +02:00
Miroslav Bajtoš 3ac18e4e06
Merge pull request #1599 from strongloop/fix/typings
Fix type definitions for PersistedModel API
2018-07-02 09:00:56 +02:00
tangyinb b180f363ac [WebFM] cs/pl/ru translation (#1600)
cs/pl/ru translation check-in by YI TANG (tangyinb@cn.ibm.com) using
WebFM tool.
2018-06-29 09:37:15 -04:00
Miroslav Bajtoš 6f3675b13c
fixup! address code review comments 2018-06-29 08:35:22 +02:00
Miroslav Bajtoš 548379ca2a
Fix type definitions for PersistedModel API
Callback's first argument is an optional Error now. Was: required `any`.

PersistedModel methods return `PersistedModel` now. Before this change,
methods were returning `PersistedData` (`PersistedModel | AnyObject`).
The problem with `AnyObject` is that it does not contain any
`PersistedModel` instance data and cannot be assigned to functions
expecting `Partial<PersistedModel>`. As a result, consumers of this API
were forced to either cast the result to `PersistedModel` (which feels
wrong) or deal with the `AnyObject` case (which never happen at
runtime).

Fix definition of `ModelData<T>` to `T | Partial<T>`. Before this
change, `ModelData` allowed any values not related to the actual
model at all, for example arrays.
2018-06-28 13:09:47 +02:00
Miroslav Bajtoš 3938c3755e
Merge pull request #1598 from strongloop/fix/apply-updates-from-hooks
Fix Operation Hooks to propagate data changes
2018-06-28 13:05:43 +02:00
Miroslav Bajtoš 9af79cf51a
Fix Operation Hooks to propagate data changes
Before this change, many Operation Hooks were not correctly propagating
changes made to `ctx.data` via reassigning ctx.data to a new object.

This change modifies existing tests to account for this different
scenario, adds few more tests for scenarios that were not covered by
tests before and finally fixes the problem discovered.
2018-06-28 12:22:16 +02:00
Miroslav Bajtoš fa0039c6a8
Merge pull request #1595 from strongloop/good-first-issues-are-not-stale
Fix stalebot config to ignore "good first issue"
2018-06-15 08:37:43 +02:00
Miroslav Bajtoš 6846ef87b4
Fix stalebot config to ignore "good first issue" 2018-06-14 15:50:21 +02:00
Miroslav Bajtoš 5d762102fe
3.22.0
* Update strong-globalize to 4.x (Miroslav Bajtoš)
 * Update remaining dev-dependencies to latest (Miroslav Bajtoš)
 * Update eslint + config to latest (Miroslav Bajtoš)
 * Disable package-lock feature of npm (Miroslav Bajtoš)
 * Travis: add Node.js 10.x to the build matrix (Miroslav Bajtoš)
 * Drop support for Node 4.x (Miroslav Bajtoš)
2018-06-12 16:26:58 +02:00
Miroslav Bajtoš 751fd7b245
Merge pull request #1594 from strongloop/upgrade-deps
Drop support for Node.js 4.x + update dependencies
2018-06-12 16:26:07 +02:00
Miroslav Bajtoš 7a8213af43
Update strong-globalize to 4.x 2018-06-12 09:17:26 +02:00
Miroslav Bajtoš 5d8c36eca0
Update remaining dev-dependencies to latest
Keep should at 8.x for compatibility with connectors.
2018-06-12 09:13:54 +02:00
Miroslav Bajtoš d2ee73b9d3
Update eslint + config to latest 2018-06-12 09:13:32 +02:00
Miroslav Bajtoš e2d75e70d1
Disable package-lock feature of npm 2018-06-12 08:42:05 +02:00
Miroslav Bajtoš 26c795fdea
Travis: add Node.js 10.x to the build matrix 2018-06-12 08:35:04 +02:00
Miroslav Bajtoš c479be7069
Drop support for Node 4.x
Node 4.x is no longer maintained by Node.js project.
2018-06-12 08:34:49 +02:00
Raymond Feng 77f11cda3b 3.21.1
* Fix tests to ensure compatibility w/ should@10 (Raymond Feng)
2018-05-24 21:11:11 -07:00
Raymond Feng ef3191d3e5
Merge pull request #1588 from strongloop/tidy-up-tests
Fix tests to ensure upward compatibility w/ should@10
2018-05-24 21:10:13 -07:00
Raymond Feng 2b4b44292a Fix tests to ensure compatibility w/ should@10 2018-05-24 14:21:12 -07:00
Raymond Feng dafb8a1ab7 3.21.0
* Fix datasource state management (Raymond Feng)
2018-05-22 10:52:51 -07:00
Raymond Feng 41c9a6d9b0
Merge pull request #1585 from strongloop/fix-lazy-connect
Fix datasource state management
2018-05-22 10:51:35 -07:00
Raymond Feng 5a66f9ad72 Fix datasource state management
Use case:
1. Configure a datasource with lazyConnect = true
2. Do NOT start the DB
3. Start the app
4. Send first request and it fails to connnect to the DB
5. Start the DB
5. Requests are now served correctly
2018-05-22 10:46:45 -07:00
Raymond Feng dd30054138 3.20.2
* Remove node ref (Raymond Feng)
2018-05-11 09:09:58 -07:00
Raymond Feng d31c43bc09 Remove node ref 2018-05-11 09:09:31 -07:00
Raymond Feng eddb17689c 3.20.1
* Update deps (Raymond Feng)
2018-05-11 08:21:07 -07:00
Raymond Feng 2bb77e60e5 Update deps 2018-05-11 08:20:15 -07:00
Raymond Feng 965655be3a 3.20.0
* Fix typescript definitions to be compatible with LB4 (Raymond Feng)
 * Allow toObject() to accept an 'options' argument (Raymond Feng)
2018-05-10 10:20:41 -07:00
Raymond Feng e49eb47e36
Merge pull request #1583 from strongloop/fix-ts-defs
Fix ts defs
2018-05-10 10:20:10 -07:00
Raymond Feng 63f8b3b323 Fix typescript definitions to be compatible with LB4 2018-05-10 10:19:15 -07:00
Raymond Feng 90163ba709 Allow toObject() to accept an 'options' argument 2018-05-10 10:18:55 -07:00
Raymond Feng 4aa51e9956 3.19.0
* Add typescript type definitions (Raymond Feng)
 * Tidy up datasource (Raymond Feng)
2018-05-10 06:58:28 -07:00
Raymond Feng c9558026d0
Merge pull request #1578 from strongloop/ts-definitions
Add TypeScript declaration files
2018-05-10 06:57:20 -07:00
Raymond Feng 77a2c9ab3b Add typescript type definitions 2018-05-09 12:47:27 -07:00
Raymond Feng cc99cd8f0f Tidy up datasource 2018-05-03 14:14:53 -07:00
Miroslav Bajtoš 1ef38a6929
3.18.1
* Polyfill Number.isFinite() to support PhantomJS (Miroslav Bajtoš)
2018-04-19 09:11:12 +02:00
Miroslav Bajtoš c213352800
Merge pull request #1575 from strongloop/fix/phantomjs
Polyfill Number.isFinite() to support PhantomJS
2018-04-19 08:34:21 +02:00
Miroslav Bajtoš f8479253fa
Polyfill Number.isFinite() to support PhantomJS 2018-04-17 10:08:39 +02:00
Miroslav Bajtoš 2ac5efa04a
3.18.0
* feat: remove a Model from all registries (Miroslav Bajtoš)
2018-04-17 09:34:00 +02:00
Miroslav Bajtoš 2d76947c07
Merge pull request #1573 from strongloop/feature/remove-model
feat: remove a Model from all registries
2018-04-17 09:33:13 +02:00
Diana Lau 3eb94c09c4 3.17.0
* feat: omit default fn for embedsMany (#1532) (Janny)
2018-04-16 08:57:21 -04:00
Miroslav Bajtoš 5af4c42728
feat: remove a Model from all registries
Add API allowing consumers (e.g. LoopBack) to remove a Model from all
juggler registries:
 - ModelBuilder's models
 - ModelBuilder's definitions
 - Connector registry of models
2018-04-16 14:24:53 +02:00
Janny 01427b1755 feat: omit default fn for embedsMany (#1532)
* feat: omit default fn for embeds many

* fix: apply feedback
2018-04-13 13:17:40 -04:00
Miroslav Bajtoš e095b77048
3.16.0
* Pass options argument to custom validators (bmatson)
 * chore: update CODEOWNERS (#1566) (Diana Lau)
2018-03-22 16:19:16 +01:00
Miroslav Bajtoš f0c092da21
Merge pull request #1508 from bmatson/master
Pass context to custom validators
2018-03-22 16:17:38 +01:00
bmatson c3e502032e
Pass options argument to custom validators 2018-03-22 15:51:21 +01:00
Diana Lau a5faee46bd
chore: update CODEOWNERS (#1566) 2018-03-22 10:32:28 -04:00
Raymond Feng 641eb13e5d 3.15.5
* Exclude .nyc_output from being published (Raymond Feng)
 * CODEOWNERS: add nitro404 (Miroslav Bajtoš)
2018-03-16 08:51:36 -07:00
Raymond Feng e56d520db4 Exclude .nyc_output from being published 2018-03-16 08:50:45 -07:00
Miroslav Bajtoš 2c37cda1aa
Merge pull request #1561 from strongloop/welcome-nitro404
CODEOWNERS: add nitro404
2018-02-16 09:18:19 +01:00
Miroslav Bajtoš faa57a8a2a
CODEOWNERS: add nitro404 2018-02-15 16:03:01 +01:00
Raymond Feng c2920c9f9b 3.15.4
* fix: allow `new DataSource(connector, settings)` (Raymond Feng)
2018-02-13 09:43:24 -08:00
Raymond Feng 5dc6a1cd13
Merge pull request #1558 from strongloop/fix-ds-constructor
fix: allow `new DataSource(connector, settings)`
2018-02-13 09:43:01 -08:00
Raymond Feng 87e1e217c3 fix: allow `new DataSource(connector, settings)` 2018-02-13 09:42:41 -08:00
Raymond Feng 310b9489d3 3.15.3
* fix: add more tests to verify new DataSource() (Raymond Feng)
2018-02-09 15:01:32 -08:00
Raymond Feng 8dd86c31a5
Merge pull request #1557 from strongloop/add-datasource-tests
fix: add more tests to verify new DataSource()
2018-02-09 15:00:57 -08:00
Raymond Feng 4be2ea8afb fix: add more tests to verify new DataSource() 2018-02-09 14:33:42 -08:00
Raymond Feng 54143dfa37 3.15.2
* feat(datasource): seperate name and connector  name (Nguyen Truong Minh)
 * Fix datasource not correctly retaining name value (Kevin Scroggins)
2018-02-07 17:14:05 -08:00
Raymond Feng bbff92c13f
Merge pull request #1555 from strongloop/truongminh-set-datasource-name
Use more meaningful names for dataSource and connector
2018-02-07 17:11:48 -08:00
Raymond Feng 9d3e6cd8f5 Merge branch 'set-datasource-name' of https://github.com/truongminh/loopback-datasource-juggler into truongminh-set-datasource-name 2018-02-07 16:50:57 -08:00
Raymond Feng 598effcabc
Merge pull request #1548 from nitro404/hotfix/retain-datasource-name
Fix datasource not correctly retaining name value
2018-02-07 16:05:43 -08:00
Nguyen Truong Minh 80f9364edc feat(datasource): seperate name and connector name 2018-02-07 16:25:25 +07:00
Diana Lau 1ec2b4d17c 3.15.1
* Added error handling for persist operation hook (#1531) (Kevin Scroggins)
 * Add warning for datasources with mismatched names (Kevin Scroggins)
2018-02-06 11:19:41 -05:00
Kevin Scroggins 25b1aa5abc Fix datasource not correctly retaining name value 2018-01-31 11:30:24 -05:00
Miroslav Bajtoš 309b422425
Merge pull request #1542 from nitro404/hotfix/datasource-name-mismatch-warning
Add warning for datasources with mismatched names
2018-01-25 07:57:25 +01:00
Kevin Scroggins 07f0310d34 Added error handling for persist operation hook (#1531)
Unrelated CI failures. -.-
2018-01-24 11:37:30 -05:00
Kevin Scroggins 92595b4348
Add warning for datasources with mismatched names 2018-01-23 14:18:49 +01:00
Kevin Delisle 943fed851e 3.15.0
* fix unauthorized fk change (#1538) (Taranveer Virk)
 * Set model constructor name to model name (Miroslav Bajtoš)
2018-01-19 12:55:16 -05:00
Taranveer Virk cc60ef8202 fix unauthorized fk change (#1538)
Downstream failures are unrelated.
2018-01-17 13:34:37 -05:00
Miroslav Bajtoš 9189dba001
Merge pull request #1534 from strongloop/feature/correct-model-ctor-name
Set model constructor name to model name
2018-01-09 09:36:40 +01:00
Miroslav Bajtoš b0b377af0c
Set model constructor name to model name
Rework the code building model constructors to leverage `Function` class
and dynamically emit a constructor function named after the model.

Before this change, all model classes were called "ModelConstructor",
which made debugging difficult.

After this change, a model class for model "User" is called "User.

Because not all valid model names are also valid JavaScript identifiers,
we implement a simple sanitization technique (replacing characters like
"-", "." and ":" with underscore "_") and fall back to legacy
"ModelConstructor" if the model name is still not a valid JS identifier.
2018-01-08 09:37:23 +01:00
Kevin Delisle 00cf01f901 3.14.0
* Allow new transaction method in postgresql (#1493) (zbarbuto)
 * Fix bug in utils uniq function (#1526) (Peter Bouda)
 * Fix query for related models (#1522) (Joost de Bruijn)
 * chore:update license (#1521) (Diana Lau)
 * Allow customizing embedded relation property (#1513) (zbarbuto)
 * 📖 Typo on README.md (#1517) (JP Ventura)
 * CODEOWNERS: move @lehni to Alumni section (Miroslav Bajtoš)
2017-12-14 11:33:39 -05:00
zbarbuto f5de99b249 Allow new transaction method in postgresql (#1493)
kv-extreme-scale needs fixing, unrelated.
2017-12-12 10:56:42 -05:00
Peter Bouda 6bd9fca080 Fix bug in utils uniq function (#1526)
The uniq function does currently not work when the database is mongodb.
In the case of mongodb, the function will receive an array of bson
object of bson type ObjectID. The indexOf function will return a
different index, even if the mongodb ID is the same, as it is wrapped
in the ObjectID. This commit first transforms any ObjectID in the array
to a string representation. We can then use indexOf to check for
uniqueness.
2017-12-04 15:39:58 -05:00
Joost de Bruijn 7a4c6ca2f9 Fix query for related models (#1522) 2017-11-14 14:22:48 -05:00
Diana Lau 994ec98b48
chore:update license (#1521) 2017-11-13 12:50:36 -05:00
zbarbuto 1d8603c491 Allow customizing embedded relation property (#1513) 2017-10-31 10:55:54 -04:00
JP Ventura 7373476fd8 📖 Typo on README.md (#1517) 2017-10-30 22:52:38 -04:00
Miroslav Bajtoš 9e5897a25f Merge pull request #1511 from strongloop/good-bye-lehni
CODEOWNERS: move @lehni to Alumni section
2017-10-19 10:49:37 +02:00
Miroslav Bajtoš 145ab8530f
CODEOWNERS: move @lehni to Alumni section 2017-10-19 10:48:41 +02:00
Diana Lau a9051ef991 3.13.0
* update strong-globalize to 3.1.0 (#1505) (Kyusung Shim)
 * Fix basic-querying (#1509) (Janny)
 * translation return for Q4 drop1 (tangyinb)
 * Allow passing null to base model ctor (Zak Barbuto)
 * CODEOWNERS: add zbarbuto (Miroslav Bajtoš)
 * update globalize string (Diana Lau)
2017-10-17 23:24:07 -04:00
Kyusung Shim b926f28c74 update strong-globalize to 3.1.0 (#1505)
* update strong-globalize to 3.1.0

* update other dependencies
2017-10-17 15:57:00 -04:00
Janny e85e0f600b Fix basic-querying (#1509)
* Fix basic-querying

* Fix duplicate MyModel
2017-10-16 16:07:01 -04:00
Diana Lau c13f35ad49 Merge pull request #1499 from candytangnb/master
translation return for Q4 drop1
2017-10-13 12:14:03 -04:00
tangyinb 3c24dd9a00 translation return for Q4 drop1
translation return for Q4 drop1
2017-10-09 17:16:00 +08:00
Miroslav Bajtoš 3a6ddf927d Merge pull request #1492 from NextFaze/fix/1486-null-data
Allow passing null to base model ctor
2017-10-04 12:14:55 +02:00
Zak Barbuto 99cea38fd0 Allow passing null to base model ctor 2017-09-28 09:42:30 +09:30
Diana Lau d213c8304a Merge pull request #1490 from strongloop/welcome-zbarbuto
CODEOWNERS: add zbarbuto
2017-09-26 16:11:49 -04:00
Miroslav Bajtoš ed21707cf0 CODEOWNERS: add zbarbuto 2017-09-25 09:55:03 +02:00
Diana Lau 7423283f5d Merge pull request #1488 from strongloop/globalize
update globalize string
2017-09-22 14:46:23 -04:00
Diana Lau 6fe3ba9153 update globalize string 2017-09-20 14:33:44 -04:00
Kevin Delisle 6d4cb6c3ad 3.12.0
* Add a better way to handle transactions (Jürg Lehni)
 * validations: use new regex per evaluation (#1479) (Joost de Bruijn)
 * Transaction: Bind timeout to tx instance (#1484) (Jürg Lehni)
 * CODEOWNERS: add lehni (#1483) (Miroslav Bajtoš)
 * Add node8 support for travis (loay)
 * Add nyc coverage, report data to coveralls.io (Miroslav Bajtoš)
 * Update translations from TVT (Allen Boone)
 * Add test coverage for hasAndBelongsToMany (loay)
 * package: use qs@6.5.0 (#1471) (Kevin Delisle)
2017-09-07 10:27:15 -04:00
Jürg Lehni 12c3e3aadb Merge pull request #1472 from lehni/feature/better-transactions
Add a better way to handle transactions by binding them to models
2017-09-06 09:56:25 +02:00
Jürg Lehni 0ce1fa9f87 Add a better way to handle transactions 2017-09-06 07:10:57 +02:00
Joost de Bruijn f18d3487c6 validations: use new regex per evaluation (#1479)
The RegExp is cloned before executing the test. Fixing issue #1475.
2017-09-01 12:48:29 -04:00
Jürg Lehni 94a602d17e Transaction: Bind timeout to tx instance (#1484) 2017-08-31 11:10:17 -04:00
Miroslav Bajtoš 37e7f0c8ab CODEOWNERS: add lehni (#1483) 2017-08-31 10:40:10 -04:00
Loay c897c24974 Merge pull request #1482 from strongloop/travis-8
Add node8 support for travis
2017-08-30 10:01:01 -04:00
loay 542c6e885c Add node8 support for travis 2017-08-30 09:27:05 -04:00
Miroslav Bajtoš 2ab4a26396 Merge pull request #1481 from strongloop/enable/coveralls
Add nyc coverage, report data to coveralls.io
2017-08-30 14:25:16 +02:00
Miroslav Bajtoš d49806a78b
Add nyc coverage, report data to coveralls.io 2017-08-30 14:17:27 +02:00
Allen Boone 666f9c5d5b Merge pull request #1477 from strongloop/tvtPIIUpdate
Update translations from TVT
2017-08-28 09:39:21 -04:00
Allen Boone 0ba720df03 Update translations from TVT 2017-08-25 16:19:11 -04:00
Loay b17af8d583 Merge pull request #1474 from strongloop/hasAndBelongsToMany
Add test coverage for hasAndBelongsToMany
2017-08-24 11:29:27 -04:00
loay e983f0c9e1 Add test coverage for hasAndBelongsToMany 2017-08-24 11:01:54 -04:00
Kevin Delisle 65f6beb00b package: use qs@6.5.0 (#1471)
Fix for advisory: https://snyk.io/vuln/npm:qs:20170213
2017-08-23 15:17:00 -04:00
rashmihunt 1fa89d6fb9 3.11.0
* Flag id as updateOnly when forceId is in effect (#1453) (Rashmi Hunt)
 * Add stalebot configuration (Kevin Delisle)
2017-08-22 13:47:21 -07:00
Rashmi Hunt 6c6df15286 Flag id as updateOnly when forceId is in effect (#1453)
* updateOnly, forceId changes

* support getUpdateOnlyProperties

* fixup! fix updateOrCreate in forceId mode

The contract of `updateOrCreate` is expecting a full object instance
to be passed to the callback.

The current implementation was creating an empty instance and
calling updateAttributes under the hood. As a result, the callback
was called with the attributes being updated only.

In order to preserve existing behaviour, we have to always build
a full initial instance by calling `findById`.

See the following discussion for more context:
https://github.com/strongloop/loopback-datasource-juggler/issues/966

* fixup! fix tests of upsert validation

* move forceId to model-builder

* remove TODO comment

* revert refactoring and test fixes

* Remove duplicate test

* change testcase names

* change to ModeClass.settingse

* forceId setup from datasource to model-builder

* fix inheritance of auto-generated forceId

* Fixed failing tests for auto change

* fixed a comment
2017-08-22 13:09:45 -07:00
Kevin Delisle aebbcd2f15 Add stalebot configuration 2017-08-22 15:12:54 -04:00
Kevin Delisle 3128c9395c 3.10.0
* Catch err using Callback (loay)
 * Update Issue and PR Templates (#1462) (Sakib Hasan)
 * Update translated strings Q3 2017 (Allen Boone)
 * test: call true/false in isValid checks (Tom Kirkpatrick)
 * fix: support numbers in validatesFormatOf (Tom Kirkpatrick)
 * Fix undefined properties in where (Raymond Feng)
 * Honor backwards compatability with validate update (ssh24)
 * Fix update validation callback (ssh24)
 * Validate updateAll (ssh24)
 * Sort arrays before testing (ssh24)
 * update translation file (Diana Lau)
 * Missing the option argument (#1426) (dmellonch)
 * Add CODEOWNER file (Diana Lau)
 * use connector flag throughout tests (biniam)
2017-08-21 14:11:24 -04:00
Loay e4d598cc3e Merge pull request #1464 from strongloop/cb-err
Catch err using Callback
2017-08-17 10:42:45 -04:00
loay 01b4c4a3a7 Catch err using Callback 2017-08-16 17:00:41 -04:00
Sakib Hasan b96d40c028 Update Issue and PR Templates (#1462)
* update issue template

* update pr template
2017-08-16 15:07:56 -04:00
Allen Boone 4ccef202d3 Merge pull request #1460 from kallenboone/master
Update translated strings Q3 2017
2017-08-11 14:23:09 -04:00
Allen Boone 770838678d Update translated strings Q3 2017 2017-08-10 16:02:08 -04:00
Loay 80f3e93367 Merge pull request #1416 from strongloop/feature/fix-2364
Fix undefined properties in where
2017-08-09 13:54:28 -04:00
Biniam Admikew 0ca56309ea Merge pull request #1438 from fullcube/tkp/validatesFormatOf-numbers-1437
fix: support numbers in validatesFormatOf
2017-08-03 16:01:26 -04:00
Tom Kirkpatrick 1ebad655e4 test: call true/false in isValid checks 2017-08-03 14:47:11 -04:00
Tom Kirkpatrick 138b99c703 fix: support numbers in validatesFormatOf
Fix for #1437
2017-08-03 14:47:11 -04:00
Raymond Feng 03753b6fe2 Fix undefined properties in where
https://github.com/strongloop/loopback/issues/2364
2017-08-03 14:09:21 -04:00
Sakib Hasan c813bf19fb Merge pull request #1451 from strongloop/backwards-compatability-validate-update
Honor backwards compatibility with validate update
2017-08-03 13:43:01 -04:00
ssh24 80f015c2d2 Honor backwards compatability with validate update 2017-08-03 11:50:44 -04:00
Sakib Hasan b8739cf80f Merge pull request #1450 from strongloop/fix/validation-callback
Fix update validation callback
2017-08-02 16:08:51 -04:00
ssh24 9cd0108fc6 Fix update validation callback 2017-08-02 14:55:47 -04:00
Sakib Hasan 2f7dd90f1f Merge pull request #1445 from strongloop/fix/validate-update
Add validation on update
2017-08-02 14:12:40 -04:00
ssh24 b1a0cb8c3b Validate updateAll 2017-08-02 13:24:21 -04:00
Sakib Hasan edf93fca17 Merge pull request #1449 from strongloop/fix/array-sort
Sort arrays before comparing
2017-08-02 11:14:22 -04:00
ssh24 aec1179a30 Sort arrays before testing
Sorting the array so the ordering is the same
2017-08-02 10:45:36 -04:00
Diana Lau dcf83dc6af Merge pull request #1447 from strongloop/translate
update translation file
2017-08-02 09:21:52 -04:00
Diana Lau 5c566274c0 update translation file 2017-08-01 22:53:25 -04:00
dmellonch 1b7c346bca Missing the option argument (#1426)
* Fix missing option arguments in scope.js

Added option arguments in find.relatedmodel
Added case test

* Add order filter in verify function

Fix for cloudant test
2017-08-01 14:15:21 -04:00
Diana Lau 25ead1ce97 Merge pull request #1440 from strongloop/add-codeowner
Add CODEOWNERS file
2017-07-26 22:28:09 -04:00
Biniam Admikew fc83ff14a5 Merge pull request #1439 from strongloop/use-connector-flag
use connector flag throughout tests
2017-07-26 21:44:54 -04:00
Diana Lau bf2679a885 Add CODEOWNER file 2017-07-26 20:50:07 -04:00
biniam 59b3ac22a8 use connector flag throughout tests 2017-07-26 16:18:30 -04:00
Kevin Delisle bebac1ee3f 3.9.3
* Catch errors using cb (loay)
 * Rename getAsync() methods to find() and get() (Jürg Lehni)
 * #1386 Allow empty values when allowBlank is true (Simo Moujami)
 * Skip imcompatible tests (#1420) (Janny)
 * Run juggler tests for Cloudant (#1414) (Janny)
2017-07-26 10:37:13 -04:00
Diana Lau 03fc097f28 Merge pull request #1435 from strongloop/create-update-pass3
Catch errors using cb
2017-07-24 15:11:13 -04:00
loay b1b2d5df0c Catch errors using cb 2017-07-24 14:08:58 -04:00
Diana Lau ff9b25a905 Merge pull request #1432 from simoami/master
#1386 Allow empty values when allowBlank is true
2017-07-20 11:23:54 -04:00
Miroslav Bajtoš 1fb7b0e24d Merge pull request #1424 from lehni/feature/rename-get-async
Rename getAsync() methods to find() and get()
2017-07-20 15:15:12 +02:00
Jürg Lehni 4c9e91423f
Rename getAsync() methods to find() and get()
Keep getAsync() around for backward compatibility, but deprecate it
2017-07-20 14:48:29 +02:00
Simo Moujami 82a8e3d9a1 #1386 Allow empty values when allowBlank is true 2017-07-19 19:26:13 -04:00
Janny 6a1b55568c Skip imcompatible tests (#1420)
* Skip imcompatible tests
2017-07-18 15:20:21 -04:00
Janny b9129e6973 Run juggler tests for Cloudant (#1414) 2017-07-11 14:56:39 -04:00
Kevin Delisle 5da8170d9e 3.9.2
* Fix the case where qWhere[idKey] is null (Tetsuo Seto)
 * test/helpers: annotate skipped tests (Kevin Delisle)
 * Fix mixins/validatable docs (ssh24)
2017-06-22 17:03:33 -04:00
Tetsuo Seto b79763d065 Merge pull request #1401 from strongloop/smart-merge-fix
Fix the case where qWhere[idKey] is null
2017-06-09 10:14:41 -07:00
Tetsuo Seto 4a6f0a4aa0 Fix the case where qWhere[idKey] is null 2017-06-09 09:33:22 -07:00
Kevin Delisle 1f27ca57b2 Merge pull request #1398 from strongloop/debug-annotations-for-tests
test/helpers: annotate skipped tests
2017-06-07 17:10:24 -04:00
Kevin Delisle 828a71e576 test/helpers: annotate skipped tests
Differentiate between tests skipped by feature flags, and those
manually marked as skipped.

Tests that use the bdd.describe and bdd.it helper functions
will be marked as [UNSUPPORTED] if they are conditionally disabled.
2017-06-07 14:05:48 -04:00
Sakib Hasan 3b45c76d0f Merge pull request #1395 from strongloop/fix/api-docs-mixins-validatable
Fix mixin and validatable docs
2017-06-06 14:46:21 -04:00
ssh24 98174251f1 Fix mixins/validatable docs 2017-06-06 14:21:49 -04:00
Kevin Delisle a54064b989 3.9.1
* Update translated strings Q2 2017 (Allen Boone)
 * Fix updateAttributes cb (ssh24)
 * Apply iteration on the model object (ssh24)
 * Remove spurious extra options arg (#1390) (Rand McKinney)
 * include: remove JSDoc refs to recursive calls (Kevin Delisle)
 * Fix count of properties (ssh24)
 * hooks: add JSDoc for .trigger (Kevin Delisle)
 * model-builder: JSDoc tidy-up (Kevin Delisle)
2017-06-01 11:37:49 -04:00
Candy fba8cf9480 Merge pull request #1385 from kallenboone/master
Update translated strings Q2 2017
2017-05-31 16:06:17 -04:00
Allen Boone 1f8d34ffb9 Update translated strings Q2 2017 2017-05-31 14:23:15 -04:00
Sakib Hasan 7eca34552d Merge pull request #1392 from strongloop/fix/model-inheritance-test
Apply iteration on the model object
2017-05-30 21:58:56 -04:00
Sakib Hasan 3a10c77cbd Merge pull request #1393 from strongloop/fix/updateAttributes-cb
Fix updateAttributes cb
2017-05-30 21:28:00 -04:00
ssh24 ba1901b2a0 Fix updateAttributes cb
Allow pass through of the new data from the connector
Specifically for cloudant since updateAttributes changes the _rev
2017-05-29 15:32:32 -04:00
ssh24 e791e9006c Apply iteration on the model object 2017-05-26 18:49:54 -04:00
Rand McKinney 0a056adee4 Remove spurious extra options arg (#1390)
* Remove spurious extra options arg

* Remove space
2017-05-26 11:34:50 -07:00
Kevin Delisle 3630bb9ae4 Merge pull request #1387 from strongloop/ref/inclusion-docs
include: remove JSDoc refs to recursive calls
2017-05-24 19:41:06 -04:00
Kevin Delisle 1b625228b9 include: remove JSDoc refs to recursive calls 2017-05-24 17:10:45 -04:00
Sakib Hasan 0abfceebaa Merge pull request #1384 from strongloop/fix/model-inheritance-test
Fix count of properties
2017-05-24 10:27:54 -04:00
ssh24 825fa3171c Fix count of properties 2017-05-23 22:17:50 -04:00
Kevin Delisle 1fb4dd70e8 Merge pull request #1383 from strongloop/ref/hookable-docs
hooks: add JSDoc for .trigger
2017-05-23 19:54:32 -04:00
Kevin Delisle d058244594 hooks: add JSDoc for .trigger 2017-05-23 12:12:11 -04:00
Kevin Delisle a007c5a3fa Merge pull request #1379 from strongloop/ref/modelbuilder-apidocs
ModelBuilder API Doc Touchup
2017-05-23 10:38:57 -04:00
Kevin Delisle 117152d090 model-builder: JSDoc tidy-up 2017-05-23 10:31:38 -04:00
Raymond Feng b34b6e0ad4 3.9.0
* Return promise for batch create (Raymond Feng)
 * Use correct data on replace callback (ssh24)
2017-05-19 16:44:40 -07:00
Raymond Feng 492b644679 Merge pull request #1380 from strongloop/feature/fix-create-promise
Return promise for batch create
2017-05-19 18:43:35 -05:00
Raymond Feng 5a0b0270f3 Return promise for batch create 2017-05-19 16:16:52 -07:00
Kevin Delisle 790ccc3961 Merge pull request #1378 from strongloop/fix/use-correct-data-replaceCb
Use correct data on replace callback
2017-05-18 17:25:15 -04:00
ssh24 54f67dc3b0 Use correct data on replace callback
Previously, it would just pass the old data
Pass the new data as cloudant updates the _rev property on CRUD
2017-05-18 17:03:21 -04:00
Raymond Feng 22428cd58c 3.8.0
* fix assert, make the test case more clear (rashmihunt)
 * code review, better asserts (rashmihunt)
 * test case to exclude base props (rashmihunt)
 * handle excludeBaseProperties (rashmihunt)
2017-05-15 09:09:55 -07:00
Raymond Feng c41487a1d1 Merge pull request #1371 from strongloop/exclude_prop
Handle excludeBaseProperties
2017-05-15 11:06:27 -05:00
Kevin Delisle a4be61377a 3.7.0
* Remove unnecessary tests for adhocSort !== false (Tetsuo Seto)
 * Fix the test case to avoid duplicate userId (Tetsuo Seto)
 * Support include rework for C* connector (Tetsuo Seto)
 * Overall review of polymorphic relations (ebarault)
 * configurable model merge (ebarault)
 * Fix assertion errors (Loay)
 * Update modelbaseclass api docs (Loay)
 * Add caseInsensitive opt to validatesUniquenessOf (Bram Borggreve)
2017-05-15 11:20:28 -04:00
Tetsuo Seto 21cd515d4d Merge pull request #1362 from strongloop/include-rework-cassandra
Support include rework for C* connector
2017-05-15 08:09:11 -07:00
Tetsuo Seto ef08458e8d Remove unnecessary tests for adhocSort !== false 2017-05-15 03:04:09 -07:00
Tetsuo Seto aa3f5fa4f4 Fix the test case to avoid duplicate userId 2017-05-14 19:17:32 -07:00
Tetsuo Seto c07f46000d Support include rework for C* connector
- Remove supportNonPrimaryKeyIN
- Add C* Uuid in build call
- Implement smartMerge in scope.js
2017-05-12 22:43:21 -07:00
Kevin Delisle 4f335cb06f Merge pull request #1301 from strongloop/fix/shortcut-polymorphic-json-definition
honor polymorphic relations via JSON as in doc
2017-05-12 16:31:50 -04:00
ebarault cfd3cdf535 Overall review of polymorphic relations
In #1298, the spec/doc for polymorphic relations was reviewed

**hasX relation**
- `type`: **hasMany**
- `as`: redefines **this** relation's name (optional)
- `model`: **modelTo**
- `polymorphic`:
  - typeOf `polymorphic` === `String`
    - matching **belongsTo** relation name
      - `foreignKey` is generated as `polymorphic + 'Id'`,
      - `discriminator` is generated as `polymorphic + 'Type'`
  - typeOf `polymorphic` === `Object`
    - `as`: **DEPRECATED** should display a warning,
            replaced by `selector`
    - `selector`: should match **belongsTo** relation name if the
                  latter is defined with {polymorphic: true}
      - (required) if both foreignKey and discriminator
        are **NOT** provided
      - (extraneous) if both foreignKey and discriminator
        are provided
    - `foreignKey`:  A property of modelTo, representing the fk to
       modelFrom's id.
      - generated by default as `selector + 'Id'`
    - `discriminator`: A property of modelTo, representing the actual
                       modelFrom to be looked up and defined
                       dynamically
      - generated by default as `selector + 'Type'`

---

**belongsTo relation**
- `type`: **belongsTo**
- `as`: redefines **this** relation's name (optional)
- `model`: **NOT EXPECTED**: should throw an error at
               relation validation
- `polymorphic`:
  - typeOf `polymorphic` === `Boolean`
      - `foreignKey` is generated as `relationName + 'Id'`,
      - `discriminator` is generated as `relationName + 'Type'`
  - typeOf `polymorphic` === `Object`
    - `as`: **DEPRECATED**: should display a warning,
            replaced by `selector`
    - `selector`:
      - (required) if both foreignKey and discriminator
        are **NOT** provided
      - (extraneous) if both foreignKey and discriminator
        are provided
    - `foreignKey`: A property of modelTo, representing the fk to
                    modelFrom's id.
      - generated by default as `selector + 'Id'`
    - `discriminator`: A property of modelTo, representing the actual
                       modelFrom to be looked up and defined
                       dynamically
      - generated by default as `selector + 'Type'`
2017-05-12 21:33:39 +02:00
rashmihunt 45bf569ec4 fix assert, make the test case more clear 2017-05-12 11:47:50 -07:00
rashmihunt fed0396d9e code review, better asserts 2017-05-11 09:59:39 -07:00
rashmihunt 5aee1fe17e test case to exclude base props 2017-05-10 12:03:42 -07:00
rashmihunt 52f8fb3416 handle excludeBaseProperties 2017-05-10 12:03:42 -07:00
Kevin Delisle d375d61519 Merge pull request #1289 from strongloop/fix/preventRelationsMerge
review model settings merge/inheritance policy (util/mergeSettings() ) : relations, acls, ...
2017-05-10 12:56:23 -04:00
ebarault 79068d142b configurable model merge
The PR superseeds the existing deepMerge algorithm used to merge
settings of parent and child models with a new algorithm that allows
to specify the way each setting is merged or mixed-in.

This configuration of this algorithm uses a merge policy specification.
The `getMergePolicy()` helper of BaseModelClass can be used to ease
model merge configuration.

Next is presented the expected merge behaviour for each option.
NOTE: This applies to top-level settings properties

- Any
  - `{replace: true}` (default): child replaces the value from parent
  - assignin `null` on child setting deletes the inherited setting

- Arrays
  - `{replace: false}`: unique elements of parent and child cumulate
  - `{rank: true}` adds the model inheritance rank to array
    elements of type Object {} as internal property `__rank`

- Object {}:
  - `{replace: false}`: deep merges parent and child objects
  - `{patch: true}`: child replaces inner properties from parent

The recommended merge policy is returned by getMergePolicy()
when calling the method with option `{configureModelMerge: true}`.

The legacy built-in merge policy is returned by `getMergePolicy()`
when avoiding option `configureModelMerge`.
NOTE: it also delivers ACLs ranking in addition to the legacy
behaviour as well as fixes for settings `description` and `relations`

`getMergePolicy()` can be customized using model's setting
`configureModelMerge` as follows:
```
{
  // ..
  options: {
    configureModelMerge: {
      // merge options
    }
  }
  // ..
}
```

`getMergePolicy()` method can also be extended programmatically as
follows:
```
myModel.getMergePolicy = function(options) {
  const origin = myModel.base.getMergePolicy(options);
  return Object.assign({}, origin, {
    // new/overriding options
  });
};
```
2017-05-10 02:33:45 +02:00
Loay e3ce44a286 Merge pull request #818 from fullcube/fullcube/validatesUniquenessOf-case-insensitive
Fullcube/validates uniqueness of case insensitive
2017-05-05 10:41:42 -04:00
Loay b39ee050f3 Merge pull request #1363 from strongloop/fix-1304
Fix error assertion
2017-05-04 11:18:19 -04:00
Loay 87dd44dd59 Fix assertion errors 2017-05-04 10:38:06 -04:00
Loay c80daae5a1 Merge pull request #1366 from strongloop/api-ModelBase
Update ModelBaseClass api docs
2017-05-03 22:31:56 -04:00
Loay 84b55d8160 Update modelbaseclass api docs 2017-05-03 21:03:36 -04:00
Kevin Delisle 6b43378396 3.6.1
* docs: add DateString definition (Kevin Delisle)
2017-05-02 18:55:44 -04:00
Kevin Delisle 53fd8d79f8 Merge pull request #1365 from strongloop/docs/datestring
docs: add DateString definition
2017-05-02 18:55:12 -04:00
Kevin Delisle 0e955b0f35 docs: add DateString definition 2017-05-02 18:51:56 -04:00
Kevin Delisle 6bbad5e9a9 3.6.0
* create sequence for nosql id (#1354) (Janny)
 * Fix order of query results (Loay)
 * Add DateString type (Kevin Delisle)
 * datatype.test: use predefined date (Kevin Delisle)
 * Update api documents (Loay)
 * Datasource documentation tune-up (Kevin Delisle)
 * Added unit tests specific to DateType where null (#1349) (Andrew McDonnell)
 * Fix/geo null (#1334) (paulussup)
 * replace exception thrown for invalid dates (Diana Lau)
 * Revert PR #1326 (#1336) (Sakib Hasan)
 * Make lib peerDepend on loopback-connector (#1326) (Russ Tyndall)
 * Add test case using updateAttributes (Loay)
 * Fix forceId bug for updateOrCreate (Loay)
 * Fix typo in description (jannyHou)
 * Fix relations test case (loay)
2017-05-02 18:34:11 -04:00
Kevin Delisle 156b638518 Merge pull request #1356 from strongloop/datetype-allow-strings
Add DateString type
2017-05-02 14:48:50 -04:00
Janny 5d10c72664 create sequence for nosql id (#1354)
* create sequence for nosql id
2017-05-02 13:35:57 -04:00
Bram Borggreve c3629633de
Add caseInsensitive opt to validatesUniquenessOf 2017-05-01 17:26:16 -05:00
Kevin Delisle 6342a0387f Merge pull request #1364 from strongloop/query-order
Fix order of query results
2017-05-01 17:21:00 -04:00
Loay 6cfdcc0128 Fix order of query results 2017-05-01 16:10:55 -04:00
Kevin Delisle 5e80837424 Add DateString type
New type that preserves string input as a string, but ensures that
the string is a valid Date.

Additionally, provides a .toDate function to provide the Date
object representation of the string.
2017-05-01 12:28:59 -04:00
Kevin Delisle 97f243f347 Merge pull request #1360 from strongloop/datatype-test/use-predefined-date
datatype.test: use predefined date
2017-04-28 16:42:10 -04:00
Kevin Delisle 8e97385a8f datatype.test: use predefined date
Some databases are storing the value in UTC (not ISO) format,
and truncating the values. Even though this is technically
unavoidable, it does fail strict string equality.
2017-04-28 15:40:19 -04:00
Loay f8046637ac Merge pull request #1358 from strongloop/api-doc-2
Update api documents
2017-04-27 23:11:57 -04:00
Loay ef61c8618a Update api documents 2017-04-27 16:28:43 -04:00
Loay bf7ea4caed Merge pull request #1333 from strongloop/api-doc-refactor
Datasource documentation tune-up
2017-04-25 16:28:54 -04:00
Kevin Delisle f7fe187120 Datasource documentation tune-up 2017-04-25 15:51:42 -04:00
Andrew McDonnell 238175b4bd Added unit tests specific to DateType where null (#1349)
* Added unit test for DateType where null

* BDD for connectors w/o null support
2017-04-25 13:05:55 -04:00
paulussup e9ff88f453 Fix/geo null (#1334)
* fix check for null

* add tests

* fix for early return

* Allow check for null and non-existent value

Some connectors uses a non existent prop instead of allowing null
Modified test case to look if null exists or the prop is non existent

* Check for null value with geo near query

* Apply requested changes

* change test to two users and simplify

* check error first

* Fix simple query test case with null value

* BDD for connectors w//o null support
2017-04-24 19:28:11 -04:00
Diana Lau ee254a1812 Merge pull request #1339 from strongloop/invalid-dates
replace exception thrown for invalid dates
2017-04-21 20:13:45 +00:00
Diana Lau a488a71dbd replace exception thrown for invalid dates 2017-04-21 15:57:11 -04:00
Sakib Hasan bcc5b559a3 Revert PR #1326 (#1336)
Make lib peerDepend on loopback-connector (#1326)

This reverts commit 67e8f3708a.
2017-04-19 14:14:50 -04:00
Russ Tyndall 67e8f3708a Make lib peerDepend on loopback-connector (#1326) 2017-04-18 16:11:18 -04:00
Loay 3aef34e552 Merge pull request #1304 from strongloop/upsert-forceid
Fix forceId bug for updateOrCreate
2017-04-18 15:07:29 -04:00
Loay 3c19beacbb Add test case using updateAttributes 2017-04-18 13:50:57 -04:00
Loay f1d10b47ce Fix forceId bug for updateOrCreate 2017-04-18 13:14:35 -04:00
Janny ddbb568154 Merge pull request #1312 from strongloop/fix/typo
Fix typo in description
2017-04-18 10:30:21 -04:00
jannyHou 7010986643 Fix typo in description 2017-04-17 21:18:25 -04:00
Loay 2f18a83006 Merge pull request #1325 from strongloop/embedsMany-relations
Alter relations test case
2017-04-17 16:41:42 -04:00
Candy 432a2e15db 3.5.0
* Add instructions for running the tests (#1330) (Andrew McDonnell)
 * handle deep geo-near queries (#1314) (Eric Barault)
 * Unskip test case (Loay)
 * Make tests work for other connectors as well as C* (Tetsuo Seto)
 * Remove debugger statement (Tetsuo Seto)
 * Fixup test support for Cassandra connector (Tetsuo Seto)
 * Add test support for Cassandra connector (Tetsuo Seto)
 * package: use loopback-connector@^4.0.0 (Kevin Delisle)
 * Revert "handle deep geo-near queries (#1216)" (Sakib Hasan)
 * Revert "Allow `after save` hook to see count of records changed (#1231)" (Sakib Hasan)
 * Allow `after save` hook to see count of records changed (#1231) (Joshua Chaitin-Pollak)
 * handle deep geo-near queries (#1216) (Corentin H)
 * Fix model def column name method (#1224) (destillat)
 * Added notify flag for create and upsert (#1277) (Jonathan Sheely)
 * Custom Table Names on rels (#1303) (Waldemar Zahn)
 * Support multiple fk relations (#1308) (Sakib Hasan)
 * #1261 Property name "constructor" is not allowed in 'Model' data (#1284) (Thaer Abbas)
2017-04-17 16:22:13 -04:00
Andrew McDonnell 85bec7fddb Add instructions for running the tests (#1330) 2017-04-17 11:14:00 -04:00
loay 1cdb431ae2 Fix relations test case 2017-04-14 03:35:46 -04:00
Eric Barault 64f64caaff handle deep geo-near queries (#1314)
* handle deep geo-near queries (#1216)

    
a dedicated mongKey is added in geo.nearFilter for mongoDB
fixes geo min distance tests as filter now expects an array

* Fix for string geoPoints

* Add geo point handle for ibmdb connectors

* Handle geo-point type for cassandra connector
2017-04-13 17:05:05 -04:00
Loay 8865659a8a Merge pull request #1309 from strongloop/skipped-test
Unskip test case
2017-04-13 14:14:54 -04:00
Loay 9dc5430652 Unskip test case 2017-04-12 12:54:30 -04:00
Tetsuo Seto 7285e4834a Merge pull request #1323 from strongloop/add-cassandra-tests
Make tests work for other connectors as well as C*
2017-04-12 09:32:37 -07:00
Tetsuo Seto c1598584d8 Make tests work for other connectors as well as C*
Adjust getSchema calls
Compare ids as strings
Run tests when explicitly set to true
2017-04-12 09:11:42 -07:00
Tetsuo Seto 100a7ea91c Merge pull request #1319 from strongloop/remove-debug-code
Remove debugger statement
2017-04-07 15:17:58 -07:00
Tetsuo Seto 696e4cfa80 Remove debugger statement 2017-04-07 15:05:15 -07:00
Tetsuo Seto 14d966d159 Merge pull request #1318 from strongloop/fixup-for-cass
Fixup test support for Cassandra connector
2017-04-07 14:31:25 -07:00
Tetsuo Seto 0f9100f185 Fixup test support for Cassandra connector 2017-04-07 14:11:33 -07:00
Tetsuo Seto bff4ea7fd5 Merge pull request #1310 from strongloop/add-cass-tests
Add test support for Cassandra connector
2017-04-07 11:26:48 -07:00
Tetsuo Seto ead1fb2965 Add test support for Cassandra connector 2017-04-07 11:10:47 -07:00
Kevin Delisle 0e946b0cd4 Merge pull request #1311 from strongloop/use-connector-4
package: use loopback-connector@^4.0.0
2017-04-07 11:43:35 -04:00
Kevin Delisle 044f999529 package: use loopback-connector@^4.0.0 2017-04-07 10:50:59 -04:00
Kevin Delisle 00fe8fd59e Merge pull request #1313 from strongloop/revert-1216-fix/geo.nearFilter-deep
Revert ""Near" fix for where clauses"
2017-04-06 18:29:48 -04:00
Sakib Hasan befea83a76 Revert "handle deep geo-near queries (#1216)"
This reverts commit 6f88cf1930.
2017-04-06 17:45:04 -04:00
Sakib Hasan b7e2f2a649 Revert "Allow `after save` hook to see count of records changed (#1231)"
This reverts commit bb3812fbfb.
2017-04-06 17:45:04 -04:00
Joshua Chaitin-Pollak bb3812fbfb Allow `after save` hook to see count of records changed (#1231)
* `after save` hook allows count of records changed

* Fix PR linter
2017-04-06 12:02:34 -04:00
Corentin H 6f88cf1930 handle deep geo-near queries (#1216)
a dedicated mongKey is added in geo.nearFilter for mongoDB
fixes geo min distance tests as filter now expects an array
2017-04-06 08:25:04 -04:00
destillat fc2f66c514 Fix model def column name method (#1224) 2017-04-05 15:12:27 -04:00
Jonathan Sheely 21b08af7a3 Added notify flag for create and upsert (#1277)
* Added notify flag for create and upsert

* Code styling

* More code styling

* Added unit test for notify

* Fix PR linter
2017-04-05 13:23:26 -04:00
Waldemar Zahn ef143dc5eb Custom Table Names on rels (#1303)
hasAndBelongsToMany relation
2017-04-05 12:42:21 -04:00
Sakib Hasan 6a962583b0 Support multiple fk relations (#1308) 2017-04-04 18:23:43 -04:00
Thaer Abbas 57ead01624 #1261 Property name "constructor" is not allowed in 'Model' data (#1284)
* check if data has a constructor prop

* test data with no constructor

* test non function constructor

* test non function ctor message

* cleanup
2017-04-04 13:35:24 -04:00
Raymond Feng 2e6fbadd9e 3.4.1
* Use dataSource.connect to avoid duplicate connects (Raymond Feng)
 * remove equality value for user defined id (#1293) (Matteo Padovano)
2017-04-04 10:29:57 -07:00
Raymond Feng 322fa48267 Merge pull request #1307 from strongloop/feature/mem-connector-connect
Use dataSource.connect to avoid duplicate connects
2017-04-04 10:28:20 -07:00
Raymond Feng 1f995ec674 Use dataSource.connect to avoid duplicate connects 2017-04-04 10:19:58 -07:00
Matteo Padovano 957058e2d4 remove equality value for user defined id (#1293)
Some connector, like arangodb, not support id as Number.
When `forceId` is set to true and id is set `Model.isValid`
report error and the field id is not coerced.
2017-04-04 12:45:23 -04:00
Raymond Feng cac575398d 3.4.0
* Fix in-mem connector file operation racing condition (Raymond Feng)
2017-04-04 08:43:04 -07:00
Raymond Feng 5981197299 Merge pull request #1300 from strongloop/feature/fix-mem-connector
Fix in-mem connector file operation racing condition
2017-04-04 08:41:36 -07:00
Raymond Feng 0a408476ec Fix in-mem connector file operation racing condition 2017-04-04 08:25:15 -07:00
Kevin Delisle 966d5daed7 3.3.0
* make geo nearFilter support minDistance (#987) (Vincent Wen)
 * Disallow regexp string in arrays for coerce (#1279) (Mikhail)
 * Fix - `_targetClass` on scope function (#1280) (Clark Wang)
 * Fixes #1275. `Include` filter transforms fields property into array. (#1276) (Nick Oikonomou)
 * Included models from include operations do not change defined `strict` model option (#1259) (Dimitris)
 * Using a filter with exclusion of a non existent property, removes an existing one (#1257) (Dimitris)
 * Clean version of PR 1272 (#1273) (Sakib Hasan)
 * Replicate new issue_template from loopback (Siddhi Pai)
 * Replicate issue_template from loopback repo (Siddhi Pai)
 * Update README.md (Rand McKinney)
 * FindOrCreate missing error callback (Diana Lau)
 * Fixes #1230 coerceArray converts empty Objects (#1269) (Dimitris)
 * override collection name for arangodb (#1243) (Matteo Padovano)
 * Add test coverage for `validatesInclusionOf` (#1249) (Rémi Bèges)
 * dao: catch errors on Model creation in find (Kevin Delisle)
 * dao: catch sync errors on setAttributes (Kevin Delisle)
 * Update error message (Loay)
 * Fix Order query test case (Loay)
 * Doc:Add option for discoverModelDefinitions (jannyHou)
 * Add tests for validatesExclusionOf (#1248) (Rémi Bèges)
 * Fix id update error message formatting (Rémi Bèges)
 * Add test case for all connectors (jannyHou)
 * Add proper statusCode for duplicate (Loay)
 * Fix datasource to report connector-loading errors (Miroslav Bajtoš)
 * Ensure replaceById returns 404 when id not found (Loay)
 * Upgrade eslint-config, fix new violations (Miroslav Bajtoš)
 * Fix option propagation in relation methods (Miroslav Bajtoš)
 * Refactor logic of options.allowExtendedOperators (Matteo Padovano)
 * Fix forceId validation error (Loay)
 * Add two basic tests for "inq" operator (Miroslav Bajtoš)
2017-03-31 10:28:23 -04:00
siddhipai 539b317ccb Merge pull request #1251 from strongloop/replicate-issue-template
Replicate issue_template from loopback repo
2017-03-28 14:54:15 -07:00
Vincent Wen 8c93710963 make geo nearFilter support minDistance (#987) 2017-03-26 10:04:16 -04:00
Mikhail 68b93e1074 Disallow regexp string in arrays for coerce (#1279)
Disallow regexp arrays for coerce
2017-03-22 20:29:01 -04:00
Clark Wang c99441247c Fix - `_targetClass` on scope function (#1280)
Fix `_targetClass` on scope function when using hasManyThrough
relation with customized relation names and foreignKey/keyThrough.

This bug is cause by `_targetClass` uses the camel-case of
`relationName`(e.g.: if `relationName` is `bbb`, `targetClass`
would be `Bbb`), which is not exists.

This will also suppress "not exposed" warnings when generating
angular sdk, and generate end-points for this scope.
2017-03-22 17:06:36 -04:00
Nick Oikonomou b3a7bc521d Fixes #1275. `Include` filter transforms fields property into array. (#1276)
* Fixes#1275 Transform *fields* property into array

`Include` filter takes into consideration string property
'fields' and transforms it into an array containing this string.

* Added error handling for `include` filter.

* ExecTasksWithInterLeave now contains a try-catch block
 in order to catch any unexpected errors.

* LinkManyToMany now checks if *modelToIdName* exists on
 *target* before continuing.

* Added unit test for *include* with string fields
2017-03-22 10:03:36 -04:00
Dimitris 77c4cd7b01 Included models from include operations do not change defined `strict` model option (#1259)
* Fixes #1252

* Allowed setting of dynamic relation property

* Fixed tests to also consider other connectors
2017-03-20 19:48:57 -04:00
Dimitris 2bfc769c4d Using a filter with exclusion of a non existent property, removes an existing one (#1257)
* #fixes 1256

* Added missing check for returned error

* Fixed test to check proper fields in each doc
2017-03-20 19:18:48 -04:00
Sakib Hasan 3c7e398f6f Clean version of PR 1272 (#1273)
Able to filter out the properties given to a model instead
Of throwing an error
2017-03-20 18:10:01 -04:00
Rand McKinney f1ef519a5c Merge pull request #1236 from strongloop/update-readme
Update README.md
2017-03-20 14:54:39 -07:00
Siddhi Pai 564bbfae12 Replicate new issue_template from loopback 2017-03-20 14:36:59 -04:00
Siddhi Pai ba655ddb8a Replicate issue_template from loopback repo 2017-03-20 14:36:59 -04:00
Rand McKinney aa917089b9 Update README.md 2017-03-20 14:33:17 -04:00
Diana Lau cc3fb8e3f1 Merge pull request #1270 from strongloop/add-error-callback
FindOrCreate missing error callback
2017-03-20 15:42:20 +00:00
Diana Lau eb2cb315e6 FindOrCreate missing error callback 2017-03-20 10:32:09 -04:00
Dimitris 6f8ecfdf5c Fixes #1230 coerceArray converts empty Objects (#1269) 2017-03-20 10:05:11 -04:00
Matteo Padovano 1f52d23d67 override collection name for arangodb (#1243)
Add collection name settings for arangodb database.
Required to pass common tests included in community connector
2017-03-20 09:01:16 -04:00
Rémi Bèges 55128f0c9b Add test coverage for `validatesInclusionOf` (#1249)
* Fix indentation

* Improve tests formatting

* Use instanceof and should.match
2017-03-18 06:50:10 -04:00
Kevin Delisle edc1fd3d83 Merge pull request #1266 from strongloop/catch-error-on-updateAttribute
dao: catch sync errors on setAttributes
2017-03-16 18:38:10 -04:00
Kevin Delisle 248aaf0541 dao: catch errors on Model creation in find 2017-03-16 17:26:53 -04:00
Kevin Delisle a6c5802940 dao: catch sync errors on setAttributes
Wrap inst.setAttributes in try-catch to prevent synchronous errors
from crashing the application.
2017-03-16 17:26:53 -04:00
Loay 1808bd3703 Merge pull request #1267 from strongloop/translationTypo
Update error message
2017-03-16 11:18:24 -04:00
Loay 46318d2094 Update error message 2017-03-16 11:02:08 -04:00
Loay 15209b87b9 Merge pull request #1265 from strongloop/orderQuery
Fix Order query test case
2017-03-15 15:24:25 -04:00
Loay 557a2e48d2 Fix Order query test case 2017-03-15 14:45:36 -04:00
dhmlau 33d0475d82 Merge pull request #1264 from strongloop/doc/discovermodeldefinitions-options
doc: Add option for discoverModelDefinitions
2017-03-15 02:40:54 +00:00
jannyHou 7373e1ae31 Doc:Add option for discoverModelDefinitions 2017-03-14 21:51:30 -04:00
Rémi Bèges 11c2a19ad2 Add tests for validatesExclusionOf (#1248) 2017-03-08 10:24:18 -05:00
Kevin Delisle 76c73d55d2 Merge pull request #1196 from Overdrivr/improve-id-update-error-message
Fix error message formatting when trying to update an id property
2017-02-16 13:38:41 -05:00
Rémi Bèges 9afaa9a66e Fix id update error message formatting
Error is raised when trying to update an id property while forceId
is set to true
2017-02-15 18:26:32 +01:00
Janny 0cf863a483 Merge pull request #1239 from strongloop/feature/query-nested-property
Support query nested properties
2017-02-14 16:37:27 -05:00
jannyHou 8b1100e3ed Add test case for all connectors 2017-02-14 14:01:44 -05:00
Loay 22cf48bd21 Merge pull request #1245 from strongloop/duplicate-code
Add proper statusCode for duplicate
2017-02-09 10:06:30 -05:00
Loay 9541bb5f15 Add proper statusCode for duplicate 2017-02-08 23:52:14 -05:00
Miroslav Bajtoš ca406b6d24 Merge pull request #1241 from strongloop/fix/connector-loader
Fix datasource to report connector-loading errors
2017-02-06 10:56:50 +01:00
Miroslav Bajtoš e8a977f55b Fix datasource to report connector-loading errors
Before this change, when resolving full connector path, all errors were
ignored. As a result, when the connector was installed but not
correctly built (e.g. loopback-connector-db2 which uses a native addon),
a very confusing message was reported by LoopBack.

In this commit, I am fixing the code handling `require()` errors
to ignore only MODULE_NOT_FOUND errors that contain the name
of the required module.
2017-02-03 20:29:11 +01:00
Loay ad9934159b Merge pull request #1240 from strongloop/replaceById-test
Ensure replaceById returns 404 when id not found
2017-02-01 13:11:26 -05:00
Loay 4bd03a25f2 Ensure replaceById returns 404 when id not found 2017-02-01 11:57:54 -05:00
Miroslav Bajtoš c509a9f7fe Merge pull request #1242 from strongloop/upgrade/eslint-config
Upgrade eslint-config, fix new violations
2017-02-01 16:34:32 +01:00
Miroslav Bajtoš d809260799 Upgrade eslint-config, fix new violations 2017-02-01 12:45:56 +01:00
Miroslav Bajtoš 121afda79b Fix option propagation in relation methods
- EmbedsMany.prototype.remove
 - EmbedsMany.prototype.add
2017-01-31 16:10:56 +01:00
Miroslav Bajtoš b781dae339 Merge pull request #979 from mrbatista/master
Refactor logic of options.allowExtendedOperators
2017-01-30 14:35:44 +01:00
Matteo Padovano 733ad1a024 Refactor logic of options.allowExtendedOperators
Implement logic to allowExtendedOperators options
per request, per Model and Datasource.
2017-01-30 00:05:56 +01:00
Loay 023856cbe9 Merge pull request #1210 from strongloop/forceId-true
Fix forceId validation error
2017-01-27 00:08:28 -05:00
Loay 44a5a7ad81 Fix forceId validation error 2017-01-26 16:52:19 -05:00
Miroslav Bajtoš ae07480f45 Merge pull request #1232 from strongloop/add-inq-tests
Add two basic tests for "inq" operator
2017-01-20 12:58:50 +01:00
Raymond Feng cf7f05db8b 3.2.0
* Fix should dep (Raymond Feng)
 * Upgrade dependencies to remove npm install warnings (Raymond Feng)
 * Add missing return for KVAO delete all (Simon Ho)
 * Add missing return in KVAO keys test suite (Simon Ho)
 * Detect deleteAll support in KVAO tests (Simon Ho)
 * Coerce array-like objects into arrays (Heath Morrison)
 * Refactor flush to deleteAll (Simon Ho)
 * Upgrade eslint-config to 7.x (Miroslav Bajtoš)
 * Throw error when model relation name is trigger (Brian Schemp)
 * Add flush operation to KVAO (Simon Ho)
 * Fix block padding (Siddhi Pai)
2017-01-19 10:28:38 -08:00
Raymond Feng 315c2774cb Fix should dep 2017-01-19 10:27:48 -08:00
Raymond Feng 6d7ae88a94 Merge pull request #1228 from strongloop/upgrade-deps
Upgrade dependencies to remove npm install warnings
2017-01-19 10:24:57 -08:00
Miroslav Bajtoš b5d03b845f Add two basic tests for "inq" operator 2017-01-19 13:33:39 +01:00
Raymond Feng 0c76bd21b9 Upgrade dependencies to remove npm install warnings 2017-01-17 09:45:51 -08:00
Simon Ho 5a7283386c Merge pull request #1222 from strongloop/fix-missing-return-for-kvao-delete-all
Add missing return for KVAO delete all
2017-01-13 00:44:56 -08:00
Simon Ho 9a0d34a7a3 Add missing return for KVAO delete all 2017-01-13 00:19:10 -08:00
Simon Ho 22f2abf225 Merge pull request #1220 from strongloop/add-kvao-test-missing-return
Add missing return in KVAO keys test suite
2017-01-11 20:59:26 -08:00
Simon Ho 188fb10c96 Add missing return in KVAO keys test suite 2017-01-11 19:35:37 -08:00
Simon Ho 736a4ad185 Merge pull request #1218 from strongloop/clear-cache-if-delete-all-supported
Detect deleteAll support in KVAO tests
2017-01-11 19:31:22 -08:00
Simon Ho 0b93c5c6dd Detect deleteAll support in KVAO tests
Clear CacheItem data between tests if connector supports `deleteAll`.
Tests fail with 501 if this check is not used.
2017-01-11 16:30:33 -08:00
Miroslav Bajtoš b530ec2a65 Merge pull request #1143 from doublemarked/hm/coerce-array-like-objects-as-arrays
Coercing conditions with array-like objects into arrays
2017-01-10 15:03:13 +01:00
Heath Morrison 2377792c22 Coerce array-like objects into arrays
The query-string parser used by express
https://github.com/ljharb/qs#parsing-arrays
limits the size of arrays that are created from query strings to 20
items. Arrays larger than that are converted to objects using numeric
indices.

This commit fixes the coercion algorithm used by queries to
treat number-indexed objects as arrays. We still maintain a strict
understanding of an "array-like object" to limit the opportunity for
subtle bugs. In particular, the presence of non-index keys is an
indication that the object was not intended to be interpreted as
an array.
2017-01-10 14:46:41 +01:00
Simon Ho 6f2a075bee Merge pull request #1214 from strongloop/refactor/kvao-flush
Refactor/kvao flush to deleteAll
2017-01-09 18:31:50 -08:00
Simon Ho 2320df1227 Refactor flush to deleteAll
- Rename `flush` to `deleteAll`
- Add `delete`
- Detect `delete/deleteAll` before running downstream test suites
- Fall back to unoptimized `deleteAll` when connector does not support
  `deleteAll` but supports `delete`
- Return 501 for connectors not supporting `delete` or `deleteAll`
2017-01-09 14:53:34 -08:00
Miroslav Bajtoš 1e0564048b Merge pull request #1215 from strongloop/upgrade-eslint
Upgrade eslint-config to 7.x
2017-01-06 14:13:05 +01:00
Miroslav Bajtoš 454bf93aaf Upgrade eslint-config to 7.x
Also upgrade eslint itself to 3.x.
2017-01-06 13:33:54 +01:00
Miroslav Bajtoš 66c54a9646 Merge pull request #1204 from schempy/fix/invalid-model-relation-name
Throw error when model relation name is trigger
2017-01-03 10:40:13 +01:00
Brian Schemp cd94be2fb8 Throw error when model relation name is trigger
Defining a model relation with the name "trigger" causes the model not
able to insert records. No error is thrown when a model relation with
the name "trigger" is defined. Adding a check for the model relation
name "trigger" will now throw an error.
2017-01-02 17:09:14 +01:00
Simon Ho 79ec4211ab Merge pull request #1206 from strongloop/add-flush-op-to-kvao
Add flush operation to KVAO
2016-12-30 22:43:10 -08:00
Simon Ho f38709b7cb Add flush operation to KVAO
Used to delete all keys (and values) associated to the current model.
2016-12-30 18:06:36 -08:00
Simon Ho d095cc1161 Merge pull request #1194 from strongloop/1237/fix-block-padding
Fix block padding
2016-12-21 14:17:42 -08:00
Miroslav Bajtoš 0ad75bd93e 3.1.1
* Update package.json for LB3 release (Simon Ho)
 * Fix eslint errors reported by the latest eslint (Miroslav Bajtoš)
 * Fix HasOne.update to propagate options arg (Miroslav Bajtoš)
 * Fix linter errors for CI (Simon Ho)
 * Replicate .github from loopback repo (Siddhi Pai)
 * Update ko translation file (Candy)
 * Honour allowExtendedOperators in "DAO.find" (Miroslav Bajtoš)
 * Fix MySql CI server Failure (Loay)
 * Upgrade eslint & config to latest (Miroslav Bajtoš)
2016-12-21 16:04:41 +01:00
Miroslav Bajtoš 05f10c859e Merge pull request #1198 from strongloop/release/3.x
Prepare for 3.x GA
2016-12-21 10:49:55 +01:00
Simon Ho b60e09756d Update package.json for LB3 release 2016-12-21 10:44:55 +01:00
Miroslav Bajtoš a9a4fa498d Merge pull request #1197 from strongloop/fix/options-propagation
Fix HasOne.update to propagate options arg
2016-12-21 10:32:45 +01:00
Miroslav Bajtoš 2ca081216b Fix eslint errors reported by the latest eslint 2016-12-20 17:37:54 +01:00
Miroslav Bajtoš 0d862890e0 Fix HasOne.update to propagate options arg 2016-12-20 11:40:22 +01:00
Siddhi Pai 3baa61590e Fix block padding
* Remove test/.eslintrc
* run eslint . --fix
2016-12-13 16:05:50 -08:00
Simon Ho d99dca6fc0 Merge pull request #1191 from strongloop/fix-linter-errors
Fix linter errors for CI
2016-12-09 18:35:52 -08:00
Simon Ho c5e905f5c4 Fix linter errors for CI 2016-12-09 18:13:58 -08:00
Simon Ho 4a4ba74114 Merge pull request #1184 from strongloop/update-support-URL
Replicate .github from loopback repo
2016-12-09 17:44:18 -08:00
Siddhi Pai d45943130c Replicate .github from loopback repo 2016-12-09 17:22:45 -08:00
Miroslav Bajtoš 29c60c7b42 Merge pull request #1180 from strongloop/feature/extended-operators-in-query
Honour allowExtendedOperators in "DAO.find"
2016-12-08 09:56:54 +01:00
Simon Ho 1b60245298 Merge pull request #1187 from strongloop/add_translation8
Update ko translation file
2016-12-07 09:46:29 -08:00
Candy 2d016fa090 Update ko translation file 2016-12-07 11:50:40 -05:00
Miroslav Bajtoš 779cf6a370 Honour allowExtendedOperators in "DAO.find"
Modify the coercion of filter.where to hounour "allowExtendedOperators"
and don't coerce property values of type object (extended operators).
2016-12-06 10:28:40 +01:00
Miroslav Bajtoš 80d2264bc9 Merge pull request #1179 from strongloop/update/eslint
Upgrade eslint & config to latest
2016-12-06 10:12:11 +01:00
Loay 64517b5b02 Merge pull request #1181 from strongloop/Mysql-CI-Fix
Fix MySql CI server Failure
2016-12-05 15:53:08 -05:00
Loay e14c48719e Fix MySql CI server Failure 2016-12-05 11:42:08 -05:00
Miroslav Bajtoš 0f7a567f18 Upgrade eslint & config to latest
- eslint ^3.11.1
 - eslint-config-loopback: ^6.0.0
 - fix linter errors (mostly no-undef)
2016-12-05 15:14:09 +01:00
Miroslav Bajtoš 0fea9ebef0 3.1.0
* Apply hasManyThrough filter on target model (jannyHou)
 * Remove valid connectors from downstream ignores (Simon Ho)
 * Add some connectors to ignoreList (jannyHou)
 * Tests cleanup (Amir Jafarian)
 * Fixed example for creating ValidationError (Boštjan Pišler)
 * Correct tests for DAO.Create (Amir Jafarian)
 * Add downstream ignore list config (Simon Ho)
 * Remove duplicate "engines" from package.json (Miroslav Bajtoš)
 * Drop support for Node v0.10 and v0.12 (Miroslav Bajtoš)
 * Fix a test (Amir Jafarian)
 * Add more robust OH tests for find method (Amir Jafarian)
 * Add support for `loaded` hook (Amir Jafarian)
 * Use imperative mood for tests (Amir Jafarian)
 * Continue _coerce after logical operators (Heath Morrison)
 * Make variable names more clear (Amir Jafarian)
 * test/kvao: add connectorCapabilities options (Miroslav Bajtoš)
 * Fix validateNumericality, nullCheck & add tests (CerealGuy)
 * Add test for operation hooks (Amir Jafarian)
 * Add ilike and nilike operators (Nick Duffy)
 * Fix JSDoc issue (Amir Jafarian)
 * Update ja translation file (Candy)
 * Remove 3.0 RELEASE-NOTES (Miroslav Bajtoš)
 * Fix linting errors (Simon Ho)
 * Update validations.js (Rand McKinney)
 * Update translation files - round#2 (Candy)
 * Fix CI Failures in MySQL (Loay)
 * Add code review fixups (Simon Ho)
 * More descriptive name for model with shortid (Tim De Pauw)
 * Polish PR (Tim De Pauw)
 * Support {defaultFn: 'shortid'} (Tim De Pauw)
2016-12-05 10:18:01 +01:00
Amirali Jafarian dd92b8d7e8 Merge pull request #1175 from BostjanPisler/patch-1
Fixed example for creating ValidationError
2016-12-03 10:59:12 -05:00
Kevin Delisle 4f2c16709b Merge pull request #1153 from strongloop/fix/filter-on-related-model
Apply filter on related model
2016-12-01 13:19:51 -05:00
jannyHou 6c8e806bc8 Apply hasManyThrough filter on target model 2016-12-01 10:08:27 -05:00
Simon Ho b95224bd83 Merge pull request #1178 from strongloop/update-downstream-ignore-list
Remove valid connectors from downstream ignore list
2016-11-30 18:24:11 -08:00
Simon Ho edb8fa393e Remove valid connectors from downstream ignores
- Remove Microsoft SQL connector
- Remove Oracle connector
2016-11-30 17:20:50 -08:00
Janny 2ccd666449 Merge pull request #1176 from strongloop/ci/ignore-list
Add some connectors to ignoreList
2016-11-30 15:09:43 -05:00
Amirali Jafarian 3ba7a5d1e8 Merge pull request #1172 from strongloop/tests_cleanup
Tests cleanup
2016-11-30 14:50:59 -05:00
jannyHou b8fb9cded3 Add some connectors to ignoreList 2016-11-30 13:18:07 -05:00
Amir Jafarian e391fd0f3e Tests cleanup
* Tests cleanup for `manipulation.test` and `scope.test`
2016-11-29 10:45:03 -05:00
Boštjan Pišler 93a739d612 Fixed example for creating ValidationError 2016-11-29 16:04:53 +01:00
Amir Jafarian fab269687b Correct tests for DAO.Create
* Create does not return data back
2016-11-28 17:18:10 -05:00
Ryan Graham c8ade9e9d0 Merge pull request #1170 from strongloop/add-downstream-ignore-list-config
Add downstream ignore list config
2016-11-25 11:24:32 -08:00
Simon Ho c352dcff7d Add downstream ignore list config 2016-11-25 10:33:00 -08:00
Miroslav Bajtoš 401b7e4296 Remove duplicate "engines" from package.json
The problem was introduced by 1fb7842
2016-11-15 15:45:24 +01:00
Miroslav Bajtoš 242f261934 Merge pull request #1165 from strongloop/drop-support-node-0x
Drop support for Node v0.10 and v0.12
2016-11-15 15:04:00 +01:00
Miroslav Bajtoš 1fb78422fa Drop support for Node v0.10 and v0.12 2016-11-15 14:21:02 +01:00
Amirali Jafarian 72c27b040c Merge pull request #1160 from strongloop/fix_test
Fix a test
2016-10-30 20:56:42 -04:00
Amir Jafarian d908a52753 Fix a test
* Fix location for an instance in a test
2016-10-30 20:50:06 -04:00
Amirali Jafarian 0b312e02d5 Merge pull request #1158 from strongloop/more_tests_geoQuery
Add more robust OH tests for find method
2016-10-28 17:57:29 -04:00
Amir Jafarian 756e936c4b Add more robust OH tests for find method 2016-10-28 16:56:38 -04:00
Amirali Jafarian 839bb9a81e Merge pull request #1149 from strongloop/near_loaded_oh
Add support for `loaded` operation hook for DAO.find() when near is used
2016-10-28 15:01:21 -04:00
Amir Jafarian 54d0f5b53d Add support for `loaded` hook
* Add support for loaded hook for DAO.find with near filter
2016-10-28 11:46:46 -04:00
Amirali Jafarian fc4ea432dd Merge pull request #1156 from strongloop/fix_test_styles
Use imperative mood for tests
2016-10-27 16:51:00 -04:00
Amir Jafarian a65311dc7c Use imperative mood for tests
* Use imperative mood for tests in test/loopback-dl.test.js
2016-10-27 16:38:40 -04:00
Amirali Jafarian 9d99f9d2af Merge pull request #1142 from doublemarked/hm/coerce-after-logical-operators
_coerce continues after encountering a logical op
2016-10-26 10:11:56 -04:00
Heath Morrison 266e9f5a9a Continue _coerce after logical operators 2016-10-25 23:09:46 +03:00
Amirali Jafarian 5091f71416 Merge pull request #1147 from strongloop/fixup_1109
Fix up #1109
2016-10-24 22:41:29 -04:00
Amir Jafarian 212e9b1f85 Make variable names more clear
* Fix up #1109
2016-10-21 17:26:39 -04:00
Amirali Jafarian d9a736a4a8 Merge pull request #1109 from C3realGuy/dev_validations
validateNumericality should skip undefined
2016-10-20 07:37:52 -04:00
Miroslav Bajtoš b76a49aedd Merge pull request #1140 from strongloop/feature/parameterize-kvao-tests
test/kvao: add connectorCapabilities options
2016-10-19 12:28:09 +02:00
Miroslav Bajtoš 011bfbb236 test/kvao: add connectorCapabilities options
- canExpire
 - canQueryTtl
 - ttlPrecision
 - canIterateKeys
 - canIterateLargeKeySets

These options allow connectors to disable shared tests for features
that are not supported/implemented.
2016-10-19 11:06:17 +02:00
CerealGuy 662458dc2c Fix validateNumericality, nullCheck & add tests
validateNumericality didn't test if attributes value is a number
only if it's type is number.
Further nullCheck had a wrong testing order. It first checked if
value is null, later if blank. Also null check only used two equals,
not three. We don't use blank() anymore, testing if variable is
undefined should be fine too.
Added tests covering validateNumericality.
2016-10-15 10:59:22 +02:00
Amirali Jafarian ec204dfa14 Merge pull request #1125 from strongloop/Add_test_for_geo_query_oh
Add test for operation hooks
2016-10-14 09:36:29 -04:00
Amir Jafarian f5e9b53289 Add test for operation hooks
* Add test for operation hook when near filter is used
2016-10-14 09:23:26 -04:00
Simon Ho 1ee04421c0 Merge pull request #1091 from duffn/ilike
Add ilike and nilike operators
2016-10-12 18:09:15 -07:00
Nick Duffy a23076d3a8 Add ilike and nilike operators
Closes #633
2016-10-12 18:31:31 -06:00
Amirali Jafarian c6e5d385c7 Merge pull request #1133 from strongloop/issue_1132
Fix JSDoc issue
2016-10-11 12:54:38 -04:00
Amir Jafarian e42b1327aa Fix JSDoc issue 2016-10-11 12:15:35 -04:00
Candy 85625829e0 Merge pull request #1130 from strongloop/add_translation3
Update ja translation file
2016-10-06 15:22:12 -04:00
Candy e1b7c31e0f Update ja translation file 2016-10-06 11:26:33 -04:00
Miroslav Bajtoš f4d92cf131 Merge pull request #1126 from strongloop/docs/remove-release-notes
Remove 3.0 RELEASE-NOTES
2016-10-06 12:44:26 +02:00
Miroslav Bajtoš d70ce8aba5 Remove 3.0 RELEASE-NOTES
The release notes were moved to loopback.io docs site.
2016-10-05 16:04:33 +02:00
Simon Ho 99a864e9c6 Merge pull request #1123 from strongloop/superkhau/fix-linting-errors
Fix linting errors
2016-09-29 20:19:08 -07:00
Simon Ho b089b0d786 Fix linting errors
Trailing spaces in comments causing linter to fail. Errors introduced
at commit 9a1ef08495.
2016-09-29 19:28:02 -07:00
Loay d557fb0808 Merge pull request #1114 from strongloop/Fix/ciMysql
Fix CI Failures in MySQL
2016-09-29 11:30:14 -04:00
Rand McKinney 9a1ef08495 Update validations.js
Add doc of allowNull options property per #372.
2016-09-28 16:43:17 -07:00
Amirali Jafarian 236bb2bb16 Merge pull request #1117 from strongloop/add_translation2
Update translation files - round#2
2016-09-28 17:15:30 -04:00
Candy 0a8b44d269 Update translation files - round#2 2016-09-28 13:56:44 -04:00
Loay 2cb0d042e4 Fix CI Failures in MySQL 2016-09-26 20:27:33 -04:00
Simon Ho 24f000d978 Merge pull request #1107 from strongloop/1101
Takeover: 1101
2016-09-22 21:00:01 -07:00
Simon Ho 06d4b90071 Add code review fixups 2016-09-22 16:15:32 -07:00
Tim De Pauw 5636c15903 More descriptive name for model with shortid 2016-09-22 16:07:34 -07:00
Tim De Pauw 419a464d06 Polish PR 2016-09-22 16:07:34 -07:00
Tim De Pauw be1d71f626 Support {defaultFn: 'shortid'} 2016-09-22 16:07:34 -07:00
Miroslav Bajtoš 8b835b1b5c 3.0.0
* Describe the change of forceId (jannyHou)
 * Add translation files (Amir Jafarian)
 * Add 'isNewInstance' for updateAttributes (Amir Jafarian)
 * Strict mode now always return validationError (David Cheung)
 * Add docs for KVAO (Simon Ho)
 * Skip test temporarily (Loay)
 * Fix BSON Object ID errors for CI (Simon Ho)
2016-09-22 12:15:54 +02:00
Miroslav Bajtoš 2ee331ef44 Merge pull request #1103 from strongloop/doc/forceId-3.x
Describe the change of forceId
2016-09-22 12:05:07 +02:00
jannyHou ea13e95d9e Describe the change of forceId 2016-09-22 11:51:31 +02:00
Amirali Jafarian baa557116c Merge pull request #1098 from strongloop/Globalization-translation
Add translation files
2016-09-21 10:22:33 -04:00
Amirali Jafarian 66f27b9b83 Merge pull request #1094 from strongloop/newInstance_loade_updateAttributes
Add 'isNewInstance' for updateAttributes
2016-09-21 09:23:57 -04:00
Amir Jafarian 4185605327 Add translation files 2016-09-20 13:34:44 -04:00
David Cheung 373e038301 Merge pull request #1084 from strongloop/strict-mode-cleanup
[SEMVER-MAJOR] Strict mode cleanup
2016-09-20 08:24:31 -04:00
Amir Jafarian fec7742a69 Add 'isNewInstance' for updateAttributes
* Add 'isNewInstance' to loaded hook for updateAttributes
2016-09-19 16:56:15 -04:00
Simon Ho 7365e3200b Merge pull request #1093 from strongloop/docs-for-kvao
Add docs for KVAO
2016-09-19 13:23:12 -07:00
David Cheung 805db78e19 Strict mode now always return validationError
- Deprecation of strict:validate and strict:throw
- When strict mode is enabled, it will now always
return validation error (previous strict:validate)
2016-09-19 10:27:24 -04:00
Simon Ho 6796fac7f1 Add docs for KVAO 2016-09-16 17:03:33 -07:00
Simon Ho 5bf18b0728 Merge pull request #1088 from strongloop/Fix-CI/mssql
Skip test temporarily
2016-09-14 13:12:21 -07:00
Loay 32a6b68f1d Skip test temporarily 2016-09-09 14:48:41 -04:00
Simon Ho 664a7dfcd4 Merge pull request #1087 from strongloop/fix-bson-object-id-errors-for-ci
Fix BSON Object ID errors for CI
2016-09-08 14:28:09 -07:00
Simon Ho 11ce971ad0 Fix BSON Object ID errors for CI 2016-09-08 13:16:55 -07:00
Miroslav Bajtoš a944244a7b 3.0.0-alpha.8
* Add missing "done" arg in test/kvao/ttl.suite (Miroslav Bajtoš)
 * Support nested queries for arrays (pponugo)
 * Refactor TTL tests for KV memory connector (Simon Ho)
 * Fix test case for expire (Simon Ho)
 * Fix failures of upsertWithWhere (Amir Jafarian)
 * Remove expired item before executing expire (Simon Ho)
 * Disable `strict` for a few files (Amir Jafarian)
2016-09-08 10:42:58 +02:00
Miroslav Bajtoš d2a20a1090 Merge pull request #1086 from strongloop/fix/kvao-ttl-test
Add missing "done" arg in test/kvao/ttl.suite
2016-09-08 10:38:43 +02:00
Miroslav Bajtoš a438c72cc5 Add missing "done" arg in test/kvao/ttl.suite 2016-09-08 10:22:27 +02:00
Miroslav Bajtoš fc06d35994 Merge pull request #1083 from strongloop/feature/query-nested-array
Support nested queries for arrays
2016-09-07 13:51:57 +02:00
pponugo a39c0236bb Support nested queries for arrays
Enhance the built-in memory connector to correctly support nested
queries for arrays in addition to objects.

E.g. if "friends" is an array of objects containing "name", then
{ where: { "friends.name": "Jane" } } should match records containing
a friend called "Jane".
2016-09-07 13:33:57 +02:00
Simon Ho 19dae302a2 Merge pull request #1078 from strongloop/forwardport/refactor-ttl-suite
Refactor TTL tests for KV memory connector
2016-09-06 16:02:01 -07:00
Simon Ho 095745c93b Refactor TTL tests for KV memory connector
Reduce the complixity in the TTL test suite for the kv-memory connector
to get CI to pass.
2016-09-04 12:27:33 -07:00
Simon Ho f102f6302b Merge pull request #1075 from strongloop/forwardport/test-fix-for-expire
Fix test case for expire
2016-09-02 16:03:54 -07:00
Amirali Jafarian d888d758c0 Merge pull request #1073 from strongloop/fix_upsertWithWhere_failures
Fix failures of upsertWithWhere
2016-09-02 17:01:43 -04:00
Simon Ho b884138923 Fix test case for expire
Forwardport of #1074. #1072 was missing Promise.resolve before using
delay(20) and causing Travis to fail on 2.x. This PR makes the test code
consistent on both master and 2.x.
2016-09-02 13:59:44 -07:00
Simon Ho 68294babdb Merge pull request #1072 from strongloop/bug/remove-expired-items-before-executing-expire
Remove expired items before executing expire
2016-09-02 13:17:44 -07:00
Amir Jafarian 581b8c61bf Fix failures of upsertWithWhere
Forwardport of #1052
2016-09-02 15:46:36 -04:00
Simon Ho 96cd8ff56b Remove expired item before executing expire
The expire feature is falsely returning 204 instead of 404 because it is
not removing expired items before execution.
2016-09-01 21:18:40 -07:00
Amirali Jafarian 72200ce935 Merge pull request #1068 from strongloop/turn_offf_strict
Disable `strict` for a few files
2016-08-26 10:21:31 -04:00
Amir Jafarian 2830062259 Disable `strict` for a few files
*Disable `strict` for a few files to disappear warnings
2016-08-26 09:54:31 -04:00
Miroslav Bajtoš f816e52ac5 3.0.0-alpha.7
* test/memory: remove dummy findOrCreate impl (Miroslav Bajtoš)
 * Fix CI introduced by `use strict` (Amir Jafarian)
 * Fix manually (Amir Jafarian)
 * Auto-update by eslint --fix (Amir Jafarian)
 * Update eslint (Amir Jafarian)
 * kvao: implement key filter (Miroslav Bajtoš)
 * kvao: add iterateKeys() and keys() (Miroslav Bajtoš)
 * Globalize KeyValue Memory connector (Simon Ho)
 * upsertWithWhere feature support in juggler DAO (Sonali Samantaray)
 * Fix typo (Amir Jafarian)
 * Rename get test suite to match other test suites (Simon Ho)
 * Add TTL for KeyValue related features (Simon Ho)
2016-08-26 10:09:27 +02:00
Miroslav Bajtoš d818168c05 Merge pull request #1063 from strongloop/cleanup/memory-test
test/memory: remove dummy findOrCreate impl
2016-08-26 09:52:28 +02:00
Miroslav Bajtoš 6d3ea21c16 test/memory: remove dummy findOrCreate impl
Let the operation-hook tests use the real implementation,
now that we have it in place.
2016-08-26 09:46:59 +02:00
Amirali Jafarian 4ce8f97b15 Merge pull request #1064 from strongloop/fix_strict
Fix CI introduced by `use strict`
2016-08-25 10:25:54 -04:00
Amir Jafarian c17a490708 Fix CI introduced by `use strict` 2016-08-25 09:49:02 -04:00
Amirali Jafarian fc9b9806c8 Merge pull request #1062 from strongloop/update_eslint
Update eslint
2016-08-24 15:55:08 -04:00
Amir Jafarian aec678d252 Fix manually 2016-08-22 19:20:12 -04:00
Amir Jafarian aa6d28268b Auto-update by eslint --fix 2016-08-22 15:12:25 -04:00
Amir Jafarian df18af9ba0 Update eslint 2016-08-22 15:12:25 -04:00
Simon Ho 5b46484277 Merge pull request #1056 from strongloop/globalize-kv-mem-connector
Globalize KeyValue Memory connector
2016-08-19 12:58:31 -07:00
Miroslav Bajtoš b3907caad2 Merge pull request #1049 from strongloop/feature/kvao-iterate-keys
kvao: add iterateKeys() and keys()
2016-08-18 10:29:45 +02:00
Miroslav Bajtoš 3b653a192b kvao: implement key filter 2016-08-18 09:59:56 +02:00
Miroslav Bajtoš 01ce7df60f kvao: add iterateKeys() and keys()
Add a core implementation of KVAO.iterateKeys() which returns an
AsyncIterator, inspired by
 - https://github.com/tc39/proposal-async-iteration
 - https://www.npmjs.com/package/async-iterators

This way we can safely iterate even large sets of data.

Also add KVAO.keys(), a sugar API converting the result of iterateKeys()
into a single array.
2016-08-18 09:59:56 +02:00
Simon Ho 8b28cb3993 Globalize KeyValue Memory connector 2016-08-17 18:22:17 -07:00
Amir-61 56aeeebfb0 Merge pull request #1001 from mountain1234585/upsertNPK
upsertWithWhere method
2016-08-16 11:50:43 -04:00
Sonali Samantaray 37541dd178 upsertWithWhere feature support in juggler DAO 2016-08-16 18:06:01 +05:30
Miroslav Bajtoš 552f50bdf1 Merge pull request #1047 from strongloop/fix-kvao-get-suite-name
Rename get test suite to match other test suites
2016-08-16 09:14:18 +02:00
Amir-61 48370fd6a5 Merge pull request #1048 from strongloop/typo
Fix typo
2016-08-15 21:52:52 -04:00
Amir Jafarian 62649b3915 Fix typo 2016-08-15 21:51:36 -04:00
Simon Ho e1a649ed58 Rename get test suite to match other test suites 2016-08-15 11:13:07 -07:00
Simon Ho 827f03a45c Merge pull request #1030 from strongloop/ttl
Ttl
2016-08-12 12:59:28 -07:00
Simon Ho 1c20cc83aa Add TTL for KeyValue related features 2016-08-11 17:12:36 -07:00
Miroslav Bajtoš d7cf478b52 3.0.0-alpha.6
* Return error if the connector does not implement (Amir Jafarian)
 * kv-memory: fix crash in regular cleanup (Miroslav Bajtoš)
 * test/relation: add missing error handlers (Miroslav Bajtoš)
 * forceId=true with auto-increment db (jannyHou)
 * Fixup globalization (Amir Jafarian)
 * kvao: return 404 when expiring unknown key (Miroslav Bajtoš)
 * Implement KeyValue API and memory connector (Miroslav Bajtoš)
 * Disallow bulk updateOrCreate. (Richard Pringle)
 * Update globalization (Amir Jafarian)
 * Use g.f instead of utils.format (Amir Jafarian)
 * Optimize related model queries (Horia Radu)
 * Support for globalization (Amir Jafarian)
 * Update include.js (Rand McKinney)
 * Fix test case typo (Supasate Choochaisri)
 * Remove unused variables in model.js (Amir Jafarian)
 * Declare `definition` (Amir Jafarian)
 * Add test to catch invalid date property (Supasate Choochaisri)
 * Update URLs in CONTRIBUTING.md (#1002) (Ryan Graham)
 * Ensure stable order of items in DAO.find() (Miroslav Bajtoš)
 * Add test for updateOrCreate (Amir Jafarian)
 * Update validations.js (Rand McKinney)
 * Remove DataSource.registerType() (gunjpan)
 * give options to validators #984 (RobinBiondi)
 * Throw Error for property names with dots (gunjpan)
 * Update datasource.js (Ritchie Martori)
2016-08-11 13:19:54 +02:00
Miroslav Bajtoš b01df10eae Merge pull request #1039 from strongloop/fix/kv-memory-reference-error
kv-memory: fix crash in regular cleanup
2016-08-10 14:18:11 +02:00
Amir-61 1e57d4f316 Merge pull request #1034 from strongloop/err_connector_not_implements_replaceById
Return error if the connector does not implement
2016-08-09 14:01:58 -04:00
Amir-61 954c0df0c6 Merge pull request #1035 from strongloop/globalization_fixup
Fixup globalization
2016-08-09 10:44:06 -04:00
Amir Jafarian 327c785347 Return error if the connector does not implement
* Return error if the connector does not implement `replaceById`
2016-08-09 10:37:15 -04:00
Janny c4b2921977 Merge pull request #982 from strongloop/fix/auto-increment-db
forceId=true with auto-increment db
2016-08-09 10:02:36 -04:00
Miroslav Bajtoš 4978cd8089 kv-memory: fix crash in regular cleanup
Fix bug in "_setupRegularCleanup()" where the interval callback
was trying to access an object that has been garbage-collected
in the meantime.
2016-08-09 15:35:23 +02:00
Miroslav Bajtoš 8e81185375 Merge pull request #1033 from strongloop/fix/kvao-expire-error-status-code
KeyValueAccessObject: return 404 when expiring unknown key
2016-08-09 10:46:37 +02:00
Miroslav Bajtoš baec1b5b77 test/relation: add missing error handlers 2016-08-08 16:26:26 -04:00
jannyHou 8935b978f3 forceId=true with auto-increment db 2016-08-08 16:26:26 -04:00
Amir Jafarian d181fd0671 Fixup globalization 2016-08-08 15:34:41 -04:00
Miroslav Bajtoš 9ced20fdcc kvao: return 404 when expiring unknown key 2016-08-08 17:22:33 +02:00
Miroslav Bajtoš 83a2826a59 Merge pull request #1023 from strongloop/kv-memory
KeyValue access object + memory connector
2016-08-08 14:43:32 +02:00
Miroslav Bajtoš f15b4e2c86 Implement KeyValue API and memory connector
Models attached to a KeyValue connector get the following *static*
methods:

    Color.set(key, value);
    Color.set(key, value, ttl);
    Color.set(key, value, { ttl: ttl });

    Color.get(key);

    Color.expire(key, ttl);
2016-08-08 10:15:34 +02:00
Miroslav Bajtoš e3b6b7891c Merge pull request #889 from strongloop/PUT-bulk-update
[SEMVER-MAJOR] Disallow bulk updateOrCreate.
2016-08-05 13:33:55 +02:00
Richard Pringle 0b62dd94ea Disallow bulk updateOrCreate. 2016-08-05 11:54:06 +02:00
Amir-61 c2a683bca4 Merge pull request #1007 from horiaradu/master
Optimize related model queries
2016-08-03 16:24:32 -04:00
Amir-61 d02720252e Merge pull request #1026 from strongloop/update_globalization
Update globalization
2016-08-03 15:19:21 -04:00
Amir Jafarian a5429dc026 Update globalization 2016-08-03 14:48:35 -04:00
Amir-61 f2edbd91c3 Merge pull request #1024 from strongloop/use_g.f_insteadof_utils.format
Use g.f instead of utils.format
2016-08-03 12:08:32 -04:00
Amir Jafarian f2f9b4a6f8 Use g.f instead of utils.format 2016-08-03 10:47:40 -04:00
Horia Radu c3f62991c3 Optimize related model queries
No longer query for the related/included model when no results are
obtained in the first query.

fix:
https://github.com/strongloop/loopback-datasource-juggler/issues/1006
2016-08-01 20:23:08 +03:00
Amir-61 799d803fa0 Merge pull request #1022 from strongloop/feature/add_globalization
Support for globalization
2016-07-28 17:00:50 -04:00
Amir Jafarian 4ce5b5d3a0 Support for globalization 2016-07-28 15:20:18 -04:00
Rand McKinney f1ed1ee023 Update include.js
Change doc comments to remove spurious API doc entry per #1008
2016-07-25 08:48:47 -07:00
Amir-61 865b782caf Merge pull request #1016 from supasate/fix-test-case-typo
Fix test case typo
2016-07-24 08:46:01 -04:00
Supasate Choochaisri f967773b2a Fix test case typo
Signed-off-by: Supasate Choochaisri <supasate.c@gmail.com>
2016-07-24 19:38:37 +07:00
Amir-61 20d8047198 Merge pull request #1009 from strongloop/declare_definition_in_destroy
Declare `definition`
2016-07-23 00:21:31 -04:00
Amir-61 bed8ca2566 Merge pull request #1010 from strongloop/remove_unused_vars
Remove unused variables in model.js
2016-07-22 18:53:46 -04:00
Amir Jafarian 2143502a9d Remove unused variables in model.js 2016-07-22 17:23:09 -04:00
Amir Jafarian 8d4c577032 Declare `definition`
Declare `definition` in `BelongsTo.prototype.destroy`
2016-07-22 15:44:53 -04:00
Simon Ho a22ff61af2 Merge pull request #1000 from supasate/test-datatype-invalid-date
Add test to catch invalid date property
2016-07-15 10:45:13 -07:00
Supasate Choochaisri 94c5c18541 Add test to catch invalid date property
Signed-off-by: Supasate Choochaisri <supasate.c@gmail.com>
2016-07-14 17:27:02 +07:00
Ryan Graham cca14a0230 Update URLs in CONTRIBUTING.md (#1002) 2016-07-13 17:53:36 -07:00
Miroslav Bajtoš 06cac9e7d4 Merge pull request #996 from strongloop/fix/order-in-find
Ensure stable order of items in DAO.find()
2016-07-13 15:15:44 +02:00
Miroslav Bajtoš 699e0587d1 Ensure stable order of items in DAO.find()
When post-processing result of find operation, use "async.map"
instead of "async.each + array.push" to ensure the order of items
is preserved.
2016-07-13 14:55:49 +02:00
Amir-61 f7e2021e93 Merge pull request #989 from strongloop/test_updateOrCreate_non_autogeneratedId
Add test for updateOrCreate
2016-07-11 10:23:31 -04:00
Amir Jafarian 9f0c10fdff Add test for updateOrCreate
* Add test for updateOrCreate when id is not autogenerated Id
2016-07-07 12:55:22 -04:00
Rand McKinney 45e14af4a9 Update validations.js
Fix API doc per https://github.com/strongloop/loopback/issues/2472
2016-06-29 16:13:44 -07:00
Gunjan Pandya 6bc4441850 Merge pull request #976 from strongloop/compatflag-cleanup
[SEMVER-MAJOR] Remove DataSource.registerType()
2016-06-29 13:32:29 -04:00
gunjpan 8076be2db1 Remove DataSource.registerType()
Result of compat flag cleanup.
- Current implementation has a wrapper
DataSource.registerType() for
ModelBuilder.registerType(). This removes
the wrapper to encourage use of original
method
2016-06-28 14:45:42 -04:00
RobinBiondi fbe58f7cf8 give options to validators #984 2016-06-24 14:44:43 -07:00
Gunjan Pandya e0a68289c5 Merge pull request #947 from strongloop/update-errormsg
[SEMVER-MAJOR] Throw Error for property names with dots
2016-06-24 16:50:00 -04:00
Amir-61 73bb418719 Merge pull request #960 from strongloop/fix/connection-err-msg
Update datasource.js
2016-06-17 11:29:26 -04:00
Miroslav Bajtoš 058d9d46c0 3.0.0-alpha.5
* Give warning if PK is changed in hooks (Amir Jafarian)
 * Remove model events (Candy)
 * Persist changes on parent for embedsOne (Dimitris Halatsis)
 * Fix (Amir Jafarian)
 * Fix error message (Amir Jafarian)
 * ModelBuilder: add new setting strictEmbeddedModels (Dimitris Halatsis)
 * Retun err for UPSERT if the connector returns err (Amir Jafarian)
 * fix error handling when applying undefined mixins (Alex Pitigoi)
 * Add test's description (Amir Jafarian)
 * Fix incompatibility between different connectors (Amir Jafarian)
 * travis: add v4, v6, drop io.js (Miroslav Bajtoš)
 * fix avoid duplicate record on scope with promise (Alex Pitigoi)
 * Document promise support for DAO::find (Sequoia McDowell)
 * Set ESLint as devdep (Simon Ho)
 * Use mocha instead of Makefile for testing (Simon Ho)
 * DAO.create: don't return the instance (Miroslav Bajtoš)
 * RELEASE-NOTES: describe 30283291 (Miroslav Bajtoš)
 * Implement operation hooks for EmbedsMany methods (Miroslav Bajtoš)
 * Implement operation hooks for EmbedsOne methods (Miroslav Bajtoš)
 * eslint config 2.0 + remove extra empty lines (Miroslav Bajtoš)
 * Test coverages for hashed password (Amir Jafarian)
 * Fix `forceId` check for `replaceById` (Amir Jafarian)
 * Fix `notify` bugs for `find` (Amir Jafarian)
 * test: extract hook-monitor helper (Miroslav Bajtoš)
 * test: extract uid-generator helper (Miroslav Bajtoš)
 * test: extract context-test-helpers (Miroslav Bajtoš)
 * Define `patch` aliases (Amir Jafarian)
2016-06-13 16:31:19 +02:00
gunjpan 8117b0403f Throw Error for property names with dots
Result of Compat Flags Clenup.
Throws an error for property names with dots, instead
of a deprecation warning.
2016-06-09 17:50:59 -04:00
Amir-61 366e93f50b Merge pull request #952 from strongloop/avoid_changing_PK_when_forceId_is_set
Give warning if PK is changed in hooks
2016-06-08 14:53:04 -04:00
Amir Jafarian 7a8803cb38 Give warning if PK is changed in hooks
* Give warning if PK is changed in `before save` and `loaded`
 operation hooks for replaceById
2016-06-08 11:56:19 -04:00
Candy a55bf40ee9 Merge pull request #965 from strongloop/remove_events
[SEMVER-MAJOR] Remove model events
2016-06-08 11:11:28 -04:00
Candy 3daca1e960 Remove model events 2016-06-08 10:27:05 -04:00
Dimitris Halatsis ea2266e453 Persist changes on parent for embedsOne
Allow direct save of changes on embedded model to be persisted on
parent document.

    Person.embedsOne(Address);
    Person.findById(someId)
      .then(function(p){
        var address = p.addressItem();
        address.street = 'new street'
        // This will now persist changes on parent document
        return address.save();
      })

[forward-port of #949]
2016-06-07 17:24:59 +02:00
Amir-61 b039b51610 Merge pull request #964 from strongloop/fixup-master
Fix
2016-06-04 21:23:16 -04:00
Amir Jafarian 8f2077e344 Fix 2016-06-03 18:00:21 -04:00
Ritchie Martori 293a22fd31 Update datasource.js
Return a real `Error` message for the default `ping()` method.
2016-06-02 14:02:06 -07:00
Amir-61 6028826826 Merge pull request #953 from strongloop/fix_error_message
Fix error message
2016-06-02 08:24:59 -04:00
Amir Jafarian cae44f0458 Fix error message
*Fix error message when PK is changed in `replaceById`
2016-06-01 16:16:35 -04:00
Amir-61 8f347fbacb Merge pull request #954 from strongloop/callback_err_from_connector_UPSERT
Retun err for UPSERT if the connector returns err
2016-06-01 15:51:35 -04:00
Miroslav Bajtoš 0e4af6d453 Merge pull request #955 from strongloop/feature/strictEmbeddedModels
ModelBuilder: add new setting strictEmbeddedModels
2016-06-01 13:39:51 +02:00
Dimitris Halatsis b7ba73f1b1 ModelBuilder: add new setting strictEmbeddedModels
The setting controls the strict mode used for embedded property types,
for example the type of "address" property in this model definition:

    modelBuilder.define('TestEmbedded', {
      name: 'string',
      address: {
        street: 'string',
      },
    });
2016-06-01 13:12:50 +02:00
Miroslav Bajtoš 6ec66a7e4a Merge pull request #950 from strongloop/add_test_description
Add test's description
2016-06-01 09:57:53 +02:00
Amir Jafarian 82546fdf47 Retun err for UPSERT if the connector returns err 2016-05-31 22:17:23 -04:00
Alex Pitigoi 5b025075dc Merge pull request #944 from strongloop/fix-mixin-err-handler
[SEMVER-MAJOR] throw error for undefined mixin
2016-05-31 13:10:08 -04:00
Alex Pitigoi 423db34bf3 fix error handling when applying undefined mixins 2016-05-31 12:24:04 -04:00
Amir Jafarian 2b6ced06a1 Add test's description 2016-05-31 11:13:28 -04:00
Amir-61 1f94f63bc1 Merge pull request #938 from strongloop/replace_incompatibility_fix
Fix incompatibility between different connectors for replace methods
2016-05-28 09:06:34 -04:00
Amir Jafarian d9a3f6226a Fix incompatibility between different connectors
* Fix incompatibility for replace methods between different connectors.
2016-05-27 13:45:24 -04:00
Miroslav Bajtoš 795952c182 Merge pull request #943 from strongloop/fix/travis
travis: add v4, v6, drop io.js
2016-05-23 11:24:06 +02:00
Miroslav Bajtoš 376ac4649e travis: add v4, v6, drop io.js 2016-05-23 11:13:40 +02:00
Miroslav Bajtoš 119a1bc6c4 Merge pull request #937 from strongloop/juggler-rel-test
fix avoid duplicate record on scope with promise
2016-05-20 14:56:55 +02:00
Alex Pitigoi 0e89a9c837 fix avoid duplicate record on scope with promise 2016-05-19 15:47:31 -04:00
Simon Ho 3113333cb2 Merge pull request #922 from Sequoia/patch-2
Document promise support for DAO::find
2016-05-11 16:10:48 -07:00
Sequoia McDowell ae7a5df47b Document promise support for DAO::find
It was previously completely undocumented. There are additional methods that add promises but I figure accurately documenting some is better than none. :)
2016-05-11 09:58:22 -04:00
Simon Ho 71e7e5b618 Merge pull request #926 from strongloop/refactor/set-eslint-as-devdep
Set ESLint as devdep
2016-05-10 13:35:33 -07:00
Simon Ho dae0bf863e Set ESLint as devdep 2016-05-10 12:38:30 -07:00
Simon Ho 1d39e41d00 Merge pull request #924 from strongloop/refactor/remove-makefile
Use mocha instead of Makefile for testing
2016-05-10 11:59:33 -07:00
Simon Ho 5be2b3f867 Use mocha instead of Makefile for testing 2016-05-10 11:56:35 -07:00
Miroslav Bajtoš 2189b9a746 Merge pull request #918 from strongloop/fix/remove-chaining-in-create
[SEMVER-MAJOR] DAO.create: don't return the instance
2016-05-02 13:09:03 +02:00
Miroslav Bajtoš 8ad53a4c0e DAO.create: don't return the instance
Simplify DataAccessObject.create() and stop returning the
instance/array of instances. Users should always use callback (or
returned promise) to get the instance(s) created.
2016-04-29 14:16:06 +02:00
Miroslav Bajtoš 89bf94245b Merge pull request #917 from strongloop/doc/add-item-to-release-notes
RELEASE-NOTES: describe 30283291
2016-04-28 19:10:30 +02:00
Miroslav Bajtoš 41d71c5a5b RELEASE-NOTES: describe 30283291
Add an entry for a breaking change made in 30283291 that was not
described previously.
2016-04-28 13:23:50 +02:00
Miroslav Bajtoš ca0c3aaa47 Merge pull request #911 from strongloop/feature/hooks-for-embeds-many
Implement operation hooks for EmbedsMany methods
2016-04-27 17:05:59 +02:00
Miroslav Bajtoš 9bde8f859b Implement operation hooks for EmbedsMany methods
create() triggers
 - before save
 - after save

updateById() triggers
 - before save
 - after save

destroy() triggers
 - before delete
 - after delete

The implementation here is intentionally left with less features
than the regular DAO methods provide, the goal is to get a partial
(but still useful!) version released soon.

Limitations:

 - `before save` & `after save` hooks don't provide `ctx.isNewInstance`
 - async validations are not supported yet
 - `persist` and `loaded` hooks are not triggered at all

 - `before delete` hook does not provide `ctx.where` property and
    it's not possible to change the outcome of `destroy()` using this
    hook. Note that regular DAO does support this.

 - updating embedded instances triggers update of the parent (owning)
   model, which is correct and expected. However, the context provided
   by `before save` and `after save` hooks on the parent model is sort of
   arbitrary and may include wrong/extra data. The same probably applies
   to the scenario when deleting embedded instances triggers update of
   the parent model.
2016-04-27 11:04:15 +02:00
Miroslav Bajtoš 7247b6637e Merge pull request #904 from strongloop/feature/hooks-for-embeds-one
Implement operation hooks for EmbedsOne methods
2016-04-20 10:29:51 +02:00
Miroslav Bajtoš b86615e2b7 Implement operation hooks for EmbedsOne methods
create() triggers
 - before save
 - after save

udpate() triggers
 - before save
 - after save

destroy() triggers
 - before delete
 - after delete

The implementation here is intentionally left with less features
than the regular DAO methods provide, the goal is to get a partial
(but still useful!) version released soon.
2016-04-20 09:36:12 +02:00
Miroslav Bajtoš 2ffc15a70c Merge pull request #909 from strongloop/eslint/config-loopback-v2.0
eslint config 2.0 + remove extra empty lines
2016-04-19 17:05:12 +02:00
Miroslav Bajtoš c7f34c3452 eslint config 2.0 + remove extra empty lines
Upgrade eslint-config-loopback to ^2.0.0.

Remove extra empty lines to make `npm run lint` pass again.
2016-04-19 16:11:43 +02:00
Amir-61 cd8be0e0a6 Merge pull request #893 from strongloop/hashed_password_tests
Test coverages for hashed password
2016-04-15 12:53:26 -04:00
Amir Jafarian 11ef948854 Test coverages for hashed password
* Test coverages for hashed password for replaceAttributes
* Test coverages for hashed password for updateAttribute
2016-04-14 18:27:19 -04:00
Amir-61 cd5f8b0ee7 Merge pull request #896 from strongloop/forceId_check_replaceById_fix
Fix `forceId` check for `replaceById`
2016-04-14 16:57:02 -04:00
Amir Jafarian 4e6351b856 Fix `forceId` check for `replaceById` 2016-04-14 15:05:56 -04:00
Amir-61 281f554365 Merge pull request #898 from strongloop/fix_notify_find_bugs
Fix notify for find method
2016-04-13 16:17:23 -04:00
Amir Jafarian e9afb46eda Fix `notify` bugs for `find` 2016-04-13 13:34:51 -04:00
Miroslav Bajtoš c9388fa955 Merge pull request #902 from strongloop/refactor/context-test-helpers
test: extract helpers used in tests for operation hooks
2016-04-13 15:04:10 +02:00
Miroslav Bajtoš 09f4c7d026 test: extract hook-monitor helper 2016-04-13 13:54:17 +02:00
Miroslav Bajtoš 616a81b496 test: extract uid-generator helper 2016-04-13 13:53:31 +02:00
Miroslav Bajtoš 3435b43a5c test: extract context-test-helpers 2016-04-13 13:52:54 +02:00
Amir-61 063983ccc9 Merge pull request #888 from strongloop/define_patch_aliases
Define `patch` aliases
2016-04-12 16:17:35 -04:00
Amir Jafarian 4bb284bb60 Define `patch` aliases
*Define `patchOrCreate` as an alias for `updateOrCreate`
*Define `PatchAttributes` as an alias for `updateAttributes`
2016-04-12 13:40:01 -04:00
Miroslav Bajtoš 1e8fe6a0d7 3.0.0-alpha.4
* Partition by foreign key for pagination (Raymond Feng)
 * Fix style errors (Raymond Feng)
 * fix remaining eslint issues (Miroslav Bajtoš)
 * eslint --fix (Miroslav Bajtoš)
 * Add eslint as "npm run lint" and "posttest" hook (Miroslav Bajtoš)
 * Remove unused support/ files (Miroslav Bajtoš)
 * Insert copyright headers (Ryan Graham)
 * Relicense as MIT only (Ryan Graham)
 * Fix Mongo compatibility issue (Amir Jafarian)
 * Add automigrate to setup tables for replace test cases (Amir Jafarian)
 * Allow test folder to be published (Amir Jafarian)
 * support custom field settings under the connector's namespace (bitmage)
 * Update error message for missing connector (gunjpan)
 * Fix tests for mysql (Amir Jafarian)
 * Add forgotten unit test (Miroslav Bajtoš)
 * fix nin support for in memory datasource (Horia Radu)
 * Improve error message on connector init error (Miroslav Bajtoš)
 * discoverSchemas returns an error when modelName is not found, discoverSchema forwards that error and does not hang when no columns, no errors are returned (bitmage)
2016-04-07 09:21:38 +02:00
Simon Ho 85ed753609 Merge pull request #786 from strongloop/feature/fix-610
Partition by foreign key for pagination
2016-04-06 14:01:08 -07:00
Raymond Feng 84da11f98e Partition by foreign key for pagination
See https://github.com/strongloop/loopback-datasource-juggler/issues/610
2016-04-05 17:21:48 -07:00
Raymond Feng e86ecab507 Merge branch 'TorchlightSoftware-discover-hang' 2016-04-05 16:18:30 -07:00
Raymond Feng daaf5e381a Merge branch 'discover-hang' of https://github.com/TorchlightSoftware/loopback-datasource-juggler into TorchlightSoftware-discover-hang
# Conflicts:
#	lib/datasource.js
#	test/discovery.test.js
2016-04-05 16:18:25 -07:00
Raymond Feng e321bafdf9 Fix style errors 2016-04-05 16:11:25 -07:00
Raymond Feng b7543e9402 Merge pull request #860 from horiaradu/master
fix nin support for in memory datasource
2016-04-05 15:42:07 -07:00
Miroslav Bajtoš 267d24de0a Merge pull request #886 from strongloop/feature/eslint
Use eslint with loopback config
2016-04-05 15:31:31 +02:00
Miroslav Bajtoš 27c6279d6c fix remaining eslint issues 2016-04-05 15:25:34 +02:00
Miroslav Bajtoš 39e04a1756 eslint --fix 2016-04-05 15:25:34 +02:00
Miroslav Bajtoš fc1aefb8d4 Add eslint as "npm run lint" and "posttest" hook 2016-04-05 15:25:34 +02:00
Miroslav Bajtoš fea70e69c9 Remove unused support/ files 2016-04-05 15:25:34 +02:00
Ryan Graham a18c1e7e5e Merge pull request #887 from strongloop/copyright
Relicense as MIT only
2016-04-04 18:44:33 -07:00
Ryan Graham c467b43c38 Insert copyright headers 2016-04-04 18:14:03 -07:00
Ryan Graham d204bfa432 Relicense as MIT only 2016-04-01 15:17:10 -07:00
Amir-61 049e888039 Merge pull request #866 from strongloop/fix_Mongo_comptaibility_replaceORCreate
Fix Mongo compatibility issue
2016-03-30 11:25:22 -04:00
Amir Jafarian 5b6bffb5b3 Fix Mongo compatibility issue
*Fix Mongo compatibility issue for replaceOrCreate
2016-03-29 14:42:13 -04:00
Amir-61 eed69a2573 Merge pull request #884 from strongloop/automigrate_to_setup_tables_replace
Add automigrate to setup tables for replace test cases
2016-03-29 13:31:12 -04:00
Amir Jafarian 8b8d474b92 Add automigrate to setup tables for replace test cases 2016-03-29 12:21:10 -04:00
Amir-61 e4918ba490 Merge pull request #881 from strongloop/allow_test_folder_tobe_published
Allow test folder to be published
2016-03-28 20:33:44 -04:00
Amir Jafarian 0b1070af01 Allow test folder to be published 2016-03-28 20:08:56 -04:00
Amir-61 fc27aa9561 Merge pull request #868 from strongloop/mySQL-fix-tests
Fix tests for mysql
2016-03-28 15:57:27 -04:00
Raymond Feng 41ad561f11 Merge pull request #875 from bitmage/custom-field-settings
support custom field settings under the connector's namespace
2016-03-28 09:21:27 -07:00
bitmage 57afba8c51 support custom field settings under the connector's namespace 2016-03-16 09:17:55 -07:00
Gunjan Pandya f1c437363c Merge pull request #873 from strongloop/update-errormsg
Update error message for missing connector
2016-03-15 17:27:18 -04:00
gunjpan 6db59cba6f Update error message for missing connector 2016-03-15 17:01:37 -04:00
Amir Jafarian 024bff6a91 Fix tests for mysql 2016-03-08 20:39:25 -05:00
Miroslav Bajtoš 3fadbe9c1d Merge pull request #862 from strongloop/add-forgotten-test
Add forgotten unit test
2016-03-02 13:10:03 +01:00
Miroslav Bajtoš 28e07d9df3 Add forgotten unit test
The test should have been added as part of #859
2016-03-02 12:32:11 +01:00
Miroslav Bajtoš ac94c2b988 Merge pull request #859 from strongloop/fix/err-msg-on-connector-error
Improve error message on connector init error
2016-03-02 12:16:28 +01:00
Horia Radu a3ae44aca0 fix nin support for in memory datasource 2016-02-27 10:27:09 +02:00
Miroslav Bajtoš 9dcf30efe9 Improve error message on connector init error 2016-02-26 14:00:24 +01:00
Miroslav Bajtoš dd4530cad6 3.0.0-alpha.3
* Fix missing connector error msg for db2, cloudant (Candy)
 * Update describe-operation-hooks (Miroslav Bajtoš)
2016-02-22 10:45:06 +01:00
Candy 9a76fb4c07 Merge pull request #852 from strongloop/add_new_connectors
Fix missing connector error msg for db2, cloudant
2016-02-10 10:34:30 -05:00
Candy 686ce5bae3 Fix missing connector error msg for db2, cloudant 2016-02-09 16:19:57 -05:00
Miroslav Bajtoš 2e0f496713 Merge pull request #847 from strongloop/doc/add-replace-to-hooks-overview
Update describe-operation-hooks
2016-02-09 13:05:46 +01:00
Miroslav Bajtoš 5d81bfc58b Update describe-operation-hooks
- drop custom findOrCreate implementation - memory connector provides
   an atomic implementation out of the box now
 - add new methods `replaceOrCreate` and `replaceByID`
 - fix error reporting to include the stack trace in the console output
2016-02-06 11:22:53 +01:00
Miroslav Bajtoš 504675fc78 3.0.0-alpha.2
* Implementtaion of replace (Amir Jafarian)
 * Fix conversion for `updateAttributes` (Amir Jafarian)
 * Prevent constructor to be property name (Jue Hou)
 * Revert "Change "npm test" to call mocha directly" (Miroslav Bajtoš)
 * Change "npm test" to call mocha directly (Hans(Zhenghan) Zhang)
 * Refactor `updateAttributes` (Amir Jafarian)
 * Update README.md (Simon Ho)
 * Add unit test to verify fix for #754 (Tom Kirkpatrick)
 * Update package.json (Janny)
 * Try mocha test (Janny)
 * Implement `findOrCreate` for memory connector (Amir Jafarian)
 * Fix a bug when validation is off for findOrCreate (Amir Jafarian)
 * Use bluebird in utils.js Replace `global.Promise` with `bluebird` (Jue Hou)
 * Fix broken code fencings in the docs (Farid Nouri Neshat)
 * Revert "Correct syntax for should and more" (Simon Ho)
 * Fix test for shouldjs 8.0.2 upgrade (Simon Ho)
 * Upgrade shouldjs to 8.0.2 (Simon Ho)
 * Enhance "persist" hook in DAO.updateOrCreate (Miroslav Bajtoš)
 * Enhance "persisted" hook in DAO.updateAttributes (Miroslav Bajtoš)
 * "loaded" hook in DAO.find: ctx.data, not instance (Miroslav Bajtoš)
 * describe-operation-hooks: add "loaded" hook (Miroslav Bajtoš)
2016-02-05 16:42:46 +01:00
Amir-61 3b9d3d0212 Merge pull request #788 from strongloop/replace
Implementation of replaceOrCreate and replace
2016-02-04 15:17:14 -05:00
Amir Jafarian 2281e95940 Implementtaion of replace
This includes:
*implementation of replaceAttributes
*implementtaion of replaceOrCreate
2016-02-03 16:06:35 -05:00
Amir-61 5dca27278a Merge pull request #839 from strongloop/fix-conversion-updateAttributes
Fix conversion for `updateAttributes`
2016-02-03 12:41:32 -05:00
Amir Jafarian ef232eae0a Fix conversion for `updateAttributes` 2016-02-03 12:04:51 -05:00
Janny 49c2bc214a Merge pull request #823 from strongloop/feature/handle-constructor
Prevent constructor to be property name
2016-02-02 13:29:03 -05:00
Jue Hou 0d9eebe3bb Prevent constructor to be property name 2016-02-02 11:51:05 -05:00
Miroslav Bajtoš 54ca067610 Revert "Change "npm test" to call mocha directly"
This reverts commit 1e9affe4ba.
2016-01-26 17:35:46 +01:00
Miroslav Bajtoš 0648dc581f Merge pull request #831 from strongloop/fix/npm-test
Change "npm test" to call mocha directly
2016-01-26 17:11:54 +01:00
Amir-61 63482ef061 Merge pull request #826 from strongloop/updateAttributes-refactoring
Refactor `updateAttributes`
2016-01-25 10:26:44 -05:00
Hans(Zhenghan) Zhang 1e9affe4ba Change "npm test" to call mocha directly
Rework the test script to call directly mocha and skip Makefile. This
allows CI enviroments to detect that this module is using Mocha as
the test runner.
2016-01-25 14:20:13 +01:00
Amir Jafarian 550cfa2a86 Refactor `updateAttributes` 2016-01-25 10:56:27 +01:00
Simon Ho d49dfa0293 Update README.md 2016-01-22 14:10:01 -08:00
Simon Ho 4ebbd0e5c2 Update README.md 2016-01-22 14:09:20 -08:00
Simon Ho c5f0be83a8 Update README.md 2016-01-22 13:50:58 -08:00
Simon Ho bd0c75fe4b Merge pull request #828 from strongloop/cc
Add unit test to verify fix for #754
2016-01-22 10:09:49 -08:00
bitmage b556d96148 discoverSchemas returns an error when modelName is not found,
discoverSchema forwards that error and does not hang when no columns,
no errors are returned
2016-01-22 10:41:06 -07:00
Tom Kirkpatrick 61047a028d Add unit test to verify fix for #754 2016-01-21 18:00:45 -08:00
Janny 2cdc4ddcbf Update package.json 2016-01-22 09:18:49 +08:00
Janny ccf52f0822 Try mocha test 2016-01-22 09:17:54 +08:00
Amir-61 adaf7dee7c Merge pull request #815 from strongloop/findOrCreate
Implement `findOrCreate` for memory connector
2016-01-16 18:48:42 -05:00
Amir Jafarian ba7161b39e Implement `findOrCreate` for memory connector 2016-01-16 18:46:53 -05:00
Amir Jafarian a5150265ec Fix a bug when validation is off for findOrCreate 2016-01-08 16:47:38 -05:00
Janny 1771bfabcc Merge pull request #790 from strongloop/feature/upgrade-to-bluebird
[SEMVER-MAJOR] Always use bluebird as the Promise implementation
2016-01-08 08:07:55 +08:00
Jue Hou 853ca03491 Use bluebird in utils.js
Replace `global.Promise` with `bluebird`
2016-01-07 15:27:33 -05:00
Miroslav Bajtoš b509c759c4 Merge pull request #796 from strongloop/fix/various
Various fixes in operation hooks
2016-01-05 11:08:35 +01:00
Simon Ho 5cf37aae5b Merge pull request #809 from alFReD-NSH/patch-1
Fix broken code fencings in the docs
2015-12-28 16:40:33 -08:00
Farid Nouri Neshat 93c9f63b0d Fix broken code fencings in the docs 2015-12-28 23:03:37 +08:00
Simon Ho bffa4b6ab6 Merge pull request #806 from strongloop/revert-redis-test-fixes
Revert "Correct syntax for should and more"
2015-12-23 17:27:50 -08:00
Simon Ho 5d453b5038 Revert "Correct syntax for should and more"
This reverts commit 62de2ed69e.
2015-12-23 15:41:16 -08:00
Simon Ho 2e22583fcc Merge pull request #804 from strongloop/upgrade-shouldjs
Upgrade shouldjs to 8.0.2
2015-12-23 15:38:37 -08:00
Simon Ho b63133d1d6 Fix test for shouldjs 8.0.2 upgrade 2015-12-22 15:03:50 -08:00
Simon Ho edd2d301e5 Upgrade shouldjs to 8.0.2 2015-12-22 15:03:16 -08:00
Miroslav Bajtoš 990307f3d5 3.0.0-alpha.1
* Start development of 3.0 (Miroslav Bajtoš)
 * Correct syntax for should and more (Amir Jafarian)
2015-12-22 13:15:52 +01:00
Miroslav Bajtoš 4319414fb2 Merge pull request #801 from strongloop/start-3.0
Start development of 3.0
2015-12-22 13:12:30 +01:00
Miroslav Bajtoš d3e2520b1f Start development of 3.0
- Update version number in package.json, publish under "next" tag
 - Add 3.0-RELEASE-NOTES.md to incrementally build release docs
2015-12-22 12:48:06 +01:00
Miroslav Bajtoš e9899a93cf Enhance "persist" hook in DAO.updateOrCreate
Report `ctx.isNewInstance` when the connector provides this info.
2015-12-18 16:08:38 +01:00
Miroslav Bajtoš fd9bef4aa7 Enhance "persisted" hook in DAO.updateAttributes
Add `isNewInstance:false` to the context reported by
DAO.updateAttributes()
2015-12-18 16:08:01 +01:00
Miroslav Bajtoš 3028329126 "loaded" hook in DAO.find: ctx.data, not instance
Fix the implementation od DAO.find to provide "ctx.data" to the
"loaded" hook.
2015-12-18 15:54:35 +01:00
Miroslav Bajtoš 89e4555bc0 describe-operation-hooks: add "loaded" hook 2015-12-18 15:42:36 +01:00
Amir-61 dfda177ff7 Merge pull request #792 from strongloop/Redis_test_failiures
Redis test failiures
2015-12-16 16:29:56 -05:00
187 changed files with 45777 additions and 11764 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
coverage
dist

14
.eslintrc Normal file
View File

@ -0,0 +1,14 @@
{
"extends": "loopback",
"rules": {
"max-len": ["error", 110, 4, {
"ignoreComments": true,
"ignoreUrls": true,
"ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)"
}],
// NOTE(bajtos) we should eventually remove this override
// and fix all of those 100+ violations
"one-var": "off",
"no-unused-expressions": "off"
}
}

53
.github/ISSUE_TEMPLATE/Bug_report.md vendored Normal file
View File

@ -0,0 +1,53 @@
---
name: Bug report
about: Create a report to help us improve
labels: bug
---
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
Are you using LoopBack version 4? Please report the bug here:
https://github.com/strongloop/loopback-next/issues/new
HELP US HELP YOU, PLEASE
- Do a quick search to avoid duplicate issues
- Provide as much information as possible (reproduction sandbox, use case for features, etc.)
- Consider using a more suitable venue for questions such as Stack Overflow, Gitter, etc.
Please fill in the *entire* template below.
-->
## Steps to reproduce
<!-- Describe how to reproduce the issue -->
## Current Behavior
<!-- Describe the observed result -->
## Expected Behavior
<!-- Describe what did you expect instead, what is the desired outcome? -->
## Link to reproduction sandbox
<!--
See https://loopback.io/doc/en/contrib/Reporting-issues.html#loopback-3x-bugs
Note: Failure to provide a sandbox application for reproduction purposes will result in the issue being closed.
-->
## Additional information
<!--
Copy+paste the output of these two commands:
node -e 'console.log(process.platform, process.arch, process.versions.node)'
npm ls --prod --depth 0 | grep loopback
-->
## Related Issues
<!-- Did you find other bugs that looked similar? -->
_See [Reporting Issues](http://loopback.io/doc/en/contrib/Reporting-issues.html) for more tips on writing good issues_

View File

@ -0,0 +1,34 @@
---
name: Feature request
about: Suggest an idea for this project
labels: feature
---
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
LoopBack version 3 is in LTS mode, we are not accepting new features.
We are actively developing version 4, you can find the new GitHub
repository here: https://github.com/strongloop/loopback-next
-->
## Suggestion
<!-- A summary of what you'd like to see added or changed -->
## Use Cases
<!--
What do you want to use this for?
What shortcomings exist with current approaches?
-->
## Examples
<!-- Show how this would be used and what the behavior would be -->
## Acceptance criteria
TBD - will be filled by the team.

27
.github/ISSUE_TEMPLATE/Question.md vendored Normal file
View File

@ -0,0 +1,27 @@
---
name: Question
about: The issue tracker is not for questions. Please use Stack Overflow or other resources for help.
labels: question
---
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
THE ISSUE TRACKER IS NOT FOR QUESTIONS.
DO NOT CREATE A NEW ISSUE TO ASK A QUESTION.
Please use one of the following resources for help:
**Questions**
- https://stackoverflow.com/tags/loopbackjs
- https://groups.google.com/forum/#!forum/loopbackjs
- https://gitter.im/strongloop/loopback
**Immediate support**
- https://strongloop.com/api-connect-faqs/
- https://strongloop.com/node-js/subscription-plans/
-->

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Report a security vulnerability
url: https://loopback.io/doc/en/contrib/Reporting-issues.html#security-issues
about: Do not report security vulnerabilities using GitHub issues. Please send an email to `security@loopback.io` instead.
- name: Get help on StackOverflow
url: https://stackoverflow.com/tags/loopbackjs
about: Please ask and answer questions on StackOverflow.
- name: Join our mailing list
url: https://groups.google.com/forum/#!forum/loopbackjs
about: You can also post your question to our mailing list.

17
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,17 @@
<!--
Please provide a high-level description of the changes made by your pull request.
Include references to all related GitHub issues and other pull requests, for example:
Fixes #123
Implements #254
See also #23
-->
## Checklist
- [ ] [Sign off your commits](https://loopback.io/doc/en/contrib/code-contrib.html) with DCO (Developer Certificate of Origin)
- [ ] `npm test` passes on your machine
- [ ] New tests added or existing tests modified to cover all changes
- [ ] Code conforms with the [style guide](https://loopback.io/doc/en/contrib/style-guide-es6.html)
- [ ] Commit messages are following our [guidelines](https://loopback.io/doc/en/contrib/git-commit-messages.html)

1
.github/codeql/codeql-config.yaml vendored Normal file
View File

@ -0,0 +1 @@
paths-ignore: [test]

24
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,24 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- critical
- p1
- major
- "good first issue"
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been closed due to continued inactivity. Thank you for your understanding.
If you believe this to be in error, please contact one of the code owners,
listed in the `CODEOWNERS` file at the top-level of this repository.

127
.github/workflows/ci.yaml vendored Normal file
View File

@ -0,0 +1,127 @@
name: CI
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 2 * * 1' # At 02:00 on Monday
permissions: {}
jobs:
test:
name: Test
timeout-minutes: 15
strategy:
matrix:
os: [ubuntu-latest]
node-version: [18, 20]
include:
- os: macos-latest
node-version: 18
- os: windows-latest
node-version: 18
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Update NPM (Node.js v10)
if: matrix.node-version == 10
run: npm install --global npm@7
- name: Update NPM
if: matrix.node-version != 10
run: npm install --global npm@8
- name: Bootstrap project
run: npm ci --ignore-scripts
- name: Build project
run: npm run build
- name: Run tests
run: npm test --ignore-scripts
- name: Generate coverage report
run: npx --no-install nyc report --reporter=lcov
- name: Publish coverage report to Coveralls
uses: coverallsapp/github-action@master
with:
flag-name: run-${{ matrix.os }}-node@${{ matrix.node-version }}
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
posttest:
name: Post-Test
needs: test
runs-on: ubuntu-latest
steps:
- name: Coveralls finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
code-lint:
name: Code Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 0
- name: Use Node.js 18
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 18
- name: Update NPM
run: npm install --global npm
- name: Bootstrap project
run: npm ci --ignore-scripts
- name: Build project
run: npm run build
- name: Verify code linting
run: npm run lint
commit-lint:
name: Commit Lint
runs-on: ubuntu-latest
if: ${{ github.event.pull_request }}
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 0
- name: Use Node.js 18
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 18
- name: Update NPM
run: npm install --global npm
- name: Bootstrap project
run: npm ci --ignore-scripts
- name: Verify commit linting
run: npx --no-install commitlint --from origin/master --to HEAD --verbose
codeql:
name: CodeQL
runs-on: ubuntu-latest
permissions:
# See: https://github.com/github/codeql-action/blob/008b2cc71c4cf3401f45919d8eede44a65b4a322/README.md#usage
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: 'javascript'
config-file: ./.github/codeql/codeql-config.yaml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

4
.gitignore vendored
View File

@ -5,6 +5,8 @@ coverage
v8.log
.idea
.DS_Store
.git
.vscode
benchmark.js
analyse.r
docs/html
@ -12,3 +14,5 @@ docs/man
npm-debug.log
.project
test/memory.json
.nyc_output
dist

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "support/nodeunit"]
path = support/nodeunit
url = https://github.com/caolan/nodeunit.git

View File

@ -1,2 +0,0 @@
node_modules
support/nodeunit

1
.mocharc.yaml Normal file
View File

@ -0,0 +1 @@
reporter: dot

View File

@ -3,9 +3,13 @@ doc
coverage.html
coverage
v8.log
.git
.DS_Store
benchmark.js
analyse.r
docs/html
npm-debug.log
.travis.yml
.nyc_output
dist
types/__test__.ts

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
package-lock=true
scripts-prepend-node-path=true

9
.nycrc Normal file
View File

@ -0,0 +1,9 @@
{
"exclude": [
"test/**/*.js"
],
"reporter": [
"html"
],
"cache": true
}

2
.prettierignore Normal file
View File

@ -0,0 +1,2 @@
*.json
*.md

6
.prettierrc Normal file
View File

@ -0,0 +1,6 @@
{
"bracketSpacing": false,
"singleQuote": true,
"printWidth": 80,
"trailingComma": "all"
}

View File

@ -1,6 +1,26 @@
sudo: false
branches:
only:
- master
arch:
- arm64
- ppc64le
- s390x
dist: bionic
language: node_js
before_install: |
NODEJS_VERSION=$(node --version)
if [ 'v10' = ${NODEJS_VERSION%%.*} ]
then
npm install --global npm@7
else
npm install --global npm@8
fi
script:
- npm run --ignore-scripts build
- npm test --ignore-scripts
node_js:
- "0.10"
- "0.12"
- "iojs"
- 10.24.1
- 12.22.12
- 14.21.3
- 16.20.2
- 17.9.1

1901
CHANGES.md

File diff suppressed because it is too large Load Diff

10
CODEOWNERS Normal file
View File

@ -0,0 +1,10 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners,
# the last matching pattern has the most precedence.
# Current maintainers
* @jannyHou @dhmlau @zbarbuto @nitro404 @emonddr
# Alumni
#
# @lehni @kjdelisle @loay @ssh24 @virkt25 @shimks @b-admike

178
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,178 @@
# Code of Conduct
LoopBack, as member project of the OpenJS Foundation, use
[Contributor Covenant v2.0](https://contributor-covenant.org/version/2/0/code_of_conduct)
as their code of conduct. The full text is included
[below](#contributor-covenant-code-of-conduct-v2.0) in English, and translations
are available from the Contributor Covenant organisation:
- [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
- [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
Refer to the sections on reporting and escalation in this document for the
specific emails that can be used to report and escalate issues.
## Reporting
### Project Spaces
For reporting issues in spaces related to LoopBack, please use the email
`tsc@loopback.io`. The LoopBack Technical Steering Committee (TSC) handles CoC issues related to the spaces that it
maintains. The project TSC commits to:
- maintain the confidentiality with regard to the reporter of an incident
- to participate in the path for escalation as outlined in the section on
Escalation when required.
### Foundation Spaces
For reporting issues in spaces managed by the OpenJS Foundation, for example,
repositories within the OpenJS organization, use the email
`report@lists.openjsf.org`. The Cross Project Council (CPC) is responsible for
managing these reports and commits to:
- maintain the confidentiality with regard to the reporter of an incident
- to participate in the path for escalation as outlined in the section on
Escalation when required.
## Escalation
The OpenJS Foundation maintains a Code of Conduct Panel (CoCP). This is a
foundation-wide team established to manage escalation when a reporter believes
that a report to a member project or the CPC has not been properly handled. In
order to escalate to the CoCP send an email to
`coc-escalation@lists.openjsf.org`.
For more information, refer to the full
[Code of Conduct governance document](https://github.com/openjs-foundation/cross-project-council/blob/HEAD/CODE_OF_CONDUCT.md).
---
## Contributor Covenant Code of Conduct v2.0
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[tsc@loopback.io](mailto:tsc@loopback.io). All complaints will be reviewed and
investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@ -11,9 +11,21 @@ Contributing to `loopback-datasource-juggler` is easy. In a few simple steps:
* Make something better or fix a bug.
* If possible update existing or add a new unit test in the [test](tests/) directory
* Adhere to code style outlined in the [Google C++ Style Guide][] and
[Google Javascript Style Guide][].
* Run lint to check adherence the style guide. Note this is also run at the end of the tests.
```
npm run lint
```
* Run tests and verify that they pass, or any that fail already failed before you introduced your change.
```
npm run test
```
* Sign the [Contributor License Agreement](https://cla.strongloop.com/agreements/strongloop/loopback-datasource-juggler)
* Submit a pull request through Github.
@ -147,5 +159,5 @@ Contributing to `loopback-datasource-juggler` is easy. In a few simple steps:
inaccurate in any respect. Email us at callback@strongloop.com.
```
[Google C++ Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
[Google C++ Style Guide]: https://google.github.io/styleguide/cppguide.html
[Google Javascript Style Guide]: https://google.github.io/styleguide/javascriptguide.xml

25
LICENSE Normal file
View File

@ -0,0 +1,25 @@
Copyright (c) IBM Corp. 2011,2017. All Rights Reserved.
Node module: loopback-datasource-juggler
This project is licensed under the MIT License, full text below.
--------
MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,9 +0,0 @@
Copyright (c) 2013-2015 StrongLoop, Inc.
loopback-datasource-juggler uses a dual license model.
You may use this library under the terms of the [MIT License][],
or under the terms of the [StrongLoop Subscription Agreement][].
[MIT License]: http://opensource.org/licenses/MIT
[StrongLoop Subscription Agreement]: http://strongloop.com/license

View File

@ -1,43 +0,0 @@
TESTER = ./node_modules/.bin/mocha
OPTS = --growl
TESTS = test/*.test.js
default: help
.PHONY: clean
clean:
rm -rf $(CURDIR)/node_modules
.PHONY: help
help:
@echo 'Usage: make [target]'
@echo 'Targets:'
@echo ' clean Delete `node_modules`'
@echo ' help Print help (this message)'
@echo ' refresh Delete `node_modules` and run `npm install`'
@echo ' test Run tests in silent mode'
@echo ' test-verbose Run tests in verbose mode'
@echo ' testing Run tests continuously'
.PHONY: refresh
refresh: clean
npm install
.PHONY: test
test:
NO_DEPRECATION=loopback-datasource-juggler $(TESTER) $(OPTS) $(TESTS)
.PHONY: test-verbose
test-verbose:
$(TESTER) $(OPTS) --reporter spec $(TESTS)
.PHONY: testing
testing:
$(TESTER) $(OPTS) --watch $(TESTS)
# Deprecated targets
.PHONY: about-testing
about-testing:
@echo 'DEPRECATED: Use `make help` instead'
make help

View File

@ -1,22 +1,50 @@
# LoopBack DataSource Juggler
# loopback-datasource-juggler
LoopBack DataSource Juggler is an ORM that provides a common set of interfaces
for interacting with databases, REST APIs, and other data sources. It was
initially forked from [JugglingDB](https://github.com/1602/jugglingdb).
An ORM/ODM that provides a common set of interfaces for interacting with databases, REST APIs, and other types of data sources. It was originally forked from [JugglingDB](https://github.com/1602/jugglingdb).
**For full documentation, see the official StrongLoop documentation**:
[Connecting models to data sources](http://docs.strongloop.com/display/LB/Connecting+models+to+data+sources)
For information on creating data sources programmatically, see [Advanced topics: data sources](http://docs.strongloop.com/display/LB/Advanced+topics%3A+data+sources).
## Supported versions
## Installation
This module adopts the [Module Long Term Support (LTS)](http://github.com/CloudNativeJS/ModuleLTS) policy, with the following End Of Life (EOL) dates:
npm install loopback-datasource-juggler
| Version | Status | Published | EOL |
| ---------- | --------------- | --------- | -------------------- |
| 4.x | Current | Oct 2018 | Apr 2023 _(minimum)_ |
| 3.x | End-of-Life | Dec 2016 | Dec 2020 |
| 2.x | End-of-Life | Jul 2014 | Apr 2019 |
Also install the appropriated connector, for example for mongodb:
Learn more about our LTS plan in the [LoopBack documentation](http://loopback.io/doc/en/contrib/Long-term-support.html).
npm install loopback-connector-mongodb
## Usage
See [StrongLoop Documentation](http://docs.strongloop.com/) for more information.
Install Juggler:
```
npm install loopback-datasource-juggler
```
Then install a connector:
```
npm install loopback-connector-mongodb // in this case, the mongodb connector
```
## Documentation
See the [LoopBack documentation](http://loopback.io/doc/en/lb3/index.html).
For information on data source connectors, see [Connecting models to data sources](https://loopback.io/doc/en/lb3/Connecting-models-to-data-sources.html).
## Contributing
This project uses [DCO](https://developercertificate.org/). Be sure to sign off
your commits using the `-s` flag or adding `Signed-off-By: Name<Email>` in the
commit message.
**Example**
```
git commit -s -m "feat: my commit message"
```
Also see the [Contributing to LoopBack](https://loopback.io/doc/en/contrib/code-contrib.html) to get you started.

19
SECURITY.md Normal file
View File

@ -0,0 +1,19 @@
# Security Policy
## Security advisories
Security advisories can be found on the
[LoopBack website](https://loopback.io/doc/en/sec/index.html).
## Reporting a vulnerability
If you think you have discovered a new security issue with any LoopBack package,
**please do not report it on GitHub**. Instead, send an email to
[security@loopback.io](mailto:security@loopback.io) with the following details:
- Full description of the vulnerability.
- Steps to reproduce the issue.
- Possible solutions.
If you are sending us any logs as part of the report, then make sure to redact
any sensitive data from them.

21
commitlint.config.js Normal file
View File

@ -0,0 +1,21 @@
// Copyright IBM Corp. 2017,2021. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const isCI = process.env.CI;
module.exports = {
extends: [
'@commitlint/config-conventional',
],
rules: {
'header-max-length': [2, 'always', 100],
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [0, 'always'],
// Only enforce the rule if CI flag is not set. This is useful for release
// commits to skip DCO
'signed-off-by': [isCI ? 0 : 2, 'always', 'Signed-off-by:'],
},
};

View File

@ -1,7 +1,13 @@
{
"content": [
"lib/dao.js",
"lib/scope.js",
"lib/relation-definition.js",
"lib/datasource.js",
"lib/model.js",
"lib/model-definition.js",
"lib/mixins.js",
"lib/date-string.js",
"lib/geo.js",
"lib/hooks.js",
"lib/include.js",

View File

@ -350,7 +350,7 @@ source.
* static and prototype methods to be mixed into the model constructor. The property can be defined
* on the prototype.
*/
connector.DataAccessObject = function {};
connector.DataAccessObject = function() {};
/**
* Connector instance can have an optional function to be called to handle data model definitions.

View File

@ -178,11 +178,11 @@ There are a set of options to control the model definition.
- strict:
- true: Only properties defined in the model are accepted. Use this
mode if you want to make sure only predefined properties are accepted.
mode if you want to make sure only predefined properties are accepted. Relational databases only support this setting.
- false: The model will be an open model. All properties are accepted,
including the ones that not predefined with the model. This mode is useful
if the mobile application just wants to store free form JSON data to
a schema-less database such as MongoDB.
a schema-less database such as MongoDB. For relational databases, the value will be converted back to true.
- undefined: Default to false unless the data source is backed by a
relational database such as Oracle or MySQL.

View File

@ -1,46 +1,53 @@
var DataSource = require('../../loopback-datasource-juggler').DataSource;
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var introspectType = require('../lib/introspection')(ModelBuilder);
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var ds = new DataSource('memory');
'use strict';
const DataSource = require('../../loopback-datasource-juggler').DataSource;
const ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
const introspectType = require('../lib/introspection')(ModelBuilder);
const ds = new DataSource('memory');
// Create a open model that doesn't require a schema
var Application = ds.createModel('Schemaless', {}, {strict: false});
const Application = ds.createModel('Schemaless', {}, {strict: false});
var application = {
const application = {
owner: 'rfeng',
name: 'MyApp1',
description: 'My first app',
pushSettings: [
{ "platform": "apns",
"apns": {
"pushOptions": {
"gateway": "gateway.sandbox.push.apple.com",
"cert": "credentials/apns_cert_dev.pem",
"key": "credentials/apns_key_dev.pem"
{'platform': 'apns',
'apns': {
'pushOptions': {
'gateway': 'gateway.sandbox.push.apple.com',
'cert': 'credentials/apns_cert_dev.pem',
'key': 'credentials/apns_key_dev.pem',
},
"feedbackOptions": {
"gateway": "feedback.sandbox.push.apple.com",
"cert": "credentials/apns_cert_dev.pem",
"key": "credentials/apns_key_dev.pem",
"batchFeedback": true,
"interval": 300
}
}}
]}
'feedbackOptions': {
'gateway': 'feedback.sandbox.push.apple.com',
'cert': 'credentials/apns_cert_dev.pem',
'key': 'credentials/apns_key_dev.pem',
'batchFeedback': true,
'interval': 300,
},
}},
]};
console.log(new Application(application).toObject());
Application.create(application, function (err, app1) {
Application.create(application, function(err, app1) {
console.log('Created: ', app1.toObject());
Application.findById(app1.id, function (err, app2) {
Application.findById(app1.id, function(err, app2) {
console.log('Found: ', app2.toObject());
});
});
// Instance JSON document
var user = {
const user = {
name: 'Joe',
age: 30,
birthday: new Date(),
@ -50,32 +57,30 @@ var user = {
city: 'San Jose',
state: 'CA',
zipcode: '95131',
country: 'US'
country: 'US',
},
friends: ['John', 'Mary'],
emails: [
{label: 'work', id: 'x@sample.com'},
{label: 'home', id: 'x@home.com'}
{label: 'home', id: 'x@home.com'},
],
tags: []
tags: [],
};
// Introspect the JSON document to generate a schema
var schema = introspectType(user);
const schema = introspectType(user);
// Create a model for the generated schema
var User = ds.createModel('User', schema, {idInjection: true});
const User = ds.createModel('User', schema, {idInjection: true});
// Use the model for CRUD
var obj = new User(user);
const obj = new User(user);
console.log(obj.toObject());
User.create(user, function (err, u1) {
User.create(user, function(err, u1) {
console.log('Created: ', u1.toObject());
User.findById(u1.id, function (err, u2) {
User.findById(u1.id, function(err, u2) {
console.log('Found: ', u2.toObject());
});
});

View File

@ -1,42 +1,45 @@
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var modelBuilder = new ModelBuilder();
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
const modelBuilder = new ModelBuilder();
// define models
var Post = modelBuilder.define('Post', {
title: { type: String, length: 255 },
content: { type: ModelBuilder.Text },
date: { type: Date, default: function () {
const Post = modelBuilder.define('Post', {
title: {type: String, length: 255},
content: {type: ModelBuilder.Text},
date: {type: Date, default: function() {
return new Date();
} },
timestamp: { type: Number, default: Date.now },
published: { type: Boolean, default: false, index: true }
}},
timestamp: {type: Number, default: Date.now},
published: {type: Boolean, default: false, index: true},
});
// simpler way to describe model
var User = modelBuilder.define('User', {
const User = modelBuilder.define('User', {
name: String,
bio: ModelBuilder.Text,
approved: Boolean,
joinedAt: Date,
age: Number
age: Number,
});
var Group = modelBuilder.define('Group', {group: String});
const Group = modelBuilder.define('Group', {group: String});
// define any custom method
User.prototype.getNameAndAge = function () {
User.prototype.getNameAndAge = function() {
return this.name + ', ' + this.age;
};
var user = new User({name: 'Joe'});
let user = new User({name: 'Joe'});
console.log(user);
console.log(modelBuilder.models);
console.log(modelBuilder.definitions);
User.mixin(Group);
var user = new User({name: 'Ray', group: 'Admin'});
user = new User({name: 'Ray', group: 'Admin'});
console.log(user);

View File

@ -1,35 +1,42 @@
var DataSource = require('../../loopback-datasource-juggler').DataSource;
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var ds = new DataSource('memory');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const DataSource = require('../../loopback-datasource-juggler').DataSource;
const ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
const ds = new DataSource('memory');
// define models
var Post = ds.define('Post', {
title: { type: String, length: 255 },
content: { type: DataSource.Text },
date: { type: Date, default: function () {
const Post = ds.define('Post', {
title: {type: String, length: 255},
content: {type: DataSource.Text},
date: {type: Date, default: function() {
return new Date;
} },
timestamp: { type: Number, default: Date.now },
published: { type: Boolean, default: false, index: true }
}},
timestamp: {type: Number, default: Date.now},
published: {type: Boolean, default: false, index: true},
});
// simplier way to describe model
var User = ds.define('User', {
const User = ds.define('User', {
name: String,
bio: DataSource.Text,
approved: Boolean,
joinedAt: Date,
age: Number
age: Number,
});
var Group = ds.define('Group', {name: String});
const Group = ds.define('Group', {name: String});
// define any custom method
User.prototype.getNameAndAge = function () {
User.prototype.getNameAndAge = function() {
return this.name + ', ' + this.age;
};
var user = new User({name: 'Joe'});
const user = new User({name: 'Joe'});
console.log(user);
// console.log(ds.models);
@ -51,46 +58,46 @@ Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
User.hasAndBelongsToMany('groups');
var user2 = new User({name: 'Smith', age: 14});
user2.save(function (err) {
const user2 = new User({name: 'Smith', age: 14});
user2.save(function(err) {
console.log(user2);
var post = user2.posts.build({title: 'Hello world'});
post.save(function (err, data) {
const post = user2.posts.build({title: 'Hello world'});
post.save(function(err, data) {
console.log(err ? err : data);
});
});
Post.findOne({where: {published: false}, order: 'date DESC'}, function (err, data) {
Post.findOne({where: {published: false}, order: 'date DESC'}, function(err, data) {
console.log(data);
});
User.create({name: 'Jeff', age: 12}, function (err, data) {
User.create({name: 'Jeff', age: 12}, function(err, data) {
if (err) {
console.log(err);
return;
}
console.log(data);
var post = data.posts.build({title: 'My Post'});
const post = data.posts.build({title: 'My Post'});
console.log(post);
});
User.create({name: 'Ray'}, function (err, data) {
User.create({name: 'Ray'}, function(err, data) {
console.log(data);
});
User.scope('minors', {where: {age: {lte: 16}}, include: 'posts'});
User.minors(function (err, kids) {
User.minors(function(err, kids) {
console.log('Kids: ', kids);
});
var Article = ds.define('Article', {title: String});
var Tag = ds.define('Tag', {name: String});
const Article = ds.define('Article', {title: String});
const Tag = ds.define('Tag', {name: String});
Article.hasAndBelongsToMany('tags');
Article.create(function (e, article) {
article.tags.create({name: 'popular'}, function (err, data) {
Article.findOne(function (e, article) {
article.tags(function (e, tags) {
Article.create(function(e, article) {
article.tags.create({name: 'popular'}, function(err, data) {
Article.findOne(function(e, article) {
article.tags(function(e, tags) {
console.log(tags);
});
});
@ -98,10 +105,10 @@ Article.create(function (e, article) {
});
// should be able to attach a data source to an existing model
var modelBuilder = new ModelBuilder();
const modelBuilder = new ModelBuilder();
Color = modelBuilder.define('Color', {
name: String
const Color = modelBuilder.define('Color', {
name: String,
});
// attach
@ -111,7 +118,7 @@ Color.create({name: 'red'});
Color.create({name: 'green'});
Color.create({name: 'blue'});
Color.all(function (err, colors) {
Color.all(function(err, colors) {
console.log(colors);
});

View File

@ -1,48 +1,53 @@
var jdb = require('../index');
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var User, Post, Passport, City, Street, Building;
var nbSchemaRequests = 0;
'use strict';
setup(function () {
const jdb = require('../index');
Passport.find({include: 'owner'}, function (err, passports) {
let User, Post, Passport, City, Street, Building;
const nbSchemaRequests = 0;
setup(function() {
Passport.find({include: 'owner'}, function(err, passports) {
console.log('passports.owner', passports);
});
User.find({include: 'posts'}, function (err, users) {
User.find({include: 'posts'}, function(err, users) {
console.log('users.posts', users);
});
Passport.find({include: {owner: 'posts'}}, function (err, passports) {
Passport.find({include: {owner: 'posts'}}, function(err, passports) {
console.log('passports.owner.posts', passports);
});
Passport.find({
include: {owner: {posts: 'author'}}
}, function (err, passports) {
include: {owner: {posts: 'author'}},
}, function(err, passports) {
console.log('passports.owner.posts.author', passports);
});
User.find({include: ['posts', 'passports']}, function (err, users) {
User.find({include: ['posts', 'passports']}, function(err, users) {
console.log('users.passports && users.posts', users);
});
});
function setup(done) {
var db = new jdb.DataSource({connector: 'memory'});
const db = new jdb.DataSource({connector: 'memory'});
City = db.define('City');
Street = db.define('Street');
Building = db.define('Building');
User = db.define('User', {
name: String,
age: Number
age: Number,
});
Passport = db.define('Passport', {
number: String
number: String,
});
Post = db.define('Post', {
title: String
title: String,
});
Passport.belongsTo('owner', {model: User});
@ -50,10 +55,10 @@ function setup(done) {
User.hasMany('posts', {foreignKey: 'userId'});
Post.belongsTo('author', {model: User, foreignKey: 'userId'});
db.automigrate(function () {
var createdUsers = [];
var createdPassports = [];
var createdPosts = [];
db.automigrate(function() {
let createdUsers = [];
let createdPassports = [];
let createdPosts = [];
createUsers();
function createUsers() {
clearAndCreate(
@ -63,12 +68,12 @@ function setup(done) {
{name: 'User B', age: 22},
{name: 'User C', age: 23},
{name: 'User D', age: 24},
{name: 'User E', age: 25}
{name: 'User E', age: 25},
],
function (items) {
function(items) {
createdUsers = items;
createPassports();
}
},
);
}
@ -78,12 +83,12 @@ function setup(done) {
[
{number: '1', ownerId: createdUsers[0].id},
{number: '2', ownerId: createdUsers[1].id},
{number: '3'}
{number: '3'},
],
function (items) {
function(items) {
createdPassports = items;
createPosts();
}
},
);
}
@ -95,25 +100,24 @@ function setup(done) {
{title: 'Post B', userId: createdUsers[0].id},
{title: 'Post C', userId: createdUsers[0].id},
{title: 'Post D', userId: createdUsers[1].id},
{title: 'Post E'}
{title: 'Post E'},
],
function (items) {
function(items) {
createdPosts = items;
done();
}
},
);
}
});
}
function clearAndCreate(model, data, callback) {
var createdItems = [];
model.destroyAll(function () {
const createdItems = [];
model.destroyAll(function() {
nextItem(null, null);
});
var itemIndex = 0;
let itemIndex = 0;
function nextItem(err, lastItem) {
if (lastItem !== null) {

View File

@ -1,4 +1,11 @@
var path = require('path'),
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const path = require('path'),
fs = require('fs'),
DataSource = require('../lib/datasource').DataSource;
@ -14,21 +21,20 @@ function loadSchemasSync(schemaFile, dataSource) {
}
// Read the dataSource JSON file
var schemas = JSON.parse(fs.readFileSync(schemaFile));
const schemas = JSON.parse(fs.readFileSync(schemaFile));
return dataSource.buildModels(schemas);
}
var models = loadSchemasSync(path.join(__dirname, 'jdb-schemas.json'));
let models = loadSchemasSync(path.join(__dirname, 'jdb-schemas.json'));
for (var s in models) {
var m = models[s];
for (const s in models) {
const m = models[s];
console.log(m.modelName, new m());
}
models = loadSchemasSync(path.join(__dirname, 'schemas.json'));
for (var s in models) {
var m = models[s];
for (const s in models) {
const m = models[s];
console.log(m.modelName, new m());
}

View File

@ -1,8 +1,15 @@
var ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
var modelBuilder = new ModelBuilder();
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const ModelBuilder = require('../../loopback-datasource-juggler').ModelBuilder;
const modelBuilder = new ModelBuilder();
// simplier way to describe model
var User = modelBuilder.define('User', {
const User = modelBuilder.define('User', {
name: String,
bio: ModelBuilder.Text,
approved: Boolean,
@ -13,21 +20,25 @@ var User = modelBuilder.define('User', {
city: String,
state: String,
zipCode: String,
country: String
country: String,
},
emails: [
{
label: String,
email: String
}
email: String,
},
],
friends: [String]
friends: [String],
});
var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
const user = new User({
name: 'Joe',
age: 20,
address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'},
emails: [
{label: 'work', email: 'xyz@sample.com'}
{label: 'work', email: 'xyz@sample.com'},
],
friends: ['John', 'Mary']});
friends: ['John', 'Mary'],
});
console.log(user);
console.log(user.toObject());

View File

@ -1,34 +1,40 @@
var DataSource = require('../index').DataSource;
var ds = new DataSource('memory');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var Order = ds.createModel('Order', {
'use strict';
const DataSource = require('../index').DataSource;
const ds = new DataSource('memory');
const Order = ds.createModel('Order', {
items: [String],
orderDate: Date,
qty: Number
qty: Number,
});
var Customer = ds.createModel('Customer', {
name: String
const Customer = ds.createModel('Customer', {
name: String,
});
Order.belongsTo(Customer);
var order1, order2, order3;
let order1, order2, order3;
Customer.create({name: 'John'}, function (err, customer) {
Order.create({customerId: customer.id, orderDate: new Date(), items: ['Book']}, function (err, order) {
Customer.create({name: 'John'}, function(err, customer) {
Order.create({customerId: customer.id, orderDate: new Date(), items: ['Book']}, function(err, order) {
order1 = order;
order.customer(console.log);
order.customer(true, console.log);
Customer.create({name: 'Mary'}, function (err, customer2) {
Customer.create({name: 'Mary'}, function(err, customer2) {
order.customer(customer2);
order.customer(console.log);
});
});
Order.create({orderDate: new Date(), items: ['Phone']}, function (err, order) {
Order.create({orderDate: new Date(), items: ['Phone']}, function(err, order) {
order.customer.create({name: 'Smith'}, function(err, customer2) {
console.log(order, customer2);
order.save(function(err, order) {
@ -36,20 +42,20 @@ Customer.create({name: 'John'}, function (err, customer) {
});
});
var customer3 = order.customer.build({name: 'Tom'});
const customer3 = order.customer.build({name: 'Tom'});
console.log('Customer 3', customer3);
});
});
Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'});
Customer.create({name: 'Ray'}, function (err, customer) {
Order.create({customerId: customer.id, qty: 3, orderDate: new Date()}, function (err, order) {
Customer.create({name: 'Ray'}, function(err, customer) {
Order.create({customerId: customer.id, qty: 3, orderDate: new Date()}, function(err, order) {
order3 = order;
customer.orders(console.log);
customer.orders.create({orderDate: new Date(), qty: 4}, function (err, order) {
customer.orders.create({orderDate: new Date(), qty: 4}, function(err, order) {
console.log(order);
Customer.include([customer], 'orders', function (err, results) {
Customer.include([customer], 'orders', function(err, results) {
console.log('Results: ', results);
});
customer.orders({where: {qty: 4}}, function(err, results) {
@ -61,18 +67,18 @@ Customer.create({name: 'Ray'}, function (err, customer) {
});
});
var Physician = ds.createModel('Physician', {
name: String
const Physician = ds.createModel('Physician', {
name: String,
});
var Patient = ds.createModel('Patient', {
name: String
const Patient = ds.createModel('Patient', {
name: String,
});
var Appointment = ds.createModel('Appointment', {
const Appointment = ds.createModel('Appointment', {
physicianId: Number,
patientId: Number,
appointmentDate: Date
appointmentDate: Date,
});
Appointment.belongsTo(Patient);
@ -81,55 +87,57 @@ Appointment.belongsTo(Physician);
Physician.hasMany(Patient, {through: Appointment});
Patient.hasMany(Physician, {through: Appointment});
Physician.create({name: 'Dr John'}, function (err, physician1) {
Physician.create({name: 'Dr Smith'}, function (err, physician2) {
Patient.create({name: 'Mary'}, function (err, patient1) {
Patient.create({name: 'Ben'}, function (err, patient2) {
Appointment.create({appointmentDate: new Date(), physicianId: physician1.id, patientId: patient1.id},
function (err, appt1) {
Appointment.create({appointmentDate: new Date(), physicianId: physician1.id, patientId: patient2.id},
function (err, appt2) {
Physician.create({name: 'Dr John'}, function(err, physician1) {
Physician.create({name: 'Dr Smith'}, function(err, physician2) {
Patient.create({name: 'Mary'}, function(err, patient1) {
Patient.create({name: 'Ben'}, function(err, patient2) {
Appointment.create(
{appointmentDate: new Date(), physicianId: physician1.id, patientId: patient1.id},
function(err, appt1) {
Appointment.create(
{appointmentDate: new Date(), physicianId: physician1.id, patientId: patient2.id},
function(err, appt2) {
physician1.patients(console.log);
physician1.patients({where: {name: 'Mary'}}, console.log);
patient1.physicians(console.log);
// Build an appointment?
var patient3 = patient1.physicians.build({name: 'Dr X'});
const patient3 = patient1.physicians.build({name: 'Dr X'});
console.log('Physician 3: ', patient3, patient3.constructor.modelName);
// Create a physician?
patient1.physicians.create({name: 'Dr X'}, function(err, patient4) {
console.log('Physician 4: ', patient4, patient4.constructor.modelName);
});
});
});
},
);
},
);
});
});
});
});
var Assembly = ds.createModel('Assembly', {
name: String
const Assembly = ds.createModel('Assembly', {
name: String,
});
var Part = ds.createModel('Part', {
partNumber: String
const Part = ds.createModel('Part', {
partNumber: String,
});
Assembly.hasAndBelongsToMany(Part);
Part.hasAndBelongsToMany(Assembly);
Assembly.create({name: 'car'}, function (err, assembly) {
Part.create({partNumber: 'engine'}, function (err, part) {
assembly.parts.add(part, function (err) {
Assembly.create({name: 'car'}, function(err, assembly) {
Part.create({partNumber: 'engine'}, function(err, part) {
assembly.parts.add(part, function(err) {
assembly.parts(function(err, parts) {
console.log('Parts: ', parts);
});
// Build an part?
var part3 = assembly.parts.build({partNumber: 'door'});
const part3 = assembly.parts.build({partNumber: 'door'});
console.log('Part3: ', part3, part3.constructor.modelName);
// Create a part?
@ -141,7 +149,6 @@ Assembly.create({name: 'car'}, function (err, assembly) {
});
});
});
});
});

36
index.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// Type definitions for loopback-datasource-juggler 3.x
// Project: https://github.com/strongloop/loopback-datasource-juggler
// Definitions by: Raymond Feng <https://github.com/raymondfeng>
// TypeScript Version: 2.8
/**
* Experimental TypeScript definitions to capture types of the key artifacts
* from `loopback-datasource-juggler` module. One of the main purposes is to
* leverage such types in `LoopBack 4`'s bridge to juggler.
*
* Please note some of the classes, properties, methods, and functions are
* intentionally not included in the definitions because of one of the following
* factors:
*
* - They are internal
* - They are to be deprecated
*/
export * from './types/common';
export * from './types/model';
export * from './types/relation';
export * from './types/query';
export * from './types/datasource';
export * from './types/kv-model';
export * from './types/persisted-model';
export * from './types/scope';
export * from './types/transaction-mixin';
export * from './types/relation-mixin';
export * from './types/observer-mixin';
export * from './types/validation-mixin';
export * from './types/inclusion-mixin';
export * from './types/connector';

View File

@ -1,3 +1,13 @@
// Copyright IBM Corp. 2011,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const SG = require('strong-globalize');
SG.SetRootDir(__dirname);
exports.ModelBuilder = exports.LDL = require('./lib/model-builder.js').ModelBuilder;
exports.DataSource = exports.Schema = require('./lib/datasource.js').DataSource;
exports.ModelBaseClass = require('./lib/model.js');
@ -5,12 +15,14 @@ exports.GeoPoint = require('./lib/geo.js').GeoPoint;
exports.ValidationError = require('./lib/validations.js').ValidationError;
Object.defineProperty(exports, 'version', {
get: function() {return require('./package.json').version;}
get: function() { return require('./package.json').version; },
});
var commonTest = './test/common_test';
const commonTest = './test/common_test';
Object.defineProperty(exports, 'test', {
get: function() {return require(commonTest);}
get: function() { return require(commonTest); },
});
exports.Transaction = require('loopback-connector').Transaction;
exports.KeyValueAccessObject = require('./lib/kvao');

97
intl/cs/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Vztah {{polymorphic}} {0}: {1} neočekává parametr `polymorphic.as` při definování vlastního parametru `foreignKey`/`discriminator` ",
"09483e03b91c8bd58732a74b3ef1ec13": "Neplatné datum: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany přijal cíl, který neobsahuje povinný \"{0}\"",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "Pořadí {0} není platné",
"0bd753a8944ad0af85a939bb25273887": "Nelze ukončit platnost neznámého klíče {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "Model {{Polymorphic}} nebyl nalezen: `{0}` nenastaven",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Tabulka '{0}' neexistuje.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} nelze aktualizovat z {0} na {1}, když je {{forceId}} nastaveno na true",
"1ae7d3e0be381efb32bfd1ba652f5172": "VAROVÁNÍ: Vztah {{polymorphic}} {0}: {1} používá klíčové slovo `polymorphic.as`, které bude ZAMÍTNUTO v LoopBack.next, vit tato dokumentace s řešeními nahrazení (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Vnoření transakcí není podporováno",
"21095484501dbff31af6556fa6039182": "Parametr {{offset/skip}} {0} není platný",
"280f4550f90e133118955ec6f6f72830": "Byl zadán typ diskriminátoru {0}, ale neexistuje žádný model s tímto názvem",
"28697ec15968a7969211f6d035ba9260": "Vztah {{polymorphic}} {0}: {1} neočekává parametr `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} není podporována",
"2c5c8519721f749aab13c2f04f41d611": "Vlastnost {0} má neplatnou klauzuli {1}: Očekávaly se přesně 2 hodnoty, přijaty {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nVAROVÁNÍ: Konektor {{LoopBack}} \"{0}\" není nainstalován jako žádný z následujících modulů:\n\n {1}\n\nChcete-li provést opravu, spusťte:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Varování: Model {0}, {{strict mode: `throw`}} byl odebrán, místo toho použijte {{`strict: true`}}, což vrací {{`Validation Error`}} pro neznámé vlastnosti,",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} není definován pro vztah {0} a není {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Žádná instance s ID {0} nebyla nalezena pro {1}",
"416dfbb7b823f51c9f3800be81060b41": "Žádná instance s {{id}} {0} nebyla nalezena pro {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "Metoda BelongsTo \"getAsync()\" je zamítnuta, místo toho použijte \"get()\".",
"4c78325cedbb826db3a05bf5df0e8546": "Musíte zadat {{id}} při nahrazení!",
"4e31b1edd10dadb724d83387de0b5062": "Parametr {{limit}} {0} není platný",
"514985b2327f061ffb1c932f6b909979": "Model {0} není definován.",
"525c856e65daab43be247e7b5410febd": "Vztah {{polymorphic}} {0}: {1} neočekává parametr `polymorphic.selector` při definování vlastního parametru `foreignKey`/`discriminator` ",
"5c18ee111dd87540cdb19a2a93b33be9": "Transakce je odvolána v důsledku vypršení časového limitu",
"5ec7e6664256f7ea78f4f06dafc7d974": "Transakce není připravena, počkejte na vyřešení vráceného závazku",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Žádný název {{id}} {0}",
"614e3355647e4127c96256102dc63376": "Vlastnost {0} má neplatnou klauzuli {1}: Byl očekáván řetězec nebo RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} má neplatný směr",
"6502a117987610380b9068ef98b1b0ee": "Nebyl nalezen žádný záznam v {0} pro ({1}. {2}, {3}. {4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Konektor {0} nepodporuje operaci {{replaceById}}. Nejde o chybu ve zpětné smyčce. Obraťte se na autory konektoru, pokud možno přes problémy GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} vyžaduje argument {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} vyžaduje argument {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "Vztah {{HasOne}} nemůže vytvořit více než jednu instanci {0}",
"728232e473bf80272c042df2b7e002f4": "Vztah {{polymorphic}} {0}: {1} vyžaduje parametr `polymorphic.discriminator`, je-li dodán parametr `polymorphic.foreignKey`",
"791ab3031a73ede03f7d6299a85e8289": "Časový limit připojení po {0} ms",
"7b277018e43d41bc445731092b91547d": "Nepřipojeno",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} vyžaduje argument {{id}}",
"7e9530c0399289be0ee601a604be71ff": "Vztah {{BelongsTo}} {0} je prázdný",
"7faa840eb6ce11250a141deb42a6c489": "Neznámý vztah {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Název vlastnosti by neměl být \"{{constructor}}\" v modelu: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Název vlastnosti \"{{constructor}}\" není povolen v datech {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Model {{Polymorphic}} nebyl nalezen: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Neplatný argument, musí být řetězec, {{regex}} nebo {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "Instance {0} není platná. Podrobnosti: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Neplatné příznaky {{regex}}: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Položkami musí být pole: {0}",
"9e1f143ee02946324d34da92f71bf74e": "Vztah {0}: {1} vyžaduje parametr `model`",
"a004f310d315e592843776fab964eaeb": "Vztahy {{Polymorphic}} vyžadují model typu through",
"a0cf0e09c26df14283223e84e6a10f00": "Nelze aktualizovat atributy. {{Object}} s {{id}} {0} neexistuje!",
"a2487abefef4259c2131d96cdb8543b1": "Připojení se nezdařilo: {0} \nBude zopakováno pro další požadavek.",
"a25e41a39c60c4702e55d0c3936576a1": "Neshoda klíče: {0}. {1}: {2}, {3}. {4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Neznámá metoda rozsahu: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Spustit příkaz \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "VAROVÁNÍ: Vlastnost {{id}} nelze změnit z {0} na {1} pro model: {2} v háčku operace {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "VAROVÁNÍ: Vlastnost {{id}} nelze změnit z {0} na {1} pro model: {2} v háčku operace {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "Metoda HasOne \"getAsync()\" je zamítnuta, místo toho použijte \"get()\".",
"b138294f132edfe1eb2a8211150c7238": "Neočekávaný parametr `undefined` v dotazu",
"b15b20280211ad258d92947f05b6e4a5": "Konektor nebyl inicializován.",
"b278876ec93ef9760f00e83f38ba313d": "Metoda Scope \"getAsync()\" je zamítnuta, místo toho použijte \"find()\".",
"ba0fd8106eb54de4d003a844206431fd": "Háček modelu \"{0}\" je zamítnut, místo toho použijte háčky operace. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Klauzule where {0} není {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Není definován typ vlastnosti {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Hodnota je prázdný {{object}}",
"bec226891a505828bfc76c5cfd73b336": "Nelze získat TTL pro neznámý klíč {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Neznámý poskytovatel výchozí hodnoty {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Názvy vlastnosti obsahující tečku(y) nejsou podporovány. Model: {0}, dynamická vlastnost: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "Zdroj dat nepodporuje transakce",
"da02dd6c53d4148320eeb31718a7aebe": "Neplatný typ pro vlastnost {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Názvy vlastnosti obsahující tečku(y) nejsou podporovány. Model: {0}, vlastnost: {1}",
"db03083e9a768388fdbee865249ac67a": "Ignorují se chyby ověření platnosti v {{updateOrCreate()}}:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Hodnota není {{array}} nebo {{object}} se sekvenčními číselnými indexy",
"ddf0aa14803f1c84f4a97f3803f7471c": "Je vyžadován název třídy",
"e08ab0e1ab55f26c357061447b635905": "Nebyl nalezen žádný vztah v {0} pro ({1}. {2}, {3}. {4})",
"e0e9504e137a3c3339144b51ed76fef2": "Konektor není definován správně: měl by vytvořit člen `{{connector}}` zdroje dat",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Vztah {{polymorphic}} {0}: {1} vyžaduje parametr `polymorphic.foreignKey`, když je dodán parametr `polymorphic.discriminator`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "Vlastnost {0} má neplatnou klauzuli {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Neznámé \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Nelze migrovat modely, které nejsou připojeny k tomuto zdroji dat: {0}",
"e54f118a75e15e132f16b985274eb46d": "Filtr dotazu {0} není {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "Vztah {{HasOne}} {0} je prázdný",
"e6161ae8459c79d810e2aa9d21282a39": "Při aktualizaci atributů musíte poskytnout {{id}}!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Vztah \"{0}\" není definován pro model {1}",
"ec42dca074f1818c447f7ad16e2d01af": "{0} není poskytnut připojeným konektorem",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} není aktivní: {0}",
"f30809cb932b72a66416a709c8531530": "Konektor nepodporuje {{method}} v rámci transakce",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "nelze vytvořit seznam z řetězce JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "Vlastnost {{id}} ({0}) nelze aktualizovat z {1} na {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Vztah {{polymorphic}} {0}: {1} vyžaduje parametr `model`",
"fca4d12faff1035d9d0438d73432571b": "Duplicitní položka pro {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Nelze najít vztah {0} pro model {1}",
"fec8ebda24db46a9d040bf863765cc44": "Operátor {0} má neplatné klauzule {1}: {2}"
}

97
intl/de/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} Beziehung: {1} erwartet keinen Parameter 'polymorphic.as' beim Definieren eines angepassten 'foreignKey'/'discriminator' ",
"09483e03b91c8bd58732a74b3ef1ec13": "Ungültiges Datum: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany hat ein Ziel empfangen, dass das erforderliche \"{0}\" nicht enthält",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "Die Reihenfolge {0} ist nicht gültig",
"0bd753a8944ad0af85a939bb25273887": "Unbekannter Schlüssel {0} darf nicht ablaufen",
"0c0b867aca0973ba26e887d3337cc4ec": "{{Polymorphic}}-Modell nicht gefunden: '{0}' nicht festgelegt",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Tabelle '{0}' ist nicht vorhanden.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} kann nicht von {0} auf {1} aktualisiert werden, wenn für {{forceId}} true festgelegt ist",
"1ae7d3e0be381efb32bfd1ba652f5172": "WARNUNG: {{polymorphic}} {0} Beziehung: {1} verwendet Schlüsselwort 'polymorphic.as', das in LoopBack.next VERALTET sein wird. Lesen Sie diese Dokumentation zu Ersatzlösungen (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Verschachtelungstransaktionen werden nicht unterstützt",
"21095484501dbff31af6556fa6039182": "Der {{offset/skip}}-Parameter {0} ist nicht gültig",
"280f4550f90e133118955ec6f6f72830": "Diskriminatortyp {0} angegeben, aber es ist kein Modell mit diesem Namen vorhanden",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} Beziehung: {1} erwartet keinen Parameter 'model'",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} wird nicht unterstützt",
"2c5c8519721f749aab13c2f04f41d611": "Die Eigenschaft {0} weist die ungültige Klausel {1} auf: Es wurden genau 2 Werte erwartet, aber {2} empfangen",
"2f4af31c144bbfab1bbf479866acd820": "\nWARNUNG: {{LoopBack}}-Konnektor \"{0}\" ist als keines der folgenden Module installiert:\n\n {1}\n\nFühren Sie zur Behebung Folgendes aus:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Warnung: Modell {0}, {{strict mode: `throw`}} wurde entfernt. Verwenden Sie stattdessen {{`strict: true`}}, wodurch {{`Validation Error`}} für unbekannte Eigenschaften zurückgegeben wird.",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} ist für Beziehung {0} nicht definiert und ist keine {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Keine Instanz mit ID {0} für {1} gefunden",
"416dfbb7b823f51c9f3800be81060b41": "Keine Instanz mit {{id}} {0} für {1} gefunden",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo-Methode \"getAsync()\" ist veraltet, verwenden Sie stattdessen \"get()\".",
"4c78325cedbb826db3a05bf5df0e8546": "Sie müssen beim Ersetzen eine {{id}} angeben!",
"4e31b1edd10dadb724d83387de0b5062": "Der {{limit}}-Parameter {0} ist nicht gültig",
"514985b2327f061ffb1c932f6b909979": "Modell {0} ist nicht definiert.",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} Beziehung: {1} erwartet keinen Parameter 'polymorphic.selector' beim Definieren eines angepassten 'foreignKey'/'discriminator' ",
"5c18ee111dd87540cdb19a2a93b33be9": "Transaktion wurde aufgrund eines Zeitlimits rückgängig gemacht",
"5ec7e6664256f7ea78f4f06dafc7d974": "Transaktion ist nicht bereit, auf die Auflösung des zurückgegebenen Promise warten",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Kein {{id}}-Name {0}",
"614e3355647e4127c96256102dc63376": "Die Eigenschaft {0} weist die ungültige Klausel {1} auf: Es wurde eine Zeichenfolge oder RegExp erwartet",
"62a2d80c405b7fec5f547c448ab1b6ff": "Die {{order}} {0} hat eine ungültige Richtung",
"6502a117987610380b9068ef98b1b0ee": "Kein Datensatz gefunden in {0} für ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Der Konnektor {0} unterstützt die Operation {{replaceById}} nicht. Hierbei handelt es sich nicht um einen Fehler in LoopBack. Wenden Sie sich an die Ersteller des Konnektors, vorzugsweise über GitHub-Probleme.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} erfordert das Argument {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} erfordert das Argument {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}}-Beziehung kann nicht mehr als eine Instanz von {0} erstellen",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} Beziehung: {1} erfordert den Parameter 'polymorphic.discriminator', wenn der Parameter 'polymorphic.foreignKey' angegeben ist",
"791ab3031a73ede03f7d6299a85e8289": "Zeitlimitüberschreitung bei Verbindungsherstellung nach {0} ms",
"7b277018e43d41bc445731092b91547d": "Nicht verbunden",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} erfordert das Argument {{id}}",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}}-Beziehung {0} ist leer",
"7faa840eb6ce11250a141deb42a6c489": "Unbekannter {{scope}} für Beziehung: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Eigenschaftsname sollte nicht \"{{constructor}}\" sein in Modell: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Eigenschaftsname \"{{constructor}}\" ist in {0}-Daten nicht zulässig",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}}-Modell nicht gefunden: '{0}'",
"89bf6d92731fe7bd2146ce8d0bec205c": "Ungültiges Argument, muss eine Zeichenfolge, ein {{regex}}-Literalwert oder ein {{RegExp}}-Objekt sein",
"8a39126103a157f501affa070367a1b0": "Die Instanz {0} ist nicht gültig. Details: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Ungültige {{regex}}-Flags: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Elemente müssen ein Array sein: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} Beziehung: {1} erfordert den Parameter 'model'",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}}-Beziehungen erfordern ein through-Modell",
"a0cf0e09c26df14283223e84e6a10f00": "Attribute konnten nicht aktualisiert werden. {{Object}} mit {{id}} {0} ist nicht vorhanden!",
"a2487abefef4259c2131d96cdb8543b1": "Verbindungsfehler: {0}\nNach der nächsten Anforderung findet ein Neuversuch statt.",
"a25e41a39c60c4702e55d0c3936576a1": "Schlüssel stimmen nicht überein: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Unbekannte Bereichsmethode: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Führen Sie den Befehl \"{{npm install loopback-datasource-juggler}} {0}\" aus ",
"a829dee089c912e68c18920ba015400c": "WARNUNG: Eigenschaft {{id}} darf für Modell {2} in Operationshook {{'loaded'}} nicht von {0} in {1} geändert werden",
"a984a076c59e451948b2bcf7a393d860": "WARNUNG: Eigenschaft {{id}} darf für Modell {2} in Operationshook {{'before save'}} nicht von {0} in {1} geändert werden",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne-Methode \"getAsync()\" ist veraltet, verwenden Sie stattdessen \"get()\".",
"b138294f132edfe1eb2a8211150c7238": "Unerwartetes 'nicht definiert' in Abfrage",
"b15b20280211ad258d92947f05b6e4a5": "Der Konnektor wurde nicht initialisiert.",
"b278876ec93ef9760f00e83f38ba313d": "Scope-Methode \"getAsync()\" ist veraltet, verwenden Sie stattdessen \"get()\".",
"ba0fd8106eb54de4d003a844206431fd": "Modellhook \"{0}\" ist veraltet, verwenden Sie stattdessen Operationshooks. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Bei der where-Klausel {0} handelt es sich nicht um ein {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Typ nicht definiert für Eigenschaft {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Wert ist ein leeres {{object}}",
"bec226891a505828bfc76c5cfd73b336": "TTL für unbekannten Schlüssel {0} kann nicht abgerufen werden",
"cd930369e86cdd222f7bd117c6f9fa94": "Unbekannter Standardwertprovider {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Eigenschaftsnamen, die Punkt(e) enthalten, werden nicht unterstützt. Modell: {0}, dynamische Eigenschaft: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource unterstützt keine Transaktionen",
"da02dd6c53d4148320eeb31718a7aebe": "Ungültiger Typ für Eigenschaft {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Eigenschaftsnamen, die Punkt(e) enthalten, werden nicht unterstützt. Modell: {0}, Eigenschaft: {1}",
"db03083e9a768388fdbee865249ac67a": "Validierungsfehler in {{updateOrCreate()}} werden ignoriert:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Der Wert ist kein {{array}} oder {{object}} mit sequenziellen numerischen Indizes",
"ddf0aa14803f1c84f4a97f3803f7471c": "Klassenname erforderlich",
"e08ab0e1ab55f26c357061447b635905": "Keine Beziehung gefunden in {0} für ({1}.{2} ,{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Konnektor ist nicht ordnungsgemäß definiert: Er sollte ein {{connector}}-Member von dataSource erstellen",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} Beziehung: {1} erfordert den Parameter 'polymorphic.foreignKey', wenn der Parameter 'polymorphic.discriminator' angegeben ist",
"e39e0f5d52bfbf511e645d19ecadd2fa": "Die Eigenschaft {0} weist die ungültige Klausel {1} auf: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Unbekannte \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Modelle, die nicht an diese Datenquelle angehängt sind, können nicht migriert werden: {0}",
"e54f118a75e15e132f16b985274eb46d": "Beim Abfragefilter {0} handelt es sich nicht um ein {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}}-Beziehung {0} ist leer",
"e6161ae8459c79d810e2aa9d21282a39": "Sie müssen beim Aktualisieren von Attributen eine {{id}} angeben!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Beziehung \"{0}\" ist nicht definiert für {1} modell",
"ec42dca074f1818c447f7ad16e2d01af": "{0} wird vom zugeordneten Konnektor nicht angegeben",
"ecb7aa804bf54c682999d20d6436104c": "Die {{transaction}} ist nicht aktiv: {0}",
"f30809cb932b72a66416a709c8531530": "Der Konnektor unterstützt {{method}} innerhalb einer Transaktion nicht",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "konnte Liste nicht aus JSON-Zeichenfolge erstellen: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}}-Eigenschaft ({0}) kann nicht von {1} in {2} aktualisiert werden",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} Beziehung: {1} erfordert den Parameter 'model'",
"fca4d12faff1035d9d0438d73432571b": "Doppelter Eintrag für {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Beziehung {0} für Modell {1} konnte nicht gefunden werden",
"fec8ebda24db46a9d040bf863765cc44": "Der Operator {0} weist ungültige Klauseln {1} auf: {2}"
}

96
intl/en/messages.json Normal file
View File

@ -0,0 +1,96 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} relation: {1} does not expect param `polymorphic.as` when defing custom `foreignKey`/`discriminator` ",
"09483e03b91c8bd58732a74b3ef1ec13": "Invalid date: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany received target that doesn't contain required \"{0}\"",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "The order {0} is not valid",
"0bd753a8944ad0af85a939bb25273887": "Cannot expire unknown key {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "{{Polymorphic}} model not found: `{0}` not set",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Table '{0}' does not exist.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} cannot be updated from {0} to {1} when {{forceId}} is set to true",
"1ae7d3e0be381efb32bfd1ba652f5172": "WARNING: {{polymorphic}} {0} relation: {1} uses keyword `polymorphic.as` which will be DEPRECATED in LoopBack.next, refer to this doc for replacement solutions (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Nesting transactions is not supported",
"21095484501dbff31af6556fa6039182": "The {{offset/skip}} parameter {0} is not valid",
"280f4550f90e133118955ec6f6f72830": "Discriminator type {0} specified but no model exists with such name",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} relation: {1} does not expect param `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} is not supported",
"2c5c8519721f749aab13c2f04f41d611": "The {0} property has invalid clause {1}: Expected precisely 2 values, received {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nWARNING: {{LoopBack}} connector \"{0}\" is not installed as any of the following modules:\n\n {1}\n\nTo fix, run:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Warning: Model {0}, {{strict mode: `throw`}} has been removed, please use {{`strict: true`}} instead, which returns{{`Validation Error`}} for unknown properties,",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} is not defined for relation {0} and is no {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "No instance with id {0} found for {1}",
"416dfbb7b823f51c9f3800be81060b41": "No instance with {{id}} {0} found for {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo method \"getAsync()\" is deprecated, use \"get()\" instead.",
"4c78325cedbb826db3a05bf5df0e8546": "You must provide an {{id}} when replacing!",
"4e31b1edd10dadb724d83387de0b5062": "The {{limit}} parameter {0} is not valid",
"514985b2327f061ffb1c932f6b909979": "Model {0} is not defined.",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} relation: {1} does not expect param `polymorphic.selector` when defing custom `foreignKey`/`discriminator` ",
"5c18ee111dd87540cdb19a2a93b33be9": "Transaction is rolled back due to timeout",
"5ec7e6664256f7ea78f4f06dafc7d974": "Transaction is not ready, wait for the returned promise to resolve",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "No {{id}} name {0}",
"614e3355647e4127c96256102dc63376": "The {0} property has invalid clause {1}: Expected a string or RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "The {{order}} {0} has invalid direction",
"6502a117987610380b9068ef98b1b0ee": "No record found in {0} for ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "The connector {0} does not support {{replaceById}} operation. This is not a bug in LoopBack. Please contact the authors of the connector, preferably via GitHub issues.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} requires the {{id}} argument",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} requires the {{id}} argument",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} relation cannot create more than one instance of {0}",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} relation: {1} requires param `polymorphic.discriminator` when param `polymorphic.foreignKey` is provided",
"791ab3031a73ede03f7d6299a85e8289": "Timeout in connecting after {0} ms",
"7b277018e43d41bc445731092b91547d": "Not connected",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} requires the {{id}} argument",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} relation {0} is empty",
"7faa840eb6ce11250a141deb42a6c489": "Unknown relation {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Property name should not be \"{{constructor}}\" in Model: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Property name \"{{constructor}}\" is not allowed in {0} data",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}} model not found: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Invalid argument, must be a string, {{regex}} literal, or {{RegExp}} object",
"8a39126103a157f501affa070367a1b0": "The {0} instance is not valid. Details: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Invalid {{regex}} flags: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Items must be an array: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} relation: {1} requires param `model`",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} relations need a through model",
"a0cf0e09c26df14283223e84e6a10f00": "Could not update attributes. {{Object}} with {{id}} {0} does not exist!",
"a2487abefef4259c2131d96cdb8543b1": "Connection fails: {0}\nIt will be retried for the next request.",
"a25e41a39c60c4702e55d0c3936576a1": "Key mismatch: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Unknown scope method: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Run \"{{npm install loopback-datasource-juggler}} {0}\" command ",
"a829dee089c912e68c18920ba015400c": "WARNING: {{id}} property cannot be changed from {0} to {1} for model:{2} in {{'loaded'}} operation hook",
"a984a076c59e451948b2bcf7a393d860": "WARNING: {{id}} property cannot be changed from {0} to {1} for model:{2} in {{'before save'}} operation hook",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne method \"getAsync()\" is deprecated, use \"get()\" instead.",
"b138294f132edfe1eb2a8211150c7238": "Unexpected `undefined` in query",
"b15b20280211ad258d92947f05b6e4a5": "The connector has not been initialized.",
"b278876ec93ef9760f00e83f38ba313d": "Scope method \"getAsync()\" is deprecated, use \"find()\" instead.",
"ba0fd8106eb54de4d003a844206431fd": "Model hook \"{0}\" is deprecated, use Operation hooks instead. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "The where clause {0} is not an {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Type not defined for property {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Value is an empty {{object}}",
"bec226891a505828bfc76c5cfd73b336": "Cannot get TTL for unknown key {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Unknown default value provider {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Property names containing dot(s) are not supported. Model: {0}, dynamic property: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource does not support transactions",
"da02dd6c53d4148320eeb31718a7aebe": "Invalid type for property {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Property names containing dot(s) are not supported. Model: {0}, property: {1}",
"db03083e9a768388fdbee865249ac67a": "Ignoring validation errors in {{updateOrCreate()}}:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Value is not an {{array}} or {{object}} with sequential numeric indices",
"ddf0aa14803f1c84f4a97f3803f7471c": "Class name required",
"e08ab0e1ab55f26c357061447b635905": "No relation found in {0} for ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Connector is not defined correctly: it should create `{{connector}}` member of dataSource",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} relation: {1} requires param `polymorphic.foreignKey` when param `polymorphic.discriminator` is provided",
"e39e0f5d52bfbf511e645d19ecadd2fa": "The {0} property has invalid clause {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Unknown \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Cannot migrate models not attached to this datasource: {0}",
"e54f118a75e15e132f16b985274eb46d": "The query filter {0} is not an {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} relation {0} is empty",
"e6161ae8459c79d810e2aa9d21282a39": "You must provide an {{id}} when updating attributes!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Relation \"{0}\" is not defined for {1} model",
"ec42dca074f1818c447f7ad16e2d01af": "{0} is not provided by the attached connector",
"ecb7aa804bf54c682999d20d6436104c": "The {{transaction}} is not active: {0}",
"f30809cb932b72a66416a709c8531530": "The connector does not support {{method}} within a transaction",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "could not create List from JSON string: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}} property ({0}) cannot be updated from {1} to {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} relation: {1} requires param `model`",
"fca4d12faff1035d9d0438d73432571b": "Duplicate entry for {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Could not find relation {0} for model {1}",
"fec8ebda24db46a9d040bf863765cc44": "The {0} operator has invalid clauses {1}: {2}"
}

97
intl/es/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Relación {0} {{polymorphic}}: {1} no espera el parámetro `polymorphic.as` al definir `foreignKey`/`discriminator` personalizado ",
"09483e03b91c8bd58732a74b3ef1ec13": "Fecha no válida: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany ha recibido un destino que no contiene el \"{0}\" obligatorio",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "El orden {0} no es válido",
"0bd753a8944ad0af85a939bb25273887": "La clave desconocida {0} no puede caducar",
"0c0b867aca0973ba26e887d3337cc4ec": "Modelo {{Polymorphic}} no encontrado: `{0}` no establecido",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "La tabla '{0}' no existe.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} no puede actualizarse de {0} a {1} cuando {{forceId}} está establecido en true",
"1ae7d3e0be381efb32bfd1ba652f5172": "AVISO: Relación {0} {{polymorphic}}: {1} utiliza la c¡palabra clave `polymorphic.as` que estará EN DESUSO en LoopBack.next, reconsulte este documento para conocer las posibles sustituciones (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Las transacciones anidadas no están soportadas",
"21095484501dbff31af6556fa6039182": "El parámetro de {{offset/skip}} {0} no es válido",
"280f4550f90e133118955ec6f6f72830": "Se ha especificado el tipo de discriminador {0}, pero no existe ningún modelo con ese nombre",
"28697ec15968a7969211f6d035ba9260": "Relación {0} {{polymorphic}}: {1} no espera el parámetro `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} no está soportada.",
"2c5c8519721f749aab13c2f04f41d611": "La propiedad {0} tiene una cláusula {1} no válida: se esperaban exactamente 2 valores, se han recibido {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nAVISO: el conector {{LoopBack}} \"{0}\" no está instalado como ninguno de los módulos siguientes:\n\n {1}\n\nPara solucionarlo, ejecute:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Aviso: el modelo {0}, {{strict mode: `throw`}} se ha eliminado; utilice {{`strict: true`}} en su lugar, que devuelve {{`Validation Error`}} para propiedades desconocidas.",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} no se ha definido para la relación {0} y no es {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "No se ha encontrado ninguna instancia con el ID {0} para {1}",
"416dfbb7b823f51c9f3800be81060b41": "No se ha encontrado ninguna instancia con el {{id}} {0} para {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "El método BelongsTo \"getAsync()\" está en desuso, utilice \"get()\" en su lugar.",
"4c78325cedbb826db3a05bf5df0e8546": "Debe proporcionar un {{id}} al sustituir.",
"4e31b1edd10dadb724d83387de0b5062": "El parámetro de {{limit}} {0} no es válido",
"514985b2327f061ffb1c932f6b909979": "El modelo {0} no se ha definido.",
"525c856e65daab43be247e7b5410febd": "Relación {0} {{polymorphic}}: {1} no espera el parámetro `polymorphic.selector` al definir `foreignKey`/`discriminator` personalizado ",
"5c18ee111dd87540cdb19a2a93b33be9": "La transacción se ha retrotraído debido a tiempo de espera excedido",
"5ec7e6664256f7ea78f4f06dafc7d974": "La transacción no está lista, espere la promesa devuelta para resolver",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Ningún {{id}} de nombre {0}",
"614e3355647e4127c96256102dc63376": "La propiedad {0} tiene una cláusula {1} no válida: se esperaba una serie o expresión regular",
"62a2d80c405b7fec5f547c448ab1b6ff": "El {{order}} {0} tiene una dirección no válida",
"6502a117987610380b9068ef98b1b0ee": "No se ha encontrado ningún registro en {0} para ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "El conector {0} no admite la operación {{replaceById}}. Esto no es un error en LoopBack. Póngase en contacto con los autores del conector, preferiblemente a través de cuestiones GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} requiere el argumento {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} requiere el argumento {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "La relación {{HasOne}} no puede crear más de una instancia de {0}",
"728232e473bf80272c042df2b7e002f4": "Relación {0} {{polymorphic}}: {1} requiere el parámetro `polymorphic.discriminator` cuando se proporciona el parámetro `polymorphic.foreignKey`",
"791ab3031a73ede03f7d6299a85e8289": "Tiempo de espera agotado al conectarse después de {0} ms",
"7b277018e43d41bc445731092b91547d": "No conectado",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} requiere el argumento {{id}}",
"7e9530c0399289be0ee601a604be71ff": "La relación {{BelongsTo}} {0} está vacía",
"7faa840eb6ce11250a141deb42a6c489": "Relación desconocida {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "El nombre de propiedad no debe ser \"{{constructor}}\" en el modelo: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "El nombre de propiedad \"{{constructor}}\" no está permitido en datos de {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Modelo {{Polymorphic}} no encontrado: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Argumento no válido, debe ser una serie, literal de {{regex}} u objeto {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "La instancia {0} no es válida. Detalles: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Distintivos de {{regex}} no válidos: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Items debe ser una matriz: {0}",
"9e1f143ee02946324d34da92f71bf74e": "Relación {0}: {1} requiere el parámetro `model`",
"a004f310d315e592843776fab964eaeb": "Las relaciones {{Polymorphic}} necesitan un modelo definido",
"a0cf0e09c26df14283223e84e6a10f00": "No se han podido actualizar atributos. {{Object}} con {{id}} {0} no existe.",
"a2487abefef4259c2131d96cdb8543b1": "La conexión falla: {0}\nSe reintentará en la siguiente solicitud.",
"a25e41a39c60c4702e55d0c3936576a1": "Discrepancia de claves: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Método de ámbito desconocido: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Ejecute el mandato \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "AVISO: la propiedad {{id}} no puede cambiarse de {0} a {1} para el modelo:{2} en el gancho de operación {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "AVISO: la propiedad {{id}} no puede cambiarse de {0} a {1} para el modelo:{2} en el gancho de operación {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "El método HasOne \"getAsync()\" está en desuso, utilice \"get()\" en su lugar.",
"b138294f132edfe1eb2a8211150c7238": "`undefined` inesperado en la consulta",
"b15b20280211ad258d92947f05b6e4a5": "El conector no se ha inicializado.",
"b278876ec93ef9760f00e83f38ba313d": "El método Scope \"getAsync()\" está en desuso, utilice \"find()\" en su lugar.",
"ba0fd8106eb54de4d003a844206431fd": "El gancho de modelo \"{0}\" está en desuso, utilice ganchos de operación en su lugar. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "La cláusula where {0} no es un {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Tipo no definido para la propiedad {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "El valor es un {{object}} vacío",
"bec226891a505828bfc76c5cfd73b336": "No se puede obtener TTL para la clave desconocida {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Proveedor de valor predeterminado desconocido {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Los nombres de propiedad que contienen puntos no están soportados. Modelo: {0}, propiedad dinámica: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource no da soporte a las transacciones",
"da02dd6c53d4148320eeb31718a7aebe": "Tipo no válido para la propiedad {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Los nombres de propiedad que contienen puntos no están soportados. Modelo: {0}, propiedad: {1}",
"db03083e9a768388fdbee865249ac67a": "Se ignoran los errores de validación en {{updateOrCreate()}}:",
"dd63416d9b7d9fa4181e89efd619dfd8": "El valor no es una {{array}} u {{object}} con índices numéricos secuenciales",
"ddf0aa14803f1c84f4a97f3803f7471c": "Nombre de clase obligatorio",
"e08ab0e1ab55f26c357061447b635905": "No se ha encontrado ninguna relación en {0} para ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "El conector no está definido correctamente: debe crear el miembro `{{connector}}` de dataSource",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Relación {0} {{polymorphic}}: {1} requiere el parámetro `polymorphic.foreignKey` cuando se proporciona el parámetro `polymorphic.discriminator`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "La propiedad {0} tiene una cláusula {1} no válida: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "{{id}} de \"{0}\" desconocido \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "No se pueden migrar modelos no conectados a este origen de datos: {0}",
"e54f118a75e15e132f16b985274eb46d": "El filtro de consultas {0} no es un {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "la relación {{HasOne}} {0} está vacía",
"e6161ae8459c79d810e2aa9d21282a39": "Debe proporcionar un {{id}} al actualizar atributos.",
"eb56c2b0c30cf006e2df00a549ec9c2c": "La relación \"{0}\" no está definida para el modelo {1}",
"ec42dca074f1818c447f7ad16e2d01af": "El conector asociado no ha proporcionado {0}",
"ecb7aa804bf54c682999d20d6436104c": "La {{transaction}} no está activa: {0}",
"f30809cb932b72a66416a709c8531530": "El conector no admite {{method}} dentro de una transacción",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "no se ha podido crear la lista a partir de la serie JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "La propiedad de {{id}} ({0}) no puede actualizarse de {1} a {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Relación {0}:{{polymorphic}}: {1} requiere el parámetro `model`",
"fca4d12faff1035d9d0438d73432571b": "Entrada duplicada para {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "No se ha podido encontrar la relación {0} para el modelo {1}",
"fec8ebda24db46a9d040bf863765cc44": "El operador {0} tiene cláusulas no válidas {1}: {2}"
}

97
intl/fr/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Relation {{polymorphic}} {0} : {1} n'attend pas le paramètre `polymorphic.as` lors de la définition de `foreignKey`/`discriminator` personnalisé ",
"09483e03b91c8bd58732a74b3ef1ec13": "Date non valide : {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany a reçu une cible qui ne contient pas \"{0}\" (requis)",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "L'ordre {0} n'est pas valide",
"0bd753a8944ad0af85a939bb25273887": "Impossible de faire expirer la clé inconnue {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "Modèle {{Polymorphic}} non trouvé : `{0}` non défini",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "La table '{0}' n'existe pas.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} ne peut pas être mis à jour depuis {0} vers {1} lorsque {{forceId}} n'a pas la valeur true",
"1ae7d3e0be381efb32bfd1ba652f5172": "AVERTISSEMENT : relation {{polymorphic}} {0} : {1} utilise le mot clé `polymorphic.as` qui sera OBSOLETE dans LoopBack.next. Reportez-vous à cette documentation pour découvrir les solutions de remplacement (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "L'imbrication des transactions n'est pas prise en charge ",
"21095484501dbff31af6556fa6039182": "Le paramètre {{offset/skip}} {0} n'est pas valide",
"280f4550f90e133118955ec6f6f72830": "Le type de discriminateur {0} est indiqué mais il n'existe pas de modèle de ce nom",
"28697ec15968a7969211f6d035ba9260": "Relation {{polymorphic}} {0} : {1} n'attend pas le paramètre `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} n'est pas pris en charge",
"2c5c8519721f749aab13c2f04f41d611": "La propriété {0} comporte une clause non valide {1} : 2 valeurs étaient attendues, {2} reçue",
"2f4af31c144bbfab1bbf479866acd820": "\nAVERTISSEMENT : Le connecteur {{LoopBack}} \"{0}\" n'est pas installé, tout comme les modules suivants :\n\n {1}\n\nPour corriger le problème, exécutez :\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Avertissement : le modèle {0}, {{strict mode: `throw`}} a été retiré, utilisez {{`strict: true`}} à la place, ce qui renvoie {{`Validation Error`}} pour les propriétés inconnues,",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} n'est pas défini pour la relation {0} et il n'est pas {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Aucune instance avec l'id {0} trouvée pour {1}",
"416dfbb7b823f51c9f3800be81060b41": "Aucune instance avec {{id}} {0} trouvée pour {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "La méthode BelongsTo \"getAsync()\" est obsolète ; utilisez \"get()\" à la place.",
"4c78325cedbb826db3a05bf5df0e8546": "Vous devez fournir un {{id}} lors du remplacement !",
"4e31b1edd10dadb724d83387de0b5062": "Le paramètre {{limit}} {0} n'est pas valide",
"514985b2327f061ffb1c932f6b909979": "Le modèle {0} n'est pas défini.",
"525c856e65daab43be247e7b5410febd": "Relation {{polymorphic}} {0} : {1} n'attend pas le paramètre `polymorphic.selector` lors de la définition de `foreignKey`/`discriminator` personnalisé ",
"5c18ee111dd87540cdb19a2a93b33be9": "La transaction est annulée car le délai d'attente a été dépassé ",
"5ec7e6664256f7ea78f4f06dafc7d974": "La transaction n'est pas prête ; attendez que la promesse renvoyée soit résolue ",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Aucun nom {{id}} {0}",
"614e3355647e4127c96256102dc63376": "La propriété {0} comporte une clause non valide {1} : chaîne ou RegExp attendu",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} a une direction non valide",
"6502a117987610380b9068ef98b1b0ee": "Aucun enregistrement trouvé dans {0} pour ({1}.{2},{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Le connecteur {0} ne prend pas en charge l'opération {{replaceById}}. IL ne s'agit pas d'un bogue dans LoopBack. Prenez contact avec les auteurs du connecteur, de préférence via les incidents GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} requiert l'argument {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} requiert l'argument {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "La relation {{HasOne}} ne peut pas créer plus d'une instance de {0}",
"728232e473bf80272c042df2b7e002f4": "Relation {{polymorphic}} {0} : {1} requiert le paramètre `polymorphic.discriminator` si le paramètre `polymorphic.foreignKey` est fourni",
"791ab3031a73ede03f7d6299a85e8289": "Expiration du délai de connexion après {0} ms",
"7b277018e43d41bc445731092b91547d": "Non connecté",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} requiert l'argument {{id}}",
"7e9530c0399289be0ee601a604be71ff": "La relation {{BelongsTo}} {0} est vide",
"7faa840eb6ce11250a141deb42a6c489": "Relation inconnue {{scope}} : {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Le nom de propriété ne doit pas être \"{{constructor}}\" dans le modèle : {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Le nom de propriété \"{{constructor}}\" n'est pas autorisé dans les données {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Modèle {{Polymorphic}} introuvable : `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Argument non valide ; doit être une chaîne, un littéral {{regex}} ou un objet {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "L'instance {0} n'est pas valide. Détails : {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Indicateurs {{regex}} non valides : {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Les éléments doivent être un tableau : {0}",
"9e1f143ee02946324d34da92f71bf74e": "Relation {0} : {1} requiert le paramètre 'model'",
"a004f310d315e592843776fab964eaeb": "Les relations {{Polymorphic}} ont besoin d'un modèle exhaustif",
"a0cf0e09c26df14283223e84e6a10f00": "Impossible de mettre à jour les attributs. {{Object}} avec {{id}} {0} n'existe pas !",
"a2487abefef4259c2131d96cdb8543b1": "Echec de la connexion : {0}\nUn nouvel essai sera effectué pour la demande suivante.",
"a25e41a39c60c4702e55d0c3936576a1": "Non-concordance des clés : {0}.{1} : {2}, {3}.{4} : {5}",
"a327355560d495454fba2c1aad6bdf09": "Méthode scope inconnue : {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Exécuter la commande \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "AVERTISSEMENT : la propriété {{id}} ne peut pas être modifiée de {0} en {1} pour le modèle :{2} dans le point d'ancrage d'opération {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "AVERTISSEMENT : la propriété {{id}} ne peut pas être modifiée de {0} en {1} pour le modèle :{2} dans le point d'ancrage d'opération {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "La méthode HasOne \"getAsync()\" est obsolète ; utilisez \"get()\" à la place.",
"b138294f132edfe1eb2a8211150c7238": "`undefined` inattendu dans la requête",
"b15b20280211ad258d92947f05b6e4a5": "Le connecteur n'a pas été initialisé.",
"b278876ec93ef9760f00e83f38ba313d": "La méthode de portée \"getAsync()\" est obsolète ; utilisez \"find()\" à la place.",
"ba0fd8106eb54de4d003a844206431fd": "Le point d'ancrage de modèle \"{0}\" est obsolète ; utilisez à la place les points d'ancrage d'opération. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "La clause where {0} n'est pas un {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Type non défini pour la propriété {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "La valeur est un {{object}} vide",
"bec226891a505828bfc76c5cfd73b336": "Impossible d'obtenir TTL pour la clé inconnue {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Fournisseur de valeur par défaut inconnu {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Les noms de propriété contenant un ou plusieurs points ne sont pas pris en charge. Modèle : {0}, propriété dynamique : {1}",
"d40328eabd8756d795bcdd49d782d4e9": "La source de données ne prend pas en charge les transactions ",
"da02dd6c53d4148320eeb31718a7aebe": "Type non valide pour la propriété {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Les noms de propriété contenant un ou plusieurs points ne sont pas pris en charge. Modèle : {0}, propriété : {1}",
"db03083e9a768388fdbee865249ac67a": "Erreurs de validation ignorées dans {{updateOrCreate()}} :",
"dd63416d9b7d9fa4181e89efd619dfd8": "La valeur n'est pas {{array}} ou {{object}} avec des indices numériques séquentiels",
"ddf0aa14803f1c84f4a97f3803f7471c": "Nom de classe obligatoire",
"e08ab0e1ab55f26c357061447b635905": "Aucune relation trouvée dans {0} pour ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Le connecteur n'est pas défini correctement ; il devrait créer le membre `{{connector}}` de la source de données",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Relation {{polymorphic}} {0} : {1} requiert le paramètre `polymorphic.foreignKey` si le paramètre `polymorphic.discriminator` est fourni",
"e39e0f5d52bfbf511e645d19ecadd2fa": "La propriété {0} comporte une clause non valide {1} : {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "\"{0}\" {{id}} \"{1}\" inconnu.",
"e54d944c2a2c85a23caa86027ae307cf": "Impossible de migrer les modèles non associés à cette source de données : {0}",
"e54f118a75e15e132f16b985274eb46d": "Le filtre de requête {0} n'est pas un {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "La relation {{HasOne}} {0} est vide",
"e6161ae8459c79d810e2aa9d21282a39": "Vous devez fournir un {{id}} lors de la mise à jour des attributs !",
"eb56c2b0c30cf006e2df00a549ec9c2c": "La relation \"{0}\" n'est pas définie pour le modèle {1}",
"ec42dca074f1818c447f7ad16e2d01af": "{0} n'est pas fourni par le connecteur associé",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} n'est pas actif : {0}",
"f30809cb932b72a66416a709c8531530": "Le connecteur ne prend pas en charge {{method}} dans une transaction",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "impossible de créer la liste à partir de la chaîne JSON : {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "La propriété {{id}} ({0}) ne peut pas être mise à jour à partir de {1} vers {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Relation {{polymorphic}} {0} : {1} requiert le paramètre `model`",
"fca4d12faff1035d9d0438d73432571b": "Entrée en double pour {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Relation {0} introuvable pour le modèle {1}",
"fec8ebda24db46a9d040bf863765cc44": "L'opérateur {0} comporte des clauses non valides {1} : {2}"
}

97
intl/it/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} Relazione {0}: {1} non prevedere il parametro `polymorphic.as` durante la definizione di `foreignKey`/`discriminator` personalizzato ",
"09483e03b91c8bd58732a74b3ef1ec13": "Data non valida: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany ha ricevuto una destinazione che non contiene il valore \"{0}\" richiesto",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "L'ordine {0} non è valido",
"0bd753a8944ad0af85a939bb25273887": "Impossibile fare scadere la chiave sconosciuta {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "Modello {{Polymorphic}} non trovato: `{0}` non impostato",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "La tabella '{0}' non esiste.",
"0ff31abb394afb555df162e74ff1a0a0": "Impossibile aggiornare {{id}} da {0} a {1} quando {{forceId}} è impostato su true",
"1ae7d3e0be381efb32bfd1ba652f5172": "AVVERTENZA: {{polymorphic}} La relazione {0}: {1} utilizza la parola chiave `polymorphic.as` che sarà OBSOLETA in LoopBack.next, fare riferimento a questa documentazione per le soluzioni di sostituzione (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "La nidificazione delle transazioni non è supportata",
"21095484501dbff31af6556fa6039182": "Il parametro {{offset/skip}} {0} non è valido",
"280f4550f90e133118955ec6f6f72830": "È stato specificato il tipo di discriminatore {0} ma non esiste alcun modello con tale nome",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} La relazione {0}: {1} non prevede il parametro `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} non supportata",
"2c5c8519721f749aab13c2f04f41d611": "La proprietà {0} ha la clausola non valida {1}: Previsti esattamente 2 valori, ricevuti {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nAVVERTENZA: il connettore {{LoopBack}} \"{0}\" non è installato come nessuno dei seguenti moduli:\n\n {1}\n\nPer correggere, eseguire:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Avvertenza: il modello {0}, {{strict mode: `throw`}} è stato rimosso, utilizzare {{`strict: true`}}, che restituisce {{`Validation Error`}} per le proprietà sconosciute,",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} non è definito per la relazione {0} e non è {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Nessuna istanza con ID {0} trovata per {1}",
"416dfbb7b823f51c9f3800be81060b41": "Nessuna istanza con {{id}} {0} trovata per {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "Il metodo BelongsTo \"getAsync()\" è obsoleto, utilizzare \"get()\".",
"4c78325cedbb826db3a05bf5df0e8546": "È necessario fornire un {{id}} durante la sostituzione.",
"4e31b1edd10dadb724d83387de0b5062": "Il parametro {{limit}} {0} non è valido",
"514985b2327f061ffb1c932f6b909979": "Il modello {0} non è definito.",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} La relazione {0}: {1} non prevede il parametro `polymorphic.selector` durante la definizione di `foreignKey`/`discriminator` personalizzato ",
"5c18ee111dd87540cdb19a2a93b33be9": "Viene effettuato il rollback della transazione a causa del timeout",
"5ec7e6664256f7ea78f4f06dafc7d974": "La transazione non è pronta, attendere la promessa di risolvere restituita",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Nessun nome {{id}} {0}",
"614e3355647e4127c96256102dc63376": "La proprietà {0} ha una clausola non valida {1}: Prevista una stringa o RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} ha una direzione non valida",
"6502a117987610380b9068ef98b1b0ee": "Nessun record trovato in {0} per ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Il connettore {0} non supporta l'operazione {{replaceById}}. Questo non è un bug in LoopBack. Contattare gli autori del connettore, preferibilmente mediante GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} richiede l'argomento {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} richiede l'argomento {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "La relazione {{HasOne}} non può creare più di una istanza di {0}",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} La relazione {0}: {1} richiede il parametro `polymorphic.discriminator` quando viene fornito il parametro `polymorphic.foreignKey`",
"791ab3031a73ede03f7d6299a85e8289": "Timeout nella connessione dopo {0} ms",
"7b277018e43d41bc445731092b91547d": "Non connesso",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} richiede l'argomento {{id}}",
"7e9530c0399289be0ee601a604be71ff": "La relazione {{BelongsTo}} {0} è vuota",
"7faa840eb6ce11250a141deb42a6c489": "Relazione sconosciuta {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Il nome della proprietà non deve essere \"{{constructor}}\" nel modello: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Nome della proprietà \"{{constructor}}\" non consentito nei dati {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Modello {{Polymorphic}} non trovato: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Argomento non valido, deve essere una stringa, un valore letterale {{regex}} o un oggetto {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "L'istanza {0} non è valida. Dettagli: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Indicatori {{regex}} non validi: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Gli elementi devono essere un array: {0}",
"9e1f143ee02946324d34da92f71bf74e": "La relazione {0}: {1} richiede il parametro `model`",
"a004f310d315e592843776fab964eaeb": "Le relazioni {{Polymorphic}} richiedono un modello di passaggio",
"a0cf0e09c26df14283223e84e6a10f00": "Impossibile aggiornare gli attributi. {{Object}} con {{id}} {0} non esiste.",
"a2487abefef4259c2131d96cdb8543b1": "Errore della connessione: {0}\nVerrà eseguito un nuovo tentativo per la richiesta successiva.",
"a25e41a39c60c4702e55d0c3936576a1": "Mancata corrispondenza della chiave: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Metodo dell'ambito sconosciuto: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Eseguire il comando \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "AVVERTENZA: impossibile modificare la proprietà {{id}} da {0} a {1} per il modello:{2} nell'hook operazione {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "AVVERTENZA: impossibile modificare la proprietà {{id}} da {0} a {1} per il modello:{2} nell'hook operazione {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "Il metodo HasOne \"getAsync()\" è obsoleto, utilizzare \"get()\".",
"b138294f132edfe1eb2a8211150c7238": "Elemento `undefined` non previsto nella query",
"b15b20280211ad258d92947f05b6e4a5": "Il connettore non è stato inizializzato.",
"b278876ec93ef9760f00e83f38ba313d": "Il metodo dell'ambito \"getAsync()\" è obsoleto, utilizzare \"find()\" invece.",
"ba0fd8106eb54de4d003a844206431fd": "L'hook del modello \"{0}\" è obsoleto, utilizzare gli hook dell'operazione. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "La clausola where {0} non è un {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Tipo non definito per la proprietà {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Il valore è un {{object}} vuoto",
"bec226891a505828bfc76c5cfd73b336": "Impossibile acquisire TTL per la chiave sconosciuta {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Provider del valore predefinito sconosciuto {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "I nomi delle proprietà che contengono punti non sono supportati. Modello: {0}, proprietà dinamica: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource non supporta le transazioni",
"da02dd6c53d4148320eeb31718a7aebe": "Tipo non valido per la proprietà {0}",
"da751a8a748adbde5b55fa83b707b4e2": "I nomi delle proprietà che contengono punti non sono supportati. Modello: {0}, proprietà: {1}",
"db03083e9a768388fdbee865249ac67a": "Errore di convalida in {{updateOrCreate()}} ignorati:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Il valore non è un {{array}} o {{object}} con indici numerici sequenziali",
"ddf0aa14803f1c84f4a97f3803f7471c": "Nome della classe obbligatorio",
"e08ab0e1ab55f26c357061447b635905": "Nessuna relazione trovata in {0} per ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Il connettore non è definito correttamente: deve creare il membro `{{connector}}` di dataSource",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} La relazione {0}: {1} richiede il parametro `polymorphic.foreignKey` quando viene fornito il parametro `polymorphic.discriminator`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "La proprietà {0} ha una clausola non valida {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "{{id}} \"{0}\" sconosciuto \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Impossibile migrare i modelli non allegati a questa origine dati: {0}",
"e54f118a75e15e132f16b985274eb46d": "Il filtro della query {0} non è un {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "La relazione {{HasOne}} {0} è vuota",
"e6161ae8459c79d810e2aa9d21282a39": "È necessario fornire un {{id}} durante l'aggiornamento degli attributi.",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Relazione \"{0}\" non definita per il modello {1}",
"ec42dca074f1818c447f7ad16e2d01af": "{0} non fornito dal connettore collegato",
"ecb7aa804bf54c682999d20d6436104c": "La {{transaction}} non è attiva: {0}",
"f30809cb932b72a66416a709c8531530": "Il connettore non supporta {{method}} all'interno di una transazione",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "impossibile creare un elenco dalla stringa JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "Impossibile aggiornare la proprietà {{id}} ({0}) da {1} a {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} La relazione {0}: {1} richiede il parametro `model`",
"fca4d12faff1035d9d0438d73432571b": "Voce duplicata per {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Impossibile trovare la relazione {0} per il modello {1}",
"fec8ebda24db46a9d040bf863765cc44": "L'operatore {0} ha delle clausole non valide {1}: {2}"
}

97
intl/ja/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} 関係: {1} は、カスタムの foreignKey/discriminator`を定義する際は、パラメーター polymorphic.as`を予期していません ",
"09483e03b91c8bd58732a74b3ef1ec13": "無効な日付: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany は、必須の \"{0}\" が含まれていないターゲットを受信しました",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "順序 {0} が無効です",
"0bd753a8944ad0af85a939bb25273887": "不明のキー {0} を期限切れにすることができません",
"0c0b867aca0973ba26e887d3337cc4ec": "{{Polymorphic}} モデルが見つかりません: `{0}` が設定されていません",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "テーブル '{0}' が存在しません。",
"0ff31abb394afb555df162e74ff1a0a0": "{{forceId}} が true に設定されている場合、{{id}} を {0} から {1} に更新することはできません",
"1ae7d3e0be381efb32bfd1ba652f5172": "警告: {{polymorphic}} {0} 関係: {1} でキーワード`polymorphic.as`が使用されていますが、これは LoopBack.next で非推奨になる予定です。代替解決策について次の文書を参照してください (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "トランザクションのネストはサポートされていません",
"21095484501dbff31af6556fa6039182": "{{offset/skip}} パラメーター {0} は無効です",
"280f4550f90e133118955ec6f6f72830": "判別プログラム・タイプ {0} が指定されていますが、このような名前のモデルは存在しません",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} 関係: {1} はパラメーター`model を予期していません`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} はサポートされていません",
"2c5c8519721f749aab13c2f04f41d611": "{0} プロパティーには無効な節 {1} があります。正確に 2 つの値が必要ですが、{2} を受け取りました",
"2f4af31c144bbfab1bbf479866acd820": "\n警告: {{LoopBack}} コネクター \"{0}\" は次のいずれのモジュールとしてもインストールされていません:\n\n {1}\n\n修正するには、以下を実行します。\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "警告: モデル {0}、{{strict mode: `throw`}} は削除されました。代わりに {{`strict: true`}} を使用してください。これにより、不明なプロパティーの {{`Validation Error`}} が返されます",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} は関係 {0} に定義されておらず、{{polymorphic}} ではありません",
"3cde8cc9bca22c67278b202ab0720106": "{1} に関する ID {0} のインスタンスが見つかりません",
"416dfbb7b823f51c9f3800be81060b41": "{1} に関する {{id}} {0} のインスタンスが見つかりません",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo のメソッド \"getAsync()\" は非推奨です。代わりに \"get()\" を使用してください。",
"4c78325cedbb826db3a05bf5df0e8546": "置換するときは {{id}} を指定する必要があります。",
"4e31b1edd10dadb724d83387de0b5062": "{{limit}} パラメーター {0} は無効です",
"514985b2327f061ffb1c932f6b909979": "モデル {0} が定義されていません。",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} 関係: {1} は、カスタムの foreignKey/discriminator`を定義する際は、パラメーター polymorphic.selector`を予期していません ",
"5c18ee111dd87540cdb19a2a93b33be9": "タイムアウトのため、トランザクションがロールバックされます",
"5ec7e6664256f7ea78f4f06dafc7d974": "トランザクションの準備ができていません。返された Promise の解決をお待ちください",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "{{id}} 名 {0} がありません",
"614e3355647e4127c96256102dc63376": "{0} プロパティーには無効な節 {1} があります。ストリングまたは正規表現を指定する必要があります",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} の方向が無効です",
"6502a117987610380b9068ef98b1b0ee": "({1}.{2}、{3}.{4}) に関して {0} でレコードが見つかりません",
"67c2bf43b5281ab929617423ea8a6f3e": "コネクター {0} では {{replaceById}} 操作はサポートされません。 これは LoopBack のバグではありません。 コネクターの作成者に (なるべく GitHub Issue を通して) 問い合わせてください。",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} には {{id}} 引数が必要です",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} には {{id}} 引数が必要です",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} 関係では {0} のインスタンスを複数作成することはできません",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} 関係: {1} では、パラメーター polymorphic.foreignKey`を指定したときは、パラメーター polymorphic.discriminator`は必須です",
"791ab3031a73ede03f7d6299a85e8289": "接続は {0} ミリ秒後にタイムアウトになります",
"7b277018e43d41bc445731092b91547d": "未接続",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} には {{id}} 引数が必要です",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} 関係 {0} が空です",
"7faa840eb6ce11250a141deb42a6c489": "不明な関係 {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "モデル {0} のプロパティー名を \"{{constructor}}\" にすることはできません",
"881e4b0cb86ed59549248ee540a9fd10": "{0} データではプロパティー名 \"{{constructor}}\" は許可されません",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}} モデルが見つかりません: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "引数が無効です。ストリング、{{regex}} リテラル、または {{RegExp}} オブジェクトでなければなりません",
"8a39126103a157f501affa070367a1b0": "{0} インスタンスは無効です。 詳細: {1}。",
"8c5ab01638c1ac1d58168c6346a8481a": "無効な {{regex}} フラグ: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "項目は配列でなければなりません: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} 関係: {1} ではパラメーター`model は必須です`",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} 関係にはスルー・モデルが必要です",
"a0cf0e09c26df14283223e84e6a10f00": "属性を更新できませんでした。 {{id}} {0} の {{Object}} は存在しません。",
"a2487abefef4259c2131d96cdb8543b1": "接続失敗: {0}\n次の要求で再試行されます。",
"a25e41a39c60c4702e55d0c3936576a1": "キーの不一致: {0}.{1}: {2}、{3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "不明なスコープ・メソッド: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "\"{{npm install loopback-datasource-juggler}} {0}\" コマンドを実行します ",
"a829dee089c912e68c18920ba015400c": "警告: {{'loaded'}} 操作フックでモデル {2} の {{id}} プロパティーを {0} から {1} に変更することはできません",
"a984a076c59e451948b2bcf7a393d860": "警告: {{'before save'}} 操作フックでモデル {2} の {{id}} プロパティーを {0} から {1} に変更することはできません",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne のメソッド \"getAsync()\" は非推奨です。代わりに \"get()\" を使用してください。",
"b138294f132edfe1eb2a8211150c7238": "照会内に予期しない `undefined` があります",
"b15b20280211ad258d92947f05b6e4a5": "コネクターが初期化されていません。",
"b278876ec93ef9760f00e83f38ba313d": "Scope のメソッド \"getAsync()\" は非推奨です。代わりに \"find()\" を使用してください。",
"ba0fd8106eb54de4d003a844206431fd": "モデル・フック \"{0}\" は非推奨です。代わりに操作フックを使用してください。 {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "where 節 {0} が {{object}} ではありません",
"bdb11cc1c780c9ccac33c316cfdc9d82": "プロパティー {0}.{1} にタイプが定義されていません",
"bdfb951c8ff7ce0cbc08c06f548fd927": "値は空の {{object}} です",
"bec226891a505828bfc76c5cfd73b336": "不明のキー {0} の TTL を取得できません",
"cd930369e86cdd222f7bd117c6f9fa94": "不明なデフォルト値プロバイダー {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "ドットが含まれたプロパティー名はサポートされていません。 モデル: {0}、動的プロパティー: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "データ・ソースがトランザクションをサポートしていません",
"da02dd6c53d4148320eeb31718a7aebe": "プロパティー {0} のタイプが無効です",
"da751a8a748adbde5b55fa83b707b4e2": "ドットが含まれたプロパティー名はサポートされていません。 モデル: {0}、プロパティー: {1}",
"db03083e9a768388fdbee865249ac67a": "{{updateOrCreate()}} での妥当性検査エラーを無視します:",
"dd63416d9b7d9fa4181e89efd619dfd8": "値は、連続した数字の索引が含まれた {{array}} または {{object}} ではありません",
"ddf0aa14803f1c84f4a97f3803f7471c": "クラス名は必須です",
"e08ab0e1ab55f26c357061447b635905": "({1}.{2}、{3}.{4}) に関して {0} で関係が見つかりません",
"e0e9504e137a3c3339144b51ed76fef2": "コネクターが正しく定義されていません: dataSource の `{{connector}}` メンバーを作成する必要があります",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} 関係: {1} では、パラメーター polymorphic.discriminator`を指定したときは、パラメーター polymorphic.foreignKey`は必須です",
"e39e0f5d52bfbf511e645d19ecadd2fa": "{0} プロパティーには無効な節 {1} があります: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "\"{0}\" {{id}} \"{1}\" が不明です。",
"e54d944c2a2c85a23caa86027ae307cf": "このデータ・ソースに付加されていないモデルはマイグレーションできません: {0}",
"e54f118a75e15e132f16b985274eb46d": "照会フィルター {0} が {{object}} ではありません",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} 関係 {0} が空です",
"e6161ae8459c79d810e2aa9d21282a39": "属性を更新するときは {{id}} を指定する必要があります。",
"eb56c2b0c30cf006e2df00a549ec9c2c": "関係 \"{0}\" は {1} モデルに定義されていません",
"ec42dca074f1818c447f7ad16e2d01af": "{0} は付加されたコネクターによって提供されません",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} がアクティブではありません: {0}",
"f30809cb932b72a66416a709c8531530": "コネクターがトランザクション内の {{method}} をサポートしていません",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "JSON ストリングからリストを作成できませんでした: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}} プロパティー ({0}) を {1} から {2} に更新できません",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} 関係: {1} ではパラメーター`model は必須です`",
"fca4d12faff1035d9d0438d73432571b": "{0}.{1} のエントリーが重複しています",
"fd3cc89dc67e2d604eaae21bdf41d403": "モデル {1} の関係 {0} が見つかりませんでした",
"fec8ebda24db46a9d040bf863765cc44": "{0} 演算子には無効な節 {1} があります: {2}"
}

97
intl/ko/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} 관계: 사용자 정의 `foreignKey`/`discriminator` 정의 중에는 {1}에 `polymorphic.as` 매개변수가 필요하지 않음 ",
"09483e03b91c8bd58732a74b3ef1ec13": "올바르지 않은 날짜: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany에 필수 \"{0}\"이(가) 포함되지 않은 대상이 수신됨",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "{0} 순서가 올바르지 않음",
"0bd753a8944ad0af85a939bb25273887": "알 수 없는 키 {0}을(를) 만료할 수 없음",
"0c0b867aca0973ba26e887d3337cc4ec": "{{Polymorphic}} 모델을 찾을 수 없음: `{0}`이(가) 설정되지 않음",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "'{0}' 테이블이 없습니다.",
"0ff31abb394afb555df162e74ff1a0a0": "{{forceId}}이(가) true로 설정된 경우 {{id}}을(를) {0}에서 {1}(으)로 업데이트할 수 없음",
"1ae7d3e0be381efb32bfd1ba652f5172": "경고: {{polymorphic}} {0} 관계: {1}이(가) LoopBack에서 더 이상 사용되지 않을 `polymorphic.as` 키워드를 사용합니다. 대체 솔루션에 대해서는 다음 문서를 참조하십시오(https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as).",
"1daef4e937fe52136597ba8fd2060f55": "중첩 트랜잭션은 지원되지 않음",
"21095484501dbff31af6556fa6039182": "{{offset/skip}} 매개변수 {0}이(가) 올바르지 않음",
"280f4550f90e133118955ec6f6f72830": "식별자 유형 {0}이(가) 지정되었지만 해당 이름의 모델이 없습니다.",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} 관계: {1}에는 `model` 매개변수가 필요하지 않음",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}}이(가) 지원되지 않음",
"2c5c8519721f749aab13c2f04f41d611": "{0} 특성에 올바르지 않은 절 {1}이(가) 있음: 정확하게 2개의 값을 예상했지만 {2}개를 수신함",
"2f4af31c144bbfab1bbf479866acd820": "\n경고: {{LoopBack}} 커넥터 \"{0}\"이(가) 다음 모듈로 설치되어 있지 않음:\n\n {1}\n\n이를 수정하려면 다음을 실행하십시오. \n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "경고: 모델 {0}, {{strict mode: `throw`}}이(가) 제거되었습니다. 알 수 없는 특성에 대해 {{`Validation Error`}}을(를) 리턴하는 {{`strict: true`}}을(를) 대신 사용하십시오.",
"38dbf42c29a4645238cc3d632e88ebc9": "관계 {0}에 대해 {{Relation.modelTo}}이(가) 정의되지 않았으며 {{polymorphic}}이(가) 아닙니다.",
"3cde8cc9bca22c67278b202ab0720106": "{1}에 대해 ID {0}의 인스턴스를 찾을 수 없음",
"416dfbb7b823f51c9f3800be81060b41": "{1}에 대해 {{id}} {0}의 인스턴스를 찾을 수 없음",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo 메소드 \"getAsync()\"는 더 이상 사용되지 않습니다. 대신 \"get()\"을 사용하십시오.",
"4c78325cedbb826db3a05bf5df0e8546": "바꾸는 경우 {{id}}을(를) 제공해야 합니다!",
"4e31b1edd10dadb724d83387de0b5062": "{{limit}} 매개변수 {0}이(가) 올바르지 않음",
"514985b2327f061ffb1c932f6b909979": "{0} 모델이 정의되지 않았습니다.",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} 관계: 사용자 정의 `foreignKey`/`discriminator` 정의 중에는 {1}에 `polymorphic.selector` 매개변수가 필요하지 않음 ",
"5c18ee111dd87540cdb19a2a93b33be9": "제한시간 초과로 인해 트랜잭션이 롤백됨",
"5ec7e6664256f7ea78f4f06dafc7d974": "트랜잭션이 준비되지 않았으니 리턴된 일정이 해결될 때까지 기다려 주십시오.",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "{{id}} 이름 {0}이(가) 아님",
"614e3355647e4127c96256102dc63376": "{0} 특성에 올바르지 않은 절 {1}이(가) 있음: 문자열 또는 RegExp를 예상함",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0}에 올바르지 않은 방향이 있음",
"6502a117987610380b9068ef98b1b0ee": "{0}에서 ({1}.{2} ,{3}.{4})에 대한 레코드를 찾을 수 없음",
"67c2bf43b5281ab929617423ea8a6f3e": "커넥터 {0}에서 {{replaceById}} 오퍼레이션을 지원하지 않습니다. 이는 LoopBack의 버그가 아닙니다. 커넥터 작성자에게 문의하십시오. GitHub 발행을 사용하는 것이 좋습니다.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}}에 {{id}} 인수가 필요함",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}}에 {{id}} 인수가 필요함",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} 관계에서 둘 이상의 {0} 인스턴스를 작성할 수 없음",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} 관계: `polymorphic.foreignKey` 매개변수가 제공된 경우 {1}에는 `polymorphic.discriminator` 매개변수가 필요함",
"791ab3031a73ede03f7d6299a85e8289": "{0}밀리초 후 연결 제한시간 초과",
"7b277018e43d41bc445731092b91547d": "연결되지 않음",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}}에 {{id}} 인수가 필요함",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} 관계 {0}이(가) 비어 있음",
"7faa840eb6ce11250a141deb42a6c489": "알 수 없는 관계 {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "모델에서 특성 이름이 \"{{constructor}}\"이어서는 안됨: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "{0} 데이터에서는 특성 이름 \"{{constructor}}\"이(가) 허용되지 않음",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}} 모델을 찾을 수 없음: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "올바르지 않은 인수가 문자열, {{regex}} 리터럴 또는 {{RegExp}} 오브젝트여야 합니다.",
"8a39126103a157f501affa070367a1b0": "{0} 인스턴스가 올바르지 않습니다. 세부사항: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "올바르지 않은 {{regex}} 플래그: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "항목이 배열이어야 함: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} 관계: {1}에 `model` 매개변수가 필요함",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} 관계에는 through 모델이 필요함",
"a0cf0e09c26df14283223e84e6a10f00": "속성을 업데이트할 수 없습니다. {{id}} {0}의 {{Object}}이(가) 없습니다!",
"a2487abefef4259c2131d96cdb8543b1": "연결 실패: {0}\n다음 요청에서 재시도됩니다.",
"a25e41a39c60c4702e55d0c3936576a1": "키 불일치: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "알 수 없는 범위 메소드: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "\"{{npm install loopback-datasource-juggler}} {0}\" 명령 실행 ",
"a829dee089c912e68c18920ba015400c": "경고: {{'loaded'}} 오퍼레이션 후크에서 모델:{2}에 대해 {{id}} 특성을 {0}에서 {1}(으)로 변경할 수 없습니다.",
"a984a076c59e451948b2bcf7a393d860": "경고: {{'before save'}} 오퍼레이션 후크에서 모델:{2}에 대해 {{id}} 특성을 {0}에서 {1}(으)로 변경할 수 없습니다.",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne 메소드 \"getAsync()\"는 더 이상 사용되지 않습니다. 대신 \"get()\"을 사용하십시오.",
"b138294f132edfe1eb2a8211150c7238": "조회에서 예상치 못한 `undefined` 항목",
"b15b20280211ad258d92947f05b6e4a5": "커넥터가 초기화되지 않았습니다.",
"b278876ec93ef9760f00e83f38ba313d": "Scope 메소드 \"getAsync()\"는 더 이상 사용되지 않습니다. 대신 \"find()\"를 사용하십시오.",
"ba0fd8106eb54de4d003a844206431fd": "모델 후크 \"{0}\"이(가) 더 이상 사용되지 않습니다. 오퍼레이션 후크가 대신 사용됩니다. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "where 절 {0}이(가) {{object}}이(가) 아님",
"bdb11cc1c780c9ccac33c316cfdc9d82": "특성 {0}.{1}에 유형이 정의되지 않음",
"bdfb951c8ff7ce0cbc08c06f548fd927": "값이 빈 {{object}}임",
"bec226891a505828bfc76c5cfd73b336": "알 수 없는 키 {0}에 대한 TTL을 가져올 수 없음",
"cd930369e86cdd222f7bd117c6f9fa94": "알 수 없는 기본값 제공자 {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "점이 포함된 특성 이름은 지원되지 않습니다. 모델: {0}, 동적 특성: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "데이터 소스에서 트랜잭션을 지원하지 않음",
"da02dd6c53d4148320eeb31718a7aebe": "특성 {0}에 대한 올바르지 않은 유형",
"da751a8a748adbde5b55fa83b707b4e2": "점이 포함된 특성 이름은 지원되지 않습니다. 모델: {0}, 특성: {1}",
"db03083e9a768388fdbee865249ac67a": "{{updateOrCreate()}}에서 유효성 검증 오류 무시:",
"dd63416d9b7d9fa4181e89efd619dfd8": "값이 순차 숫자 색인을 가진 {{array}} 또는 {{object}}이(가) 아님",
"ddf0aa14803f1c84f4a97f3803f7471c": "클래스 이름 필수",
"e08ab0e1ab55f26c357061447b635905": "{0}에서 ({1}.{2} ,{3}.{4})에 대한 관계를 찾을 수 없음",
"e0e9504e137a3c3339144b51ed76fef2": "커넥터가 제대로 정의되지 않음: 데이터 소스의 `{{connector}}` 멤버를 작성해야 합니다.",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} 관계: `polymorphic.discriminator` 매개변수가 제공된 경우 {1}에는 `polymorphic.foreignKey` 매개변수가 필요함",
"e39e0f5d52bfbf511e645d19ecadd2fa": "{0} 특성에 올바르지 않은 절 {1}이(가) 있음: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "알 수 없는 \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "이 데이터 소스에 첨부되지 않은 모델은 마이그레이션할 수 없음: {0}",
"e54f118a75e15e132f16b985274eb46d": "조회 필터 {0}이(가) {{object}}가 아님",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} 관계 {0}이(가) 비어 있음",
"e6161ae8459c79d810e2aa9d21282a39": "속성을 업데이트하는 경우 {{id}}을(를) 제공해야 합니다!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "{1} 모델에 대해 관계 \"{0}\"이(가) 정의되지 않음",
"ec42dca074f1818c447f7ad16e2d01af": "첨부된 커넥터에서 {0}을(를) 제공하지 않음",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}}이(가) 활성 상태가 아님: {0}",
"f30809cb932b72a66416a709c8531530": "커넥터가 트랜잭션 내에서 {{method}}을(를) 지원하지 않음",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "JSON 문자열에서 목록을 작성할 수 없음: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}} 특성({0})을 {1}에서 {2}(으)로 업데이트할 수 없음",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} 관계: {1}에 `model` 매개변수가 필요함",
"fca4d12faff1035d9d0438d73432571b": "{0}.{1}의 중복 항목",
"fd3cc89dc67e2d604eaae21bdf41d403": "{1} 모델에 대해 {0} 관계를 찾을 수 없음",
"fec8ebda24db46a9d040bf863765cc44": "{0} 연산자에 올바르지 않은 절 {1}이(가) 있음: {2}"
}

97
intl/nl/messages.json Executable file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} relatie: {1} verwacht niet dat de parameter `polymorphic.as` wordt gebruikt bij het definiëren van een aangepaste `foreignKey`/`discriminator` ",
"09483e03b91c8bd58732a74b3ef1ec13": "Ongeldige datum: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany heeft een doel ontvangen dat niet de vereiste \"{0}\" bevat",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "De volgorde {0} is niet geldig",
"0bd753a8944ad0af85a939bb25273887": "Onbekende sleutel {0} kan niet vervallen",
"0c0b867aca0973ba26e887d3337cc4ec": "Model {{Polymorphic}} is niet gevonden: '{0}' niet ingesteld",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Tabel '{0}' bestaat niet.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} kan niet worden bijgewerkt van {0} naar {1} zolang {{forceId}} is ingesteld op true",
"1ae7d3e0be381efb32bfd1ba652f5172": "WAARSCHUWING: {{polymorphic}} {0} relatie: {1} gebruikt trefwoord `polymorphic.as`. Dit wordt in LoopBack.next gedeprecieerd. Raadpleeg dit document voor vervangende oplossingen: (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Het nesten van transacties wordt niet ondersteund",
"21095484501dbff31af6556fa6039182": "De {{offset/skip}}-parameter {0} is niet geldig",
"280f4550f90e133118955ec6f6f72830": "Discriminatortype {0} opgegeven, maar er bestaat geen model met deze naam",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} relatie: {1} verwacht niet dat de parameter `model` wordt gebruikt",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} wordt niet ondersteund",
"2c5c8519721f749aab13c2f04f41d611": "De eigenschap {0} heeft een ongeldige clausule {1}: Er werden precies twee waarden verwacht. Ontvangen: {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nWaarschuwing: {{LoopBack}}-connector \"{0}\" is niet geïnstalleerd als een van de volgende modules:\n\n {1}\n\nU lost dit op door het uitvoeren van:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Waarschuwing: Model {0}, {{strict mode: `throw`}} is verwijderd. Gebruik in plaats hiervan {{`strict: true`}}; hiermee wordt {{`Validation Error`}} gemeld voor onbekende eigenschappen.",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} is niet gedefinieerd voor relatie {0} en is geen {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Geen instance met ID {0} gevonden voor {1}",
"416dfbb7b823f51c9f3800be81060b41": "Geen instance met {{id}} {0} gevonden voor {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo-methode \"getAsync()\" is gedeprecieerd. In plaats daarvan moet u \"get()\" gebruiken.",
"4c78325cedbb826db3a05bf5df0e8546": "U moet een {{id}} opgeven bij een vervanging.",
"4e31b1edd10dadb724d83387de0b5062": "De {{limit}}-parameter {0} is niet geldig",
"514985b2327f061ffb1c932f6b909979": "Model {0} is niet gedefinieerd.",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} relatie: {1} verwacht niet dat de parameter `polymorphic.selector` wordt gebruikt bij het definiëren van een aangepaste `foreignKey`/`discriminator` ",
"5c18ee111dd87540cdb19a2a93b33be9": "De transactie is teruggedraaid vanwege een timeout",
"5ec7e6664256f7ea78f4f06dafc7d974": "De transactie is niet gereed, wacht tot de geretourneerde promise omgezet is",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Geen {{id}}-naam {0}",
"614e3355647e4127c96256102dc63376": "De eigenschap {0} heeft een ongeldige clausule {1}: Er werd een tekenreeks of expressie verwacht",
"62a2d80c405b7fec5f547c448ab1b6ff": "De {{order}} {0} heeft een ongeldige richting",
"6502a117987610380b9068ef98b1b0ee": "Geen record gevonden in {0} voor ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "De connector {0} biedt geen ondersteuning voor de bewerking {{replaceById}}. Dit is geen programmafout in LoopBack. Neem contact op met de auteurs van de connector, bij voorkeur via GitHub-problemen.",
"6c3234937d69763fc7f6bcafccc59bbc": "Voor {{Model::deleteById}} is het argument {{id}} vereist",
"6eb6fd4fbd73394000bc25f5776fd20c": "Voor {{Model::exists}} is het argument {{id}} vereist",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}}-relatie kan niet resulteren in meer dan één instance van {0}",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} relatie: als de parameter `polymorphic.foreignKey` wordt opgegeven, vereist {1} de parameter `polymorphic.discriminator`",
"791ab3031a73ede03f7d6299a85e8289": "Timeout voor het maken van verbinding na {0} ms",
"7b277018e43d41bc445731092b91547d": "Geen verbinding",
"7bbbdece4eea90e42aa5c0bce295e503": "Voor {{Model::findById}} is het argument {{id}} vereist",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}}-relatie {0} is leeg",
"7faa840eb6ce11250a141deb42a6c489": "Onbekende relatie {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Eigenschapnaam mag niet \"{{constructor}}\" zijn in model: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Eigenschapnaam \"{{constructor}}\" is niet toegestaan in {0}-gegevens",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}}-model is niet gevonden: '{0}'",
"89bf6d92731fe7bd2146ce8d0bec205c": "Ongeldig argument, moet een tekenreeks, {{regex}}-literaal of {{RegExp}}-object zijn",
"8a39126103a157f501affa070367a1b0": "De instance {0} is niet geldig. Details: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Ongeldige {{regex}}-vlaggen: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Items moeten een array zijn: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} relatie: {1} vereist de parameter `model`",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}}-relaties hebben een doorvoermodel nodig",
"a0cf0e09c26df14283223e84e6a10f00": "De kenmerken kunnen niet worden bijgewerkt. {{Object}} met {{id}} {0} bestaat niet!",
"a2487abefef4259c2131d96cdb8543b1": "Verbinding mislukt: {0}\nVerbindingspoging wordt herhaald bij volgende opdracht.",
"a25e41a39c60c4702e55d0c3936576a1": "Niet-overeenkomende sleutels: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Onbekende methode voor bereik: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Voer de opdracht \"{{npm install loopback-datasource-juggler}} {0}\" uit",
"a829dee089c912e68c18920ba015400c": "Waarschuwing: Eigenschap {{id}} kan niet worden gewijzigd van {0} in {1} voor model:{2} in operation hook {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "Waarschuwing: Eigenschap {{id}} kan niet worden gewijzigd van {0} in {1} voor model:{2} in operation hook {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne-methode \"getAsync()\" is gedeprecieerd. In plaats daarvan moet u \"get()\" gebruiken.",
"b138294f132edfe1eb2a8211150c7238": "Onverwacht item 'undefined' in query",
"b15b20280211ad258d92947f05b6e4a5": "De connector is niet geïnitialiseerd.",
"b278876ec93ef9760f00e83f38ba313d": "Scope-methode \"getAsync()\" is gedeprecieerd. In plaats daarvan moet u \"find()\" gebruiken.",
"ba0fd8106eb54de4d003a844206431fd": "Model hook \"{0}\" is gedeprecieerd; gebruik in plaats daarvan operation hooks. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "De WHERE-clausule {0} is geen {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Type niet gedefinieerd voor eigenschap {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Waarde is een leeg {{object}}",
"bec226891a505828bfc76c5cfd73b336": "TTL voor onbekende sleutel {0} kan niet worden opgehaald",
"cd930369e86cdd222f7bd117c6f9fa94": "Onbekende standaardwaarde voor provider {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Eigenschapnamen met punt(en) worden niet ondersteund. Model: {0}, dynamische eigenschap: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource ondersteunt geen transacties",
"da02dd6c53d4148320eeb31718a7aebe": "Ongeldig type voor eigenschap {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Eigenschapnamen met punt(en) worden niet ondersteund. Model: {0}, eigenschap: {1}",
"db03083e9a768388fdbee865249ac67a": "Validatiefouten in {{updateOrCreate()}} worden genegeerd:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Waarde is geen {{array}} of {{object}} met sequentiële numerieke indices",
"ddf0aa14803f1c84f4a97f3803f7471c": "Klassennaam vereist",
"e08ab0e1ab55f26c357061447b635905": "Geen relatie gevonden in in {0} voor ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Connector is niet juist gedefinieerd: moet '{{connector}}'-lid van gegevensbron maken",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} relatie: als de parameter `polymorphic.discriminator` wordt opgegeven, vereist {1} de parameter `polymorphic.foreignKey`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "De eigenschap {0} heeft een ongeldige clausule {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Onbekend \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Kan geen modellen migreren die niet zijn gekoppeld aan deze gegevensbron: {0}",
"e54f118a75e15e132f16b985274eb46d": "Het queryfilter {0} is geen {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}}-relatie {0} is leeg",
"e6161ae8459c79d810e2aa9d21282a39": "U moet een {{id}} opgeven bij het bijwerken van kenmerken.",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Relatie \"{0}\" is niet gedefinieerd voor model {1}",
"ec42dca074f1818c447f7ad16e2d01af": "{0} is niet opgegeven door gekoppelde connector",
"ecb7aa804bf54c682999d20d6436104c": "De {{transaction}} is niet actief: {0}",
"f30809cb932b72a66416a709c8531530": "De connector ondersteunt {{method}} niet binnen een transactie",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "kan geen lijst maken op basis van JSON-reeks: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}}-eigenschap ({0}) kan niet worden bijgewerkt van {1} in {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} relatie: {1} vereist de parameter `model`",
"fca4d12faff1035d9d0438d73432571b": "Dubbel item voor {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Relatie {0} voor model {1} is niet gevonden",
"fec8ebda24db46a9d040bf863765cc44": "De operator {0} heeft ongeldige clausules {1}: {2}"
}

97
intl/pl/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Relacja {{polymorphic}} {0}: {1} nie oczekuje parametru `polymorphic.as` podczas definiowania niestandardowego obiektu `foreignKey`/`discriminator` ",
"09483e03b91c8bd58732a74b3ef1ec13": "Niepoprawna data: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "Funkcja LinkManyToMany otrzymała element docelowy, który nie zawiera wymaganej wartości \"{0}\"",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "Kolejność {0} jest niepoprawna",
"0bd753a8944ad0af85a939bb25273887": "Nie można unieważnić nieznanego klucza {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "Model {{Polymorphic}} nie został znaleziony: nie ustawiono właściwości `{0}`",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Tabela '{0}' nie istnieje.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} nie może być zaktualizowany z {0} na {1}, gdy właściwość {{forceId}} ma wartość true",
"1ae7d3e0be381efb32bfd1ba652f5172": "OSTRZEŻENIE: Relacja {{polymorphic}} {0}: {1} używa słowa kluczowego `polymorphic.as`, które będzie NIEAKTUALNE w aplikacji LoopBack.next; aby uzyskać informacje o rozwiązaniach zastępczych, zapoznaj się z tym dokumentem (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Zagnieżdżanie transakcji nie jest obsługiwane",
"21095484501dbff31af6556fa6039182": "Parametr {{offset/skip}} {0} jest niepoprawny",
"280f4550f90e133118955ec6f6f72830": "Określono typ wyróżnika {0}, ale nie istnieje model o takiej nazwie",
"28697ec15968a7969211f6d035ba9260": "Relacja {{polymorphic}} {0}: {1} nie oczekuje parametru `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} nie jest obsługiwana",
"2c5c8519721f749aab13c2f04f41d611": "Właściwość {0} ma niepoprawną klauzulę {1}: oczekiwano dokładnie 2 wartości, otrzymano {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nOSTRZEŻENIE: Konektor {{LoopBack}} \"{0}\" nie jest zainstalowany jako żaden z następujących modułów:\n\n {1}\n\nAby to naprawić, uruchom komendę:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Ostrzeżenie: model {0}, {{strict mode: `throw`}}, został usunięty, zamiast niego użyj modelu {{`strict: true`}}, który zwraca {{`Validation Error`}} dla nieznanych właściwości,",
"38dbf42c29a4645238cc3d632e88ebc9": "Model {{Relation.modelTo}} nie został zdefiniowany dla relacji {0} i nie jest {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Nie znaleziono instancji o identyfikatorze {0} dla {1}",
"416dfbb7b823f51c9f3800be81060b41": "Nie znaleziono instancji o identyfikatorze {{id}} {0} dla {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "Metoda BelongsTo \"getAsync()\" jest nieaktualna, zamiast niej użyj metody \"get()\".",
"4c78325cedbb826db3a05bf5df0e8546": "Podczas zastępowania należy podać {{id}}!",
"4e31b1edd10dadb724d83387de0b5062": "Parametr {{limit}} {0} jest niepoprawny",
"514985b2327f061ffb1c932f6b909979": "Model {0} nie jest zdefiniowany.",
"525c856e65daab43be247e7b5410febd": "Relacja {{polymorphic}} {0}: {1} nie oczekuje parametru `polymorphic.selector` podczas definiowania niestandardowego obiektu `foreignKey`/`discriminator` ",
"5c18ee111dd87540cdb19a2a93b33be9": "Transakcja została wycofana z powodu przekroczenia limitu czasu",
"5ec7e6664256f7ea78f4f06dafc7d974": "Transakcja nie jest gotowa, poczekaj na rozstrzygnięcie zwróconej obietnicy",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Brak nazwy {{id}} {0}",
"614e3355647e4127c96256102dc63376": "Właściwość {0} ma niepoprawną klauzulę {1}: oczekiwano łańcucha lub wyrażenia regularnego",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} ma niepoprawny kierunek",
"6502a117987610380b9068ef98b1b0ee": "Nie znaleziono rekordu w {0} dla ({1}.{2}, {3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Konektor {0} nie obsługuje operacji {{replaceById}}. To nie jest błąd aplikacji LoopBack. Skontaktuj się z autorami konektora, najlepiej za pośrednictwem sekcji serwisu GitHub poświęconej problemom.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} wymaga argumentu {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} wymaga argumentu {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "Relacja {{HasOne}} nie może tworzyć więcej niż jednej instancji elementu {0}",
"728232e473bf80272c042df2b7e002f4": "Relacja {{polymorphic}} {0}: {1} wymaga parametru `polymorphic.discriminator`, jeśli określono parametr `polymorphic.foreignKey`",
"791ab3031a73ede03f7d6299a85e8289": "Przekroczono limit czasu połączenia po {0} ms",
"7b277018e43d41bc445731092b91547d": "Nie połączono",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} wymaga argumentu {{id}}",
"7e9530c0399289be0ee601a604be71ff": "Relacja {{BelongsTo}} {0} jest pusta",
"7faa840eb6ce11250a141deb42a6c489": "Nieznana relacja {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Nazwą właściwości nie może być \"{{constructor}}\" w modelu: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Nazwa właściwości \"{{constructor}}\" nie jest dozwolona w danych {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Model {{Polymorphic}} nie został znaleziony: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Niepoprawny argument; musi to być łańcuch, literał {{regex}} lub obiekt {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "Instancja {0} nie jest poprawna. Szczegóły: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Niepoprawne flagi {{regex}}: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Elementy muszą być tablicą: {0}",
"9e1f143ee02946324d34da92f71bf74e": "Relacja {0}: {1} wymaga parametru `model`",
"a004f310d315e592843776fab964eaeb": "Relacje {{Polymorphic}} wymagają modelu pośredniego",
"a0cf0e09c26df14283223e84e6a10f00": "Nie można zaktualizować atrybutów. Obiekt {{Object}} o identyfikatorze {{id}} {0} nie istnieje!",
"a2487abefef4259c2131d96cdb8543b1": "Nawiązanie połączenia nie powiodło się: {0}\nZostanie podjęta ponowna próba wykonania następnego żądania.",
"a25e41a39c60c4702e55d0c3936576a1": "Niezgodność klucza: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Nieznana metoda zasięgu: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Uruchom komendę \"{{npm install loopback-datasource-juggler}} {0}\"",
"a829dee089c912e68c18920ba015400c": "OSTRZEŻENIE: właściwość {{id}} nie może zostać zmieniona z {0} na {1} dla modelu: {2} w haku operacji {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "OSTRZEŻENIE: właściwość {{id}} nie może zostać zmieniona z {0} na {1} dla modelu: {2} w haku operacji {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "Metoda HasOne \"getAsync()\" jest nieaktualna, zamiast niej użyj metody \"get()\".",
"b138294f132edfe1eb2a8211150c7238": "Nieoczekiwany element `undefined` w zapytaniu",
"b15b20280211ad258d92947f05b6e4a5": "Konektor nie został zainicjowany.",
"b278876ec93ef9760f00e83f38ba313d": "Metoda Scope \"getAsync()\" jest nieaktualna, zamiast niej użyj metody \"find()\".",
"ba0fd8106eb54de4d003a844206431fd": "Hak modelu \"{0}\" jest nieaktualny, zamiast niego użyj haków operacji. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Klauzula where {0} nie jest obiektem {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Nie zdefiniowano typu dla właściwości {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Wartość jest pustym elementem {{object}}",
"bec226891a505828bfc76c5cfd73b336": "Nie można uzyskać wartości TTL dla nieznanego klucza {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Nieznany dostawca wartości domyślnych {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Nazwy właściwości zawierające kropki nie są obsługiwane. Model: {0}, właściwość dynamiczna: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "Źródło danych nie obsługuje transakcji",
"da02dd6c53d4148320eeb31718a7aebe": "Niepoprawny typ właściwości {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Nazwy właściwości zawierające kropki nie są obsługiwane. Model: {0}, właściwość: {1}",
"db03083e9a768388fdbee865249ac67a": "Ignorowanie błędów sprawdzania poprawności w metodzie {{updateOrCreate()}}:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Wartość nie jestem elementem {{array}} lub {{object}} z sekwencyjnymi indeksami liczbowymi",
"ddf0aa14803f1c84f4a97f3803f7471c": "Nazwa klasy jest wymagana",
"e08ab0e1ab55f26c357061447b635905": "Nie znaleziono relacji w {0} dla ({1}.{2}.{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Konektor nie został poprawnie zdefiniowany: powinien utworzyć element '{{connector}}' źródła danych",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Relacja {{polymorphic}} {0}: {1} wymaga parametru `polymorphic.foreignKey`, jeśli określono parametr `polymorphic.discriminator`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "Właściwość {0} ma niepoprawną klauzulę {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Nieznany identyfikator {{id}} \"{0}\" \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Nie można migrować modeli, które nie są przyłączone do tego źródła danych: {0}",
"e54f118a75e15e132f16b985274eb46d": "Filtr zapytania {0} nie jest obiektem {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "Relacja {{HasOne}} {0} jest pusta",
"e6161ae8459c79d810e2aa9d21282a39": "Podczas aktualizowania atrybutów należy podać identyfikator {{id}}!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Relacja \"{0}\" nie została zdefiniowana dla modelu {1}",
"ec42dca074f1818c447f7ad16e2d01af": "Element {0} nie został udostępniony przez przyłączony konektor",
"ecb7aa804bf54c682999d20d6436104c": "Transakcja {{transaction}} nie jest aktywna: {0}",
"f30809cb932b72a66416a709c8531530": "Metoda {{method}} w transakcji nie jest obsługiwana przez konektor",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "nie można utworzyć listy z łańcucha JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "Właściwość {{id}} ({0}) nie może zostać zaktualizowana z {1} na {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Relacja {{polymorphic}} {0}: {1} wymaga parametru `model`",
"fca4d12faff1035d9d0438d73432571b": "Zduplikowany wpis dla {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Nie można znaleźć relacji {0} dla modelu {1}",
"fec8ebda24db46a9d040bf863765cc44": "Operator {0} zawiera niepoprawne klauzule {1}: {2}"
}

97
intl/pt/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Relação {{polymorphic}} de {0}: {1} não espera o parâmetro 'polymorphic.as' ao definir 'foreignKey'/'discriminator' customizado ",
"09483e03b91c8bd58732a74b3ef1ec13": "Data inválida: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany recebeu destino que não contém \"{0}\" necessário",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "A ordem {0} não é válida",
"0bd753a8944ad0af85a939bb25273887": "Não é possível expirar chave desconhecida {0}",
"0c0b867aca0973ba26e887d3337cc4ec": "Modelo de {{Polymorphic}} não localizado: `{0}` não configurado",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "A tabela '{0}' não existe.",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}} não pode ser atualizado de {0} para {1} quando {{forceId}} é configurado como true",
"1ae7d3e0be381efb32bfd1ba652f5172": "AVISO: relação {{polymorphic}} de {0}: {1} usa a palavra-chave 'polymorphic.as', que será DESCONTINUADA em LoopBack.next; consulte este doc para obter soluções de substituição (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Transações aninhadas não são suportadas",
"21095484501dbff31af6556fa6039182": "O parâmetro {{offset/skip}} {0} não é válido",
"280f4550f90e133118955ec6f6f72830": "Tipo de discriminador {0} especificado, mas não existe nenhum modelo com esse nome",
"28697ec15968a7969211f6d035ba9260": "Relação {{polymorphic}} de {0}: {1} não espera o parâmetro 'model'",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} não é suportada",
"2c5c8519721f749aab13c2f04f41d611": "A propriedade {0} possui cláusula inválida {1}: esperado exatamente 2 valores, recebidos {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nAVISO: conector {{LoopBack}} \"{0}\" não foi instalado como qualquer um dos módulos a seguir:\n\n {1}\n\nPara corrigir, execute:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Aviso: o modelo {0}, {{strict mode: `throw`}} foi removido, use {{`strict: true`}} no lugar, que retorna {{`Validation Error`}} para as propriedades desconhecidas,",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} não foi definido para a relação {0} e não é {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Nenhuma instância com ID {0} localizada para {1}",
"416dfbb7b823f51c9f3800be81060b41": "Nenhuma instância com {{id}} {0} localizada para {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "O método BelongsTo \"getAsync()\" está descontinuado, use \"get()\" em vez disso.",
"4c78325cedbb826db3a05bf5df0e8546": "Deve-se fornecer um {{id}} ao substituir!",
"4e31b1edd10dadb724d83387de0b5062": "O parâmetro {0} de {{limit}} não é válido",
"514985b2327f061ffb1c932f6b909979": "O modelo {0} não está definido.",
"525c856e65daab43be247e7b5410febd": "Relação {{polymorphic}} de {0}: {1} não espera o parâmetro 'polymorphic.selector' ao definir 'foreignKey'/'discriminator' customizado ",
"5c18ee111dd87540cdb19a2a93b33be9": "A transação é recuperada devido à transcorrência do tempo limite",
"5ec7e6664256f7ea78f4f06dafc7d974": "A transação não está pronta, aguarde a promessa retornada para resolver",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Nenhum nome de {{id}} {0}",
"614e3355647e4127c96256102dc63376": "A propriedade {0} possui cláusula inválida {1}: esperada uma sequência ou um RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "A {{order}} {0} possui direção inválida",
"6502a117987610380b9068ef98b1b0ee": "Nenhum registro encontrado em {0} para ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "O conector {0} não suporta operação {{replaceById}}. Este não é um erro no LoopBack. Entre em contato com os autores do conector, de preferência via problemas do GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} requer o argumento {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} requer o argumento {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "A relação {{HasOne}} não pode criar mais de uma instância de {0}",
"728232e473bf80272c042df2b7e002f4": "Relação {{polymorphic}} de {0}: {1} requer o parâmetro 'polymorphic.discriminator' quando o parâmetro 'polymorphic.foreignKey' é fornecido",
"791ab3031a73ede03f7d6299a85e8289": "Tempo limite na conexão após {0} ms",
"7b277018e43d41bc445731092b91547d": "Não está conectado",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} requer o argumento {{id}}",
"7e9530c0399289be0ee601a604be71ff": "Relação {{BelongsTo}} {0} está vazia",
"7faa840eb6ce11250a141deb42a6c489": "{{scope}} da relação desconhecido: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "O nome da propriedade não deve ser \"{{constructor}}\" no Modelo: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "O nome da propriedade \"{{constructor}}\" não é permitido nos dados de {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Modelo de {{Polymorphic}} não localizado: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Argumento inválido, deve ser uma sequência, literal {{regex}} ou objeto {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "A instância de {0} não é válida. Detalhes: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Sinalizações de {{regex}} inválidas: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Itens devem ser uma matriz: {0}",
"9e1f143ee02946324d34da92f71bf74e": "Relação de {0}: {1} requer o parâmetro 'model'",
"a004f310d315e592843776fab964eaeb": "Relações de {{Polymorphic}} precisam de um modelo completo",
"a0cf0e09c26df14283223e84e6a10f00": "Não foi possível atualizar atributos. {{Object}} com {{id}} {0} não existe!",
"a2487abefef4259c2131d96cdb8543b1": "Falha de conexão: {0}\nEla será tentada novamente para a próxima solicitação.",
"a25e41a39c60c4702e55d0c3936576a1": "Incompatibilidade de chaves: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Método de escopo desconhecido: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Execute o comando \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "AVISO: a propriedade {{id}} não pode ser mudada de {0} para {1} para o modelo:{2} no gancho de operação {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "AVISO: a propriedade {{id}} não pode ser mudada de {0} para {1} para o modelo:{2} no gancho de operação {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "O método HasOne \"getAsync()\" está descontinuado, use \"get()\" em vez disso.",
"b138294f132edfe1eb2a8211150c7238": "`Indefinido` inesperado na consulta",
"b15b20280211ad258d92947f05b6e4a5": "O conector não foi inicializado.",
"b278876ec93ef9760f00e83f38ba313d": "O método Scope \"getAsync()\" está descontinuado, use \"find()\" em vez disso.",
"ba0fd8106eb54de4d003a844206431fd": "O gancho de modelo \"{0}\" está descontinuado, use ganchos de Operação no lugar. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "A cláusula where {0} não é um {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Tipo não definido para a propriedade {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "O valor é um {{object}} vazio",
"bec226891a505828bfc76c5cfd73b336": "Não é possível obter TTL para chave desconhecida {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Provedor do valor padrão {0} desconhecido",
"cfee4d8149316d9a647c0885cf3cafaf": "Nomes da propriedade contendo pontos não são suportados. Modelo: {0}, propriedade dinâmica: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "A Origem de Dados não suporta transações",
"da02dd6c53d4148320eeb31718a7aebe": "Tipo inválido para a propriedade {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Nomes da propriedade contendo pontos não são suportados. Modelo: {0}, propriedade: {1}",
"db03083e9a768388fdbee865249ac67a": "Ignorando erros de validação em {{updateOrCreate()}}:",
"dd63416d9b7d9fa4181e89efd619dfd8": "O valor não é um {{array}} ou {{object}} com índices numéricos sequenciais",
"ddf0aa14803f1c84f4a97f3803f7471c": "Nome de classe necessário",
"e08ab0e1ab55f26c357061447b635905": "Nenhuma relação encontrada em {0} para ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "O conector não foi definido corretamente: ele deve criar um membro de `{{connector}}` igual a dataSource",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Relação {{polymorphic}} de {0}: {1} requer o parâmetro 'polymorphic.foreignKey' quando o parâmetro 'polymorphic.discriminator' é fornecido",
"e39e0f5d52bfbf511e645d19ecadd2fa": "A propriedade {0} possui cláusula inválida {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "\"{0}\" {{id}} \"{1}\" desconhecido.",
"e54d944c2a2c85a23caa86027ae307cf": "Não é possível migrar modelos não conectados a esta origem de dados: {0}",
"e54f118a75e15e132f16b985274eb46d": "O filtro de consulta {0} não é um {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "Relação {{HasOne}} {0} está vazia",
"e6161ae8459c79d810e2aa9d21282a39": "Deve-se fornecer um {{id}} ao atualizar atributos!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "A relação \"{0}\" não foi definida para o modelo {1}",
"ec42dca074f1818c447f7ad16e2d01af": "{0} não é fornecido pelo conector conectado",
"ecb7aa804bf54c682999d20d6436104c": "A {{transaction}} não está ativa: {0}",
"f30809cb932b72a66416a709c8531530": "O conector não suporta {{method}} dentro de uma transação",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "não foi possível criar Lista a partir da sequência JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "A propriedade de {{id}} ({0}) não pode ser atualizada de {1} para {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Relação {{polymorphic}} de {0}: {1} requer o parâmetro 'model'",
"fca4d12faff1035d9d0438d73432571b": "Entrada suplicada para {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Não foi possível localizar a relação {0} para o modelo {1}",
"fec8ebda24db46a9d040bf863765cc44": "O operador {0} possui cláusulas inválidas {1}: {2}"
}

97
intl/ru/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "Связь {0} {{polymorphic}}: {1} не предполагает параметр `polymorphic.as` при определении пользовательского атрибута `foreignKey`/`discriminator` ",
"09483e03b91c8bd58732a74b3ef1ec13": "Недопустимая дата: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany полученный целевой объект не содержит обязательный параметр \"{0}\"",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "Недопустимый порядок {0}",
"0bd753a8944ad0af85a939bb25273887": "Не удалось преобразовать неизвестный ключ {0} в устаревший",
"0c0b867aca0973ba26e887d3337cc4ec": "Модель {{Polymorphic}} не найдена: не задан параметр `{0}`",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "Таблица '{0}' не существует.",
"0ff31abb394afb555df162e74ff1a0a0": "Для {{id}} не удается изменить значение {0} на {1}, если параметру {{forceId}} присвоено значение true",
"1ae7d3e0be381efb32bfd1ba652f5172": "ПРЕДУПРЕЖДЕНИЕ: связь {0} {{polymorphic}}: {1} использует ключевое слово `polymorphic.as`, которое УСТАРЕЕТ в LoopBack.next. Решение по замене приведены в следующем документе: (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "Вложенные транзакции не поддерживаются",
"21095484501dbff31af6556fa6039182": "Параметр {{offset/skip}} {0} недопустим",
"280f4550f90e133118955ec6f6f72830": "Указан тип дискриминатора {0}, но модель с таким именем не существует",
"28697ec15968a7969211f6d035ba9260": "Связь {0} {{polymorphic}}: в {1} не используется параметр `model`",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} не поддерживается",
"2c5c8519721f749aab13c2f04f41d611": "Свойство {0} содержит недопустимый оператор {1}: требуется ровно 2 значения, но получено {2}",
"2f4af31c144bbfab1bbf479866acd820": "\nПРЕДУПРЕЖДЕНИЕ: Коннектор {{LoopBack}} \"{0}\" не установлен как один из следующих модулей:\n\n {1}\n\nДля исправления этой ошибки выполните следующую команду:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Предупреждение: Модель {0} {{strict mode: `throw`}} была удалена, используйте вместо нее {{`strict: true`}}, возвращающий для неизвестных свойств значение {{`Validation Error`}},",
"38dbf42c29a4645238cc3d632e88ebc9": "Параметр {{Relation.modelTo}} не определен для связи {0} и не является {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "Не найден экземпляр с ИД {0} для {1}",
"416dfbb7b823f51c9f3800be81060b41": "Не найден экземпляр с {{id}} {0} для {1}",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "Метод BelongsTo \"getAsync()\" устарел, используйте вместо него \"get()\".",
"4c78325cedbb826db3a05bf5df0e8546": "При замене необходимо указать {{id}}!",
"4e31b1edd10dadb724d83387de0b5062": "Параметр {{limit}} {0} недопустим",
"514985b2327f061ffb1c932f6b909979": "Модель {0} не определена.",
"525c856e65daab43be247e7b5410febd": "Связь {0} {{polymorphic}}: {1} не предполагает параметр `polymorphic.selector` при определении пользовательского атрибута `foreignKey`/`discriminator` ",
"5c18ee111dd87540cdb19a2a93b33be9": "Выполнен откат транзакции из-за тайм-аута",
"5ec7e6664256f7ea78f4f06dafc7d974": "Транзакция не готова, дождитесь возвращенного обязательства устранить неполадку",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "Отсутствует имя {{id}} {0}",
"614e3355647e4127c96256102dc63376": "Свойство {0} содержит недопустимый оператор {1}: ожидается строка или регулярное выражение",
"62a2d80c405b7fec5f547c448ab1b6ff": "Недопустимое направление {{order}} {0}",
"6502a117987610380b9068ef98b1b0ee": "В {0} не обнаружены записи для ({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "Коннектор {0} не поддерживает операцию {{replaceById}}. Это не является ошибкой LoopBack. Обратитесь к авторам коннектора, желательно через раздел ошибок на GitHub.",
"6c3234937d69763fc7f6bcafccc59bbc": "Для {{Model::deleteById}} требуется аргумент {{id}}",
"6eb6fd4fbd73394000bc25f5776fd20c": "Для {{Model::exists}} требуется аргумент {{id}}",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "Связи {{HasOne}} не удается создать больше одного экземпляра {0}",
"728232e473bf80272c042df2b7e002f4": "Связь {0} {{polymorphic}}: для {1} требуется параметр `polymorphic.discriminator`, если задан параметр `polymorphic.foreignKey`",
"791ab3031a73ede03f7d6299a85e8289": "Тайм-аут соединения наступает через {0} мс",
"7b277018e43d41bc445731092b91547d": "Не подключено",
"7bbbdece4eea90e42aa5c0bce295e503": "Для {{Model::findById}} требуется аргумент {{id}}",
"7e9530c0399289be0ee601a604be71ff": "Пустая связь {{BelongsTo}} {0}",
"7faa840eb6ce11250a141deb42a6c489": "Неизвестная связь {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Имя свойства не должно быть \"{{constructor}}\" в модели: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "Имя свойства \"{{constructor}}\" не разрешено в данных {0}",
"89afd3a9249f5a8d3edda07d84ca049d": "Модель {{Polymorphic}} не найдена: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Недопустимый аргумент, требуется строка, литерал {{regex}} или объект {{RegExp}}",
"8a39126103a157f501affa070367a1b0": "Недопустимый экземпляр {0}. Сведения: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Недопустимые флаги {{regex}}: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Элементы должны быть массивом: {0}",
"9e1f143ee02946324d34da92f71bf74e": "Связь {0}: для {1} требуется параметр `model`",
"a004f310d315e592843776fab964eaeb": "Связи {{Polymorphic}} требуется промежуточная модель",
"a0cf0e09c26df14283223e84e6a10f00": "Не удалось обновить атрибуты. {{Object}} с {{id}} {0} не существует",
"a2487abefef4259c2131d96cdb8543b1": "Соединение не выполнено: {0}\nПопытка соединения будет выполнена повторно при следующем запросе.",
"a25e41a39c60c4702e55d0c3936576a1": "Несоответствие ключей: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Неизвестный метод области: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "Выполните команду \"{{npm install loopback-datasource-juggler}} {0}\" ",
"a829dee089c912e68c18920ba015400c": "Предупреждение: значение свойства {{id}} {0} не может быть изменено на {1} для модели {2} в перехватчике операции {{'loaded'}}",
"a984a076c59e451948b2bcf7a393d860": "Предупреждение: значение свойства {{id}} {0} не может быть изменено на {1} для модели {2} в перехватчике операции {{'before save'}}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "Метод HasOne \"getAsync()\" устарел, используйте вместо него \"get()\".",
"b138294f132edfe1eb2a8211150c7238": "Непредвиденный параметр `undefined` в запросе",
"b15b20280211ad258d92947f05b6e4a5": "Коннектор не инициализирован.",
"b278876ec93ef9760f00e83f38ba313d": "Метод Scope \"getAsync()\" устарел, используйте вместо него \"find()\".",
"ba0fd8106eb54de4d003a844206431fd": "Перехватчик Model \"{0}\" устарел, используйте вместо него перехватчики Operation. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Оператор where {0} не является объектом {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "Не определен тип для свойства {0}.{1}",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Значение - пустой объект {{object}}",
"bec226891a505828bfc76c5cfd73b336": "Не удалось получить TTL для неизвестного ключа {0}",
"cd930369e86cdd222f7bd117c6f9fa94": "Неизвестный поставщик значений по умолчанию {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Не поддерживаются имена свойств, содержащие точку. Модель: {0}, динамическое свойство: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource не поддерживает транзакции",
"da02dd6c53d4148320eeb31718a7aebe": "Недопустимый тип для свойства {0}",
"da751a8a748adbde5b55fa83b707b4e2": "Не поддерживаются имена свойств, содержащие точку. Модель: {0}, свойство: {1}",
"db03083e9a768388fdbee865249ac67a": "Ошибки проверки в {{updateOrCreate()}} игнорируются:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Значение не является {{array}} или {{object}} с последовательными числовыми индексами",
"ddf0aa14803f1c84f4a97f3803f7471c": "Необходимо указать имя класса",
"e08ab0e1ab55f26c357061447b635905": "В {0} не найдена связь для ({1}.{2},{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "Неправильно определен коннектор: он должен создавать элемент `{{connector}}` в dataSource",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "Связь {0} {{polymorphic}}: для {1} требуется параметр `polymorphic.foreignKey`, если указан параметр `polymorphic.discriminator`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "Свойство {0} содержит недопустимый оператор {1}: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Неизвестный {{id}} \"{0}\" \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Не удается перенести модели, которые не подключены к этому источнику данных: {0}",
"e54f118a75e15e132f16b985274eb46d": "Фильтр запроса {0} не является объектом {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "Пустая связь {{HasOne}} {0}",
"e6161ae8459c79d810e2aa9d21282a39": "При обновлении атрибутов необходимо указать {{id}}",
"eb56c2b0c30cf006e2df00a549ec9c2c": "Связь \"{0}\" не определена для модели {1}",
"ec42dca074f1818c447f7ad16e2d01af": "Подключенный коннектор не указал {0}",
"ecb7aa804bf54c682999d20d6436104c": "Неактивная транзакция {{transaction}}: {0}",
"f30809cb932b72a66416a709c8531530": "Коннектор не поддерживает {{method}} в транзакции",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "Не удалось создать атрибут List из строки JSON: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "Для свойства {{id}} ({0}) не удалось изменить значение {1} на {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "Связь {0} {{polymorphic}}: для {1} требуется параметр `model`",
"fca4d12faff1035d9d0438d73432571b": "Создать копию для {0}.{1}",
"fd3cc89dc67e2d604eaae21bdf41d403": "Не удалось найти связь {0} для модели {1}",
"fec8ebda24db46a9d040bf863765cc44": "Оператор {0} содержит недопустимые операторы {1}: {2}"
}

97
intl/tr/messages.json Normal file
View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} ilişkisi: {1}, özel `foreignKey`/`discriminator` tanımlarken `polymorphic.as` parametresini beklemiyor ",
"09483e03b91c8bd58732a74b3ef1ec13": "Geçersiz tarih: {0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany, gerekli \"{0}\" öğesini içermeyen hedef aldı",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "{0} sırası geçerli değil",
"0bd753a8944ad0af85a939bb25273887": "Bilinmeyen {0} anahtarı süre bitimine uğratılamaz",
"0c0b867aca0973ba26e887d3337cc4ec": "{{Polymorphic}} model bulunamadı: `{0}` ayarlı değil",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "'{0}' tablosu yok",
"0ff31abb394afb555df162e74ff1a0a0": "{{id}}, {{forceId}} true olarak ayarlandığında {0} durumundan {1} durumuna güncellenemiyor",
"1ae7d3e0be381efb32bfd1ba652f5172": "UYARI: {{polymorphic}} {0} ilişkisi: {1}, LoopBack.next içinde KULLANIMDAN KALDIRILACAK `polymorphic.as` anahtar sözcüğünü kullanıyor; değiştirme çözümleri için bu belgeye bakın (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "İç içe geçmiş işlemler desteklenmiyor",
"21095484501dbff31af6556fa6039182": "{{offset/skip}} parametresi {0} geçerli değil",
"280f4550f90e133118955ec6f6f72830": "{0} ayrımsayıcı tipi belirtildi, ancak bu adı taşıyan bir model yok",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} ilişkisi: {1}, `model` parametresini beklemiyor",
"2c4904377a87fdab502118719cc0d266": "{{Transaction}} desteklenmiyor",
"2c5c8519721f749aab13c2f04f41d611": "{0} özelliği geçersiz {1} yantümcesi içeriyor: Tam olarak 2 değer bekleniyor, {2} alındı",
"2f4af31c144bbfab1bbf479866acd820": "\nUYARI: {{LoopBack}} bağlayıcısı \"{0}\" şu modüllerden biri olarak kurulmadı:\n\n {1}\n\nDüzeltmek için şu komutu çalıştırın:\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "Uyarı: {0} modeli, {{strict mode: `throw`}} kaldırıldı, lütfen bunun yerine bilinmeyen özellikler için {{`Validation Error`}} döndüren {{`strict: true`}} kullanın",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}}, {0} ilişkisi için tanımlanmadı ve {{polymorphic}} değil",
"3cde8cc9bca22c67278b202ab0720106": "{1} için {0} tanıtıcılı bir eşgörünüm bulunamadı",
"416dfbb7b823f51c9f3800be81060b41": "{1} için {{id}} {0} tanıtıcılı bir eşgörünüm bulunamadı",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "\"getAsync()\" BelongsTo yöntemi kullanımdan kaldırıldı, bunun yerine \"get()\" kullanın.",
"4c78325cedbb826db3a05bf5df0e8546": "Değiştirirken bir {{id}} belirtmelisiniz!",
"4e31b1edd10dadb724d83387de0b5062": "{{limit}} parametresi {0} geçerli değil",
"514985b2327f061ffb1c932f6b909979": "{0} modeli tanımlanmadı",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} ilişkisi: {1}, özel `foreignKey`/`discriminator` öğesini tanımlarken `polymorphic.selector` parametresini beklemiyor ",
"5c18ee111dd87540cdb19a2a93b33be9": "Zaman aşımı nedeniyle işlem geri alındı",
"5ec7e6664256f7ea78f4f06dafc7d974": "İşlem hazır değil, çözüm için döndürülen durumu bekleyin. ",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "{{id}} adı {0} yok",
"614e3355647e4127c96256102dc63376": "{0} özelliğinde geçersiz {1} yantümcesi var: Bir dizgi ya da RegExp bekleniyor",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} sırasının yönü geçersiz",
"6502a117987610380b9068ef98b1b0ee": "({1}.{2} ,{3}.{4}) için {0} içinde kayıt bulunamadı. ",
"67c2bf43b5281ab929617423ea8a6f3e": "{0} bağlayıcısı {{replaceById}} işlemini desteklemiyor. Bu LoopBack'deki bir hata değil. Lütfen, mümkünse GitHub sorunlarıyla birlikte, bağlayıcının yazarlarına başvurun.",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}}, {{id}} bağımsız değişkenini gerektirir",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}}, {{id}} bağımsız değişkenini gerektirir",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} ilişkisi birden çok {0} eşgörünümü yaratamaz",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} ilişkisi: `polymorphic.foreignKey` parametresi sağlandığında {1} için `polymorphic.discriminator` parametresi gerekir",
"791ab3031a73ede03f7d6299a85e8289": "{0} milisaniyeden sonra bağlantıda zaman aşımı oluştu",
"7b277018e43d41bc445731092b91547d": "Bağlı değil",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}}, {{id}} bağımsız değişkenini gerektirir",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} ilişkisi {0} boş",
"7faa840eb6ce11250a141deb42a6c489": "Bilinmeyen ilişki {{scope}}: {0}",
"8091838319a5cc7d6a34af2f2a616ce9": "Şu modelde özellik adı \"{{constructor}}\" olmamalıdır: {0}",
"881e4b0cb86ed59549248ee540a9fd10": "{0} verilerinde \"{{constructor}}\" özellik adına izin verilmez",
"89afd3a9249f5a8d3edda07d84ca049d": "{{Polymorphic}} model bulunamadı: `{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "Bağımsız değişken geçersiz; bir dizgi, {{regex}} hazır bilgisi ya da {{RegExp}} nesnesi olmalıdır",
"8a39126103a157f501affa070367a1b0": "{0} eşgörünümü geçerli değil. Ayrıntılar: {1}.",
"8c5ab01638c1ac1d58168c6346a8481a": "Geçersiz {{regex}} işaretleri: {0}",
"938401ea4ce48159efa9be1d4a5e8bab": "Öğeler bir dizi olmalıdır: {0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} ilişkisi: {1} için `model` parametresi gerekir",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} ilişkileri için aracı model gerekir",
"a0cf0e09c26df14283223e84e6a10f00": "Öznitelikler güncellenemedi. Tanıtıcısı {{id}} olan {0} {{Object}} nesnesi yok!",
"a2487abefef4259c2131d96cdb8543b1": "Bağlantı başarısız oldu: {0}\nSonraki istek için yeniden denenecek.",
"a25e41a39c60c4702e55d0c3936576a1": "Anahtar uyuşmazlığı: {0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "Bilinmeyen kapsam yöntemi: {0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "\"{{npm install loopback-datasource-juggler}} {0}\" komutunu çalıştırın ",
"a829dee089c912e68c18920ba015400c": "UYARI: {{id}} özelliği, {{'loaded'}} işlem çengelinde {2} modeli için {0} değerinden {1} değerine çevrilemiyor",
"a984a076c59e451948b2bcf7a393d860": "UYARI: {{id}} özelliği, {{'before save'}} işlem çengelinde {2} modeli için {0} değerinden {1} değerine çevrilemiyor",
"ac04cf275b71c1eb89a41cf6bbad7a64": "\"getAsync()\" HasOne yöntemi kullanımdan kaldırıldı, bunun yerine \"get()\" kullanın",
"b138294f132edfe1eb2a8211150c7238": "Sorguda beklenmeyen `undefined`",
"b15b20280211ad258d92947f05b6e4a5": "Bağlayıcı başlatılmamış.",
"b278876ec93ef9760f00e83f38ba313d": "\"getAsync()\" kapsam yöntemi kullanımdan kaldırıldı, bunun yerine \"find()\" kullanın.",
"ba0fd8106eb54de4d003a844206431fd": "\"{0}\" model çengeli kullanımdan kaldırıldı, onun yerine işlem çengellerini kullanın. {{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Where yantümcesi {0} bir {{object}} değil",
"bdb11cc1c780c9ccac33c316cfdc9d82": "{0}.{1} özelliği için tip tanımlanmadı",
"bdfb951c8ff7ce0cbc08c06f548fd927": "Değer boş bir {{object}}",
"bec226891a505828bfc76c5cfd73b336": "Bilinmeyen {0} anahtarı için TTL alınamıyor",
"cd930369e86cdd222f7bd117c6f9fa94": "Bilinmeyen varsayılan değer sağlayıcısı {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "Nokta içeren özellik adları desteklenmez. Model: {0}, dinamik özellik: {1}",
"d40328eabd8756d795bcdd49d782d4e9": "DataSource işlemleri desteklemiyor",
"da02dd6c53d4148320eeb31718a7aebe": "{0} özelliği için geçersiz tip",
"da751a8a748adbde5b55fa83b707b4e2": "Nokta içeren özellik adları desteklenmez. Model: {0}, özellik: {1}",
"db03083e9a768388fdbee865249ac67a": "{{updateOrCreate()}} işlemindeki doğrulama hataları yoksayılıyor:",
"dd63416d9b7d9fa4181e89efd619dfd8": "Değer, sıralı sayısal dizeler içeren bir {{array}} ya da {{object}} değil",
"ddf0aa14803f1c84f4a97f3803f7471c": "Sınıf adı zorunludur",
"e08ab0e1ab55f26c357061447b635905": "({1}.{2} ,{3}.{4}) için {0} içinde ilişki bulunamadı.",
"e0e9504e137a3c3339144b51ed76fef2": "Bağlayıcı doğru tanımlanmadı: Veri kaynağının `{{connector}}` üyesini yaratmalıdır",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} ilişkisi: `polymorphic.discriminator` parametresi sağlandığında {1} için `polymorphic.foreignKey` parametresi gerekir",
"e39e0f5d52bfbf511e645d19ecadd2fa": "{0} özelliğinde geçersiz {1} yantümcesi var: {2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "Bilinmeyen \"{0}\" {{id}} \"{1}\".",
"e54d944c2a2c85a23caa86027ae307cf": "Bu veri kaynağına eklenmemiş modeller geçirilemez: {0}",
"e54f118a75e15e132f16b985274eb46d": "Sorgu süzgeci {0} bir {{object}} değil",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} ilişkisi {0} boş",
"e6161ae8459c79d810e2aa9d21282a39": "Öznitelikleri güncellerken bir {{id}} belirtmelisiniz!",
"eb56c2b0c30cf006e2df00a549ec9c2c": "{1} modeli için \"{0}\" ilişkisi tanımlanmadı",
"ec42dca074f1818c447f7ad16e2d01af": "Eklenen bağlayıcı tarafından {0} sağlanmadı",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} etkin değil: {0}",
"f30809cb932b72a66416a709c8531530": "Bağlayıcısı bir işlem içinde {{method}} yöntemini desteklemiyor.",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "JSON dizgisinden liste yaratılamadı: {0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}} özelliği ({0}), {1} değerinden {2} değerine güncellenemiyor",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} ilişkisi: {1} için `model` parametresi gerekir",
"fca4d12faff1035d9d0438d73432571b": "{0}.{1} için yinelenen giriş",
"fd3cc89dc67e2d604eaae21bdf41d403": "{1} modeli için {0} ilişkisi bulunamadı",
"fec8ebda24db46a9d040bf863765cc44": "{0} işlecinde geçersiz {1} yantümceleri var: {2}"
}

View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} 关系:定义定制 `foreignKey`/`discriminator` 时,{1} 不期望参数 `polymorphic.as`",
"09483e03b91c8bd58732a74b3ef1ec13": "无效日期:{0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany 收到的目标不包含必需的“{0}”",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "顺序 {0} 无效",
"0bd753a8944ad0af85a939bb25273887": "无法使未知键 {0} 到期",
"0c0b867aca0973ba26e887d3337cc4ec": "找不到 {{Polymorphic}} 模型:未设置“{0}”",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "表“{0}”不存在。",
"0ff31abb394afb555df162e74ff1a0a0": "将 {{forceId}} 设置为 true 时,{{id}} 无法从 {0} 更新为 {1}",
"1ae7d3e0be381efb32bfd1ba652f5172": "警告:{{polymorphic}} {0} 关系:{1} 使用关键字 `polymorphic.as`,在 LoopBack.next 中不推荐使用此关键字,请参阅以下文档以了解替代解决方案 (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "不支持嵌套事务",
"21095484501dbff31af6556fa6039182": "{{offset/skip}} 参数 {0} 无效",
"280f4550f90e133118955ec6f6f72830": "已指定鉴别器类型 {0},但是不存在具有此类名称的模型",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} 关系:{1} 不期望参数 `model`",
"2c4904377a87fdab502118719cc0d266": "不支持 {{Transaction}}",
"2c5c8519721f749aab13c2f04f41d611": "{0} 属性具有无效子句 {1}:预期精确为 2 个值,接收 {2}",
"2f4af31c144bbfab1bbf479866acd820": "\n警告未作为以下任何模块安装 {{LoopBack}} 连接器“{0}”\n\n {1}\n\n要修正请运行\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "警告:模型 {0} {{strict mode: `throw`}} 已移除,请使用 {{`strict: true`}} 代替,其将返回未知属性的 {{`Validation Error`}}。",
"38dbf42c29a4645238cc3d632e88ebc9": "未针对关系 {0} 定义 {{Relation.modelTo}},并且不是 {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "对于 {1},找不到具有标识 {0} 的实例",
"416dfbb7b823f51c9f3800be81060b41": "对于 {1},找不到具有 {{id}} {0} 的实例",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "不推荐使用 BelongsTo 方法“getAsync()”请改为使用“get()”。",
"4c78325cedbb826db3a05bf5df0e8546": "在替换时必须提供 {{id}}",
"4e31b1edd10dadb724d83387de0b5062": "{{limit}} 参数 {0} 无效",
"514985b2327f061ffb1c932f6b909979": "未定义模型 {0}。",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} 关系:定义定制 `foreignKey`/`discriminator` 时,{1} 不期望参数 `polymorphic.selector`",
"5c18ee111dd87540cdb19a2a93b33be9": "事务因超时而回滚",
"5ec7e6664256f7ea78f4f06dafc7d974": "事务未就绪,请等待返回的约定解决",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "无 {{id}} 名称 {0}",
"614e3355647e4127c96256102dc63376": "{0} 属性具有无效子句 {1}:预期为字符串或 RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} 具有无效的方向",
"6502a117987610380b9068ef98b1b0ee": "在 {0} 中找不到以下项的记录:({1}.{2} ,{3}.{4})",
"67c2bf43b5281ab929617423ea8a6f3e": "连接器 {0} 不支持 {{replaceById}} 操作。这不是 LoopBack 中的错误。请联系连接器的作者,首选通过 GitHub 提交问题。",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} 需要 {{id}} 自变量",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} 需要 {{id}} 自变量",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} 关系无法创建 {0} 的多个实例",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} 关系:提供参数 `polymorphic.foreignKey` 时,{1} 需要参数 `polymorphic.discriminator`",
"791ab3031a73ede03f7d6299a85e8289": "在 {0} 毫秒后连接超时",
"7b277018e43d41bc445731092b91547d": "未连接",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} 需要 {{id}} 自变量",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} 关系 {0} 为空",
"7faa840eb6ce11250a141deb42a6c489": "未知的关系 {{scope}}{0}",
"8091838319a5cc7d6a34af2f2a616ce9": "属性名称不应是模型中的“{{constructor}}”:{0}",
"881e4b0cb86ed59549248ee540a9fd10": "{0} 数据中不允许属性名称“{{constructor}}”",
"89afd3a9249f5a8d3edda07d84ca049d": "找不到 {{Polymorphic}} 模型:“{0}”",
"89bf6d92731fe7bd2146ce8d0bec205c": "无效的自变量,必须是字符串、{{regex}} 字面值或 {{RegExp}} 对象",
"8a39126103a157f501affa070367a1b0": "{0} 实例无效。详细信息:{1}。",
"8c5ab01638c1ac1d58168c6346a8481a": "无效的 {{regex}} 标志:{0}",
"938401ea4ce48159efa9be1d4a5e8bab": "项必须是数组:{0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} 关系:{1} 需要参数 `model`",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} 关系需要直通模型",
"a0cf0e09c26df14283223e84e6a10f00": "无法更新属性。包含 {{id}} {0} 的 {{Object}} 不存在!",
"a2487abefef4259c2131d96cdb8543b1": "连接失败:{0}\n将在下一次请求时重试。",
"a25e41a39c60c4702e55d0c3936576a1": "键不匹配:{0}.{1}: {2}, {3}.{4}: {5}",
"a327355560d495454fba2c1aad6bdf09": "未知的作用域方法:{0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "运行“{{npm install loopback-datasource-juggler}} {0}”命令",
"a829dee089c912e68c18920ba015400c": "警告:对于以下模型,{{id}} 属性无法从 {0} 更改为 {1}{{'loaded'}} 操作挂钩中的 {2}",
"a984a076c59e451948b2bcf7a393d860": "警告:对于以下模型,{{id}} 属性无法从 {0} 更改为 {1}{{'before save'}} 操作挂钩中的 {2}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "不推荐使用 HasOne 方法“getAsync()”请改为使用“get()”。",
"b138294f132edfe1eb2a8211150c7238": "查询中存在意外的“未定义”",
"b15b20280211ad258d92947f05b6e4a5": "连接器尚未进行初始化。",
"b278876ec93ef9760f00e83f38ba313d": "不推荐使用 Scope 方法“getAsync()”请改为使用“find()”。",
"ba0fd8106eb54de4d003a844206431fd": "不推荐使用模型挂钩“{0}”,请改用操作挂钩。{{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "Where 子句 {0} 不是 {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "未针对属性 {0}.{1} 定义类型",
"bdfb951c8ff7ce0cbc08c06f548fd927": "值为空的 {{object}}",
"bec226891a505828bfc76c5cfd73b336": "无法获取未知键 {0} 的 TTL",
"cd930369e86cdd222f7bd117c6f9fa94": "未知的缺省值提供程序 {0}",
"cfee4d8149316d9a647c0885cf3cafaf": "不支持包含点的属性名称。模型:{0},动态属性:{1}",
"d40328eabd8756d795bcdd49d782d4e9": "数据源不支持事务",
"da02dd6c53d4148320eeb31718a7aebe": "属性 {0} 的类型无效",
"da751a8a748adbde5b55fa83b707b4e2": "不支持包含点的属性名称。模型:{0},属性:{1}",
"db03083e9a768388fdbee865249ac67a": "正在忽略 {{updateOrCreate()}} 中的验证错误:",
"dd63416d9b7d9fa4181e89efd619dfd8": "值不是具有有序数字索引的 {{array}} 或 {{object}}",
"ddf0aa14803f1c84f4a97f3803f7471c": "类名是必需的",
"e08ab0e1ab55f26c357061447b635905": "在 {0} 中找不到以下项的关系:({1}.{2} ,{3}.{4})",
"e0e9504e137a3c3339144b51ed76fef2": "连接器定义不正确:应创建数据源的“{{connector}}”成员",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} 关系:提供参数 `polymorphic.discriminator` 时,{1} 需要参数 `polymorphic.foreignKey`",
"e39e0f5d52bfbf511e645d19ecadd2fa": "{0} 属性有无效子句 {1}{2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "未知的“{0}”{{id}}“{1}”。",
"e54d944c2a2c85a23caa86027ae307cf": "无法迁移未附加到此数据源的模型:{0}",
"e54f118a75e15e132f16b985274eb46d": "查询过滤器 {0} 不是 {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} 关系 {0} 为空",
"e6161ae8459c79d810e2aa9d21282a39": "在更新属性时必须提供 {{id}}",
"eb56c2b0c30cf006e2df00a549ec9c2c": "未针对 {1} 模型定义关系“{0}”",
"ec42dca074f1818c447f7ad16e2d01af": "连接的连接器未提供 {0}",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} 不活动:{0}",
"f30809cb932b72a66416a709c8531530": "连接器不支持某个事务内的 {{method}}",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "无法从 JSON 字符串创建列表:{0}",
"f6e8c96c93b9c7687d6c172b3695e898": "{{id}} 属性 ({0}) 无法从 {1} 更新为 {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} 关系:{1} 需要参数 `model`",
"fca4d12faff1035d9d0438d73432571b": "{0}.{1} 的重复条目",
"fd3cc89dc67e2d604eaae21bdf41d403": "针对模型 {1} 找不到关系 {0}",
"fec8ebda24db46a9d040bf863765cc44": "{0} 操作员有无效子句 {1}{2}"
}

View File

@ -0,0 +1,97 @@
{
"0483a77cf77741504204e5c066597487": "{{polymorphic}} {0} 關係:定義自訂 'foreignKey'/'discriminator' 時 {1} 並未預期參數 'polymorphic.as'",
"09483e03b91c8bd58732a74b3ef1ec13": "無效日期:{0}",
"0a5aa17f7866a85e3aee37ef5369403c": "LinkManyToMany 收到的目標不含必要的 \"{0}\"",
"0b16d3ffc42f91b4b9a4b3b50c41c838": "順序 {0} 無效",
"0bd753a8944ad0af85a939bb25273887": "無法使不明金鑰 {0} 到期",
"0c0b867aca0973ba26e887d3337cc4ec": "找不到 {{Polymorphic}} 模型:`{0}` 未設定",
"0c4eb8b6c2ff6e51d7e195eee346ced9": "表格 '{0}' 不存在。",
"0ff31abb394afb555df162e74ff1a0a0": "當 {{forceId}} 設定為 true 時,無法將 {{id}} 從 {0} 更新為 {1}",
"1ae7d3e0be381efb32bfd1ba652f5172": "警告:{{polymorphic}} {0} 關係:{1} 使用關鍵字 'polymorphic.as'(將在 LoopBack.next 中淘汰),請參閱此文件以取得取代解決方案 (https://loopback.io/doc/en/lb3/Polymorphic-relations.html#deprecated-polymorphic-as)",
"1daef4e937fe52136597ba8fd2060f55": "不支援巢狀交易",
"21095484501dbff31af6556fa6039182": "{{offset/skip}} 參數 {0} 無效",
"280f4550f90e133118955ec6f6f72830": "已指定鑑別器類型 {0},但不存在此名稱的模型",
"28697ec15968a7969211f6d035ba9260": "{{polymorphic}} {0} 關係:{1} 並未預期參數 'model'",
"2c4904377a87fdab502118719cc0d266": "不支援 {{Transaction}}",
"2c5c8519721f749aab13c2f04f41d611": "{0} 內容具有無效的子句 {1}:預期為正好 2 個值,但接收到 {2} 個",
"2f4af31c144bbfab1bbf479866acd820": "\n警告{{LoopBack}} 連接器 \"{0}\" 未安裝為下列任一模組:\n\n {1}\n\n若要修正請執行\n\n {{npm install {2} --save}}\n",
"3864f9be10f27723074566d2b3893514": "警告:模型 {0} {{strict mode: `throw`}} 已被移除,請改為使用 {{`strict: true`}},其會對不明內容傳回 {{`Validation Error`}}",
"38dbf42c29a4645238cc3d632e88ebc9": "{{Relation.modelTo}} 未定義給關係 {0},而且不是 {{polymorphic}}",
"3cde8cc9bca22c67278b202ab0720106": "對於 {1},找不到 id 為 {0} 的實例",
"416dfbb7b823f51c9f3800be81060b41": "對於 {1},找不到 {{id}} 為 {0} 的實例",
"49b5afd8c6a19ad9c8abeffb2f8114eb": "BelongsTo 方法 \"getAsync()\" 已淘汰,請改用 \"get()\"。",
"4c78325cedbb826db3a05bf5df0e8546": "取代時必須提供 {{id}}",
"4e31b1edd10dadb724d83387de0b5062": "{{limit}} 參數 {0} 無效",
"514985b2327f061ffb1c932f6b909979": "模型 {0} 未定義。",
"525c856e65daab43be247e7b5410febd": "{{polymorphic}} {0} 關係:定義自訂 'foreignKey'/'discriminator' 時 {1} 並未預期參數 'polymorphic.selector'",
"5c18ee111dd87540cdb19a2a93b33be9": "由於逾時,已回復交易",
"5ec7e6664256f7ea78f4f06dafc7d974": "交易尚未備妥,等候解析傳回的承諾",
"5ec8efeb715a2c34b440f2d76e2cf87d": " {0}",
"6111399276924ffa3bc9a410cdfcb2e5": "沒有 {{id}} 名稱 {0}",
"614e3355647e4127c96256102dc63376": "{0} 內容具有無效的子句 {1}:預期為字串或 RegExp",
"62a2d80c405b7fec5f547c448ab1b6ff": "{{order}} {0} 的方向無效",
"6502a117987610380b9068ef98b1b0ee": "在 {0} 中找不到 ({1}.{2}{3}.{4}) 的記錄",
"67c2bf43b5281ab929617423ea8a6f3e": "連接器 {0} 不支援 {{replaceById}} 作業。這不是 LoopBack 的錯誤。請聯絡連接器的作者,建議透過 GitHub 問題聯絡。",
"6c3234937d69763fc7f6bcafccc59bbc": "{{Model::deleteById}} 需要 {{id}} 引數",
"6eb6fd4fbd73394000bc25f5776fd20c": "{{Model::exists}} 需要 {{id}} 引數",
"6fcc2ff0db7a4f490f5e0ce9e24691f3": "{{HasOne}} 關係無法建立多個 {0} 實例",
"728232e473bf80272c042df2b7e002f4": "{{polymorphic}} {0} 關係:提供參數 'polymorphic.foreignKey' 時 {1} 需要參數 'polymorphic.discriminator'",
"791ab3031a73ede03f7d6299a85e8289": "連接 {0} 毫秒之後逾時",
"7b277018e43d41bc445731092b91547d": "未連接",
"7bbbdece4eea90e42aa5c0bce295e503": "{{Model::findById}} 需要 {{id}} 引數",
"7e9530c0399289be0ee601a604be71ff": "{{BelongsTo}} 關係 {0} 是空的",
"7faa840eb6ce11250a141deb42a6c489": "不明關係 {{scope}}{0}",
"8091838319a5cc7d6a34af2f2a616ce9": "在模型中,內容名稱不應該為 \"{{constructor}}\"{0}",
"881e4b0cb86ed59549248ee540a9fd10": "{0} 資料中不接受內容名稱 \"{{constructor}}\"",
"89afd3a9249f5a8d3edda07d84ca049d": "找不到 {{Polymorphic}} 模型:`{0}`",
"89bf6d92731fe7bd2146ce8d0bec205c": "引數無效,必須是字串、{{regex}} 文字或 {{RegExp}} 物件",
"8a39126103a157f501affa070367a1b0": "{0} 實例無效。詳細資料:{1}。",
"8c5ab01638c1ac1d58168c6346a8481a": "無效 {{regex}} 旗標:{0}",
"938401ea4ce48159efa9be1d4a5e8bab": "項目必須是陣列:{0}",
"9e1f143ee02946324d34da92f71bf74e": "{0} 關係:{1} 需要參數 'model'",
"a004f310d315e592843776fab964eaeb": "{{Polymorphic}} 關係需要有通過模型",
"a0cf0e09c26df14283223e84e6a10f00": "無法更新屬性。{{id}} 為 {0} 的 {{Object}} 不存在!",
"a2487abefef4259c2131d96cdb8543b1": "連線失敗:{0}\n將在下一次要求時重試。",
"a25e41a39c60c4702e55d0c3936576a1": "金鑰不符:{0}.{1}{2}{3}.{4}{5}",
"a327355560d495454fba2c1aad6bdf09": "不明範圍方法:{0}",
"a6c18a7f4390cd3d59a2a7a047ae2aab": "執行 \"{{npm install loopback-datasource-juggler}} {0}\" 指令",
"a829dee089c912e68c18920ba015400c": "警告:在 {{'loaded'}} 作業連結鉤中,無法將 model:{2} 的 {{id}} 內容從 {0} 變更為 {1}",
"a984a076c59e451948b2bcf7a393d860": "警告:在 {{'before save'}} 作業連結鉤中,無法將 model:{2} 的 {{id}} 內容從 {0} 變更為 {1}",
"ac04cf275b71c1eb89a41cf6bbad7a64": "HasOne 方法 \"getAsync()\" 已淘汰,請改用 \"get()\"。",
"b138294f132edfe1eb2a8211150c7238": "查詢中有非預期的 `undefined`",
"b15b20280211ad258d92947f05b6e4a5": "尚未起始設定連接器。",
"b278876ec93ef9760f00e83f38ba313d": "Scope 方法 \"getAsync()\" 已淘汰,請改用 \"find()\"。",
"ba0fd8106eb54de4d003a844206431fd": "模型連結鉤 \"{0}\" 已淘汰,請改用作業連結鉤。{{http://docs.strongloop.com/display/LB/Operation+hooks}}",
"baf2c8b0c5a574b8a894e9b6304fece1": "where 子句 {0} 不是 {{object}}",
"bdb11cc1c780c9ccac33c316cfdc9d82": "未針對內容 {0}.{1} 定義類型",
"bdfb951c8ff7ce0cbc08c06f548fd927": "值是空的 {{object}}",
"bec226891a505828bfc76c5cfd73b336": "無法取得不明金鑰 {0} 的 TTL",
"cd930369e86cdd222f7bd117c6f9fa94": "預設值提供者 {0} 不明",
"cfee4d8149316d9a647c0885cf3cafaf": "不支援含有點的內容名稱。模型:{0},動態內容:{1}",
"d40328eabd8756d795bcdd49d782d4e9": "資料來源不支援交易",
"da02dd6c53d4148320eeb31718a7aebe": "內容 {0} 的類型無效",
"da751a8a748adbde5b55fa83b707b4e2": "不支援含有點的內容名稱。模型:{0},內容:{1}",
"db03083e9a768388fdbee865249ac67a": "忽略 {{updateOrCreate()}} 中的驗證錯誤:",
"dd63416d9b7d9fa4181e89efd619dfd8": "值不是具有循序數值索引的 {{array}} 或 {{object}}",
"ddf0aa14803f1c84f4a97f3803f7471c": "需要類別名稱",
"e08ab0e1ab55f26c357061447b635905": "在 {0} 中找不到 ({1}.{2}{3}.{4}) 的關係",
"e0e9504e137a3c3339144b51ed76fef2": "未正確定義連接器:應該建立資料來源的 `{{connector}}` 成員",
"e2f282cbe3efba001d6d3a09f7f6ca8c": "{{polymorphic}} {0} 關係:提供參數 'polymorphic.discriminator' 時 {1} 需要參數 'polymorphic.foreignKey'",
"e39e0f5d52bfbf511e645d19ecadd2fa": "{0} 內容具有無效的子句 {1}{2}",
"e4434de4bb8f5a3cd1d416e4d80d7e0b": "\"{0}\" {{id}} \"{1}\" 不明。",
"e54d944c2a2c85a23caa86027ae307cf": "無法移轉未連接至這個資料來源的模型:{0}",
"e54f118a75e15e132f16b985274eb46d": "查詢過濾器 {0} 不是 {{object}}",
"e55937649d8d7a11706b8cec22d02eae": "{{HasOne}} 關係 {0} 是空的",
"e6161ae8459c79d810e2aa9d21282a39": "更新屬性時必須提供 {{id}}",
"eb56c2b0c30cf006e2df00a549ec9c2c": "未定義 {1} 模型的關係 \"{0}\"",
"ec42dca074f1818c447f7ad16e2d01af": "連接的連接器未提供 {0}",
"ecb7aa804bf54c682999d20d6436104c": "{{transaction}} 為非作用中:{0}",
"f30809cb932b72a66416a709c8531530": "連接器在交易內不支援 {{method}}",
"f41bd91dc0f000a79c0bf842f1b7fdf9": "無法從 JSON 字串建立 List{0}",
"f6e8c96c93b9c7687d6c172b3695e898": "無法將 {{id}} 內容 ({0}) 從 {1} 更新為 {2}",
"fa9ae17e8e008d0eb0f0421a2972308c": "{{polymorphic}} {0} 關係:{1} 需要參數 'model'",
"fca4d12faff1035d9d0438d73432571b": "{0}.{1} 的重複項目",
"fd3cc89dc67e2d604eaae21bdf41d403": "找不到模型 {1} 的關係 {0}",
"fec8ebda24db46a9d040bf863765cc44": "{0} 運算子具有無效的子句 {1}{2}"
}

View File

@ -1,6 +1,13 @@
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
// A lightweight alternative to "depd" that works in the browser
module.exports = function depd(namespace) {
var warned = {};
const warned = {};
return function deprecate(message) {
if (warned[message]) return;
warned[message] = true;

242
lib/connectors/kv-memory.js Normal file
View File

@ -0,0 +1,242 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const g = require('strong-globalize')();
const assert = require('assert');
const Connector = require('loopback-connector').Connector;
const debug = require('debug')('loopback:connector:kv-memory');
const minimatch = require('minimatch');
const util = require('util');
exports.initialize = function initializeDataSource(dataSource, cb) {
const settings = dataSource.settings;
dataSource.connector = new KeyValueMemoryConnector(settings, dataSource);
if (cb) process.nextTick(cb);
};
function KeyValueMemoryConnector(settings, dataSource) {
Connector.call(this, 'kv-memory', settings);
debug('Connector settings', settings);
this.dataSource = dataSource;
this.DataAccessObject = dataSource.juggler.KeyValueAccessObject;
this._store = Object.create(null);
this._setupRegularCleanup();
}
util.inherits(KeyValueMemoryConnector, Connector);
KeyValueMemoryConnector.prototype._setupRegularCleanup = function() {
// Scan the database for expired keys at a regular interval
// in order to release memory. Note that GET operation checks
// key expiration too, the scheduled cleanup is merely a performance
// optimization.
this._cleanupTimer = setInterval(
() => {
if (this && this._removeExpiredItems) {
this._removeExpiredItems();
} else {
// The datasource/connector was destroyed - cancel the timer
clearInterval(this._cleanupTimer);
}
},
1000,
);
this._cleanupTimer.unref();
};
KeyValueMemoryConnector._removeExpiredItems = function() {
debug('Running scheduled cleanup of expired items.');
for (const modelName in this._store) {
const modelStore = this._store[modelName];
for (const key in modelStore) {
if (modelStore[key].isExpired()) {
debug('Removing expired key', key);
delete modelStore[key];
}
}
}
};
KeyValueMemoryConnector.prototype._getStoreForModel = function(modelName) {
if (!(modelName in this._store)) {
this._store[modelName] = Object.create(null);
}
return this._store[modelName];
};
KeyValueMemoryConnector.prototype._removeIfExpired = function(modelName, key) {
const store = this._getStoreForModel(modelName);
let item = store[key];
if (item && item.isExpired()) {
debug('Removing expired key', key);
delete store[key];
item = undefined;
return true;
}
return false;
};
KeyValueMemoryConnector.prototype.get =
function(modelName, key, options, callback) {
this._removeIfExpired(modelName, key);
const store = this._getStoreForModel(modelName);
const item = store[key];
let value = item ? item.value : null;
debug('GET %j %j -> %s', modelName, key, value);
if (/^buffer:/.test(value)) {
value = new Buffer(value.slice(7), 'base64');
} else if (/^date:/.test(value)) {
value = new Date(value.slice(5));
} else if (value != null) {
value = JSON.parse(value);
}
process.nextTick(function() {
callback(null, value);
});
};
KeyValueMemoryConnector.prototype.set =
function(modelName, key, value, options, callback) {
const store = this._getStoreForModel(modelName);
if (Buffer.isBuffer(value)) {
value = 'buffer:' + value.toString('base64');
} else if (value instanceof Date) {
value = 'date:' + value.toISOString();
} else {
value = JSON.stringify(value);
}
debug('SET %j %j %s %j', modelName, key, value, options);
store[key] = new StoreItem(value, options && options.ttl);
process.nextTick(callback);
};
KeyValueMemoryConnector.prototype.expire =
function(modelName, key, ttl, options, callback) {
this._removeIfExpired(modelName, key);
const store = this._getStoreForModel(modelName);
if (!(key in store)) {
return process.nextTick(function() {
const err = new Error(g.f('Cannot expire unknown key %j', key));
err.statusCode = 404;
callback(err);
});
}
debug('EXPIRE %j %j %s', modelName, key, ttl || '(never)');
store[key].setTtl(ttl);
process.nextTick(callback);
};
KeyValueMemoryConnector.prototype.ttl =
function(modelName, key, options, callback) {
this._removeIfExpired(modelName, key);
const store = this._getStoreForModel(modelName);
// key is unknown
if (!(key in store)) {
return process.nextTick(function() {
const err = new Error(g.f('Cannot get TTL for unknown key %j', key));
err.statusCode = 404;
callback(err);
});
}
const ttl = store[key].getTtl();
debug('TTL %j %j -> %s', modelName, key, ttl);
process.nextTick(function() {
callback(null, ttl);
});
};
KeyValueMemoryConnector.prototype.iterateKeys =
function(modelName, filter, options, callback) {
const store = this._getStoreForModel(modelName);
const self = this;
const checkFilter = createMatcher(filter.match);
const keys = Object.keys(store).filter(function(key) {
return !self._removeIfExpired(modelName, key) && checkFilter(key);
});
debug('ITERATE KEYS %j -> %s keys', modelName, keys.length);
let ix = 0;
return {
next: function(cb) {
const value = ix < keys.length ? keys[ix++] : undefined;
setImmediate(function() { cb(null, value); });
},
};
};
function createMatcher(pattern) {
if (!pattern) return function matchAll() { return true; };
return minimatch.filter(pattern, {
nobrace: true,
noglobstar: true,
dot: true,
noext: true,
nocomment: true,
});
}
KeyValueMemoryConnector.prototype.disconnect = function(callback) {
if (this._cleanupTimer)
clearInterval(this._cleanupTimer);
this._cleanupTimer = null;
process.nextTick(callback);
};
KeyValueMemoryConnector.prototype.delete =
function(modelName, key, options, callback) {
const store = this._getStoreForModel(modelName);
delete store[key];
callback();
};
KeyValueMemoryConnector.prototype.deleteAll =
function(modelName, options, callback) {
const modelStore = this._getStoreForModel(modelName);
for (const key in modelStore)
delete modelStore[key];
callback();
};
function StoreItem(value, ttl) {
this.value = value;
this.setTtl(ttl);
}
StoreItem.prototype.isExpired = function() {
return this.expires && this.expires <= Date.now();
};
StoreItem.prototype.setTtl = function(ttl) {
if (ttl) {
this.expires = Date.now() + ttl;
} else {
this.expires = undefined;
}
};
StoreItem.prototype.getTtl = function() {
return !this.expires ? undefined : this.expires - Date.now();
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,15 @@
var util = require('util');
var Connector = require('loopback-connector').Connector;
var utils = require('../utils');
var crypto = require('crypto');
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const g = require('strong-globalize')();
const util = require('util');
const Connector = require('loopback-connector').Connector;
const utils = require('../utils');
const crypto = require('crypto');
/**
* Initialize the Transient connector against the given data source
@ -42,7 +50,7 @@ Transient.prototype.getTypes = function() {
return ['db', 'nosql', 'transient'];
};
Transient.prototype.connect = function (callback) {
Transient.prototype.connect = function(callback) {
if (this.isTransaction) {
this.onTransactionExec = callback;
} else {
@ -51,40 +59,41 @@ Transient.prototype.connect = function (callback) {
};
Transient.prototype.generateId = function(model, data, idName) {
var idType;
var props = this._models[model].properties;
let idType;
const props = this._models[model].properties;
if (idName) idType = props[idName] && props[idName].type;
idType = idType || this.getDefaultIdType();
if (idType === Number) {
return Math.floor(Math.random() * 10000); // max. 4 digits
} else {
return crypto.randomBytes(Math.ceil(24/2))
.toString('hex') // convert to hexadecimal format
.slice(0, 24); // return required number of characters
return crypto.randomBytes(Math.ceil(24 / 2))
.toString('hex') // convert to hexadecimal format
.slice(0, 24); // return required number of characters
}
};
Transient.prototype.exists = function exists(model, id, callback) {
process.nextTick(function () { callback(null, false); }.bind(this));
process.nextTick(function() { callback(null, false); }.bind(this));
};
Transient.prototype.find = function find(model, id, callback) {
process.nextTick(function () { callback(null, null); }.bind(this));
process.nextTick(function() { callback(null, null); }.bind(this));
};
Transient.prototype.all = function all(model, filter, callback) {
process.nextTick(function () { callback(null, []); });
process.nextTick(function() { callback(null, []); });
};
Transient.prototype.count = function count(model, callback, where) {
process.nextTick(function () { callback(null, 0); });
process.nextTick(function() { callback(null, 0); });
};
Transient.prototype.create = function create(model, data, callback) {
var props = this._models[model].properties;
var idName = this.idName(model);
const props = this._models[model].properties;
const idName = this.idName(model);
let id = undefined;
if (idName && props[idName]) {
var id = this.getIdValue(model, data) || this.generateId(model, data, idName);
id = this.getIdValue(model, data) || this.generateId(model, data, idName);
id = (props[idName] && props[idName].type && props[idName].type(id)) || id;
this.setIdValue(model, data, id);
}
@ -97,13 +106,13 @@ Transient.prototype.save = function save(model, data, callback) {
Transient.prototype.update =
Transient.prototype.updateAll = function updateAll(model, where, data, cb) {
var count = 0;
const count = 0;
this.flush('update', {count: count}, cb);
};
};
Transient.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
if (!id) {
var err = new Error('You must provide an id when updating attributes!');
const err = new Error(g.f('You must provide an {{id}} when updating attributes!'));
if (cb) {
return cb(err);
} else {
@ -131,15 +140,15 @@ Transient.prototype.destroyAll = function destroyAll(model, where, callback) {
* Flush the cache - noop.
* @param {Function} callback
*/
Transient.prototype.flush = function (action, result, callback) {
process.nextTick(function () { callback && callback(null, result); });
Transient.prototype.flush = function(action, result, callback) {
process.nextTick(function() { callback && callback(null, result); });
};
Transient.prototype.transaction = function () {
Transient.prototype.transaction = function() {
return new Transient(this);
};
Transient.prototype.exec = function (callback) {
Transient.prototype.exec = function(callback) {
this.onTransactionExec();
setTimeout(callback, 50);
};

2571
lib/dao.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

110
lib/date-string.js Normal file
View File

@ -0,0 +1,110 @@
// Copyright IBM Corp. 2017,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const inspect = require('util').inspect;
module.exports = DateString;
/**
* A String whose value is a valid representation of a Date.
* Use this type if you need to preserve the format of the value and still
* check if it's valid.
* Example:
* ```js
* var loopback = require('loopback');
* var dt = new loopback.DateString('2001-01-01');
*
* dt.toString();
* // '2001-01-01'
* dt._date.toISOString();
* // '2001-01-01T00:00:00.000Z'
* ```
*
* You can use this definition on your models as well:
* ```json
* {
* "name": "Person",
* "base": "PersistedModel",
* "properties": {
* "name": {
* "type": "string"
* },
* "dob": {
* "type": "DateString",
* "required": true
* },
* },
* "validations": [],
* "relations": {},
* "acls": [],
* "methods": {}
* }
* ```
* @class DateString
* @param {String} value
* @constructor
*/
function DateString(value) {
if (!(this instanceof DateString)) {
return new DateString(value);
}
if (value instanceof DateString) {
value = value.when;
}
if (typeof(value) !== 'string') {
throw new Error('Input must be a string');
}
Object.defineProperty(this, 'when', {
get: () => { return this._when; },
set: (val) => {
const d = new Date(val);
if (isNaN(d.getTime())) {
throw new Error('Invalid date');
} else {
this._when = val;
this._date = d;
}
},
});
this.when = value;
}
/**
* Returns the value of DateString in its original form.
* @returns {String} The Date as a String.
*/
DateString.prototype.toString = function() {
return this.when;
};
/**
* Returns the JSON representation of the DateString object.
* @returns {String} A JSON string.
*/
DateString.prototype.toJSON = function() {
return JSON.stringify({
when: this.when,
});
};
DateString.prototype.inspect = function(depth, options) {
return 'DateString ' + inspect({
when: this.when,
_date: this._date,
});
};
if (inspect.custom) {
// Node.js 12+ no longer recognizes "inspect" method,
// it uses "inspect.custom" symbol as the key instead
// TODO(semver-major) always use the symbol key only (requires Node.js 8+).
DateString.prototype[inspect.custom] = DateString.prototype.inspect;
}

View File

@ -1,106 +1,146 @@
var assert = require('assert');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
/*!
* Get a near filter from a given where object. For connector use only.
*/
exports.nearFilter = function nearFilter(where) {
var result = false;
const nearResults = [];
nearSearch(where);
return (!nearResults.length ? false : nearResults);
if (where && typeof where === 'object') {
Object.keys(where).forEach(function (key) {
var ex = where[key];
function nearSearch(clause, parentKeys) {
if (typeof clause !== 'object') {
return false;
}
parentKeys = parentKeys || [];
if (ex && ex.near) {
result = {
near: ex.near,
maxDistance: ex.maxDistance,
unit: ex.unit,
key: key
};
Object.keys(clause).forEach(function(clauseKey) {
if (typeof clause[clauseKey] !== 'object' || !clause[clauseKey]) return;
if (Array.isArray(clause[clauseKey])) {
clause[clauseKey].forEach(function(el, index) {
const ret = nearSearch(el, parentKeys.concat(clauseKey).concat(index));
if (ret) return ret;
});
} else {
if (clause[clauseKey].hasOwnProperty('near')) {
const result = clause[clauseKey];
nearResults.push({
near: result.near,
maxDistance: result.maxDistance,
minDistance: result.minDistance,
unit: result.unit,
// If key is at root, define a single string, otherwise append it to the full path array
mongoKey: parentKeys.length ? parentKeys.concat(clauseKey) : clauseKey,
key: clauseKey,
});
}
}
});
}
return result;
}
};
/*!
* Filter a set of objects using the given `nearFilter`.
* Filter a set of results using the given filters returned by `nearFilter()`.
* Can support multiple locations, but will include results from all of them.
*
* WARNING: "or" operator with GeoPoint does not work as expected, eg:
* {where: {or: [{location: {near: (29,-90)}},{name:'Sean'}]}}
* Will actually work as if you had used "and". This is because geo filtering
* takes place outside of the SQL query, so the result set of "name = Sean" is
* returned by the database, and then the location filtering happens in the app
* logic. So the "near" operator is always an "and" of the SQL filters, and "or"
* of other GeoPoint filters.
*
* Additionally, since this step occurs after the SQL result set is returned,
* if using GeoPoints with pagination the result set may be smaller than the
* page size. The page size is enforced at the DB level, and then we may
* remove results at the Geo-app level. If we "limit: 25", but 4 of those results
* do not have a matching geopoint field, the request will only return 21 results.
* This may make it erroneously look like a given page is the end of the result set.
*/
exports.filter = function (arr, filter) {
var origin = filter.near;
var max = filter.maxDistance > 0 ? filter.maxDistance : false;
var unit = filter.unit;
var key = filter.key;
exports.filter = function(rawResults, filters) {
const distances = {};
const results = [];
// create distance index
var distances = {};
var result = [];
filters.forEach(function(filter) {
const origin = filter.near;
const max = filter.maxDistance > 0 ? filter.maxDistance : false;
const min = filter.minDistance > 0 ? filter.minDistance : false;
const unit = filter.unit;
const key = filter.key;
arr.forEach(function (obj) {
var loc = obj[key];
// create distance index
rawResults.forEach(function(result) {
let loc = result[key];
// filter out objects without locations
if (!loc) return;
// filter out results without locations
if (!loc) return;
if (!(loc instanceof GeoPoint)) {
loc = GeoPoint(loc);
}
if (!(loc instanceof GeoPoint)) loc = GeoPoint(loc);
if (typeof loc.lat !== 'number') return;
if (typeof loc.lng !== 'number') return;
if (typeof loc.lat !== 'number') return;
if (typeof loc.lng !== 'number') return;
var d = GeoPoint.distanceBetween(origin, loc, {type: unit});
const d = GeoPoint.distanceBetween(origin, loc, {type: unit});
if (max && d > max) {
// dont add
} else {
distances[obj.id] = d;
result.push(obj);
}
// filter result if distance is either < minDistance or > maxDistance
if ((min && d < min) || (max && d > max)) return;
distances[result.id] = d;
results.push(result);
});
results.sort(function(resA, resB) {
const a = resA[key];
const b = resB[key];
if (a && b) {
const da = distances[resA.id];
const db = distances[resB.id];
if (db === da) return 0;
return da > db ? 1 : -1;
} else {
return 0;
}
});
});
return result.sort(function (objA, objB) {
var a = objA[key];
var b = objB[key];
if (a && b) {
var da = distances[objA.id];
var db = distances[objB.id];
if (db === da) return 0;
return da > db ? 1 : -1;
} else {
return 0;
}
});
}
return results;
};
exports.GeoPoint = GeoPoint;
/**
/**
* The GeoPoint object represents a physical location.
*
*
* For example:
*
*
* ```js
* var loopback = require(loopback);
* var here = new loopback.GeoPoint({lat: 10.32424, lng: 5.84978});
* ```
*
*
* Embed a latitude / longitude point in a model.
*
*
* ```js
* var CoffeeShop = loopback.createModel('coffee-shop', {
* location: 'GeoPoint'
* });
* ```
*
*
* You can query LoopBack models with a GeoPoint property and an attached data source using geo-spatial filters and
* sorting. For example, the following code finds the three nearest coffee shops.
*
*
* ```js
* CoffeeShop.attachTo(oracle);
* var here = new GeoPoint({lat: 10.32424, lng: 5.84978});
@ -109,9 +149,9 @@ exports.GeoPoint = GeoPoint;
* });
* ```
* @class GeoPoint
* @property {Number} lat The latitude in degrees.
* @property {Number} lng The longitude in degrees.
*
* @property {Number} lat The latitude in degrees.
* @property {Number} lng The longitude in degrees.
*
* @options {Object} Options Object with two Number properties: lat and long.
* @property {Number} lat The latitude point in degrees. Range: -90 to 90.
* @property {Number} lng The longitude point in degrees. Range: -180 to 180.
@ -126,23 +166,28 @@ function GeoPoint(data) {
return new GeoPoint(data);
}
if(arguments.length === 2) {
if (arguments.length === 2) {
data = {
lat: arguments[0],
lng: arguments[1]
lng: arguments[1],
};
}
assert(Array.isArray(data) || typeof data === 'object' || typeof data === 'string', 'must provide valid geo-coordinates array [lat, lng] or object or a "lat, lng" string');
assert(Array.isArray(data) || typeof data === 'object' || typeof data === 'string',
'must provide valid geo-coordinates array [lat, lng] or object or a "lat, lng" string');
if (typeof data === 'string') {
data = data.split(/,\s*/);
assert(data.length === 2, 'must provide a string "lat,lng" creating a GeoPoint with a string');
try {
data = JSON.parse(data);
} catch (err) {
data = data.split(/,\s*/);
assert(data.length === 2, 'must provide a string "lat,lng" creating a GeoPoint with a string');
}
}
if (Array.isArray(data)) {
data = {
lat: Number(data[0]),
lng: Number(data[1])
lng: Number(data[1]),
};
} else {
data.lng = Number(data.lng);
@ -157,18 +202,18 @@ function GeoPoint(data) {
assert(data.lat <= 90, 'lat must be <= 90');
assert(data.lat >= -90, 'lat must be >= -90');
this.lat = data.lat;
this.lat = data.lat;
this.lng = data.lng;
}
/**
* Determine the spherical distance between two GeoPoints.
*
*
* @param {GeoPoint} pointA Point A
* @param {GeoPoint} pointB Point B
* @options {Object} options Options object with one key, 'type'. See below.
* @property {String} type Unit of measurement, one of:
*
*
* - `miles` (default)
* - `radians`
* - `kilometers`
@ -186,11 +231,11 @@ GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
b = GeoPoint(b);
}
var x1 = a.lat;
var y1 = a.lng;
const x1 = a.lat;
const y1 = a.lng;
var x2 = b.lat;
var y2 = b.lng;
const x2 = b.lat;
const y2 = b.lng;
return geoDistance(x1, y1, x2, y2, options);
};
@ -200,16 +245,16 @@ GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
* Example:
* ```js
* var loopback = require(loopback);
*
*
* var here = new loopback.GeoPoint({lat: 10, lng: 10});
* var there = new loopback.GeoPoint({lat: 5, lng: 5});
*
*
* loopback.GeoPoint.distanceBetween(here, there, {type: 'miles'}) // 438
* ```
* @param {Object} point GeoPoint object to which to measure distance.
* @options {Object} options Options object with one key, 'type'. See below.
* @property {String} type Unit of measurement, one of:
*
*
* - `miles` (default)
* - `radians`
* - `kilometers`
@ -219,7 +264,7 @@ GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
* - `degrees`
*/
GeoPoint.prototype.distanceTo = function (point, options) {
GeoPoint.prototype.distanceTo = function(point, options) {
return GeoPoint.distanceBetween(this, point, options);
};
@ -227,7 +272,7 @@ GeoPoint.prototype.distanceTo = function (point, options) {
* Simple serialization.
*/
GeoPoint.prototype.toString = function () {
GeoPoint.prototype.toString = function() {
return this.lat + ',' + this.lng;
};
@ -238,24 +283,23 @@ GeoPoint.prototype.toString = function () {
*/
// factor to convert degrees to radians
var DEG2RAD = 0.01745329252;
const DEG2RAD = 0.01745329252;
// factor to convert radians degrees to degrees
var RAD2DEG = 57.29577951308;
const RAD2DEG = 57.29577951308;
// radius of the earth
var EARTH_RADIUS = {
const EARTH_RADIUS = {
kilometers: 6370.99056,
meters: 6370990.56,
miles: 3958.75,
feet: 20902200,
radians: 1,
degrees: RAD2DEG
degrees: RAD2DEG,
};
function geoDistance(x1, y1, x2, y2, options) {
var type = (options && options.type) || 'miles';
const type = (options && options.type) || 'miles';
// Convert to radians
x1 = x1 * DEG2RAD;
@ -263,14 +307,13 @@ function geoDistance(x1, y1, x2, y2, options) {
x2 = x2 * DEG2RAD;
y2 = y2 * DEG2RAD;
// use the haversine formula to calculate distance for any 2 points on a sphere.
// use the haversine formula to calculate distance for any 2 points on a sphere.
// ref http://en.wikipedia.org/wiki/Haversine_formula
var haversine = function(a) {
const haversine = function(a) {
return Math.pow(Math.sin(a / 2.0), 2);
};
var f = Math.sqrt(haversine(x2 - x1) + Math.cos(x2) * Math.cos(x1) * haversine(y2 - y1));
const f = Math.sqrt(haversine(x2 - x1) + Math.cos(x2) * Math.cos(x1) * haversine(y2 - y1));
return 2 * Math.asin(f) * EARTH_RADIUS[type];
}

View File

@ -1,4 +1,12 @@
var deprecated = require('depd')('loopback-datasource-juggler');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const deprecated = require('depd')('loopback-datasource-juggler');
const g = require('strong-globalize')();
/*!
* Module exports
@ -28,18 +36,28 @@ Hookable.afterUpdate = null;
Hookable.beforeDestroy = null;
Hookable.afterDestroy = null;
// TODO: Evaluate https://github.com/bnoguchi/hooks-js/
/**
* @deprecated
* Setup a Model-based hook to trigger when the specified action occurs.
* The trigger is broken up into three segments: `beforeHook`, `work` and
* `afterHook`.
* @param {string} actionName The name of the action that triggers the hook.
* @param {Function} work The 2nd phase of the trigger.
* @param {*} data The value(s) to provide to the 1st phase (`beforeHook`) call.
* @callback
* @param {Function} callback
*/
Hookable.prototype.trigger = function trigger(actionName, work, data, callback) {
var capitalizedName = capitalize(actionName);
var beforeHook = this.constructor["before" + capitalizedName]
|| this.constructor["pre" + capitalizedName];
var afterHook = this.constructor["after" + capitalizedName]
|| this.constructor["post" + capitalizedName];
const capitalizedName = capitalize(actionName);
let beforeHook = this.constructor['before' + capitalizedName] ||
this.constructor['pre' + capitalizedName];
let afterHook = this.constructor['after' + capitalizedName] ||
this.constructor['post' + capitalizedName];
if (actionName === 'validate') {
beforeHook = beforeHook || this.constructor.beforeValidation;
afterHook = afterHook || this.constructor.afterValidation;
}
var inst = this;
const inst = this;
if (actionName !== 'initialize') {
if (beforeHook)
@ -52,7 +70,7 @@ Hookable.prototype.trigger = function trigger(actionName, work, data, callback)
if (work) {
if (beforeHook) {
// before hook should be called on instance with two parameters: next and data
beforeHook.call(inst, function () {
beforeHook.call(inst, function() {
// Check arguments to next(err, result)
if (arguments.length) {
return callback && callback.apply(null, arguments);
@ -82,14 +100,14 @@ function capitalize(string) {
}
function deprecateHook(ctor, prefixes, capitalizedName) {
var candidateNames = prefixes.map(function(p) { return p + capitalizedName; });
const candidateNames = prefixes.map(function(p) { return p + capitalizedName; });
if (capitalizedName === 'Validate')
candidateNames.push(prefixes[0] + 'Validation');
var hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0];
let hookName = candidateNames.filter(function(hook) { return !!ctor[hook]; })[0];
if (!hookName) return; // just to be sure, this should never happen
if (ctor.modelName) hookName = ctor.modelName + '.' + hookName;
deprecated('Model hook "' + hookName + '" is deprecated, ' +
if (ctor.modelName) hookName = ctor.modelName + '.' + hookName;
deprecated(g.f('Model hook "%s" is deprecated, ' +
'use Operation hooks instead. ' +
'http://docs.strongloop.com/display/LB/Operation+hooks');
'{{http://docs.strongloop.com/display/LB/Operation+hooks}}', hookName));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,31 @@
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const g = require('strong-globalize')();
module.exports.buildOneToOneIdentityMapWithOrigKeys = buildOneToOneIdentityMapWithOrigKeys;
module.exports.buildOneToManyIdentityMapWithOrigKeys = buildOneToManyIdentityMapWithOrigKeys;
module.exports.join = join;
module.exports.KVMap = KVMap;
const util = require('util');
function getId(obj, idName) {
const id = obj && obj[idName];
if (id == null) {
const msg = g.f('ID property "%s" is missing for included item: %j. ' +
'Please make sure `fields` include "%s" if it\'s present in the `filter`',
idName, obj, idName);
const err = new Error(msg);
err.statusCode = 400;
throw err;
}
return id;
}
/**
* Effectively builds associative map on id -> object relation and stores original keys.
* Map returned in form of object with ids in keys and object as values.
@ -12,28 +35,27 @@ module.exports.KVMap = KVMap;
* @returns {} object where keys are ids and values are objects itself
*/
function buildOneToOneIdentityMapWithOrigKeys(objs, idName) {
var kvMap = new KVMap();
for(var i = 0; i < objs.length; i++) {
var obj = objs[i];
var id = obj[idName];
const kvMap = new KVMap();
for (let i = 0; i < objs.length; i++) {
const obj = objs[i];
const id = getId(obj, idName);
kvMap.set(id, obj);
}
return kvMap;
}
function buildOneToManyIdentityMapWithOrigKeys(objs, idName) {
var kvMap = new KVMap();
for(var i = 0; i < objs.length; i++) {
var obj = objs[i];
var id = obj[idName];
var value = kvMap.get(id) || [];
const kvMap = new KVMap();
for (let i = 0; i < objs.length; i++) {
const obj = objs[i];
const id = getId(obj, idName);
const value = kvMap.get(id) || [];
value.push(obj);
kvMap.set(id, value);
}
return kvMap;
}
/**
* Yeah, it joins. You need three things id -> obj1 map, id -> [obj2] map and merge function.
* This functions will take each obj1, locate all data to join in map2 and call merge function.
@ -42,57 +64,56 @@ function buildOneToManyIdentityMapWithOrigKeys(objs, idName) {
* @param mergeF function(obj, objectsToMergeIn)
*/
function join(oneToOneIdMap, oneToManyIdMap, mergeF) {
var ids = oneToOneIdMap.getKeys();
for(var i = 0; i < ids.length; i++) {
var id = ids[i];
var obj = oneToOneIdMap.get(id);
var objectsToMergeIn = oneToManyIdMap.get(id) || [];
const ids = oneToOneIdMap.getKeys();
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
const obj = oneToOneIdMap.get(id);
const objectsToMergeIn = oneToManyIdMap.get(id) || [];
mergeF(obj, objectsToMergeIn);
}
}
/**
* Map with arbitrary keys and values. User .set() and .get() to work with values instead of []
* @returns {{set: Function, get: Function, remove: Function, exist: Function, getKeys: Function}}
* @constructor
*/
function KVMap(){
var _originalKeyFieldName = 'originalKey';
var _valueKeyFieldName = 'value';
var _dict = {};
var keyToString = function(key){ return key.toString() };
var mapImpl = {
set: function(key, value){
var recordObj = {};
function KVMap() {
const _originalKeyFieldName = 'originalKey';
const _valueKeyFieldName = 'value';
const _dict = {};
const keyToString = function(key) { return key.toString(); };
const mapImpl = {
set: function(key, value) {
const recordObj = {};
recordObj[_originalKeyFieldName] = key;
recordObj[_valueKeyFieldName] = value;
_dict[keyToString(key)] = recordObj;
return true;
},
get: function(key){
var storeObj = _dict[keyToString(key)];
if(storeObj) {
get: function(key) {
const storeObj = _dict[keyToString(key)];
if (storeObj) {
return storeObj[_valueKeyFieldName];
} else {
return undefined;
}
},
remove: function(key){
remove: function(key) {
delete _dict[keyToString(key)];
return true;
},
exist: function(key) {
var result = _dict.hasOwnProperty(keyToString(key));
const result = _dict.hasOwnProperty(keyToString(key));
return result;
},
getKeys: function(){
var result = [];
for(var key in _dict) {
getKeys: function() {
const result = [];
for (const key in _dict) {
result.push(_dict[key][_originalKeyFieldName]);
}
return result;
}
},
};
return mapImpl;

View File

@ -1,21 +1,26 @@
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
module.exports = function getIntrospector(ModelBuilder) {
function introspectType(value) {
// Unknown type, using Any
if (value === null || value === undefined) {
return ModelBuilder.Any;
}
// Check registered schemaTypes
for (var t in ModelBuilder.schemaTypes) {
var st = ModelBuilder.schemaTypes[t];
for (const t in ModelBuilder.schemaTypes) {
const st = ModelBuilder.schemaTypes[t];
if (st !== Object && st !== Array && (value instanceof st)) {
return t;
}
}
var type = typeof value;
const type = typeof value;
if (type === 'string' || type === 'number' || type === 'boolean') {
return type;
}
@ -24,9 +29,9 @@ module.exports = function getIntrospector(ModelBuilder) {
return 'date';
}
var itemType;
let itemType;
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
for (let i = 0; i < value.length; i++) {
if (value[i] === null || value[i] === undefined) {
continue;
}
@ -42,8 +47,8 @@ module.exports = function getIntrospector(ModelBuilder) {
return value.constructor.name;
}
var properties = {};
for (var p in value) {
const properties = {};
for (const p in value) {
itemType = introspectType(value[p]);
if (itemType) {
properties[p] = itemType;
@ -57,6 +62,4 @@ module.exports = function getIntrospector(ModelBuilder) {
ModelBuilder.introspect = introspectType;
return introspectType;
}
};

View File

@ -1,23 +1,30 @@
var util = require('util');
// Copyright IBM Corp. 2011,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const util = require('util');
/**
*
* @param newClass
* @param baseClass
*/
exports.inherits = function (newClass, baseClass, options) {
exports.inherits = function(newClass, baseClass, options) {
util.inherits(newClass, baseClass);
options = options || {
staticProperties: true,
override: false
override: false,
};
if (options.staticProperties) {
Object.keys(baseClass).forEach(function (classProp) {
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp)
|| options.override)) {
var pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
Object.keys(baseClass).forEach(function(classProp) {
if (classProp !== 'super_' && (!newClass.hasOwnProperty(classProp) ||
options.override)) {
const pd = Object.getOwnPropertyDescriptor(baseClass, classProp);
Object.defineProperty(newClass, classProp, pd);
}
});
@ -30,7 +37,7 @@ exports.inherits = function (newClass, baseClass, options) {
* @param mixinClass The class to be mixed in
* @param options
*/
exports.mixin = function (newClass, mixinClass, options) {
exports.mixin = function(newClass, mixinClass, options) {
if (Array.isArray(newClass._mixins)) {
if (newClass._mixins.indexOf(mixinClass) !== -1) {
return;
@ -44,7 +51,7 @@ exports.mixin = function (newClass, mixinClass, options) {
staticProperties: true,
instanceProperties: true,
override: false,
proxyFunctions: false
proxyFunctions: false,
};
if (options.staticProperties === undefined) {
@ -67,14 +74,14 @@ exports.mixin = function (newClass, mixinClass, options) {
};
function mixInto(sourceScope, targetScope, options) {
Object.keys(sourceScope).forEach(function (propertyName) {
var targetPropertyExists = targetScope.hasOwnProperty(propertyName);
var sourceProperty = Object.getOwnPropertyDescriptor(sourceScope, propertyName);
var targetProperty = targetPropertyExists && Object.getOwnPropertyDescriptor(targetScope, propertyName);
var sourceIsFunc = typeof sourceProperty.value === 'function';
var isFunc = targetPropertyExists && typeof targetProperty.value === 'function';
var isDelegate = isFunc && targetProperty.value._delegate;
var shouldOverride = options.override || !targetPropertyExists || isDelegate;
Object.keys(sourceScope).forEach(function(propertyName) {
const targetPropertyExists = targetScope.hasOwnProperty(propertyName);
const sourceProperty = Object.getOwnPropertyDescriptor(sourceScope, propertyName);
const targetProperty = targetPropertyExists && Object.getOwnPropertyDescriptor(targetScope, propertyName);
const sourceIsFunc = typeof sourceProperty.value === 'function';
const isFunc = targetPropertyExists && typeof targetProperty.value === 'function';
const isDelegate = isFunc && targetProperty.value._delegate;
const shouldOverride = options.override || !targetPropertyExists || isDelegate;
if (propertyName == '_mixins') {
mergeMixins(sourceScope._mixins, targetScope._mixins);
@ -89,8 +96,8 @@ function mixInto(sourceScope, targetScope, options) {
function mergeMixins(source, target) {
// hand-written equivalent of lodash.union()
for (var ix in source) {
var mx = source[ix];
for (const ix in source) {
const mx = source[ix];
if (target.indexOf(mx) === -1)
target.push(mx);
}

68
lib/kvao/delete-all.js Normal file
View File

@ -0,0 +1,68 @@
// Copyright IBM Corp. 2017,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const async = require('async');
const debug = require('debug')('loopback:kvao:delete-all');
const utils = require('../utils');
/**
* Delete all keys (and values) associated to the current model.
*
* @options {Object} options Unused ATM, placeholder for future options.
* @callback {Function} callback
* @param {Error} err Error object.
* @promise
*
* @header KVAO.prototype.deleteAll([options, ]cb)
*/
module.exports = function deleteAll(options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (!options) {
options = {};
}
assert(typeof options === 'object', 'options must be an object');
callback = callback || utils.createPromiseCallback();
const connector = this.getConnector();
if (typeof connector.deleteAll === 'function') {
connector.deleteAll(this.modelName, options, callback);
} else if (typeof connector.delete === 'function') {
debug('Falling back to unoptimized key-value pair deletion');
iterateAndDelete(connector, this.modelName, options, callback);
} else {
const errMsg = 'Connector does not support key-value pair deletion';
debug(errMsg);
process.nextTick(function() {
const err = new Error(errMsg);
err.statusCode = 501;
callback(err);
});
}
return callback.promise;
};
function iterateAndDelete(connector, modelName, options, callback) {
const iter = connector.iterateKeys(modelName, {});
const keys = [];
iter.next(onNextKey);
function onNextKey(err, key) {
if (err) return callback(err);
if (key === undefined) return callback();
connector.delete(modelName, key, options, onDeleted);
}
function onDeleted(err) {
if (err) return callback(err);
iter.next(onNextKey);
}
}

50
lib/kvao/delete.js Normal file
View File

@ -0,0 +1,50 @@
// Copyright IBM Corp. 2017,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const debug = require('debug')('loopback:kvao:delete');
const utils = require('../utils');
/**
* Delete the key-value pair associated to the given key.
*
* @param {String} key Key to use when searching the database.
* @options {Object} options
* @callback {Function} callback
* @param {Error} err Error object.
* @param {*} result Value associated with the given key.
* @promise
*
* @header KVAO.prototype.delete(key[, options], cb)
*/
module.exports = function keyValueDelete(key, options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (!options) {
options = {};
}
assert(typeof key === 'string' && key, 'key must be a non-empty string');
callback = callback || utils.createPromiseCallback();
const connector = this.getConnector();
if (typeof connector.delete === 'function') {
connector.delete(this.modelName, key, options, callback);
} else {
const errMsg = 'Connector does not support key-value pair deletion';
debug(errMsg);
process.nextTick(function() {
const err = new Error(errMsg);
err.statusCode = 501;
callback(err);
});
}
return callback.promise;
};

39
lib/kvao/expire.js Normal file
View File

@ -0,0 +1,39 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Set the TTL (time to live) in ms (milliseconds) for a given key. TTL is the
* remaining time before a key-value pair is discarded from the database.
*
* @param {String} key Key to use when searching the database.
* @param {Number} ttl TTL in ms to set for the key.
* @options {Object} options
* @callback {Function} callback
* @param {Error} err Error object.
* @promise
*
* @header KVAO.expire(key, ttl, cb)
*/
module.exports = function keyValueExpire(key, ttl, options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (!options) {
options = {};
}
assert(typeof key === 'string' && key, 'key must be a non-empty string');
assert(typeof ttl === 'number' && ttl > 0, 'ttl must be a positive integer');
assert(typeof options === 'object', 'options must be an object');
callback = callback || utils.createPromiseCallback();
this.getConnector().expire(this.modelName, key, ttl, options, callback);
return callback.promise;
};

39
lib/kvao/get.js Normal file
View File

@ -0,0 +1,39 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Return the value associated with a given key.
*
* @param {String} key Key to use when searching the database.
* @options {Object} options
* @callback {Function} callback
* @param {Error} err Error object.
* @param {*} result Value associated with the given key.
* @promise
*
* @header KVAO.get(key, cb)
*/
module.exports = function keyValueGet(key, options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (!options) {
options = {};
}
assert(typeof key === 'string' && key, 'key must be a non-empty string');
callback = callback || utils.createPromiseCallback();
this.getConnector().get(this.modelName, key, options, function(err, result) {
// TODO convert raw result to Model instance (?)
callback(err, result);
});
return callback.promise;
};

25
lib/kvao/index.js Normal file
View File

@ -0,0 +1,25 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
function KeyValueAccessObject() {
}
module.exports = KeyValueAccessObject;
KeyValueAccessObject.delete = require('./delete');
KeyValueAccessObject.deleteAll = require('./delete-all');
KeyValueAccessObject.get = require('./get');
KeyValueAccessObject.set = require('./set');
KeyValueAccessObject.expire = require('./expire');
KeyValueAccessObject.ttl = require('./ttl');
KeyValueAccessObject.iterateKeys = require('./iterate-keys');
KeyValueAccessObject.keys = require('./keys');
KeyValueAccessObject.getConnector = function() {
return this.getDataSource().connector;
};

43
lib/kvao/iterate-keys.js Normal file
View File

@ -0,0 +1,43 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Asynchronously iterate all keys in the database. Similar to `.keys()` but
* instead allows for iteration over large data sets without having to load
* everything into memory at once.
*
* @param {Object} filter An optional filter object with the following
* @param {String} filter.match Glob string to use to filter returned
* keys (i.e. `userid.*`). All connectors are required to support `*` and
* `?`. They may also support additional special characters that are
* specific to the backing database.
* @param {Object} options
* @returns {AsyncIterator} An Object implementing `next(cb) -> Promise`
* function that can be used to iterate all keys.
*
* @header KVAO.iterateKeys(filter)
*/
module.exports = function keyValueIterateKeys(filter, options) {
filter = filter || {};
options = options || {};
assert(typeof filter === 'object', 'filter must be an object');
assert(typeof options === 'object', 'options must be an object');
const iter = this.getConnector().iterateKeys(this.modelName, filter, options);
// promisify the returned iterator
return {
next: function(callback) {
callback = callback || utils.createPromiseCallback();
iter.next(callback);
return callback.promise;
},
};
};

61
lib/kvao/keys.js Normal file
View File

@ -0,0 +1,61 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Return all keys in the database.
*
* **WARNING**: This method is not suitable for large data sets as all
* key-values pairs are loaded into memory at once. For large data sets,
* use `iterateKeys()` instead.
*
* @param {Object} filter An optional filter object with the following
* @param {String} filter.match Glob string used to filter returned
* keys (i.e. `userid.*`). All connectors are required to support `*` and
* `?`, but may also support additional special characters specific to the
* database.
* @param {Object} options
* @callback {Function} callback
* @promise
*
*
* @header KVAO.keys(filter, callback)
*/
module.exports = function keyValueKeys(filter, options, callback) {
if (callback === undefined) {
if (typeof options === 'function') {
callback = options;
options = undefined;
} else if (options === undefined && typeof filter === 'function') {
callback = filter;
filter = undefined;
}
}
filter = filter || {};
options = options || {};
assert(typeof filter === 'object', 'filter must be an object');
assert(typeof options === 'object', 'options must be an object');
callback = callback || utils.createPromiseCallback();
const iter = this.iterateKeys(filter, options);
const keys = [];
iter.next(onNextKey);
function onNextKey(err, key) {
if (err) return callback(err);
if (key === undefined) return callback(null, keys);
keys.push(key);
iter.next(onNextKey);
}
return callback.promise;
};

49
lib/kvao/set.js Normal file
View File

@ -0,0 +1,49 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Persist a value and associate it with the given key.
*
* @param {String} key Key to associate with the given value.
* @param {*} value Value to persist.
* @options {Number|Object} options Optional settings for the key-value
* pair. If a Number is provided, it is set as the TTL (time to live) in ms
* (milliseconds) for the key-value pair.
* @property {Number} ttl TTL for the key-value pair in ms.
* @callback {Function} callback
* @param {Error} err Error object.
* @promise
*
* @header KVAO.set(key, value, cb)
*/
module.exports = function keyValueSet(key, value, options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (typeof options === 'number') {
options = {ttl: options};
} else if (!options) {
options = {};
}
assert(typeof key === 'string' && key, 'key must be a non-empty string');
assert(value != null, 'value must be defined and not null');
assert(typeof options === 'object', 'options must be an object');
if (options && 'ttl' in options) {
assert(typeof options.ttl === 'number' && options.ttl > 0,
'options.ttl must be a positive number');
}
callback = callback || utils.createPromiseCallback();
// TODO convert possible model instance in "value" to raw data via toObect()
this.getConnector().set(this.modelName, key, value, options, callback);
return callback.promise;
};

39
lib/kvao/ttl.js Normal file
View File

@ -0,0 +1,39 @@
// Copyright IBM Corp. 2016,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const utils = require('../utils');
/**
* Return the TTL (time to live) for a given key. TTL is the remaining time
* before a key-value pair is discarded from the database.
*
* @param {String} key Key to use when searching the database.
* @options {Object} options
* @callback {Function} callback
* @param {Error} error
* @param {Number} ttl Expiration time for the key-value pair. `undefined` if
* TTL was not initially set.
* @promise
*
* @header KVAO.ttl(key, cb)
*/
module.exports = function keyValueTtl(key, options, callback) {
if (callback == undefined && typeof options === 'function') {
callback = options;
options = {};
} else if (!options) {
options = {};
}
assert(typeof key === 'string' && key, 'key must be a non-empty string');
assert(typeof options === 'object', 'options must be an object');
callback = callback || utils.createPromiseCallback();
this.getConnector().ttl(this.modelName, key, options, callback);
return callback.promise;
};

View File

@ -1,10 +1,21 @@
var util = require('util');
var Any = require('./types').Types.Any;
// Copyright IBM Corp. 2012,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const g = require('strong-globalize')();
const util = require('util');
const Any = require('./types').Types.Any;
const {
applyParentProperty,
} = require('./utils');
module.exports = List;
function List(items, itemType, parent) {
var list = this;
const list = this;
if (!(list instanceof List)) {
return new List(items, itemType, parent);
}
@ -13,23 +24,28 @@ function List(items, itemType, parent) {
try {
items = JSON.parse(items);
} catch (e) {
var err = new Error(util.format('could not create List from JSON string: %j', items));
const err = new Error(g.f('could not create List from JSON string: %j', items));
err.statusCode = 400;
throw err;
}
}
var arr = [];
if (typeof items === 'number') {
// trying to initialise empty array with a length
items = [...new Array(items)];
}
const arr = [];
arr.__proto__ = List.prototype;
items = items || [];
if (!Array.isArray(items)) {
var err = new Error(util.format('Items must be an array: %j', items));
const err = new Error(g.f('Items must be an array: %j', items));
err.statusCode = 400;
throw err;
}
if(!itemType) {
if (!itemType) {
itemType = items[0] && items[0].constructor;
}
@ -37,30 +53,32 @@ function List(items, itemType, parent) {
itemType = itemType[0];
}
if(itemType === Array) {
if (itemType === Array) {
itemType = Any;
}
Object.defineProperty(arr, 'itemType', {
writable: true,
enumerable: false,
value: itemType
value: itemType,
});
if (parent) {
// List constructor now called with actual model instance
Object.defineProperty(arr, 'parent', {
writable: true,
enumerable: false,
value: parent
value: parent,
});
}
items.forEach(function (item, i) {
items.forEach(function(item, i) {
if (itemType && !(item instanceof itemType)) {
arr[i] = itemType(item);
arr[i] = arr.toItem(item);
} else {
arr[i] = item;
}
if (parent && arr[i] && typeof arr[i] === 'object') applyParentProperty(arr[i], parent);
});
return arr;
@ -68,18 +86,37 @@ function List(items, itemType, parent) {
util.inherits(List, Array);
var _push = List.prototype.push;
const _push = List.prototype.push;
List.prototype.push = function (obj) {
var item = this.itemType && (obj instanceof this.itemType) ? obj : this.itemType(obj);
List.prototype.toItem = function(item) {
if (isClass(this.itemType)) {
return new this.itemType(item);
} else {
if (Array.isArray(item)) {
return item;
} else if (this.itemType === Date) {
if (item === null) return null;
return new Date(item);
} else {
return this.itemType(item);
}
}
};
List.prototype.push = function(obj) {
const item = this.itemType && (obj instanceof this.itemType) ? obj : this.toItem(obj);
if (item && typeof item === 'object' && this.parent) applyParentProperty(item, this.parent);
_push.call(this, item);
return item;
};
List.prototype.toObject = function (onlySchema, removeHidden, removeProtected) {
var items = [];
this.forEach(function (item) {
if (item && typeof item === 'object' && item.toObject) {
List.prototype.toObject = function(onlySchema, removeHidden, removeProtected) {
const items = [];
this.forEach(function(item) {
if (item && Array.isArray(item) && item.toArray) {
const subArray = item.toArray();
items.push(subArray);
} else if (item && typeof item === 'object' && item.toObject) {
items.push(item.toObject(onlySchema, removeHidden, removeProtected));
} else {
items.push(item);
@ -88,11 +125,27 @@ List.prototype.toObject = function (onlySchema, removeHidden, removeProtected) {
return items;
};
List.prototype.toJSON = function () {
/**
* Convert itself to a plain array.
*
* Some modules such as `should` checks prototype for comparison
*/
List.prototype.toArray = function() {
const items = [];
this.forEach(function(item) {
items.push(item);
});
return items;
};
List.prototype.toJSON = function() {
return this.toObject(true);
};
List.prototype.toString = function () {
List.prototype.toString = function() {
return JSON.stringify(this.toJSON());
};
function isClass(fn) {
return fn && fn.toString().indexOf('class ') === 0;
}

View File

@ -1,6 +1,13 @@
var debug = require('debug')('loopback:mixin');
var assert = require('assert');
var DefaultModelBaseClass = require('./model.js');
// Copyright IBM Corp. 2014,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const debug = require('debug')('loopback:mixin');
const assert = require('assert');
const DefaultModelBaseClass = require('./model.js');
function isModelClass(cls) {
if (!cls) {
@ -23,7 +30,7 @@ function MixinProvider(modelBuilder) {
* @param {Object} options
*/
MixinProvider.prototype.applyMixin = function applyMixin(modelClass, name, options) {
var fn = this.mixins[name];
const fn = this.mixins[name];
if (typeof fn === 'function') {
if (modelClass.dataSource) {
fn(modelClass, options || {});
@ -34,12 +41,14 @@ MixinProvider.prototype.applyMixin = function applyMixin(modelClass, name, optio
}
} else {
// Try model name
var model = this.modelBuilder.getModel(name);
if(model) {
const model = this.modelBuilder.getModel(name);
if (model) {
debug('Mixin is resolved to a model: %s', name);
modelClass.mixin(model, options);
} else {
debug('Invalid mixin: %s', name);
const errMsg = 'Model "' + modelClass.modelName + '" uses unknown mixin: ' + name;
debug(errMsg);
throw new Error(errMsg);
}
}
};
@ -57,11 +66,10 @@ MixinProvider.prototype.define = function defineMixin(name, mixin) {
debug('Defining mixin: %s', name);
}
if (isModelClass(mixin)) {
this.mixins[name] = function (Model, options) {
this.mixins[name] = function(Model, options) {
Model.mixin(mixin, options);
};
} else if (typeof mixin === 'function') {
this.mixins[name] = mixin;
}
};

View File

@ -1,22 +1,36 @@
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
/*!
* Module dependencies
*/
var inflection = require('inflection');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var assert = require('assert');
var deprecated = require('depd')('loopback-datasource-juggler');
var DefaultModelBaseClass = require('./model.js');
var List = require('./list.js');
var ModelDefinition = require('./model-definition.js');
var mergeSettings = require('./utils').mergeSettings;
var MixinProvider = require('./mixins');
const g = require('strong-globalize')();
const inflection = require('inflection');
const EventEmitter = require('events').EventEmitter;
const util = require('util');
const assert = require('assert');
const deprecated = require('depd')('loopback-datasource-juggler');
const DefaultModelBaseClass = require('./model.js');
const List = require('./list.js');
const ModelDefinition = require('./model-definition.js');
const MixinProvider = require('./mixins');
const {
deepMerge,
deepMergeProperty,
rankArrayElements,
isClass,
applyParentProperty,
} = require('./utils');
// Set up types
require('./types')(ModelBuilder);
var introspect = require('./introspection')(ModelBuilder);
const introspect = require('./introspection')(ModelBuilder);
/*!
* Export public API
@ -26,7 +40,7 @@ exports.ModelBuilder = exports.Schema = ModelBuilder;
/*!
* Helpers
*/
var slice = Array.prototype.slice;
const slice = Array.prototype.slice;
/**
* ModelBuilder - A builder to define data models.
@ -39,6 +53,7 @@ function ModelBuilder() {
// create blank models pool
this.models = {};
this.definitions = {};
this.settings = {};
this.mixins = new MixinProvider(this);
this.defaultModelBaseClass = DefaultModelBaseClass;
}
@ -61,10 +76,10 @@ function isModelClass(cls) {
*
* @param {String} name The model name
* @param {Boolean} forceCreate Whether the create a stub for the given name if a model doesn't exist.
* @returns {*} The model class
* @returns {ModelClass} The model class
*/
ModelBuilder.prototype.getModel = function (name, forceCreate) {
var model = this.models[name];
ModelBuilder.prototype.getModel = function(name, forceCreate) {
let model = this.models[name];
if (!model && forceCreate) {
model = this.define(name, {}, {unresolved: true});
}
@ -76,7 +91,7 @@ ModelBuilder.prototype.getModel = function (name, forceCreate) {
* @param {String} name The model name
* @returns {ModelDefinition} The model definition
*/
ModelBuilder.prototype.getModelDefinition = function (name) {
ModelBuilder.prototype.getModelDefinition = function(name) {
return this.definitions[name];
};
@ -106,20 +121,20 @@ ModelBuilder.prototype.getModelDefinition = function (name) {
* @param {Object} properties Hash of class properties in format `{property: Type, property2: Type2, ...}` or `{property: {type: Type}, property2: {type: Type2}, ...}`
* @param {Object} settings Other configuration of class
* @param {Function} parent Parent model
* @return newly created class
* @return {ModelClass} The class constructor.
*
*/
ModelBuilder.prototype.define = function defineClass(className, properties, settings, parent) {
var modelBuilder = this;
var args = slice.call(arguments);
var pluralName = (settings && settings.plural) ||
const modelBuilder = this;
const args = slice.call(arguments);
const pluralName = (settings && settings.plural) ||
inflection.pluralize(className);
var httpOptions = (settings && settings.http) || {};
var pathName = httpOptions.path || pluralName;
const httpOptions = (settings && settings.http) || {};
let pathName = httpOptions.path || pluralName;
if (!className) {
throw new Error('Class name required');
throw new Error(g.f('Class name required'));
}
if (args.length === 1) {
properties = {};
@ -139,8 +154,8 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
}
// Set up the base model class
var ModelBaseClass = parent || this.defaultModelBaseClass;
var baseClass = settings.base || settings['super'];
let ModelBaseClass = parent || this.defaultModelBaseClass;
const baseClass = settings.base || settings['super'];
if (baseClass) {
// Normalize base model property
settings.base = baseClass;
@ -154,6 +169,15 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
}
}
// Assert current model's base class provides method `getMergePolicy()`.
assert(ModelBaseClass.getMergePolicy, `Base class ${ModelBaseClass.modelName}
does not provide method getMergePolicy(). Most likely it is not inheriting
from datasource-juggler's built-in default ModelBaseClass, which is an
incorrect usage of the framework.`);
// Initialize base model inheritance rank if not set already
ModelBaseClass.__rank = ModelBaseClass.__rank || 1;
// Make sure base properties are inherited
// See https://github.com/strongloop/loopback-datasource-juggler/issues/293
if ((parent && !settings.base) || (!parent && settings.base)) {
@ -161,47 +185,29 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
}
// Check if there is a unresolved model with the same name
var ModelClass = this.models[className];
let ModelClass = this.models[className];
// Create the ModelClass if it doesn't exist or it's resolved (override)
// TODO: [rfeng] We need to decide what names to use for built-in models such as User.
if (!ModelClass || !ModelClass.settings.unresolved) {
// every class can receive hash of data as optional param
ModelClass = function ModelConstructor(data, options) {
if (!(this instanceof ModelConstructor)) {
return new ModelConstructor(data, options);
}
if (ModelClass.settings.unresolved) {
throw new Error('Model ' + ModelClass.modelName + ' is not defined.');
}
ModelBaseClass.apply(this, arguments);
};
ModelClass = createModelClassCtor(className, ModelBaseClass);
// mix in EventEmitter (don't inherit from)
var events = new EventEmitter();
const events = new EventEmitter();
// The model can have more than 10 listeners for lazy relationship setup
// See https://github.com/strongloop/loopback/issues/404
events.setMaxListeners(32);
for (var f in EventEmitter.prototype) {
for (const f in EventEmitter.prototype) {
if (typeof EventEmitter.prototype[f] === 'function') {
if (f !== 'on') {
ModelClass[f] = EventEmitter.prototype[f].bind(events);
continue;
}
// report deprecation warnings at the time Model.on() is called
ModelClass.on = function(event) {
if (['changed', 'deleted', 'deletedAll'].indexOf(event) !== -1) {
deprecated(this.modelName + '\'s event "' + event + '" ' +
'is deprecated, use Operation hooks instead. ' +
'http://docs.strongloop.com/display/LB/Operation+hooks');
}
EventEmitter.prototype.on.apply(events, arguments);
};
ModelClass[f] = EventEmitter.prototype[f].bind(events);
}
}
hiddenProperty(ModelClass, 'modelName', className);
}
// Iterate sub model inheritance rank over base model rank
ModelClass.__rank = ModelBaseClass.__rank + 1;
util.inherits(ModelClass, ModelBaseClass);
// store class in model pool
@ -222,12 +228,13 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Support both flavors path: 'x' and path: '/x'
pathName = '/' + pathName;
}
hiddenProperty(ModelClass, 'http', { path: pathName });
hiddenProperty(ModelClass, 'http', {path: pathName});
hiddenProperty(ModelClass, 'base', ModelBaseClass);
hiddenProperty(ModelClass, '_observers', {});
hiddenProperty(ModelClass, '_warned', {});
// inherit ModelBaseClass static methods
for (var i in ModelBaseClass) {
for (const i in ModelBaseClass) {
// We need to skip properties that are already in the subclass, for example, the event emitter methods
if (i !== '_mixins' && !(i in ModelClass)) {
ModelClass[i] = ModelBaseClass[i];
@ -236,8 +243,8 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Load and inject the model classes
if (settings.models) {
Object.keys(settings.models).forEach(function (m) {
var model = settings.models[m];
Object.keys(settings.models).forEach(function(m) {
const model = settings.models[m];
ModelClass[m] = typeof model === 'string' ? modelBuilder.getModel(model, true) : model;
});
}
@ -245,21 +252,36 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
ModelClass.getter = {};
ModelClass.setter = {};
for (var p in properties) {
// Remove properties that reverted by the subclass
if (properties[p] === null || properties[p] === false) {
for (const p in properties) {
// e.g excludePropertyList = ['id'] - base properties listed in excludePropertyList will be excluded from the model.
// excludeBaseProperties is introduced in SOAP model generation only for now and below logic
// handles excludeBaseProperties. Generated SOAP model has base as 'Model' which means 'id' property gets added
// automatically and 'id' property shouldn't be there for SOAP models. idInjection = false will not work
// for SOAP generator case, since base 'Model' has already id property. 'id: false' at the property level will not
// work either for SOAP generator case since generators use ModelDefinition.create to create property in the model
// dynamically, that execution path has strict validation where doesn't accept 'id: false' in a property.
// See https://github.com/strongloop/loopback-workspace/issues/486 for some more details.
const excludePropertyList = settings['excludeBaseProperties'];
// Remove properties that reverted by the subclass of the property from excludePropertyList
if (properties[p] === null || properties[p] === false ||
(excludePropertyList != null && excludePropertyList.indexOf(p) != -1)) {
// Hide the base property
delete properties[p];
}
// Warn about properties with unsupported names
// Throw error for properties with unsupported names
if (/\./.test(p)) {
deprecated('Property names containing a dot are not supported. ' +
'Model: ' + className + ', property: ' + p);
throw new Error(g.f('Property names containing dot(s) are not supported. ' +
'Model: %s, property: %s', className, p));
}
// Warn if property name is 'constructor'
if (p === 'constructor') {
deprecated(g.f('Property name should not be "{{constructor}}" in Model: %s', className));
}
}
var modelDefinition = new ModelDefinition(this, className, properties, settings);
const modelDefinition = new ModelDefinition(this, className, properties, settings);
this.definitions[className] = modelDefinition;
@ -268,13 +290,13 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// keep a pointer to settings as models can use it for configuration
ModelClass.settings = modelDefinition.settings;
var idInjection = settings.idInjection;
let idInjection = settings.idInjection;
if (idInjection !== false) {
// Default to true if undefined
idInjection = true;
}
var idNames = modelDefinition.idNames();
let idNames = modelDefinition.idNames();
if (idNames.length > 0) {
// id already exists
idInjection = false;
@ -283,51 +305,77 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// Add the id property
if (idInjection) {
// Set up the id property
ModelClass.definition.defineProperty('id', { type: Number, id: 1, generated: true });
ModelClass.definition.defineProperty('id', {type: Number, id: 1, generated: true});
}
idNames = modelDefinition.idNames(); // Reload it after rebuild
// Create a virtual property 'id'
if (idNames.length === 1) {
var idProp = idNames[0];
const idProp = idNames[0];
if (idProp !== 'id') {
Object.defineProperty(ModelClass.prototype, 'id', {
get: function () {
var idProp = ModelClass.definition.idNames()[0];
get: function() {
const idProp = ModelClass.definition.idNames()[0];
return this.__data[idProp];
},
configurable: true,
enumerable: false
enumerable: false,
});
}
} else {
// Now the id property is an object that consists of multiple keys
Object.defineProperty(ModelClass.prototype, 'id', {
get: function () {
var compositeId = {};
var idNames = ModelClass.definition.idNames();
for (var i = 0, p; i < idNames.length; i++) {
get: function() {
const compositeId = {};
const idNames = ModelClass.definition.idNames();
for (let i = 0, p; i < idNames.length; i++) {
p = idNames[i];
compositeId[p] = this.__data[p];
}
return compositeId;
},
configurable: true,
enumerable: false
enumerable: false,
});
}
// updateOnly property is added to indicate that this property will appear in
// the model for update/updateorcreate operations but and not for create operation.
let forceId = ModelClass.settings.forceId;
if (idNames.length > 0) {
const idName = modelDefinition.idName();
const idProp = ModelClass.definition.rawProperties[idName];
if (idProp.generated && forceId !== false) {
forceId = 'auto';
} else if (!idProp.generated && forceId === 'auto') {
// One of our parent models has enabled forceId because
// it uses an auto-generated id property. However,
// this particular model does not use auto-generated id,
// therefore we need to disable `forceId`.
forceId = false;
}
if (forceId) {
ModelClass.validatesAbsenceOf(idName, {if: 'isNewRecord'});
}
ModelClass.definition.properties[idName].updateOnly = !!forceId;
ModelClass.definition.rawProperties[idName].updateOnly = !!forceId;
ModelClass.settings.forceId = forceId;
}
// A function to loop through the properties
ModelClass.forEachProperty = function (cb) {
var props = ModelClass.definition.properties;
var keys = Object.keys(props);
for (var i = 0, n = keys.length; i < n; i++) {
ModelClass.forEachProperty = function(cb) {
const props = ModelClass.definition.properties;
const keys = Object.keys(props);
for (let i = 0, n = keys.length; i < n; i++) {
cb(keys[i], props[keys[i]]);
}
};
// A function to attach the model class to a data source
ModelClass.attachTo = function (dataSource) {
ModelClass.attachTo = function(dataSource) {
dataSource.attach(this);
};
@ -347,59 +395,61 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
* ```
*
* @param {String} className Name of the new model being defined.
* @options {Object} properties Properties to define for the model, added to properties of model being extended.
* @options {Object} settings Model settings, such as relations and acls.
*
* @options {Object} subClassProperties child model properties, added to base model
* properties.
* @options {Object} subClassSettings child model settings such as relations and acls,
* merged with base model settings.
*/
ModelClass.extend = function (className, subclassProperties, subclassSettings) {
var properties = ModelClass.definition.properties;
var settings = ModelClass.definition.settings;
ModelClass.extend = function(className, subClassProperties, subClassSettings) {
const baseClassProperties = ModelClass.definition.properties;
const baseClassSettings = ModelClass.definition.settings;
subclassProperties = subclassProperties || {};
subclassSettings = subclassSettings || {};
subClassProperties = subClassProperties || {};
subClassSettings = subClassSettings || {};
// Check if subclass redefines the ids
var idFound = false;
for (var k in subclassProperties) {
if (subclassProperties[k] && subclassProperties[k].id) {
let idFound = false;
for (const k in subClassProperties) {
if (subClassProperties[k] && subClassProperties[k].id) {
idFound = true;
break;
}
}
// Merging the properties
var keys = Object.keys(properties);
for (var i = 0, n = keys.length; i < n; i++) {
var key = keys[i];
const keys = Object.keys(baseClassProperties);
for (let i = 0, n = keys.length; i < n; i++) {
const key = keys[i];
if (idFound && properties[key].id) {
if (idFound && baseClassProperties[key].id) {
// don't inherit id properties
continue;
}
if (subclassProperties[key] === undefined) {
var baseProp = properties[key];
var basePropCopy = baseProp;
if (subClassProperties[key] === undefined) {
const baseProp = baseClassProperties[key];
let basePropCopy = baseProp;
if (baseProp && typeof baseProp === 'object') {
// Deep clone the base prop
basePropCopy = mergeSettings(null, baseProp);
// Deep clone the base properties
basePropCopy = deepMerge(baseProp);
}
subclassProperties[key] = basePropCopy;
subClassProperties[key] = basePropCopy;
}
}
// Merge the settings
var originalSubclassSettings = subclassSettings;
subclassSettings = mergeSettings(settings, subclassSettings);
// Merging the settings
const originalSubclassSettings = subClassSettings;
const mergePolicy = ModelClass.getMergePolicy(subClassSettings);
subClassSettings = mergeSettings(baseClassSettings, subClassSettings, mergePolicy);
// Ensure 'base' is not inherited. Note we don't have to delete 'super'
// as that is removed from settings by modelBuilder.define and thus
// it is never inherited
if (!originalSubclassSettings.base) {
subclassSettings.base = ModelClass;
subClassSettings.base = ModelClass;
}
// Define the subclass
var subClass = modelBuilder.define(className, subclassProperties, subclassSettings, ModelClass);
const subClass = modelBuilder.define(className, subClassProperties, subClassSettings, ModelClass);
// Calling the setup function
if (typeof subClass.setup === 'function') {
@ -409,33 +459,120 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
return subClass;
};
/*
* Merge parent and child model settings according to the provided merge policy.
*
* Below is presented the expected merge behaviour for each option of the policy.
* NOTE: This applies to top-level settings properties
*
* - Any
* - `{replace: true}` (default): child replaces the value from parent
* - assigning `null` on child setting deletes the inherited setting
*
* - Arrays:
* - `{replace: false}`: unique elements of parent and child cumulate
* - `{rank: true}` adds the model inheritance rank to array
* elements of type Object {} as internal property `__rank`
*
* - Object {}:
* - `{replace: false}`: deep merges parent and child objects
* - `{patch: true}`: child replaces inner properties from parent
*
* Here is an example of merge policy:
* ```
* {
* description: {replace: true}, // string or array
* properties: {patch: true}, // object
* hidden: {replace: false}, // array
* protected: {replace: false}, // array
* relations: {acls: true}, // object
* acls: {rank: true}, // array
* }
* ```
*
* @param {Object} baseClassSettings parent model settings.
* @param {Object} subClassSettings child model settings.
* @param {Object} mergePolicy merge policy, as defined in `ModelClass.getMergePolicy()`
* @return {Object} mergedSettings merged parent and child models settings.
*/
function mergeSettings(baseClassSettings, subClassSettings, mergePolicy) {
// deep clone base class settings
const mergedSettings = deepMerge(baseClassSettings);
Object.keys(baseClassSettings).forEach(function(key) {
// rank base class settings arrays elements where required
if (mergePolicy[key] && mergePolicy[key].rank) {
baseClassSettings[key] = rankArrayElements(baseClassSettings[key], ModelBaseClass.__rank);
}
});
Object.keys(subClassSettings).forEach(function(key) {
// assign default merge policy to unknown settings if specified
// if none specified, a deep merge will be applied eventually
if (mergePolicy[key] == null) { // undefined or null
mergePolicy[key] = mergePolicy.__default || {};
}
// allow null value to remove unwanted settings from base class settings
if (subClassSettings[key] === mergePolicy.__delete) {
delete mergedSettings[key];
return;
}
// rank sub class settings arrays elements where required
if (mergePolicy[key].rank) {
subClassSettings[key] = rankArrayElements(subClassSettings[key], ModelBaseClass.__rank + 1);
}
// replace base class settings where required
if (mergePolicy[key].replace) {
mergedSettings[key] = subClassSettings[key];
return;
}
// patch inner properties of base class settings where required
if (mergePolicy[key].patch) {
// mergedSettings[key] might not be initialized
mergedSettings[key] = mergedSettings[key] || {};
Object.keys(subClassSettings[key]).forEach(function(innerKey) {
mergedSettings[key][innerKey] = subClassSettings[key][innerKey];
});
return;
}
// in case no merge policy matched, apply a deep merge
// this for example handles {replace: false} and {rank: true}
mergedSettings[key] = deepMergeProperty(baseClassSettings[key], subClassSettings[key]);
});
return mergedSettings;
}
/**
* Register a property for the model class
* @param {String} propertyName Name of the property.
*/
ModelClass.registerProperty = function (propertyName) {
var properties = modelDefinition.build();
var prop = properties[propertyName];
var DataType = prop.type;
ModelClass.registerProperty = function(propertyName) {
const properties = modelDefinition.build();
const prop = properties[propertyName];
const DataType = prop.type;
if (!DataType) {
throw new Error('Invalid type for property ' + propertyName);
throw new Error(g.f('Invalid type for property %s', propertyName));
}
if (prop.required) {
var requiredOptions = typeof prop.required === 'object' ? prop.required : undefined;
const requiredOptions = typeof prop.required === 'object' ? prop.required : undefined;
ModelClass.validatesPresenceOf(propertyName, requiredOptions);
}
if (DataType === Date) ModelClass.validatesDateOf(propertyName);
Object.defineProperty(ModelClass.prototype, propertyName, {
get: function () {
get: function() {
if (ModelClass.getter[propertyName]) {
return ModelClass.getter[propertyName].call(this); // Try getter first
} else {
return this.__data && this.__data[propertyName]; // Try __data
}
},
set: function (value) {
var DataType = ModelClass.definition.properties[propertyName].type;
set: function(value) {
let DataType = ModelClass.definition.properties[propertyName].type;
if (Array.isArray(DataType) || DataType === Array) {
DataType = List;
} else if (DataType === Date) {
@ -446,7 +583,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
DataType = modelBuilder.resolveType(DataType);
}
var persistUndefinedAsNull = ModelClass.definition.settings.persistUndefinedAsNull;
const persistUndefinedAsNull = ModelClass.definition.settings.persistUndefinedAsNull;
if (value === undefined && persistUndefinedAsNull) {
value = null;
}
@ -459,50 +596,58 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
this.__data[propertyName] = value;
} else {
if (DataType === List) {
this.__data[propertyName] = DataType(value, properties[propertyName].type, this.__data);
this.__data[propertyName] = isClass(DataType) ?
new DataType(value, properties[propertyName].type, this) :
DataType(value, properties[propertyName].type, this);
} else {
// Assume the type constructor handles Constructor() call
// If not, we should call new DataType(value).valueOf();
this.__data[propertyName] = (value instanceof DataType) ? value : DataType(value);
this.__data[propertyName] = (value instanceof DataType) ?
value :
isClass(DataType) ? new DataType(value) : DataType(value);
if (value && this.__data[propertyName] instanceof DefaultModelBaseClass) {
// we are dealing with an embedded model, apply parent
applyParentProperty(this.__data[propertyName], this);
}
}
}
}
},
configurable: true,
enumerable: true
enumerable: true,
});
// FIXME: [rfeng] Do we need to keep the raw data?
// Use $ as the prefix to avoid conflicts with properties such as _id
Object.defineProperty(ModelClass.prototype, '$' + propertyName, {
get: function () {
get: function() {
return this.__data && this.__data[propertyName];
},
set: function (value) {
set: function(value) {
if (!this.__data) {
this.__data = {};
}
this.__data[propertyName] = value;
},
configurable: true,
enumerable: false
enumerable: false,
});
};
var props = ModelClass.definition.properties;
var keys = Object.keys(props);
var size = keys.length;
for (i = 0; i < size; i++) {
var propertyName = keys[i];
const props = ModelClass.definition.properties;
let keys = Object.keys(props);
let size = keys.length;
for (let i = 0; i < size; i++) {
const propertyName = keys[i];
ModelClass.registerProperty(propertyName);
}
var mixinSettings = settings.mixins || {};
const mixinSettings = settings.mixins || {};
keys = Object.keys(mixinSettings);
size = keys.length;
for (i = 0; i < size; i++) {
var name = keys[i];
var mixin = mixinSettings[name];
for (let i = 0; i < size; i++) {
const name = keys[i];
let mixin = mixinSettings[name];
if (mixin === true) {
mixin = {};
}
@ -521,15 +666,50 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
ModelClass.emit('defined', ModelClass);
return ModelClass;
};
function createModelClassCtor(name, ModelBaseClass) {
// A simple sanitization to handle most common characters
// that are used in model names but cannot be used as a function/class name.
// Note that the rules for valid JS indentifiers are way too complex,
// implementing a fully spec-compliant sanitization is not worth the effort.
// See https://mathiasbynens.be/notes/javascript-identifiers-es6
name = name.replace(/[-.:]/g, '_');
try {
// It is not possible to access closure variables like "ModelBaseClass"
// from a dynamically defined function. The solution is to
// create a dynamically defined factory function that accepts
// closure variables as arguments.
const factory = new Function('ModelBaseClass', `
// every class can receive hash of data as optional param
return function ${name}(data, options) {
if (!(this instanceof ${name})) {
return new ${name}(data, options);
}
if (${name}.settings.unresolved) {
throw new Error(g.f('Model %s is not defined.', ${JSON.stringify(name)}));
}
ModelBaseClass.apply(this, arguments);
};`);
return factory(ModelBaseClass);
} catch (err) {
// modelName is not a valid function/class name, e.g. 'grand-child'
// and our simple sanitization was not good enough.
// Falling back to legacy 'ModelConstructor' name.
if (err.name === 'SyntaxError') {
return createModelClassCtor('ModelConstructor', ModelBaseClass);
} else {
throw err;
}
}
}
// DataType for Date
function DateType(arg) {
var d = new Date(arg);
if (isNaN(d.getTime())) {
throw new Error('Invalid date: ' + arg);
}
if (arg === null) return null;
const d = new Date(arg);
return d;
}
@ -558,7 +738,7 @@ function BooleanType(arg) {
* @param {String} propertyName Name of property
* @param {Object} propertyDefinition Property settings
*/
ModelBuilder.prototype.defineProperty = function (model, propertyName, propertyDefinition) {
ModelBuilder.prototype.defineProperty = function(model, propertyName, propertyDefinition) {
this.definitions[model].defineProperty(propertyName, propertyDefinition);
this.models[model].registerProperty(propertyName);
};
@ -602,20 +782,20 @@ ModelBuilder.prototype.defineValueType = function(type, aliases) {
* @property {String} type Datatype of property: Must be an [LDL type](http://docs.strongloop.com/display/LB/LoopBack+types).
* @property {Boolean} index True if the property is an index; false otherwise.
*/
ModelBuilder.prototype.extendModel = function (model, props) {
var t = this;
var keys = Object.keys(props);
for (var i = 0; i < keys.length; i++) {
var definition = props[keys[i]];
ModelBuilder.prototype.extendModel = function(model, props) {
const t = this;
const keys = Object.keys(props);
for (let i = 0; i < keys.length; i++) {
const definition = props[keys[i]];
t.defineProperty(model, keys[i], definition);
}
};
ModelBuilder.prototype.copyModel = function copyModel(Master) {
var modelBuilder = this;
var className = Master.modelName;
var md = Master.modelBuilder.definitions[className];
var Slave = function SlaveModel() {
const modelBuilder = this;
const className = Master.modelName;
const md = Master.modelBuilder.definitions[className];
const Slave = function SlaveModel() {
Master.apply(this, [].slice.call(arguments));
};
@ -628,18 +808,27 @@ ModelBuilder.prototype.copyModel = function copyModel(Master) {
hiddenProperty(Slave, 'relations', Master.relations);
if (!(className in modelBuilder.models)) {
// store class in model pool
modelBuilder.models[className] = Slave;
modelBuilder.definitions[className] = {
properties: md.properties,
settings: md.settings
settings: md.settings,
};
}
return Slave;
};
/**
* Remove a model from the registry.
*
* @param {String} modelName
*/
ModelBuilder.prototype.deleteModelByName = function(modelName) {
delete this.models[modelName];
delete this.definitions[modelName];
};
/*!
* Define hidden property
*/
@ -648,14 +837,17 @@ function hiddenProperty(where, property, value) {
writable: true,
enumerable: false,
configurable: true,
value: value
value: value,
});
}
/**
* Get the schema name
* Get the schema name. If no parameter is given, then an anonymous model name
* is generated and returned.
* @param {string=} name The optional name parameter.
* @returns {string} The schema name.
*/
ModelBuilder.prototype.getSchemaName = function (name) {
ModelBuilder.prototype.getSchemaName = function(name) {
if (name) {
return name;
}
@ -670,43 +862,46 @@ ModelBuilder.prototype.getSchemaName = function (name) {
/**
* Resolve the type string to be a function, for example, 'String' to String.
* Returns {Function} if the type is resolved
* @param {String} type The type string, such as 'number', 'Number', 'boolean', or 'String'. It's case insensitive
* @param {String | Object | Array} prop The object whose type is to be resolved
*/
ModelBuilder.prototype.resolveType = function (type) {
if (!type) {
return type;
ModelBuilder.prototype.resolveType = function(prop, isSubProperty) {
if (!prop) {
return prop;
}
if (Array.isArray(type) && type.length > 0) {
if (Array.isArray(prop) && prop.length > 0) {
// For array types, the first item should be the type string
var itemType = this.resolveType(type[0]);
const itemType = this.resolveType(prop[0]);
if (typeof itemType === 'function') {
return [itemType];
}
else {
} else {
return itemType; // Not resolved, return the type string
}
}
if (typeof type === 'string') {
var schemaType = ModelBuilder.schemaTypes[type.toLowerCase()] || this.models[type];
if (typeof prop === 'string') {
const schemaType = ModelBuilder.schemaTypes[prop.toLowerCase()] || this.models[prop];
if (schemaType) {
return schemaType;
} else {
// The type cannot be resolved, let's create a place holder
type = this.define(type, {}, {unresolved: true});
return type;
prop = this.define(prop, {}, {unresolved: true});
return prop;
}
} else if (type.constructor.name === 'Object') {
} else if (prop.constructor.name === 'Object') {
// We also support the syntax {type: 'string', ...}
if (type.type) {
return this.resolveType(type.type);
if (!isSubProperty && prop.type) {
return this.resolveType(prop.type, true);
} else {
return this.define(this.getSchemaName(null),
type, {anonymous: true, idInjection: false});
prop, {
anonymous: true,
idInjection: false,
strict: this.settings.strictEmbeddedModels || false,
});
}
} else if ('function' === typeof type) {
return type;
} else if ('function' === typeof prop) {
return prop;
}
return type;
return prop;
};
/**
@ -719,10 +914,11 @@ ModelBuilder.prototype.resolveType = function (type) {
* 3. A list of property definitions (anonymous)
*
* @param {*} schemas The schemas
* @returns {Object} A map of model constructors keyed by model name
* @returns {Object.<string, ModelClass>} A map of model constructors keyed by
* model name.
*/
ModelBuilder.prototype.buildModels = function (schemas, createModel) {
var models = {};
ModelBuilder.prototype.buildModels = function(schemas, createModel) {
const models = {};
// Normalize the schemas to be an array of the schema objects {name: <name>, properties: {}, options: {}}
if (!Array.isArray(schemas)) {
@ -735,31 +931,28 @@ ModelBuilder.prototype.buildModels = function (schemas, createModel) {
{
name: this.getSchemaName(),
properties: schemas,
options: {anonymous: true}
}
options: {anonymous: true},
},
];
}
}
var relations = [];
for (var s = 0, n = schemas.length; s < n; s++) {
var name = this.getSchemaName(schemas[s].name);
let relations = [];
for (let s = 0, n = schemas.length; s < n; s++) {
const name = this.getSchemaName(schemas[s].name);
schemas[s].name = name;
var model;
if(typeof createModel === 'function') {
model = createModel(schemas[s].name, schemas[s].properties, schemas[s].options);
} else {
model = this.define(schemas[s].name, schemas[s].properties, schemas[s].options);
}
const model = typeof createModel === 'function' ?
createModel(schemas[s].name, schemas[s].properties, schemas[s].options) :
this.define(schemas[s].name, schemas[s].properties, schemas[s].options);
models[name] = model;
relations = relations.concat(model.definition.relations);
}
// Connect the models based on the relations
for (var i = 0; i < relations.length; i++) {
var relation = relations[i];
var sourceModel = models[relation.source];
var targetModel = models[relation.target];
for (let i = 0; i < relations.length; i++) {
const relation = relations[i];
const sourceModel = models[relation.source];
const targetModel = models[relation.target];
if (sourceModel && targetModel) {
if (typeof sourceModel[relation.type] === 'function') {
sourceModel[relation.type](targetModel, {as: relation.as});
@ -774,16 +967,12 @@ ModelBuilder.prototype.buildModels = function (schemas, createModel) {
* @param {String} name The model name
* @param {Object} json The JSON object
* @param {Object} options The options
* @returns {}
* @returns {ModelClass} The generated model class constructor.
*/
ModelBuilder.prototype.buildModelFromInstance = function (name, json, options) {
ModelBuilder.prototype.buildModelFromInstance = function(name, json, options) {
// Introspect the JSON document to generate a schema
var schema = introspect(json);
const schema = introspect(json);
// Create a model for the generated schema
return this.define(name, schema, options);
};

View File

@ -1,9 +1,16 @@
var assert = require('assert');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var traverse = require('traverse');
var ModelBaseClass = require('./model');
var ModelBuilder = require('./model-builder');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const assert = require('assert');
const util = require('util');
const EventEmitter = require('events').EventEmitter;
const traverse = require('traverse');
const ModelBaseClass = require('./model');
const ModelBuilder = require('./model-builder');
/**
* Model definition
@ -29,7 +36,7 @@ function ModelDefinition(modelBuilder, name, properties, settings) {
assert(name, 'name is missing');
if (arguments.length === 2 && typeof name === 'object') {
var schema = name;
const schema = name;
this.name = schema.name;
this.rawProperties = schema.properties || {}; // Keep the raw property definitions
this.settings = schema.settings || {};
@ -53,8 +60,8 @@ require('./types')(ModelDefinition);
* Return table name for specified `modelName`
* @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
*/
ModelDefinition.prototype.tableName = function (connectorType) {
var settings = this.settings;
ModelDefinition.prototype.tableName = function(connectorType) {
const settings = this.settings;
if (settings[connectorType]) {
return settings[connectorType].table || settings[connectorType].tableName || this.name;
} else {
@ -68,12 +75,12 @@ ModelDefinition.prototype.tableName = function (connectorType) {
* @param propertyName The property name
* @returns {String} columnName
*/
ModelDefinition.prototype.columnName = function (connectorType, propertyName) {
ModelDefinition.prototype.columnName = function(connectorType, propertyName) {
if (!propertyName) {
return propertyName;
}
this.build();
var property = this.properties[propertyName];
const property = this.properties[propertyName];
if (property && property[connectorType]) {
return property[connectorType].column || property[connectorType].columnName || propertyName;
} else {
@ -87,12 +94,12 @@ ModelDefinition.prototype.columnName = function (connectorType, propertyName) {
* @param propertyName The property name
* @returns {Object} column metadata
*/
ModelDefinition.prototype.columnMetadata = function (connectorType, propertyName) {
ModelDefinition.prototype.columnMetadata = function(connectorType, propertyName) {
if (!propertyName) {
return propertyName;
}
this.build();
var property = this.properties[propertyName];
const property = this.properties[propertyName];
if (property && property[connectorType]) {
return property[connectorType];
} else {
@ -105,13 +112,13 @@ ModelDefinition.prototype.columnMetadata = function (connectorType, propertyName
* @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
* @returns {String[]} column names
*/
ModelDefinition.prototype.columnNames = function (connectorType) {
ModelDefinition.prototype.columnNames = function(connectorType) {
this.build();
var props = this.properties;
var cols = [];
for (var p in props) {
const props = this.properties;
const cols = [];
for (const p in props) {
if (props[p][connectorType]) {
cols.push(props[connectorType].column || props[p][connectorType].columnName || p);
cols.push(props[p][connectorType].column || props[p][connectorType].columnName || p);
} else {
cols.push(p);
}
@ -123,15 +130,15 @@ ModelDefinition.prototype.columnNames = function (connectorType) {
* Find the ID properties sorted by the index
* @returns {Object[]} property name/index for IDs
*/
ModelDefinition.prototype.ids = function () {
ModelDefinition.prototype.ids = function() {
if (this._ids) {
return this._ids;
}
var ids = [];
const ids = [];
this.build();
var props = this.properties;
for (var key in props) {
var id = props[key].id;
const props = this.properties;
for (const key in props) {
let id = props[key].id;
if (!id) {
continue;
}
@ -140,7 +147,7 @@ ModelDefinition.prototype.ids = function () {
}
ids.push({name: key, id: id, property: props[key]});
}
ids.sort(function (a, b) {
ids.sort(function(a, b) {
return a.id - b.id;
});
this._ids = ids;
@ -152,7 +159,7 @@ ModelDefinition.prototype.ids = function () {
* @param {String} modelName The model name
* @returns {String} columnName for ID
*/
ModelDefinition.prototype.idColumnName = function (connectorType) {
ModelDefinition.prototype.idColumnName = function(connectorType) {
return this.columnName(connectorType, this.idName());
};
@ -160,8 +167,8 @@ ModelDefinition.prototype.idColumnName = function (connectorType) {
* Find the ID property name
* @returns {String} property name for ID
*/
ModelDefinition.prototype.idName = function () {
var id = this.ids()[0];
ModelDefinition.prototype.idName = function() {
const id = this.ids()[0];
if (this.properties.id && this.properties.id.id) {
return 'id';
} else {
@ -173,9 +180,9 @@ ModelDefinition.prototype.idName = function () {
* Find the ID property names sorted by the index
* @returns {String[]} property names for IDs
*/
ModelDefinition.prototype.idNames = function () {
var ids = this.ids();
var names = ids.map(function (id) {
ModelDefinition.prototype.idNames = function() {
const ids = this.ids();
const names = ids.map(function(id) {
return id.name;
});
return names;
@ -185,15 +192,15 @@ ModelDefinition.prototype.idNames = function () {
*
* @returns {{}}
*/
ModelDefinition.prototype.indexes = function () {
ModelDefinition.prototype.indexes = function() {
this.build();
var indexes = {};
const indexes = {};
if (this.settings.indexes) {
for (var i in this.settings.indexes) {
for (const i in this.settings.indexes) {
indexes[i] = this.settings.indexes[i];
}
}
for (var p in this.properties) {
for (const p in this.properties) {
if (this.properties[p].index) {
indexes[p + '_index'] = this.properties[p].index;
}
@ -205,7 +212,7 @@ ModelDefinition.prototype.indexes = function () {
* Build a model definition
* @param {Boolean} force Forcing rebuild
*/
ModelDefinition.prototype.build = function (forceRebuild) {
ModelDefinition.prototype.build = function(forceRebuild) {
if (forceRebuild) {
this.properties = null;
this.relations = [];
@ -216,22 +223,22 @@ ModelDefinition.prototype.build = function (forceRebuild) {
return this.properties;
}
this.properties = {};
for (var p in this.rawProperties) {
var prop = this.rawProperties[p];
var type = this.modelBuilder.resolveType(prop);
for (const p in this.rawProperties) {
const prop = this.rawProperties[p];
const type = this.modelBuilder.resolveType(prop);
if (typeof type === 'string') {
this.relations.push({
source: this.name,
target: type,
type: Array.isArray(prop) ? 'hasMany' : 'belongsTo',
as: p
as: p,
});
} else {
var typeDef = {
type: type
const typeDef = {
type: type,
};
if (typeof prop === 'object' && prop !== null) {
for (var a in prop) {
for (const a in prop) {
// Skip the type property but don't delete it Model.extend() shares same instances of the properties from the base class
if (a !== 'type') {
typeDef[a] = prop[a];
@ -249,7 +256,7 @@ ModelDefinition.prototype.build = function (forceRebuild) {
* @param {String} propertyName The property name
* @param {Object} propertyDefinition The property definition
*/
ModelDefinition.prototype.defineProperty = function (propertyName, propertyDefinition) {
ModelDefinition.prototype.defineProperty = function(propertyName, propertyDefinition) {
this.rawProperties[propertyName] = propertyDefinition;
this.build(true);
};
@ -261,21 +268,21 @@ function isModelClass(cls) {
return cls.prototype instanceof ModelBaseClass;
}
ModelDefinition.prototype.toJSON = function (forceRebuild) {
ModelDefinition.prototype.toJSON = function(forceRebuild) {
if (forceRebuild) {
this.json = null;
}
if (this.json) {
return this.json;
}
var json = {
const json = {
name: this.name,
properties: {},
settings: this.settings
settings: this.settings,
};
this.build(forceRebuild);
var mapper = function (val) {
const mapper = function(val) {
if (val === undefined || val === null) {
return val;
}
@ -296,7 +303,7 @@ ModelDefinition.prototype.toJSON = function (forceRebuild) {
return val;
}
};
for (var p in this.properties) {
for (const p in this.properties) {
json.properties[p] = traverse(this.properties[p]).map(mapper);
}
this.json = json;

586
lib/model-utils.js Normal file
View File

@ -0,0 +1,586 @@
// Copyright IBM Corp. 2018,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// Turning on strict for this file breaks lots of test cases;
// disabling strict for this file
/* eslint-disable strict */
module.exports = ModelUtils;
/*!
* Module dependencies
*/
const g = require('strong-globalize')();
const geo = require('./geo');
const {
fieldsToArray,
sanitizeQuery: sanitizeQueryOrData,
isPlainObject,
isClass,
toRegExp,
} = require('./utils');
const BaseModel = require('./model');
/**
* A mixin to contain utility methods for DataAccessObject
*/
function ModelUtils() {
}
/**
* Verify if allowExtendedOperators is enabled
* @options {Object} [options] Optional options to use.
* @property {Boolean} allowExtendedOperators.
* @returns {Boolean} Returns `true` if allowExtendedOperators is enabled, else `false`.
*/
ModelUtils._allowExtendedOperators = function(options) {
const flag = this._getSetting('allowExtendedOperators', options);
if (flag != null) return !!flag;
// Default to `false`
return false;
};
/**
* Get settings via hierarchical determination
* - method level options
* - model level settings
* - data source level settings
*
* @param {String} key The setting key
*/
ModelUtils._getSetting = function(key, options) {
// Check method level options
let val = options && options[key];
if (val !== undefined) return val;
// Check for settings in model
const m = this.definition;
if (m && m.settings) {
val = m.settings[key];
if (val !== undefined) {
return m.settings[key];
}
// Fall back to data source level
}
// Check for settings in connector
const ds = this.getDataSource();
if (ds && ds.settings) {
return ds.settings[key];
}
return undefined;
};
const operators = {
eq: '=',
gt: '>',
gte: '>=',
lt: '<',
lte: '<=',
between: 'BETWEEN',
inq: 'IN',
nin: 'NOT IN',
neq: '!=',
like: 'LIKE',
nlike: 'NOT LIKE',
ilike: 'ILIKE',
nilike: 'NOT ILIKE',
regexp: 'REGEXP',
};
/*
* Normalize the filter object and throw errors if invalid values are detected
* @param {Object} filter The query filter object
* @options {Object} [options] Optional options to use.
* @property {Boolean} allowExtendedOperators.
* @returns {Object} The normalized filter object
* @private
*/
ModelUtils._normalize = function(filter, options) {
if (!filter) {
return undefined;
}
let err = null;
if ((typeof filter !== 'object') || Array.isArray(filter)) {
err = new Error(g.f('The query filter %j is not an {{object}}', filter));
err.statusCode = 400;
throw err;
}
if (filter.limit || filter.skip || filter.offset) {
const limit = Number(filter.limit || 100);
const offset = Number(filter.skip || filter.offset || 0);
if (isNaN(limit) || limit <= 0 || Math.ceil(limit) !== limit) {
err = new Error(g.f('The {{limit}} parameter %j is not valid',
filter.limit));
err.statusCode = 400;
throw err;
}
if (isNaN(offset) || offset < 0 || Math.ceil(offset) !== offset) {
err = new Error(g.f('The {{offset/skip}} parameter %j is not valid',
filter.skip || filter.offset));
err.statusCode = 400;
throw err;
}
filter.limit = limit;
filter.offset = offset;
filter.skip = offset;
}
if (filter.order) {
let order = filter.order;
if (!Array.isArray(order)) {
order = [order];
}
const fields = [];
for (let i = 0, m = order.length; i < m; i++) {
if (typeof order[i] === 'string') {
// Normalize 'f1 ASC, f2 DESC, f3' to ['f1 ASC', 'f2 DESC', 'f3']
const tokens = order[i].split(/(?:\s*,\s*)+/);
for (let t = 0, n = tokens.length; t < n; t++) {
let token = tokens[t];
if (token.length === 0) {
// Skip empty token
continue;
}
const parts = token.split(/\s+/);
if (parts.length >= 2) {
const dir = parts[1].toUpperCase();
if (dir === 'ASC' || dir === 'DESC') {
token = parts[0] + ' ' + dir;
} else {
err = new Error(g.f('The {{order}} %j has invalid direction', token));
err.statusCode = 400;
throw err;
}
}
fields.push(token);
}
} else {
err = new Error(g.f('The order %j is not valid', order[i]));
err.statusCode = 400;
throw err;
}
}
if (fields.length === 1 && typeof filter.order === 'string') {
filter.order = fields[0];
} else {
filter.order = fields;
}
}
// normalize fields as array of included property names
if (filter.fields) {
filter.fields = fieldsToArray(filter.fields,
Object.keys(this.definition.properties), this.settings.strict);
}
filter = this._sanitizeQuery(filter, options);
this._coerce(filter.where, options);
return filter;
};
function DateType(arg) {
const d = new Date(arg);
if (isNaN(d.getTime())) {
throw new Error(g.f('Invalid date: %s', arg));
}
return d;
}
function BooleanType(arg) {
if (typeof arg === 'string') {
switch (arg) {
case 'true':
case '1':
return true;
case 'false':
case '0':
return false;
}
}
if (arg == null) {
return null;
}
return Boolean(arg);
}
function NumberType(val) {
const num = Number(val);
return !isNaN(num) ? num : val;
}
function coerceArray(val) {
if (Array.isArray(val)) {
return val;
}
if (!isPlainObject(val)) {
throw new Error(g.f('Value is not an {{array}} or {{object}} with sequential numeric indices'));
}
// It is an object, check if empty
const props = Object.keys(val);
if (props.length === 0) {
throw new Error(g.f('Value is an empty {{object}}'));
}
const arrayVal = new Array(props.length);
for (let i = 0; i < arrayVal.length; ++i) {
if (!val.hasOwnProperty(i)) {
throw new Error(g.f('Value is not an {{array}} or {{object}} with sequential numeric indices'));
}
arrayVal[i] = val[i];
}
return arrayVal;
}
function _normalizeAsArray(result) {
if (typeof result === 'string') {
result = [result];
}
if (Array.isArray(result)) {
return result;
} else {
// See https://github.com/strongloop/loopback-datasource-juggler/issues/1646
// `ModelBaseClass` normalize the properties to an object such as `{secret: true}`
const keys = [];
for (const k in result) {
if (result[k]) keys.push(k);
}
return keys;
}
}
/**
* Get an array of hidden property names
*/
ModelUtils._getHiddenProperties = function() {
const settings = this.definition.settings || {};
const result = settings.hiddenProperties || settings.hidden || [];
return _normalizeAsArray(result);
};
/**
* Get an array of protected property names
*/
ModelUtils._getProtectedProperties = function() {
const settings = this.definition.settings || {};
const result = settings.protectedProperties || settings.protected || [];
return _normalizeAsArray(result);
};
/**
* Get the maximum depth of a query object
*/
ModelUtils._getMaxDepthOfQuery = function(options, defaultValue) {
options = options || {};
// See https://github.com/strongloop/loopback-datasource-juggler/issues/1651
let maxDepth = this._getSetting('maxDepthOfQuery', options);
if (maxDepth == null) {
maxDepth = defaultValue || 32;
}
return +maxDepth;
};
/**
* Get the maximum depth of a data object
*/
ModelUtils._getMaxDepthOfData = function(options, defaultValue) {
options = options || {};
// See https://github.com/strongloop/loopback-datasource-juggler/issues/1651
let maxDepth = this._getSetting('maxDepthOfData', options);
if (maxDepth == null) {
maxDepth = defaultValue || 64;
}
return +maxDepth;
};
/**
* Get the prohibitHiddenPropertiesInQuery flag
*/
ModelUtils._getProhibitHiddenPropertiesInQuery = function(options, defaultValue) {
const flag = this._getSetting('prohibitHiddenPropertiesInQuery', options);
if (flag == null) return !!defaultValue;
return !!flag;
};
/**
* Sanitize the query object
*/
ModelUtils._sanitizeQuery = function(query, options) {
options = options || {};
// Get settings to normalize `undefined` values
const normalizeUndefinedInQuery = this._getSetting('normalizeUndefinedInQuery', options);
// Get setting to prohibit hidden/protected properties in query
const prohibitHiddenPropertiesInQuery = this._getProhibitHiddenPropertiesInQuery(options);
// See https://github.com/strongloop/loopback-datasource-juggler/issues/1651
const maxDepthOfQuery = this._getMaxDepthOfQuery(options);
let prohibitedKeys = [];
// Check violation of keys
if (prohibitHiddenPropertiesInQuery) {
prohibitedKeys = this._getHiddenProperties();
if (options.prohibitProtectedPropertiesInQuery) {
prohibitedKeys = prohibitedKeys.concat(this._getProtectedProperties());
}
}
return sanitizeQueryOrData(query,
Object.assign({
maxDepth: maxDepthOfQuery,
prohibitedKeys: prohibitedKeys,
normalizeUndefinedInQuery: normalizeUndefinedInQuery,
}, options));
};
/**
* Sanitize the data object
*/
ModelUtils._sanitizeData = function(data, options) {
options = options || {};
return sanitizeQueryOrData(data,
Object.assign({
maxDepth: this._getMaxDepthOfData(options),
}, options));
};
/*
* Coerce values based the property types
* @param {Object} where The where clause
* @options {Object} [options] Optional options to use.
* @param {Object} Optional model definition to use.
* @property {Boolean} allowExtendedOperators.
* @returns {Object} The coerced where clause
* @private
*/
ModelUtils._coerce = function(where, options, modelDef) {
const self = this;
if (where == null) {
return where;
}
options = options || {};
let err;
if (typeof where !== 'object' || Array.isArray(where)) {
err = new Error(g.f('The where clause %j is not an {{object}}', where));
err.statusCode = 400;
throw err;
}
let props;
if (modelDef && modelDef.properties) {
props = modelDef.properties;
} else {
props = self.definition.properties;
}
for (const p in where) {
// Handle logical operators
if (p === 'and' || p === 'or' || p === 'nor') {
let clauses = where[p];
try {
clauses = coerceArray(clauses);
} catch (e) {
err = new Error(g.f('The %s operator has invalid clauses %j: %s', p, clauses, e.message));
err.statusCode = 400;
throw err;
}
for (let k = 0; k < clauses.length; k++) {
self._coerce(clauses[k], options);
}
where[p] = clauses;
continue;
}
let DataType = props[p] && props[p].type;
if (!DataType) {
continue;
}
if ((Array.isArray(DataType) || DataType === Array) && !isNestedModel(DataType)) {
DataType = DataType[0];
}
if (DataType === Date) {
DataType = DateType;
} else if (DataType === Boolean) {
DataType = BooleanType;
} else if (DataType === Number) {
// This fixes a regression in mongodb connector
// For numbers, only convert it produces a valid number
// LoopBack by default injects a number id. We should fix it based
// on the connector's input, for example, MongoDB should use string
// while RDBs typically use number
DataType = NumberType;
}
if (!DataType) {
continue;
}
if (DataType === geo.GeoPoint) {
// Skip the GeoPoint as the near operator breaks the assumption that
// an operation has only one property
// We should probably fix it based on
// http://docs.mongodb.org/manual/reference/operator/query/near/
// The other option is to make operators start with $
continue;
}
let val = where[p];
if (val === null || val === undefined) {
continue;
}
// Check there is an operator
let operator = null;
const exp = val;
if (val.constructor === Object) {
for (const op in operators) {
if (op in val) {
val = val[op];
operator = op;
switch (operator) {
case 'inq':
case 'nin':
case 'between':
try {
val = coerceArray(val);
} catch (e) {
err = new Error(g.f('The %s property has invalid clause %j: %s', p, where[p], e));
err.statusCode = 400;
throw err;
}
if (operator === 'between' && val.length !== 2) {
err = new Error(g.f(
'The %s property has invalid clause %j: Expected precisely 2 values, received %d',
p,
where[p],
val.length,
));
err.statusCode = 400;
throw err;
}
break;
case 'like':
case 'nlike':
case 'ilike':
case 'nilike':
if (!(typeof val === 'string' || val instanceof RegExp)) {
err = new Error(g.f(
'The %s property has invalid clause %j: Expected a string or RegExp',
p,
where[p],
));
err.statusCode = 400;
throw err;
}
break;
case 'regexp':
val = toRegExp(val);
if (val instanceof Error) {
val.statusCode = 400;
throw val;
}
break;
}
break;
}
}
}
try {
// Coerce val into an array if it resembles an array-like object
val = coerceArray(val);
} catch (e) {
// NOOP when not coercable into an array.
}
const allowExtendedOperators = self._allowExtendedOperators(options);
// Coerce the array items
if (Array.isArray(val) && !isNestedModel(DataType)) {
for (let i = 0; i < val.length; i++) {
if (val[i] !== null && val[i] !== undefined) {
if (!(val[i] instanceof RegExp)) {
val[i] = isClass(DataType) ? new DataType(val[i]) : DataType(val[i]);
}
}
}
} else {
if (val != null) {
if (operator === null && val instanceof RegExp) {
// Normalize {name: /A/} to {name: {regexp: /A/}}
operator = 'regexp';
} else if (operator === 'regexp' && val instanceof RegExp) {
// Do not coerce regex literals/objects
} else if ((operator === 'like' || operator === 'nlike' ||
operator === 'ilike' || operator === 'nilike') && val instanceof RegExp) {
// Do not coerce RegExp operator value
} else if (allowExtendedOperators && typeof val === 'object') {
// Do not coerce object values when extended operators are allowed
} else {
if (!allowExtendedOperators) {
const extendedOperators = Object.keys(val).filter(function(k) {
return k[0] === '$';
});
if (extendedOperators.length) {
const msg = g.f('Operators "' + extendedOperators.join(', ') + '" are not allowed in query');
const err = new Error(msg);
err.code = 'OPERATOR_NOT_ALLOWED_IN_QUERY';
err.statusCode = 400;
err.details = {
operators: extendedOperators,
where: where,
};
throw err;
}
}
if (isNestedModel(DataType)) {
if (Array.isArray(DataType) && Array.isArray(val)) {
if (val === null || val === undefined) continue;
for (const it of val) {
self._coerce(it, options, DataType[0].definition);
}
} else {
self._coerce(val, options, DataType.definition);
}
continue;
} else {
val = isClass(DataType) ? new DataType(val) : DataType(val);
}
}
}
}
// Rebuild {property: {operator: value}}
if (operator && operator !== 'eq') {
const value = {};
value[operator] = val;
if (exp.options) {
// Keep options for operators
value.options = exp.options;
}
val = value;
}
where[p] = val;
}
return where;
};
/**
* A utility function which checks for nested property definitions
*
* @param {*} propType Property type metadata
*
*/
function isNestedModel(propType) {
if (!propType) return false;
if (Array.isArray(propType)) return isNestedModel(propType[0]);
return propType.hasOwnProperty('definition') && propType.definition.hasOwnProperty('properties');
}

View File

@ -1,3 +1,12 @@
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
// Turning on strict for this file breaks lots of test cases;
// disabling strict for this file
/* eslint-disable strict */
/*!
* Module exports class Model
*/
@ -7,26 +16,28 @@ module.exports = ModelBaseClass;
* Module dependencies
*/
var async = require('async');
var util = require('util');
var jutil = require('./jutil');
var List = require('./list');
var Hookable = require('./hooks');
var validations = require('./validations');
var _extend = util._extend;
var utils = require('./utils');
var fieldsToArray = utils.fieldsToArray;
var uuid = require('node-uuid');
var deprecated = require('depd')('loopback-datasource-juggler');
const g = require('strong-globalize')();
const util = require('util');
const jutil = require('./jutil');
const List = require('./list');
const DataAccessUtils = require('./model-utils');
const Observer = require('./observer');
const Hookable = require('./hooks');
const validations = require('./validations');
const _extend = util._extend;
const utils = require('./utils');
const fieldsToArray = utils.fieldsToArray;
const uuid = require('uuid');
const {nanoid} = require('nanoid');
// Set up an object for quick lookup
var BASE_TYPES = {
const BASE_TYPES = {
'String': true,
'Boolean': true,
'Number': true,
'Date': true,
'Text': true,
'ObjectID': true
'ObjectID': true,
};
/**
@ -36,10 +47,12 @@ var BASE_TYPES = {
*
* @class
* @param {Object} data Initial object data
* @param {Object} options An object to control the instantiation
* @returns {ModelBaseClass} an instance of the ModelBaseClass
*/
function ModelBaseClass(data, options) {
options = options || {};
if(!('applySetters' in options)) {
if (!('applySetters' in options)) {
// Default to true
options.applySetters = true;
}
@ -59,15 +72,20 @@ function ModelBaseClass(data, options) {
* @property {Boolean} persisted Whether the instance has been persisted
* @private
*/
ModelBaseClass.prototype._initProperties = function (data, options) {
var self = this;
var ctor = this.constructor;
ModelBaseClass.prototype._initProperties = function(data, options) {
const self = this;
const ctor = this.constructor;
if(data instanceof ctor) {
if (typeof data !== 'undefined' && data !== null && data.constructor &&
typeof (data.constructor) !== 'function') {
throw new Error(g.f('Property name "{{constructor}}" is not allowed in %s data', ctor.modelName));
}
if (data instanceof ctor) {
// Convert the data to be plain object to avoid pollutions
data = data.toObject(false);
}
var properties = _extend({}, ctor.definition.properties);
const properties = _extend({}, ctor.definition.properties);
data = data || {};
if (typeof ctor.applyProperties === 'function') {
@ -75,15 +93,19 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
}
options = options || {};
var applySetters = options.applySetters;
var applyDefaultValues = options.applyDefaultValues;
var strict = options.strict;
const applySetters = options.applySetters;
const applyDefaultValues = options.applyDefaultValues;
let strict = options.strict;
if(strict === undefined) {
if (strict === undefined) {
strict = ctor.definition.settings.strict;
} else if (strict === 'throw') {
g.warn('Warning: Model %s, {{strict mode: `throw`}} has been removed, ' +
'please use {{`strict: true`}} instead, which returns' +
'{{`Validation Error`}} for unknown properties,', ctor.modelName);
}
var persistUndefinedAsNull = ctor.definition.settings.persistUndefinedAsNull;
const persistUndefinedAsNull = ctor.definition.settings.persistUndefinedAsNull;
if (ctor.hideInternalProperties) {
// Object.defineProperty() is expensive. We only try to make the internal
@ -94,14 +116,14 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
writable: true,
enumerable: false,
configurable: true,
value: {}
value: {},
},
__data: {
writable: true,
enumerable: false,
configurable: true,
value: {}
value: {},
},
// Instance level data source
@ -109,7 +131,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
writable: true,
enumerable: false,
configurable: true,
value: options.dataSource
value: options.dataSource,
},
// Instance level strict mode
@ -117,23 +139,23 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
writable: true,
enumerable: false,
configurable: true,
value: strict
value: strict,
},
__persisted: {
writable: true,
enumerable: false,
configurable: true,
value: false
value: false,
},
});
if (strict === 'validate') {
if (strict) {
Object.defineProperty(this, '__unknownProperties', {
writable: true,
enumerable: false,
configrable: true,
value: []
value: [],
});
}
} else {
@ -142,7 +164,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
this.__dataSource = options.dataSource;
this.__strict = strict;
this.__persisted = false;
if (strict === 'validate') {
if (strict) {
this.__unknownProperties = [];
}
}
@ -155,7 +177,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
this.__cachedRelations = data.__cachedRelations;
}
var keys = Object.keys(data);
let keys = Object.keys(data);
if (Array.isArray(options.fields)) {
keys = keys.filter(function(k) {
@ -163,9 +185,9 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
});
}
var size = keys.length;
var p, propVal;
for (var k = 0; k < size; k++) {
let size = keys.length;
let p, propVal;
for (let k = 0; k < size; k++) {
p = keys[k];
propVal = data[p];
if (typeof propVal === 'function') {
@ -184,16 +206,18 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
self.__data[p] = propVal;
}
} else if (ctor.relations[p]) {
var relationType = ctor.relations[p].type;
const relationType = ctor.relations[p].type;
var modelTo;
let modelTo;
if (!properties[p]) {
modelTo = ctor.relations[p].modelTo || ModelBaseClass;
var multiple = ctor.relations[p].multiple;
var typeName = multiple ? 'Array' : modelTo.modelName;
var propType = multiple ? [modelTo] : modelTo;
properties[p] = { name: typeName, type: propType };
const multiple = ctor.relations[p].multiple;
const typeName = multiple ? 'Array' : modelTo.modelName;
const propType = multiple ? [modelTo] : modelTo;
properties[p] = {name: typeName, type: propType};
/* Issue #1252
this.setStrict(false);
*/
}
// Relation
@ -202,12 +226,16 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
if (ctor.relations[p].options.embedsProperties) {
var fields = fieldsToArray(ctor.relations[p].properties,
const fields = fieldsToArray(ctor.relations[p].properties,
modelTo.definition.properties, modelTo.settings.strict);
if (!~fields.indexOf(ctor.relations[p].keyTo)) {
fields.push(ctor.relations[p].keyTo);
}
self.__data[p] = new modelTo(propVal, { fields: fields, applySetters: false, persisted: options.persisted });
self.__data[p] = new modelTo(propVal, {
fields: fields,
applySetters: false,
persisted: options.persisted,
});
}
}
@ -218,16 +246,18 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
self[p] = self.__data[p] =
(propVal !== undefined) ? propVal : self.__cachedRelations[p];
// Warn about properties with unsupported names
// Throw error for properties with unsupported names
if (/\./.test(p)) {
deprecated('Property names containing a dot are not supported. ' +
'Model: ' + this.constructor.modelName +
', dynamic property: ' + p);
throw new Error(g.f(
'Property names containing dot(s) are not supported. ' +
'Model: %s, dynamic property: %s',
this.constructor.modelName, p,
));
}
} else {
if (strict !== 'filter') {
this.__unknownProperties.push(p);
}
} else if (strict === 'throw') {
throw new Error('Unknown property: ' + p);
} else if (strict === 'validate') {
this.__unknownProperties.push(p);
}
}
}
@ -242,14 +272,14 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
size = keys.length;
for (k = 0; k < size; k++) {
for (let k = 0; k < size; k++) {
p = keys[k];
propVal = self.__data[p];
var type = properties[p].type;
const type = properties[p].type;
// Set default values
if (applyDefaultValues && propVal === undefined) {
var def = properties[p]['default'];
if (applyDefaultValues && propVal === undefined && appliesDefaultsOnWrites(properties[p])) {
let def = properties[p]['default'];
if (def !== undefined) {
if (typeof def === 'function') {
if (def === Date) {
@ -269,9 +299,13 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
}
}
if (ignoresMatchedDefault(properties[p]) && properties[p].default === propVal) {
delete self.__data[p];
}
// Set default value using a named function
if (applyDefaultValues && propVal === undefined) {
var defn = properties[p].defaultFn;
const defn = properties[p].defaultFn;
switch (defn) {
case undefined:
break;
@ -287,9 +321,13 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
case 'now':
propVal = new Date();
break;
case 'shortid':
case 'nanoid':
propVal = nanoid(9);
break;
default:
// TODO Support user-provided functions via a registry of functions
console.warn('Unknown default value provider ' + defn);
g.warn('Unknown default value provider %s', defn);
}
// FIXME: We should coerce the value
// will implement it after we refactor the PropertyDefinition
@ -303,7 +341,6 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
// Handle complex types (JSON/Object)
if (!BASE_TYPES[type.name]) {
if (typeof self.__data[p] !== 'object' && self.__data[p]) {
try {
self.__data[p] = JSON.parse(self.__data[p] + '');
@ -313,15 +350,16 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
}
if (type.prototype instanceof ModelBaseClass) {
if (!(self.__data[p] instanceof type)
&& typeof self.__data[p] === 'object'
&& self.__data[p] !== null ) {
if (!(self.__data[p] instanceof type) &&
typeof self.__data[p] === 'object' &&
self.__data[p] !== null) {
self.__data[p] = new type(self.__data[p]);
utils.applyParentProperty(self.__data[p], this);
}
} else if (type.name === 'Array' || Array.isArray(type)) {
if (!(self.__data[p] instanceof List)
&& self.__data[p] !== undefined
&& self.__data[p] !== null ) {
if (!(self.__data[p] instanceof List) &&
self.__data[p] !== undefined &&
self.__data[p] !== null) {
self.__data[p] = List(self.__data[p], type, self);
}
}
@ -330,33 +368,58 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
this.trigger('initialize');
};
// Implementation of persistDefaultValues property
function ignoresMatchedDefault(property) {
if (property && property.persistDefaultValues === false) {
return true;
}
}
// Helper function for determing the applyDefaultOnWrites value of a property
function appliesDefaultsOnWrites(property) {
if (property && ('applyDefaultOnWrites' in property)) {
return property.applyDefaultOnWrites;
}
return true;
}
/**
* Define a property on the model.
* @param {String} prop Property name
* @param {Object} params Various property configuration
*/
ModelBaseClass.defineProperty = function (prop, params) {
if(this.dataSource) {
ModelBaseClass.defineProperty = function(prop, params) {
if (this.dataSource) {
this.dataSource.defineProperty(this.modelName, prop, params);
} else {
this.modelBuilder.defineProperty(this.modelName, prop, params);
}
};
ModelBaseClass.getPropertyType = function (propName) {
var prop = this.definition.properties[propName];
/**
* Get model property type.
* @param {String} propName Property name
* @returns {String} Name of property type
*/
ModelBaseClass.getPropertyType = function(propName) {
const prop = this.definition.properties[propName];
if (!prop) {
// The property is not part of the definition
return null;
}
if (!prop.type) {
throw new Error('Type not defined for property ' + this.modelName + '.' + propName);
throw new Error(g.f('Type not defined for property %s.%s', this.modelName, propName));
// return null;
}
return prop.type.name;
};
ModelBaseClass.prototype.getPropertyType = function (propName) {
/**
* Get model property type.
* @param {String} propName Property name
* @returns {String} Name of property type
*/
ModelBaseClass.prototype.getPropertyType = function(propName) {
return this.constructor.getPropertyType(propName);
};
@ -364,7 +427,7 @@ ModelBaseClass.prototype.getPropertyType = function (propName) {
* Return string representation of class
* This overrides the default `toString()` method
*/
ModelBaseClass.toString = function () {
ModelBaseClass.toString = function() {
return '[Model ' + this.modelName + ']';
};
@ -373,29 +436,38 @@ ModelBaseClass.toString = function () {
* Returns a canonical object representation (no getters and setters).
*
* @param {Boolean} onlySchema Restrict properties to dataSource only. Default is false. If true, the function returns only properties defined in the schema; Otherwise it returns all enumerable properties.
* @param {Boolean} removeHidden Boolean flag as part of the transformation. If true, then hidden properties should not be brought out.
* @param {Boolean} removeProtected Boolean flag as part of the transformation. If true, then protected properties should not be brought out.
* @returns {Object} returns Plain JSON object
*/
ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden, removeProtected) {
ModelBaseClass.prototype.toObject = function(onlySchema, removeHidden, removeProtected) {
if (typeof onlySchema === 'object' && onlySchema != null) {
const options = onlySchema;
onlySchema = options.onlySchema;
removeHidden = options.removeHidden;
removeProtected = options.removeProtected;
}
if (onlySchema === undefined) {
onlySchema = true;
}
var data = {};
var self = this;
var Model = this.constructor;
const data = {};
const self = this;
const Model = this.constructor;
// if it is already an Object
if (Model === Object) {
return self;
}
var strict = this.__strict;
var schemaLess = (strict === false) || !onlySchema;
var persistUndefinedAsNull = Model.definition.settings.persistUndefinedAsNull;
const strict = this.__strict;
const schemaLess = (strict === false) || !onlySchema;
const persistUndefinedAsNull = Model.definition.settings.persistUndefinedAsNull;
var props = Model.definition.properties;
var keys = Object.keys(props);
var propertyName, val;
const props = Model.definition.properties;
let keys = Object.keys(props);
let propertyName, val;
for (var i = 0; i < keys.length; i++) {
for (let i = 0; i < keys.length; i++) {
propertyName = keys[i];
val = self[propertyName];
@ -431,8 +503,8 @@ ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden, removePr
// If the property is not declared in the model definition, no setter will be
// triggered to add it to __data
keys = Object.keys(self);
var size = keys.length;
for (i = 0; i < size; i++) {
let size = keys.length;
for (let i = 0; i < size; i++) {
propertyName = keys[i];
if (props[propertyName]) {
continue;
@ -466,7 +538,7 @@ ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden, removePr
// Now continue to check __data
keys = Object.keys(self.__data);
size = keys.length;
for (i = 0; i < size; i++) {
for (let i = 0; i < size; i++) {
propertyName = keys[i];
if (propertyName.indexOf('__') === 0) {
continue;
@ -478,7 +550,7 @@ ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden, removePr
if (removeProtected && Model.isProtectedProperty(propertyName)) {
continue;
}
var ownVal = self[propertyName];
const ownVal = self[propertyName];
// The ownVal can be a relation function
val = (ownVal !== undefined && (typeof ownVal !== 'function')) ? ownVal : self.__data[propertyName];
if (typeof val === 'function') {
@ -499,50 +571,50 @@ ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden, removePr
return data;
};
ModelBaseClass.isProtectedProperty = function (propertyName) {
var Model = this;
var settings = Model.definition && Model.definition.settings;
var protectedProperties = settings && (settings.protectedProperties || settings.protected);
if (Array.isArray(protectedProperties)) {
// Cache the protected properties as an object for quick lookup
settings.protectedProperties = {};
for (var i = 0; i < protectedProperties.length; i++) {
settings.protectedProperties[protectedProperties[i]] = true;
/**
* Convert an array of strings into an object as the map
* @param {string[]} arr An array of strings
*/
function asObjectMap(arr) {
const obj = {};
if (Array.isArray(arr)) {
for (let i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
protectedProperties = settings.protectedProperties;
}
if (protectedProperties) {
return protectedProperties[propertyName];
} else {
return false;
return obj;
}
return arr || obj;
}
/**
* Checks if property is protected.
* @param {String} propertyName Property name
* @returns {Boolean} true or false if protected or not.
*/
ModelBaseClass.isProtectedProperty = function(propertyName) {
const settings = (this.definition && this.definition.settings) || {};
const protectedProperties = settings.protectedProperties || settings.protected;
settings.protectedProperties = asObjectMap(protectedProperties);
return settings.protectedProperties[propertyName];
};
ModelBaseClass.isHiddenProperty = function (propertyName) {
var Model = this;
var settings = Model.definition && Model.definition.settings;
var hiddenProperties = settings && (settings.hiddenProperties || settings.hidden);
if (Array.isArray(hiddenProperties)) {
// Cache the hidden properties as an object for quick lookup
settings.hiddenProperties = {};
for (var i = 0; i < hiddenProperties.length; i++) {
settings.hiddenProperties[hiddenProperties[i]] = true;
}
hiddenProperties = settings.hiddenProperties;
}
if (hiddenProperties) {
return hiddenProperties[propertyName];
} else {
return false;
}
/**
* Checks if property is hidden.
* @param {String} propertyName Property name
* @returns {Boolean} true or false if hidden or not.
*/
ModelBaseClass.isHiddenProperty = function(propertyName) {
const settings = (this.definition && this.definition.settings) || {};
const hiddenProperties = settings.hiddenProperties || settings.hidden;
settings.hiddenProperties = asObjectMap(hiddenProperties);
return settings.hiddenProperties[propertyName];
};
ModelBaseClass.prototype.toJSON = function () {
ModelBaseClass.prototype.toJSON = function() {
return this.toObject(false, true, false);
};
ModelBaseClass.prototype.fromObject = function (obj) {
for (var key in obj) {
ModelBaseClass.prototype.fromObject = function(obj) {
for (const key in obj) {
this[key] = obj[key];
}
};
@ -552,9 +624,9 @@ ModelBaseClass.prototype.fromObject = function (obj) {
* This method does not perform any database operations; it just resets the object to its
* initial state.
*/
ModelBaseClass.prototype.reset = function () {
var obj = this;
for (var k in obj) {
ModelBaseClass.prototype.reset = function() {
const obj = this;
for (const k in obj) {
if (k !== 'id' && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) {
delete obj[k];
}
@ -564,35 +636,48 @@ ModelBaseClass.prototype.reset = function () {
// Node v0.11+ allows custom inspect functions to return an object
// instead of string. That way options like `showHidden` and `colors`
// can be preserved.
var versionParts = process.versions && process.versions.node ?
const versionParts = process.versions && process.versions.node ?
process.versions.node.split(/\./g).map(function(v) { return +v; }) :
[1, 0, 0]; // browserify ships 1.0-compatible version of util.inspect
var INSPECT_SUPPORTS_OBJECT_RETVAL =
const INSPECT_SUPPORTS_OBJECT_RETVAL =
versionParts[0] > 0 ||
versionParts[1] > 11 ||
(versionParts[0] === 11 && versionParts[1] >= 14);
ModelBaseClass.prototype.inspect = function (depth) {
ModelBaseClass.prototype.inspect = function(depth) {
if (INSPECT_SUPPORTS_OBJECT_RETVAL)
return this.__data;
return this.__data;
// Workaround for older versions
// See also https://github.com/joyent/node/commit/66280de133
return util.inspect(this.__data, {
showHidden: false,
depth: depth,
colors: false
colors: false,
});
};
ModelBaseClass.mixin = function (anotherClass, options) {
if (util.inspect.custom) {
// Node.js 12+ no longer recognizes "inspect" method,
// it uses "inspect.custom" symbol as the key instead
// TODO(semver-major) always use the symbol key only (requires Node.js 8+).
ModelBaseClass.prototype[util.inspect.custom] = ModelBaseClass.prototype.inspect;
}
/**
*
* @param {String} anotherClass could be string or class. Name of the class or the class itself
* @param {Object} options An object to control the instantiation
* @returns {ModelClass}
*/
ModelBaseClass.mixin = function(anotherClass, options) {
if (typeof anotherClass === 'string') {
this.modelBuilder.mixins.applyMixin(this, anotherClass, options);
} else {
if (anotherClass.prototype instanceof ModelBaseClass) {
var props = anotherClass.definition.properties;
for (var i in props) {
const props = anotherClass.definition.properties;
for (const i in props) {
if (this.definition.properties[i]) {
continue;
}
@ -603,20 +688,187 @@ ModelBaseClass.mixin = function (anotherClass, options) {
}
};
ModelBaseClass.prototype.getDataSource = function () {
ModelBaseClass.prototype.getDataSource = function() {
return this.__dataSource || this.constructor.dataSource;
};
ModelBaseClass.getDataSource = function () {
ModelBaseClass.getDataSource = function() {
return this.dataSource;
};
ModelBaseClass.prototype.setStrict = function (strict) {
ModelBaseClass.prototype.setStrict = function(strict) {
this.__strict = strict;
};
/**
*
* `getMergePolicy()` provides model merge policies to apply when extending
* a child model from a base model. Such a policy drives the way parent/child model
* properties/settings are merged/mixed-in together.
*
* Below is presented the expected merge behaviour for each option.
* NOTE: This applies to top-level settings properties
*
*
* - Any
* - `{replace: true}` (default): child replaces the value from parent
* - assignin `null` on child setting deletes the inherited setting
*
* - Arrays:
* - `{replace: false}`: unique elements of parent and child cumulate
* - `{rank: true}` adds the model inheritance rank to array
* elements of type Object {} as internal property `__rank`
*
* - Object {}:
* - `{replace: false}`: deep merges parent and child objects
* - `{patch: true}`: child replaces inner properties from parent
*
*
* The recommended built-in merge policy is as follows. It is returned by getMergePolicy()
* when calling the method with option `{configureModelMerge: true}`.
*
* ```
* {
* description: {replace: true}, // string or array
* options: {patch: true}, // object
* hidden: {replace: false}, // array
* protected: {replace: false}, // array
* indexes: {patch: true}, // object
* methods: {patch: true}, // object
* mixins: {patch: true}, // object
* relations: {patch: true}, // object
* scope: {replace: true}, // object
* scopes: {patch: true}, // object
* acls: {rank: true}, // array
* // this setting controls which child model property's value allows deleting
* // a base model's property
* __delete: null,
* // this setting controls the default merge behaviour for settings not defined
* // in the mergePolicy specification
* __default: {replace: true},
* }
* ```
*
* The legacy built-in merge policy is as follows, it is retuned by `getMergePolicy()`
* when avoiding option `configureModelMerge`.
* NOTE: it also provides the ACLs ranking in addition to the legacy behaviour, as well
* as fixes for settings 'description' and 'relations': matching relations from child
* replace relations from parents.
*
* ```
* {
* description: {replace: true}, // string or array
* properties: {patch: true}, // object
* hidden: {replace: false}, // array
* protected: {replace: false}, // array
* relations: {acls: true}, // object
* acls: {rank: true}, // array
* }
* ```
*
*
* `getMergePolicy()` can be customized using model's setting `configureModelMerge` as follows:
*
* ``` json
* {
* // ..
* options: {
* configureModelMerge: {
* // merge options
* }
* }
* // ..
* }
* ```
*
* NOTE: mergePolicy parameter can also defined at JSON model definition root
*
* `getMergePolicy()` method can also be extended programmatically as follows:
*
* ``` js
* myModel.getMergePolicy = function(options) {
* const origin = myModel.base.getMergePolicy(options);
* return Object.assign({}, origin, {
* // new/overriding options
* });
* };
* ```
*
* @param {Object} options option `configureModelMerge` can be used to alter the
* returned merge policy:
* - `configureModelMerge: true` will have the method return the recommended merge policy.
* - `configureModelMerge: {..}` will actually have the method return the provided object.
* - not providing this options will have the method return a merge policy emulating the
* the model merge behaviour up to datasource-juggler v3.6.1, as well as the ACLs ranking.
* @returns {Object} mergePolicy The model merge policy to apply when using the
* current model as base class for a child model
*/
ModelBaseClass.getMergePolicy = function(options) {
// NOTE: merge policy equivalent to datasource-juggler behaviour up to v3.6.1
// + fix for description arrays that should not be merged
// + fix for relations that should patch matching relations
// + ranking of ACLs
let mergePolicy = {
description: {replace: true}, // string or array
properties: {patch: true}, // object
hidden: {replace: false}, // array
protected: {replace: false}, // array
relations: {patch: true}, // object
acls: {rank: true}, // array
};
const config = (options || {}).configureModelMerge;
if (config === true) {
// NOTE: recommended merge policy from datasource-juggler v3.6.2
mergePolicy = {
description: {replace: true}, // string or array
options: {patch: true}, // object
// properties: {patch: true}, // object // NOTE: not part of configurable merge
hidden: {replace: false}, // array
protected: {replace: false}, // array
indexes: {patch: true}, // object
methods: {patch: true}, // object
mixins: {patch: true}, // object
// validations: {patch: true}, // object // NOTE: not implemented
relations: {patch: true}, // object
scope: {replace: true}, // object
scopes: {patch: true}, // object
acls: {rank: true}, // array
// this option controls which value assigned on child model allows deleting
// a base model's setting
__delete: null,
// this option controls the default merge behaviour for settings not defined
// in the mergePolicy specification
__default: {replace: true},
};
}
// override mergePolicy with provided model setting if required
if (config && typeof config === 'object' && !Array.isArray(config)) {
// config is an object
mergePolicy = config;
}
return mergePolicy;
};
/**
* Gets properties defined with 'updateOnly' flag set to true from the model. This flag is also set to true
* internally for the id property, if this property is generated and IdInjection is true.
* @returns {updateOnlyProps} List of properties with updateOnly set to true.
*/
ModelBaseClass.getUpdateOnlyProperties = function() {
const props = this.definition.properties;
return Object.keys(props).filter(key => props[key].updateOnly);
};
// Mix in utils
jutil.mixin(ModelBaseClass, DataAccessUtils);
// Mixin observer
jutil.mixin(ModelBaseClass, require('./observer'));
jutil.mixin(ModelBaseClass, Observer);
jutil.mixin(ModelBaseClass, Hookable);
jutil.mixin(ModelBaseClass, validations.Validatable);

View File

@ -1,10 +1,18 @@
var async = require('async');
var utils = require('./utils');
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const async = require('async');
const utils = require('./utils');
const debug = require('debug')('loopback:observer');
module.exports = ObserverMixin;
/**
* ObserverMixin class. Use to add observe/notifyObserversOf APIs to other
* ObserverMixin class. Use to add observe/notifyObserversOf APIs to other
* classes.
*
* @class ObserverMixin
@ -14,12 +22,30 @@ function ObserverMixin() {
/**
* Register an asynchronous observer for the given operation (event).
*
* Example:
*
* Registers a `before save` observer for a given model.
*
* ```javascript
* MyModel.observe('before save', function filterProperties(ctx, next) {
if (ctx.options && ctx.options.skipPropertyFilter) return next();
if (ctx.instance) {
FILTERED_PROPERTIES.forEach(function(p) {
ctx.instance.unsetAttribute(p);
});
} else {
FILTERED_PROPERTIES.forEach(function(p) {
delete ctx.data[p];
});
}
next();
});
* ```
*
* @param {String} operation The operation name.
* @callback {function} listener The listener function. It will be invoked with
* `this` set to the model constructor, e.g. `User`.
* @param {Object} context Operation-specific context.
* @param {function(Error=)} next The callback to call when the observer
* has finished.
* @end
*/
ObserverMixin.observe = function(operation, listener) {
@ -33,6 +59,16 @@ ObserverMixin.observe = function(operation, listener) {
/**
* Unregister an asynchronous observer for the given operation (event).
*
* Example:
*
* ```javascript
* MyModel.removeObserver('before save', function removedObserver(ctx, next) {
// some logic user want to apply to the removed observer...
next();
});
* ```
*
* @param {String} operation The operation name.
* @callback {function} listener The listener function.
* @end
@ -40,7 +76,7 @@ ObserverMixin.observe = function(operation, listener) {
ObserverMixin.removeObserver = function(operation, listener) {
if (!(this._observers && this._observers[operation])) return;
var index = this._observers[operation].indexOf(listener);
const index = this._observers[operation].indexOf(listener);
if (index !== -1) {
return this._observers[operation].splice(index, 1);
}
@ -48,6 +84,15 @@ ObserverMixin.removeObserver = function(operation, listener) {
/**
* Unregister all asynchronous observers for the given operation (event).
*
* Example:
*
* Remove all observers connected to the `before save` operation.
*
* ```javascript
* MyModel.clearObservers('before save');
* ```
*
* @param {String} operation The operation name.
* @end
*/
@ -59,13 +104,32 @@ ObserverMixin.clearObservers = function(operation) {
/**
* Invoke all async observers for the given operation(s).
*
* Example:
*
* Notify all async observers for the `before save` operation.
*
* ```javascript
* var context = {
Model: Model,
instance: obj,
isNewInstance: true,
hookState: hookState,
options: options,
};
* Model.notifyObserversOf('before save', context, function(err) {
if (err) return cb(err);
// user can specify the logic after the observers have been notified
});
* ```
*
* @param {String|String[]} operation The operation name(s).
* @param {Object} context Operation-specific context.
* @param {function(Error=)} callback The callback to call when all observers
* has finished.
* @callback {function(Error=)} callback The callback to call when all observers
* have finished.
*/
ObserverMixin.notifyObserversOf = function(operation, context, callback) {
var self = this;
const self = this;
if (!callback) callback = utils.createPromiseCallback();
function createNotifier(op) {
@ -79,14 +143,14 @@ ObserverMixin.notifyObserversOf = function(operation, context, callback) {
}
if (Array.isArray(operation)) {
var tasks = [];
for (var i = 0, n = operation.length; i < n; i++) {
const tasks = [];
for (let i = 0, n = operation.length; i < n; i++) {
tasks.push(createNotifier(operation[i]));
}
return async.waterfall(tasks, callback);
}
var observers = this._observers && this._observers[operation];
const observers = this._observers && this._observers[operation];
this._notifyBaseObservers(operation, context, function doNotify(err) {
if (err) return callback(err, context);
@ -95,15 +159,15 @@ ObserverMixin.notifyObserversOf = function(operation, context, callback) {
async.eachSeries(
observers,
function notifySingleObserver(fn, next) {
var retval = fn(context, next);
const retval = fn(context, next);
if (retval && typeof retval.then === 'function') {
retval.then(
function() { next(); return null; },
next // error handler
next, // error handler
);
}
},
function(err) { callback(err, context) }
function(err) { callback(err, context); },
);
});
return callback.promise;
@ -117,23 +181,45 @@ ObserverMixin._notifyBaseObservers = function(operation, context, callback) {
};
/**
* Run the given function with before/after observers. It's done in three serial
* steps asynchronously:
* Run the given function with before/after observers.
*
* It's done in three serial asynchronous steps:
*
* - Notify the registered observers under 'before ' + operation
* - Execute the function
* - Notify the registered observers under 'after ' + operation
*
* If an error happens, it fails fast and calls the callback with err.
* If an error happens, it fails first and calls the callback with err.
*
* Example:
*
* ```javascript
* var context = {
Model: Model,
instance: obj,
isNewInstance: true,
hookState: hookState,
options: options,
};
* function work(done) {
process.nextTick(function() {
done(null, 1);
});
}
* Model.notifyObserversAround('execute', context, work, function(err) {
if (err) return cb(err);
// user can specify the logic after the observers have been notified
});
* ```
*
* @param {String} operation The operation name
* @param {Context} context The context object
* @param {Function} fn The task to be invoked as fn(done) or fn(context, done)
* @param {Function} callback The callback function
* @callback {Function} callback The callback function
* @returns {*}
*/
ObserverMixin.notifyObserversAround = function(operation, context, fn, callback) {
var self = this;
const self = this;
context = context || {};
// Add callback to the context object so that an observer can skip other
// ones by calling the callback function directly and not calling next
@ -146,23 +232,40 @@ ObserverMixin.notifyObserversAround = function(operation, context, fn, callback)
if (err) return callback(err);
function cbForWork(err) {
var args = [].slice.call(arguments, 0);
if (err) return callback.apply(null, args);
const args = [].slice.call(arguments, 0);
if (err) {
// call observer in case of error to hook response
context.error = err;
self.notifyObserversOf('after ' + operation + ' error', context,
function(_err, context) {
if (_err && err) {
debug(
'Operation %j failed and "after %s error" hook returned an error too. ' +
'Calling back with the hook error only.' +
'\nOriginal error: %s\nHook error: %s\n',
err.stack || err,
_err.stack || _err,
);
}
callback.call(null, _err || err, context);
});
return;
}
// Find the list of params from the callback in addition to err
var returnedArgs = args.slice(1);
const returnedArgs = args.slice(1);
// Set up the array of results
context.results = returnedArgs;
// Notify after observers
self.notifyObserversOf('after ' + operation, context,
function(err, context) {
if (err) return callback(err, context);
var results = returnedArgs;
let results = returnedArgs;
if (context && Array.isArray(context.results)) {
// Pickup the results from context
results = context.results;
}
// Build the list of params for final callback
var args = [err].concat(results);
const args = [err].concat(results);
callback.apply(null, args);
});
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,20 @@
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
/*!
* Dependencies
*/
var relation = require('./relation-definition');
var RelationDefinition = relation.RelationDefinition;
const relation = require('./relation-definition');
const RelationDefinition = relation.RelationDefinition;
module.exports = RelationMixin;
/**
* RelationMixin class. Use to define relationships between models.
* RelationMixin class. Use to define relationships between models.
*
* @class RelationMixin
*/
@ -15,13 +22,13 @@ function RelationMixin() {
}
/**
* Define a "one to many" relationship by specifying the model name
*
* Define a "one to many" relationship by specifying the model name.
*
* Examples:
* ```
* User.hasMany(Post, {as: 'posts', foreignKey: 'authorId'});
* ```
*
*
* ```
* Book.hasMany(Chapter);
* ```
@ -34,35 +41,43 @@ function RelationMixin() {
*
* ```js
* Book.create(function(err, book) {
*
*
* // Create a chapter instance ready to be saved in the data source.
* var chapter = book.chapters.build({name: 'Chapter 1'});
*
*
* // Save the new chapter
* chapter.save();
*
*
* // you can also call the Chapter.create method with the `chapters` property which will build a chapter
* // instance and save the it in the data source.
* book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
* // this callback is optional
* // this callback is optional
* });
*
* // Query chapters for the book
* book.chapters(function(err, chapters) { // all chapters with bookId = book.id
*
* // Query chapters for the book
* book.chapters(function(err, chapters) {
* // all chapters with bookId = book.id
* console.log(chapters);
* });
*
*
* // Query chapters for the book with a filter
* book.chapters({where: {name: 'test'}, function(err, chapters) {
* // All chapters with bookId = book.id and name = 'test'
* console.log(chapters);
* });
* });
*```
* ```
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} parameters Configuration parameters; see below.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} foreignKey Property name of foreign key field.
* @property {Object} model Model object
* @property {String} polymorphic Define a polymorphic relation name.
* @property {String} through Name of the through model.
* @property {String} keyThrough Property name of the foreign key in the through model.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Boolean} invert Specify if the relation is inverted.
* @property {Object} model The model object.
*/
RelationMixin.hasMany = function hasMany(modelTo, params) {
return RelationDefinition.hasMany(this, modelTo, params);
@ -86,12 +101,13 @@ RelationMixin.hasMany = function hasMany(modelTo, params) {
* Get the User object for the post author synchronously:
* ```
* post.author();
* ```
* Set the author to be the given user:
* ```
* post.author(user)
* post.author(user)
* ```
* Examples:
*
*
* Suppose the model Post has a *belongsTo* relationship with User (the author of the post). You could declare it this way:
* ```js
* Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
@ -116,15 +132,20 @@ RelationMixin.hasMany = function hasMany(modelTo, params) {
* @param {Class|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} primaryKey Property name of primary key field.
* @property {String} foreignKey Name of foreign key property.
*
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Object} options Property level options.
* @property {Boolean} options.invertProperties Specify if the properties should be inverted.
*/
RelationMixin.belongsTo = function (modelTo, params) {
RelationMixin.belongsTo = function(modelTo, params) {
return RelationDefinition.belongsTo(this, modelTo, params);
};
/**
* A hasAndBelongsToMany relation creates a direct many-to-many connection with another model, with no intervening model.
*
* For example, if your application includes users and groups, with each group having many users and each user appearing
* in many groups, you could declare the models this way:
* ```
@ -144,32 +165,436 @@ RelationMixin.belongsTo = function (modelTo, params) {
* ```
* Remove the user from the group:
* ```
* user.groups.remove(group, callback);
* user.groups.remove(group, callback);
* ```
*
*
* @param {String|Object} modelTo Model object (or String name of model) to which you are creating the relationship.
* the relation
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} foreignKey Property name of foreign key field.
* @property {Object} model Model object
* @property {String} throughTable The table name of the through model.
* @property {String} through Name of the through model.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} model The model object.
*/
RelationMixin.hasAndBelongsToMany = function hasAndBelongsToMany(modelTo, params) {
return RelationDefinition.hasAndBelongsToMany(this, modelTo, params);
};
/**
* Define a "one to one" relationship by specifying the model name.
*
* Examples:
* ```
* Supplier.hasOne(Account, {as: 'account', foreignKey: 'supplierId'});
* ```
*
* If the target model doesnt have a foreign key property, LoopBack will add a property with the same name.
*
* The type of the property will be the same as the type of the target models id property.
*
* Please note the foreign key property is defined on the target model (in this example, Account).
*
* If you dont specify them, then LoopBack derives the relation name and foreign key as follows:
* - Relation name: Camel case of the model name, for example, for the supplier model the relation is supplier.
* - Foreign key: The relation name appended with Id, for example, for relation name supplier the default foreign key is supplierId.
*
* Build a new account for the supplier with the supplierId to be set to the id of the supplier.
* ```js
* var supplier = supplier.account.build(data);
* ```
*
* Create a new account for the supplier. If there is already an account, an error will be reported.
* ```js
* supplier.account.create(data, function(err, account) {
* ...
* });
* ```
*
* Find the supplier's account model.
* ```js
* supplier.account(function(err, account) {
* ...
* });
* ```
*
* Update the associated account.
* ```js
* supplier.account.update({balance: 100}, function(err, account) {
* ...
* });
* ```
*
* Remove the account for the supplier.
* ```js
* supplier.account.destroy(function(err) {
* ...
* });
* ```
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} primaryKey Property name of primary key field.
* @property {String} foreignKey Property name of foreign key field.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} model The model object.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
RelationMixin.hasOne = function hasOne(modelTo, params) {
return RelationDefinition.hasOne(this, modelTo, params);
};
/**
* References one or more instances of the target model.
*
* For example, a Customer model references one or more instances of the Account model.
*
* Define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"accounts": {
"type": "referencesMany",
"model": "Account",
"foreignKey": "accountIds",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of Account model:
* ```json
* {
"name": "Account",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"balance": {
"type": "number"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* On the bootscript, create a customer instance and for that customer instance reference many account instances.
*
* For example:
* ```javascript
* var Customer = app.models.Customer;
var accounts = [
{
name: 'Checking',
balance: 5000
},
{
name: 'Saving',
balance: 2000
}
];
Customer.create({name: 'Mary Smith'}, function(err, customer) {
console.log('Customer:', customer);
async.each(accounts, function(account, done) {
customer.accounts.create(account, done);
}, function(err) {
console.log('Customer with accounts:', customer);
customer.accounts(console.log);
cb(err);
});
});
* ```
*
* Sample referencesMany model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
accounts: [
"saving-01", "checking-01",
]
}
* ```
*
* Supported helper methods:
* - customer.accounts()
* - customer.accounts.create()
* - customer.accounts.build()
* - customer.accounts.findById()
* - customer.accounts.destroy()
* - customer.accounts.updateById()
* - customer.accounts.exists()
* - customer.accounts.add()
* - customer.accounts.remove()
* - customer.accounts.at()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {String} foreignKey Property name of foreign key field.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
RelationMixin.referencesMany = function referencesMany(modelTo, params) {
return RelationDefinition.referencesMany(this, modelTo, params);
};
/**
* Represent a model that embeds another model.
*
* For example, a Customer embeds one billingAddress from the Address model.
*
* - Define the relation in bootscript:
* ```js
* Customer.embedsOne(Address, {
* as: 'address', // default to the relation name - address
* property: 'billingAddress' // default to addressItem
* });
* ```
*
* OR, define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"address": {
"type": "embedsOne",
"model": "Address",
"property": "billingAddress",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of Address model:
* ```json
* {
"name": "Address",
"base": "Model",
"idInjection": true,
"properties": {
"street": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"zipCode": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* Sample embedded model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
billingAddress: {
street: '123 Main St',
city: 'San Jose',
state: 'CA',
zipCode: '95124'
}
}
* ```
*
* Supported helper methods:
* - customer.address()
* - customer.address.build()
* - customer.address.create()
* - customer.address.update()
* - customer.address.destroy()
* - customer.address.value()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} property Name of the property for the embedded item.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
RelationMixin.embedsOne = function embedsOne(modelTo, params) {
return RelationDefinition.embedsOne(this, modelTo, params);
};
/**
* Represent a model that can embed many instances of another model.
*
* For example, a Customer can have multiple email addresses and each email address is a complex object that contains label and address.
*
* Define the relation code in bootscript:
* ```javascript
Customer.embedsMany(EmailAddress, {
as: 'emails', // default to the relation name - emailAddresses
property: 'emailList' // default to emailAddressItems
});
* ```
*
* OR, define the relation in the model definition:
*
* - Definition of Customer model:
* ```json
* {
"name": "Customer",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"validations": [],
"relations": {
"emails": {
"type": "embedsMany",
"model": "EmailAddress",
"property": "emailList",
"options": {
"validate": true,
"forceId": false
}
}
},
"acls": [],
"methods": {}
}
* ```
*
* - Definition of EmailAddress model:
* ```json
* {
"name": "EmailAddress",
"base": "Model",
"idInjection": true,
"properties": {
"label": {
"type": "string"
},
"address": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
* ```
*
* Sample embedded model data:
* ```javascript
* {
id: 1,
name: 'John Smith',
emails: [{
label: 'work',
address: 'john@xyz.com'
}, {
label: 'home',
address: 'john@gmail.com'
}]
}
* ```
*
* Supported helper methods:
* - customer.emails()
* - customer.emails.create()
* - customer.emails.build()
* - customer.emails.findById()
* - customer.emails.destroyById()
* - customer.emails.updateById()
* - customer.emails.exists()
* - customer.emails.add()
* - customer.emails.remove()
* - customer.emails.at()
* - customer.emails.value()
*
* @param {Object|String} modelTo Model object (or String name of model) to which you are creating the relationship.
* @options {Object} params Configuration parameters; see below.
* @property {String} as Name of the property in the referring model that corresponds to the foreign key field in the related model.
* @property {String} property Name of the property for the embedded item.
* @property {Any} default The default value.
* @property {Object} options Options to specify for the relationship.
* @property {Boolean} options.forceId Force generation of id for embedded items. Default is false.
* @property {Boolean} options.validate Denote if the embedded items should be validated. Default is true.
* @property {Boolean} options.persistent Denote if the embedded items should be persisted. Default is false.
* @property {String} polymorphic Define a polymorphic relation name.
* @property {Object|Function} scope Explicitly define additional scopes.
* @property {Object} properties Properties inherited from the parent object.
* @property {Function} methods Scoped methods for the given relation.
*/
RelationMixin.embedsMany = function embedsMany(modelTo, params) {
return RelationDefinition.embedsMany(this, modelTo, params);
};

View File

@ -1,9 +1,21 @@
var i8n = require('inflection');
var utils = require('./utils');
var defineCachedRelations = utils.defineCachedRelations;
var setScopeValuesFromWhere = utils.setScopeValuesFromWhere;
var mergeQuery = utils.mergeQuery;
var DefaultModelBaseClass = require('./model.js');
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const _ = require('lodash');
const i8n = require('inflection');
const g = require('strong-globalize')();
const utils = require('./utils');
const defineCachedRelations = utils.defineCachedRelations;
const setScopeValuesFromWhere = utils.setScopeValuesFromWhere;
const mergeQuery = utils.mergeQuery;
const DefaultModelBaseClass = require('./model.js');
const collectTargetIds = utils.collectTargetIds;
const idName = utils.idName;
const deprecated = require('depd')('loopback-datasource-juggler');
/**
* Module exports
@ -21,14 +33,14 @@ function ScopeDefinition(definition) {
}
ScopeDefinition.prototype.targetModel = function(receiver) {
var modelTo;
let modelTo;
if (typeof this.options.modelTo === 'function') {
modelTo = this.options.modelTo.call(this, receiver) || this.modelTo;
} else {
modelTo = this.modelTo;
}
if (!(modelTo.prototype instanceof DefaultModelBaseClass)) {
var msg = 'Invalid target model for scope `';
let msg = 'Invalid target model for scope `';
msg += (this.isStatic ? this.modelFrom : this.modelFrom.constructor).modelName;
msg += this.isStatic ? '.' : '.prototype.';
msg += this.name + '`.';
@ -47,12 +59,12 @@ ScopeDefinition.prototype.targetModel = function(receiver) {
* @returns {*}
*/
ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefresh, options, cb) {
var name = this.name;
var self = receiver;
const name = this.name;
const self = receiver;
var actualCond = {};
var actualRefresh = false;
var saveOnCache = receiver instanceof DefaultModelBaseClass;
let actualCond = {};
let actualRefresh = false;
let saveOnCache = receiver instanceof DefaultModelBaseClass;
if (typeof condOrRefresh === 'function' &&
options === undefined && cb === undefined) {
// related(receiver, scopeParams, cb)
@ -74,25 +86,86 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
}
}
cb = cb || utils.createPromiseCallback();
if (!self.__cachedRelations || self.__cachedRelations[name] === undefined
|| actualRefresh) {
const refreshIsNeeded = !self.__cachedRelations ||
self.__cachedRelations[name] === undefined ||
actualRefresh;
if (refreshIsNeeded) {
// It either doesn't hit the cache or refresh is required
var params = mergeQuery(actualCond, scopeParams, {nestedInclude: true});
var targetModel = this.targetModel(receiver);
targetModel.find(params, options, function (err, data) {
const params = mergeQuery(actualCond, scopeParams, {nestedInclude: true});
const targetModel = this.targetModel(receiver);
// If there is a through model
// run another query to apply filter on relatedModel(targetModel)
// see github.com/strongloop/loopback-datasource-juggler/issues/166
const scopeOnRelatedModel = params.collect &&
params.include.scope !== null &&
typeof params.include.scope === 'object';
let filter, queryRelated;
if (scopeOnRelatedModel) {
filter = params.include;
// The filter applied on relatedModel
queryRelated = filter.scope;
delete params.include.scope;
}
targetModel.find(params, options, function(err, data) {
if (!err && saveOnCache) {
defineCachedRelations(self);
self.__cachedRelations[name] = data;
}
cb(err, data);
if (scopeOnRelatedModel === true) {
const relatedModel = targetModel.relations[filter.relation].modelTo;
const IdKey = idName(relatedModel);
// return {inq: [1,2,3]}}
const smartMerge = function(idCollection, qWhere) {
if (!qWhere[IdKey]) return idCollection;
let merged = {};
const idsA = idCollection.inq;
const idsB = qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]];
const intersect = _.intersectionWith(idsA, idsB, _.isEqual);
if (intersect.length === 1) merged = intersect[0];
if (intersect.length > 1) merged = {inq: intersect};
return merged;
};
if (queryRelated.where !== undefined) {
// Merge queryRelated filter and targetId filter
const IdKeyCondition = {};
IdKeyCondition[IdKey] = smartMerge(collectTargetIds(data, IdKey),
queryRelated.where);
// if the id in filter doesn't exist after the merge,
// return empty result
if (_.isObject(IdKeyCondition[IdKey]) && _.isEmpty(IdKeyCondition[IdKey])) return cb(null, []);
const mergedWhere = {
and: [
IdKeyCondition,
_.omit(queryRelated.where, IdKey),
],
};
queryRelated.where = mergedWhere;
} else {
queryRelated.where = {};
queryRelated.where[IdKey] = collectTargetIds(data, IdKey);
}
relatedModel.find(queryRelated, options, cb);
} else {
cb(err, data);
}
});
} else {
// Return from cache
cb(null, self.__cachedRelations[name]);
}
return cb.promise;
}
};
/**
* Define a scope method
@ -101,7 +174,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
*/
ScopeDefinition.prototype.defineMethod = function(name, fn) {
return this.methods[name] = fn;
}
};
/**
* Define a scope to the class
@ -130,18 +203,18 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = options || {};
// Check if the cls is the class itself or its prototype
var isStatic = (typeof cls === 'function') || options.isStatic || false;
var definition = new ScopeDefinition({
const isStatic = (typeof cls === 'function') || options.isStatic || false;
const definition = new ScopeDefinition({
isStatic: isStatic,
modelFrom: cls,
modelTo: targetClass,
name: name,
params: params,
methods: methods,
options: options
options: options,
});
if(isStatic) {
if (isStatic) {
cls.scopes = cls.scopes || {};
cls.scopes[name] = definition;
} else {
@ -164,11 +237,11 @@ function defineScope(cls, targetClass, name, params, methods, options) {
* user.accounts.create(act, cb).
*
*/
get: function () {
var targetModel = definition.targetModel(this);
var self = this;
get: function() {
const targetModel = definition.targetModel(this);
const self = this;
var f = function(condOrRefresh, options, cb) {
const f = function(condOrRefresh, options, cb) {
if (arguments.length === 0) {
if (typeof f.value === 'function') {
return f.value(self);
@ -176,8 +249,10 @@ function defineScope(cls, targetClass, name, params, methods, options) {
return self.__cachedRelations[name];
}
} else {
if (typeof condOrRefresh === 'function'
&& options === undefined && cb === undefined) {
const condOrRefreshIsCallBack = typeof condOrRefresh === 'function' &&
options === undefined &&
cb === undefined;
if (condOrRefreshIsCallBack) {
// customer.orders(cb)
cb = condOrRefresh;
options = {};
@ -187,23 +262,14 @@ function defineScope(cls, targetClass, name, params, methods, options) {
cb = options;
options = {};
}
options = options || {}
options = options || {};
// Check if there is a through model
// see https://github.com/strongloop/loopback/issues/1076
if (f._scope.collect &&
condOrRefresh !== null && typeof condOrRefresh === 'object') {
//extract the paging filters to the through model
['limit','offset','skip','order'].forEach(function(pagerFilter){
if(typeof(condOrRefresh[pagerFilter]) !== 'undefined'){
f._scope[pagerFilter] = condOrRefresh[pagerFilter];
delete condOrRefresh[pagerFilter];
}
});
// Adjust the include so that the condition will be applied to
// the target model
f._scope.include = {
relation: f._scope.collect,
scope: condOrRefresh
scope: condOrRefresh,
};
condOrRefresh = {};
}
@ -217,24 +283,28 @@ function defineScope(cls, targetClass, name, params, methods, options) {
f._targetClass = targetModel.modelName;
if (f._scope.collect) {
f._targetClass = i8n.camelize(f._scope.collect);
const rel = targetModel.relations[f._scope.collect];
f._targetClass = rel && rel.modelTo && rel.modelTo.modelName || i8n.camelize(f._scope.collect);
}
f.getAsync = function(condOrRefresh, options, cb) {
if (typeof condOrRefresh === 'function'
&& options === undefined && cb === undefined) {
// customer.orders.getAsync(cb)
f.find = function(condOrRefresh, options, cb) {
if (typeof condOrRefresh === 'function' &&
options === undefined && cb === undefined) {
cb = condOrRefresh;
options = {};
condOrRefresh = {};
} else if (typeof options === 'function' && cb === undefined) {
// customer.orders.getAsync(condOrRefresh, cb);
cb = options;
options = {};
}
options = options || {}
options = options || {};
return definition.related(self, f._scope, condOrRefresh, options, cb);
}
};
f.getAsync = function() {
deprecated(g.f('Scope method "getAsync()" is deprecated, use "find()" instead.'));
return this.find.apply(this, arguments);
};
f.build = build;
f.create = create;
@ -244,7 +314,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
f.findOne = findOne;
f.count = count;
for (var i in definition.methods) {
for (const i in definition.methods) {
f[i] = definition.methods[i].bind(self);
}
@ -254,77 +324,77 @@ function defineScope(cls, targetClass, name, params, methods, options) {
// Station.scope('active', {where: {isActive: true}});
// Station.scope('subway', {where: {isUndeground: true}});
// Station.active.subway(cb);
Object.keys(targetClass._scopeMeta).forEach(function (name) {
Object.keys(targetClass._scopeMeta).forEach(function(name) {
Object.defineProperty(f, name, {
enumerable: false,
get: function () {
get: function() {
mergeQuery(f._scope, targetModel._scopeMeta[name]);
return f;
}
},
});
}.bind(self));
return f;
}
},
});
// Wrap the property into a function for remoting
var fn = function () {
const fn = function() {
// primaryObject.scopeName, such as user.accounts
var f = this[name];
const f = this[name];
// set receiver to be the scope property whose value is a function
f.apply(this[name], arguments);
};
cls['__get__' + name] = fn;
var fn_create = function () {
var f = this[name].create;
const fnCreate = function() {
const f = this[name].create;
f.apply(this[name], arguments);
};
cls['__create__' + name] = fn_create;
cls['__create__' + name] = fnCreate;
var fn_delete = function () {
var f = this[name].destroyAll;
const fnDelete = function() {
const f = this[name].destroyAll;
f.apply(this[name], arguments);
};
cls['__delete__' + name] = fn_delete;
cls['__delete__' + name] = fnDelete;
var fn_update = function () {
var f = this[name].updateAll;
const fnUpdate = function() {
const f = this[name].updateAll;
f.apply(this[name], arguments);
};
cls['__update__' + name] = fn_update;
cls['__update__' + name] = fnUpdate;
var fn_findById = function (cb) {
var f = this[name].findById;
const fnFindById = function(cb) {
const f = this[name].findById;
f.apply(this[name], arguments);
};
cls['__findById__' + name] = fn_findById;
cls['__findById__' + name] = fnFindById;
var fn_findOne = function (cb) {
var f = this[name].findOne;
const fnFindOne = function(cb) {
const f = this[name].findOne;
f.apply(this[name], arguments);
};
cls['__findOne__' + name] = fn_findOne;
cls['__findOne__' + name] = fnFindOne;
var fn_count = function (cb) {
var f = this[name].count;
const fnCount = function(cb) {
const f = this[name].count;
f.apply(this[name], arguments);
};
cls['__count__' + name] = fn_count;
cls['__count__' + name] = fnCount;
// and it should have create/build methods with binded thisModelNameId param
function build(data) {
data = data || {};
// Find all fixed property values for the scope
var targetModel = definition.targetModel(this._receiver);
var where = (this._scope && this._scope.where) || {};
const targetModel = definition.targetModel(this._receiver);
const where = (this._scope && this._scope.where) || {};
setScopeValuesFromWhere(data, where, targetModel);
return new targetModel(data);
}
@ -362,9 +432,9 @@ function defineScope(cls, targetClass, name, params, methods, options) {
}
options = options || {};
var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {} });
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.destroyAll(filter.where, options, cb);
}
@ -382,9 +452,9 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {} });
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.updateAll(filter.where, data, options, cb);
}
@ -407,12 +477,12 @@ function defineScope(cls, targetClass, name, params, methods, options) {
}
}
}
options = options || {};
filter = filter || {};
var targetModel = definition.targetModel(this._receiver);
var idName = targetModel.definition.idName();
var query = {where: {}};
const targetModel = definition.targetModel(this._receiver);
const idName = targetModel.definition.idName();
let query = {where: {}};
query.where[idName] = id;
query = mergeQuery(query, filter);
return this.findOne(query, options, cb);
@ -430,9 +500,9 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {};
filter = mergeQuery({ where: scoped }, filter || {});
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
filter = mergeQuery({where: scoped}, filter || {});
return targetModel.findOne(filter, options, cb);
}
@ -448,9 +518,9 @@ function defineScope(cls, targetClass, name, params, methods, options) {
}
options = options || {};
var targetModel = definition.targetModel(this._receiver);
var scoped = (this._scope && this._scope.where) || {};
var filter = mergeQuery({ where: scoped }, { where: where || {} });
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
return targetModel.count(filter.where, options, cb);
}

View File

@ -1,10 +1,18 @@
var debug = require('debug')('loopback:connector:transaction');
var uuid = require('node-uuid');
var utils = require('./utils');
var jutil = require('./jutil');
var ObserverMixin = require('./observer');
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var Transaction = require('loopback-connector').Transaction;
'use strict';
const g = require('strong-globalize')();
const debug = require('debug')('loopback:connector:transaction');
const uuid = require('uuid');
const utils = require('./utils');
const jutil = require('./jutil');
const ObserverMixin = require('./observer');
const Transaction = require('loopback-connector').Transaction;
module.exports = TransactionMixin;
@ -17,35 +25,9 @@ function TransactionMixin() {
}
/**
* Begin a new transaction
* @param {Object|String} [options] Options can be one of the forms:
* - Object: {isolationLevel: '...', timeout: 1000}
* - String: isolationLevel
* Begin a new transaction.
*
* Valid values of `isolationLevel` are:
*
* - Transaction.READ_COMMITTED = 'READ COMMITTED'; // default
* - Transaction.READ_UNCOMMITTED = 'READ UNCOMMITTED';
* - Transaction.SERIALIZABLE = 'SERIALIZABLE';
* - Transaction.REPEATABLE_READ = 'REPEATABLE READ';
*
* @param {Function} cb Callback function. It calls back with (err, transaction).
* To pass the transaction context to one of the CRUD methods, use the `options`
* argument with `transaction` property, for example,
*
* ```js
*
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
* MyModel.create({x: 1, y: 'a'}, {transaction: tx}, function(err, inst) {
* MyModel.find({x: 1}, {transaction: tx}, function(err, results) {
* // ...
* tx.commit(function(err) {...});
* });
* });
* });
* ```
*
* The transaction can be committed or rolled back. If timeout happens, the
* A transaction can be committed or rolled back. If timeout happens, the
* transaction will be rolled back. Please note a transaction is typically
* associated with a pooled connection. Committing or rolling back a transaction
* will release the connection back to the pool.
@ -58,22 +40,57 @@ function TransactionMixin() {
* source/connector instance. CRUD methods will not join the current transaction
* if its model is not attached the same data source.
*
* Example:
*
* To pass the transaction context to one of the CRUD methods, use the `options`
* argument with `transaction` property, for example,
*
* ```js
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
* MyModel.create({x: 1, y: 'a'}, {transaction: tx}, function(err, inst) {
* MyModel.find({x: 1}, {transaction: tx}, function(err, results) {
* // ...
* tx.commit(function(err) {...});
* });
* });
* });
* ```
*
* @param {Object|String} options Options to be passed upon transaction.
*
* Can be one of the forms:
* - Object: {isolationLevel: '...', timeout: 1000}
* - String: isolationLevel
*
* Valid values of `isolationLevel` are:
*
* - Transaction.READ_COMMITTED = 'READ COMMITTED'; // default
* - Transaction.READ_UNCOMMITTED = 'READ UNCOMMITTED';
* - Transaction.SERIALIZABLE = 'SERIALIZABLE';
* - Transaction.REPEATABLE_READ = 'REPEATABLE READ';
* @callback {Function} cb Callback function.
* @returns {Promise|undefined} Returns a callback promise.
*/
TransactionMixin.beginTransaction = function(options, cb) {
cb = cb || utils.createPromiseCallback();
if (Transaction) {
var connector = this.getConnector();
const connector = this.getConnector();
Transaction.begin(connector, options, function(err, transaction) {
if (err) return cb(err);
if (transaction) {
// NOTE(lehni) As part of the process of moving the handling of
// transaction id and timeout from TransactionMixin.beginTransaction() to
// Transaction.begin() in loopback-connector, switch to only setting id
// and timeout if it wasn't taken care of already by Transaction.begin().
// Eventually, we can remove the following two if-blocks altogether.
if (!transaction.id) {
// Set an informational transaction id
transaction.id = uuid.v1();
}
if (options.timeout) {
setTimeout(function() {
var context = {
if (options.timeout && !transaction.timeout) {
transaction.timeout = setTimeout(function() {
const context = {
transaction: transaction,
operation: 'timeout'
operation: 'timeout',
};
transaction.notifyObserversOf('timeout', context, function(err) {
if (!err) {
@ -89,7 +106,7 @@ TransactionMixin.beginTransaction = function(options, cb) {
});
} else {
process.nextTick(function() {
var err = new Error('Transaction is not supported');
const err = new Error(g.f('{{Transaction}} is not supported'));
cb(err);
});
}
@ -100,73 +117,93 @@ TransactionMixin.beginTransaction = function(options, cb) {
if (Transaction) {
jutil.mixin(Transaction.prototype, ObserverMixin);
/**
* Commit a transaction and release it back to the pool
* @param {Function} cb Callback function
* @returns {Promise|undefined}
* Commit a transaction and release it back to the pool.
*
* Example:
*
* ```js
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
* // some crud operation of your choice
* tx.commit(function(err) {
* // release the connection pool upon committing
* tx.close(err);
* });
* });
* ```
*
* @callback {Function} cb Callback function.
* @returns {Promise|undefined} Returns a callback promise.
*/
Transaction.prototype.commit = function(cb) {
var self = this;
cb = cb || utils.createPromiseCallback();
// Report an error if the transaction is not active
if (!self.connection) {
process.nextTick(function() {
cb(new Error('The transaction is not active: ' + self.id));
});
return cb.promise;
if (this.ensureActive(cb)) {
const context = {
transaction: this,
operation: 'commit',
};
this.notifyObserversAround('commit', context,
done => {
this.connector.commit(this.connection, done);
},
err => {
// Deference the connection to mark the transaction is not active
// The connection should have been released back the pool
this.connection = null;
cb(err);
});
}
var context = {
transaction: self,
operation: 'commit'
};
function work(done) {
self.connector.commit(self.connection, done);
}
self.notifyObserversAround('commit', context, work, function(err) {
// Deference the connection to mark the transaction is not active
// The connection should have been released back the pool
self.connection = null;
cb(err);
});
return cb.promise;
};
/**
* Rollback a transaction and release it back to the pool
* @param {Function} cb Callback function
* @returns {Promise|undefined}
* Rollback a transaction and release it back to the pool.
*
* Example:
*
* ```js
* MyModel.beginTransaction('READ COMMITTED', function(err, tx) {
* // some crud operation of your choice
* tx.rollback(function(err) {
* // release the connection pool upon committing
* tx.close(err);
* });
* });
* ```
*
* @callback {Function} cb Callback function.
* @returns {Promise|undefined} Returns a callback promise.
*/
Transaction.prototype.rollback = function(cb) {
var self = this;
cb = cb || utils.createPromiseCallback();
// Report an error if the transaction is not active
if (!self.connection) {
process.nextTick(function() {
cb(new Error('The transaction is not active: ' + self.id));
});
return cb.promise;
if (this.ensureActive(cb)) {
const context = {
transaction: this,
operation: 'rollback',
};
this.notifyObserversAround('rollback', context,
done => {
this.connector.rollback(this.connection, done);
},
err => {
// Deference the connection to mark the transaction is not active
// The connection should have been released back the pool
this.connection = null;
cb(err);
});
}
var context = {
transaction: self,
operation: 'rollback'
};
function work(done) {
self.connector.rollback(self.connection, done);
}
self.notifyObserversAround('rollback', context, work, function(err) {
// Deference the connection to mark the transaction is not active
// The connection should have been released back the pool
self.connection = null;
cb(err);
});
return cb.promise;
};
Transaction.prototype.ensureActive = function(cb) {
// Report an error if the transaction is not active
if (!this.connection) {
process.nextTick(() => {
cb(new Error(g.f('The {{transaction}} is not active: %s', this.id)));
});
}
return !!this.connection;
};
Transaction.prototype.toJSON = function() {
return this.id;
};
@ -177,5 +214,3 @@ if (Transaction) {
}
TransactionMixin.Transaction = Transaction;

View File

@ -1,4 +1,11 @@
var Types = {};
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const Types = {};
/**
* Schema types
*/
@ -9,7 +16,7 @@ Types.Text = function Text(value) {
this.value = value;
}; // Text type
Types.Text.prototype.toObject = Types.Text.prototype.toJSON = function () {
Types.Text.prototype.toObject = Types.Text.prototype.toJSON = function() {
return this.value;
};
@ -19,7 +26,7 @@ Types.JSON = function JSON(value) {
}
this.value = value;
}; // JSON Object
Types.JSON.prototype.toObject = Types.JSON.prototype.toJSON = function () {
Types.JSON.prototype.toObject = Types.JSON.prototype.toJSON = function() {
return this.value;
};
@ -29,23 +36,23 @@ Types.Any = function Any(value) {
}
this.value = value;
}; // Any Type
Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function () {
Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function() {
return this.value;
};
module.exports = function (modelTypes) {
module.exports = function(modelTypes) {
const DateString = require('./date-string');
const GeoPoint = require('./geo').GeoPoint;
var GeoPoint = require('./geo').GeoPoint;
for(var t in Types) {
for (const t in Types) {
modelTypes[t] = Types[t];
}
modelTypes.schemaTypes = {};
modelTypes.registerType = function (type, names) {
modelTypes.registerType = function(type, names) {
names = names || [];
names = names.concat([type.name]);
for (var n = 0; n < names.length; n++) {
for (let n = 0; n < names.length; n++) {
this.schemaTypes[names[n].toLowerCase()] = type;
}
};
@ -58,10 +65,11 @@ module.exports = function (modelTypes) {
modelTypes.registerType(Number);
modelTypes.registerType(Boolean);
modelTypes.registerType(Date);
modelTypes.registerType(DateString);
modelTypes.registerType(Buffer, ['Binary']);
modelTypes.registerType(Array);
modelTypes.registerType(GeoPoint);
modelTypes.registerType(Object);
};
module.exports.Types = Types;
module.exports.Types = Types;

View File

@ -1,9 +1,17 @@
// Copyright IBM Corp. 2012,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
exports.safeRequire = safeRequire;
exports.fieldsToArray = fieldsToArray;
exports.selectFields = selectFields;
exports.removeUndefined = removeUndefined;
exports.sanitizeQuery = sanitizeQuery;
exports.parseSettings = parseSettings;
exports.mergeSettings = exports.deepMerge = mergeSettings;
exports.mergeSettings = exports.deepMerge = deepMerge;
exports.deepMergeProperty = deepMergeProperty;
exports.isPlainObject = isPlainObject;
exports.defineCachedRelations = defineCachedRelations;
exports.sortObjectsByIds = sortObjectsByIds;
@ -16,17 +24,38 @@ exports.toRegExp = toRegExp;
exports.hasRegExpFlags = hasRegExpFlags;
exports.idEquals = idEquals;
exports.findIndexOf = findIndexOf;
exports.collectTargetIds = collectTargetIds;
exports.idName = idName;
exports.rankArrayElements = rankArrayElements;
exports.idsHaveDuplicates = idsHaveDuplicates;
exports.isClass = isClass;
exports.escapeRegExp = escapeRegExp;
exports.applyParentProperty = applyParentProperty;
var traverse = require('traverse');
var assert = require('assert');
const g = require('strong-globalize')();
const traverse = require('traverse');
const assert = require('assert');
const debug = require('debug')('loopback:juggler:utils');
/**
* The name of the property in modelBuilder settings that will enable the child parent reference functionality
* @type {string}
*/
const BUILDER_PARENT_SETTING = 'parentRef';
/**
* The property name that should be defined on each child instance if parent feature flag enabled
* @type {string}
*/
const PARENT_PROPERTY_NAME = '__parent';
function safeRequire(module) {
try {
return require(module);
} catch (e) {
console.log('Run "npm install loopback-datasource-juggler ' + module
+ '" command to use loopback-datasource-juggler using ' + module
+ ' database engine');
g.log('Run "{{npm install loopback-datasource-juggler}} %s" command ',
'to use {{loopback-datasource-juggler}} using %s database engine',
module, module);
process.exit(1);
}
}
@ -39,20 +68,20 @@ function safeRequire(module) {
* @param {Object} The where clause
*/
function setScopeValuesFromWhere(data, where, targetModel) {
for (var i in where) {
for (const i in where) {
if (i === 'and') {
// Find fixed property values from each subclauses
for (var w = 0, n = where[i].length; w < n; w++) {
for (let w = 0, n = where[i].length; w < n; w++) {
setScopeValuesFromWhere(data, where[i][w], targetModel);
}
continue;
}
var prop = targetModel.definition.properties[i];
const prop = targetModel.definition.properties[i];
if (prop) {
var val = where[i];
if (typeof val !== 'object' || val instanceof prop.type
|| prop.type.name === 'ObjectID') // MongoDB key
{
const val = where[i];
if (typeof val !== 'object' || val instanceof prop.type ||
prop.type.name === 'ObjectID' || // MongoDB key
prop.type.name === 'uuidFromString') { // C*
// Only pick the {propertyName: propertyValue}
data[i] = where[i];
}
@ -69,26 +98,26 @@ function setScopeValuesFromWhere(data, where, targetModel) {
* @returns {Object}
*/
function mergeIncludes(destination, source) {
var destArray = convertToArray(destination);
var sourceArray = convertToArray(source);
const destArray = convertToArray(destination);
const sourceArray = convertToArray(source);
if (destArray.length === 0) {
return sourceArray;
}
if (sourceArray.length === 0) {
return destArray;
}
var relationNames = [];
var resultArray = [];
for (var j in sourceArray) {
var sourceEntry = sourceArray[j];
var sourceEntryRelationName = (typeof (sourceEntry.rel || sourceEntry.relation) === 'string') ?
const relationNames = [];
const resultArray = [];
for (const j in sourceArray) {
const sourceEntry = sourceArray[j];
const sourceEntryRelationName = (typeof (sourceEntry.rel || sourceEntry.relation) === 'string') ?
sourceEntry.relation : Object.keys(sourceEntry)[0];
relationNames.push(sourceEntryRelationName);
resultArray.push(sourceEntry);
}
for (var i in destArray) {
var destEntry = destArray[i];
var destEntryRelationName = (typeof (destEntry.rel || destEntry.relation) === 'string') ?
for (const i in destArray) {
const destEntry = destArray[i];
const destEntryRelationName = (typeof (destEntry.rel || destEntry.relation) === 'string') ?
destEntry.relation : Object.keys(destEntry)[0];
if (relationNames.indexOf(destEntryRelationName) === -1) {
resultArray.push(destEntry);
@ -107,32 +136,31 @@ function mergeIncludes(destination, source) {
*/
function convertToArray(include) {
if (typeof include === 'string') {
var obj = {};
const obj = {};
obj[include] = true;
return [obj];
} else if (isPlainObject(include)) {
//if include is of the form - {relation:'',scope:''}
// if include is of the form - {relation:'',scope:''}
if (include.rel || include.relation) {
return [include];
}
// Build an array of key/value pairs
var newInclude = [];
for (var key in include) {
var obj = {};
const newInclude = [];
for (const key in include) {
const obj = {};
obj[key] = include[key];
newInclude.push(obj);
}
return newInclude;
} else if (Array.isArray(include)) {
var normalized = [];
for (var i in include) {
var includeEntry = include[i];
const normalized = [];
for (const i in include) {
const includeEntry = include[i];
if (typeof includeEntry === 'string') {
var obj = {};
const obj = {};
obj[includeEntry] = true;
normalized.push(obj)
}
else{
normalized.push(obj);
} else {
normalized.push(includeEntry);
}
}
@ -169,17 +197,16 @@ function mergeQuery(base, update, spec) {
if (!base.include) {
base.include = update.include;
} else {
if (spec.nestedInclude === true){
//specify nestedInclude=true to force nesting of inclusions on scoped
//queries. e.g. In physician.patients.getAsync({include: 'address'}),
//inclusion should be on patient model, not on physician model.
var saved = base.include;
if (spec.nestedInclude === true) {
// specify nestedInclude=true to force nesting of inclusions on scoped
// queries. e.g. In physician.patients.find({include: 'address'}),
// inclusion should be on patient model, not on physician model.
const saved = base.include;
base.include = {};
base.include[update.include] = saved;
}
else{
//default behaviour of inclusion merge - merge inclusions at the same
//level. - https://github.com/strongloop/loopback-datasource-juggler/pull/569#issuecomment-95310874
} else {
// default behaviour of inclusion merge - merge inclusions at the same
// level. - https://github.com/strongloop/loopback-datasource-juggler/pull/569#issuecomment-95310874
base.include = mergeIncludes(base.include, update.include);
}
}
@ -206,7 +233,7 @@ function mergeQuery(base, update, spec) {
base.limit = update.limit;
}
var skip = spec.skip !== false && spec.offset !== false;
const skip = spec.skip !== false && spec.offset !== false;
if (skip && update.skip !== undefined) {
base.skip = update.skip;
@ -230,8 +257,8 @@ function fieldsToArray(fields, properties, excludeUnknown) {
if (!fields) return;
// include all properties by default
var result = properties;
var i, n;
let result = properties;
let i, n;
if (typeof fields === 'string') {
result = [fields];
@ -240,13 +267,13 @@ function fieldsToArray(fields, properties, excludeUnknown) {
result = fields;
} else if ('object' === typeof fields) {
// { field1: boolean, field2: boolean ... }
var included = [];
var excluded = [];
var keys = Object.keys(fields);
const included = [];
const excluded = [];
const keys = Object.keys(fields);
if (!keys.length) return;
for (i = 0, n = keys.length; i < n; i++) {
var k = keys[i];
const k = keys[i];
if (fields[k]) {
included.push(k);
} else if ((k in fields) && !fields[k]) {
@ -257,13 +284,13 @@ function fieldsToArray(fields, properties, excludeUnknown) {
result = included;
} else if (excluded.length > 0) {
for (i = 0, n = excluded.length; i < n; i++) {
var index = result.indexOf(excluded[i]);
result.splice(index, 1);
const index = result.indexOf(excluded[i]);
if (index !== -1) result.splice(index, 1); // only when existing field excluded
}
}
}
var fieldArray = [];
let fieldArray = [];
if (excludeUnknown) {
for (i = 0, n = result.length; i < n; i++) {
if (properties.indexOf(result[i]) !== -1) {
@ -278,11 +305,11 @@ function fieldsToArray(fields, properties, excludeUnknown) {
function selectFields(fields) {
// map function
return function (obj) {
var result = {};
var key;
return function(obj) {
const result = {};
let key;
for (var i = 0; i < fields.length; i++) {
for (let i = 0; i < fields.length; i++) {
key = fields[i];
result[key] = obj[key];
@ -291,46 +318,144 @@ function selectFields(fields) {
};
}
function isProhibited(key, prohibitedKeys) {
if (!prohibitedKeys || !prohibitedKeys.length) return false;
if (typeof key !== 'string') {
return false;
}
for (const k of prohibitedKeys) {
if (k === key) return true;
// x.secret, secret.y, or x.secret.y
if (key.split('.').indexOf(k) !== -1) return true;
}
return false;
}
/**
* Remove undefined values from the queury object
* @param query
* @param handleUndefined {String} either "nullify", "throw" or "ignore" (default: "ignore")
* @returns {exports.map|*}
* Accept an operator key and return whether it is used for a regular expression query or not
* @param {string} operator
* @returns {boolean}
*/
function removeUndefined(query, handleUndefined) {
function isRegExpOperator(operator) {
return ['like', 'nlike', 'ilike', 'nilike', 'regexp'].includes(operator);
}
/**
* Accept a RegExp string and make sure that any special characters for RegExp are escaped in case they
* create an invalid Regexp
* @param {string} str
* @returns {string}
*/
function escapeRegExp(str) {
assert.strictEqual(typeof str, 'string', 'String required for regexp escaping');
try {
new RegExp(str); // try to parse string as regexp
return str;
} catch (unused) {
console.warn(
'Auto-escaping invalid RegExp value %j supplied by the caller. ' +
'Please note this behavior may change in the future.',
str,
);
return str.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, '\\$&');
}
}
/**
* Sanitize the query object
* @param query {object} The query object
* @param options
* @property normalizeUndefinedInQuery {String} either "nullify", "throw" or "ignore" (default: "ignore")
* @property prohibitedKeys {String[]} An array of prohibited keys to be removed
* @returns {*}
*/
function sanitizeQuery(query, options) {
debug('Sanitizing query object: %j', query);
if (typeof query !== 'object' || query === null) {
return query;
}
options = options || {};
if (typeof options === 'string') {
// Keep it backward compatible
options = {normalizeUndefinedInQuery: options};
}
const prohibitedKeys = options.prohibitedKeys;
const offendingKeys = [];
const normalizeUndefinedInQuery = options.normalizeUndefinedInQuery;
const maxDepth = options.maxDepth || Number.MAX_SAFE_INTEGER;
// WARNING: [rfeng] Use map() will cause mongodb to produce invalid BSON
// as traverse doesn't transform the ObjectId correctly
return traverse(query).forEach(function (x) {
const result = traverse(query).forEach(function(x) {
/**
* Security risk if the client passes in a very deep where object
*/
if (this.circular) {
const msg = g.f('The query object is circular');
const err = new Error(msg);
err.statusCode = 400;
err.code = 'QUERY_OBJECT_IS_CIRCULAR';
throw err;
}
if (this.level > maxDepth) {
const msg = g.f('The query object exceeds maximum depth %d', maxDepth);
const err = new Error(msg);
err.statusCode = 400;
err.code = 'QUERY_OBJECT_TOO_DEEP';
throw err;
}
/**
* Make sure prohibited keys are removed from the query to prevent
* sensitive values from being guessed
*/
if (isProhibited(this.key, prohibitedKeys)) {
offendingKeys.push(this.key);
this.remove();
return;
}
/**
* Handle undefined values
*/
if (x === undefined) {
switch (handleUndefined) {
switch (normalizeUndefinedInQuery) {
case 'nullify':
this.update(null);
break;
case 'throw':
throw new Error('Unexpected `undefined` in query');
break;
throw new Error(g.f('Unexpected `undefined` in query'));
case 'ignore':
default:
this.remove();
}
}
if (!Array.isArray(x) && (typeof x === 'object' && x !== null
&& x.constructor !== Object)) {
if (!Array.isArray(x) && (typeof x === 'object' && x !== null &&
x.constructor !== Object)) {
// This object is not a plain object
this.update(x, true); // Stop navigating into this object
return x;
}
if (isRegExpOperator(this.key) && typeof x === 'string') { // we have regexp supporting operator and string to escape
return escapeRegExp(x);
}
return x;
});
if (offendingKeys.length) {
console.error(
g.f(
'Potential security alert: hidden/protected properties %j are used in query.',
offendingKeys,
),
);
}
return result;
}
var url = require('url');
var qs = require('qs');
const url = require('url');
const qs = require('qs');
/**
* Parse a URL into a settings object
@ -341,18 +466,18 @@ function parseSettings(urlStr) {
if (!urlStr) {
return {};
}
var uri = url.parse(urlStr, false);
var settings = {};
const uri = url.parse(urlStr, false);
const settings = {};
settings.connector = uri.protocol && uri.protocol.split(':')[0]; // Remove the trailing :
settings.host = settings.hostname = uri.hostname;
settings.port = uri.port && Number(uri.port); // port is a string
settings.user = settings.username = uri.auth && uri.auth.split(':')[0]; // <username>:<password>
settings.password = uri.auth && uri.auth.split(':')[1];
settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading /
settings.database = uri.pathname && uri.pathname.split('/')[1]; // remove the leading /
settings.url = urlStr;
if (uri.query) {
var params = qs.parse(uri.query);
for (var p in params) {
const params = qs.parse(uri.query);
for (const p in params) {
settings[p] = params[p];
}
}
@ -360,52 +485,64 @@ function parseSettings(urlStr) {
}
/**
* Merge model settings
* Objects deep merge
*
* Folked from https://github.com/nrf110/deepmerge/blob/master/index.js
* Forked from https://github.com/nrf110/deepmerge/blob/master/index.js
*
* The original function tries to merge array items if they are objects
* The original function tries to merge array items if they are objects, this
* was changed to always push new items in arrays, independently of their type.
*
* @param {Object} target The target settings object
* @param {Object} src The source settings object
* @returns {Object} The merged settings object
* NOTE: The function operates as a deep clone when called with a single object
* argument.
*
* @param {Object} base The base object
* @param {Object} extras The object to merge with base
* @returns {Object} The merged object
*/
function mergeSettings(target, src) {
var array = Array.isArray(src);
var dst = array && [] || {};
function deepMerge(base, extras) {
// deepMerge allows undefined extras to allow deep cloning of arrays
const array = Array.isArray(base) && (Array.isArray(extras) || !extras);
let dst = array && [] || {};
if (array) {
target = target || [];
// Add items from target into dst
dst = dst.concat(target);
// Add non-existent items from source into dst
src.forEach(function(e) {
// extras or base is an array
extras = extras || [];
// Add items from base into dst
dst = dst.concat(base);
// Add non-existent items from extras into dst
extras.forEach(function(e) {
if (dst.indexOf(e) === -1) {
dst.push(e);
}
});
} else {
if (target != null && typeof target === 'object') {
// Add properties from target to dst
Object.keys(target).forEach(function(key) {
dst[key] = target[key];
if (base != null && typeof base === 'object') {
// Add properties from base to dst
Object.keys(base).forEach(function(key) {
if (base[key] && typeof base[key] === 'object') {
// call deepMerge on nested object to operate a deep clone
dst[key] = deepMerge(base[key]);
} else {
dst[key] = base[key];
}
});
}
if (src != null && typeof src === 'object') {
// Source is an object
Object.keys(src).forEach(function(key) {
var srcValue = src[key];
if (srcValue == null || typeof srcValue !== 'object') {
// The source item value is null, undefined or not an object
dst[key] = srcValue;
if (extras != null && typeof extras === 'object') {
// extras is an object {}
Object.keys(extras).forEach(function(key) {
const extra = extras[key];
if (extra == null || typeof extra !== 'object') {
// extra item value is null, undefined or not an object
dst[key] = extra;
} else {
// The source item value is an object
if (target == null || typeof target !== 'object' ||
target[key] == null) {
// If target is not an object or target item value
dst[key] = srcValue;
// The extra item value is an object
if (base == null || typeof base !== 'object' ||
base[key] == null) {
// base is not an object or base item value is undefined or null
dst[key] = extra;
} else {
dst[key] = mergeSettings(target[key], src[key]);
// call deepMerge on nested object
dst[key] = deepMerge(base[key], extra);
}
}
});
@ -415,6 +552,57 @@ function mergeSettings(target, src) {
return dst;
}
/**
* Properties deep merge
* Similar as deepMerge but also works on single properties of any type
*
* @param {Object} base The base property
* @param {Object} extras The property to merge with base
* @returns {Object} The merged property
*/
function deepMergeProperty(base, extras) {
const mergedObject = deepMerge({key: base}, {key: extras});
const mergedProperty = mergedObject.key;
return mergedProperty;
}
const numberIsFinite = Number.isFinite || function(value) {
return typeof value === 'number' && isFinite(value);
};
/**
* Adds a property __rank to array elements of type object {}
* If an inner element already has the __rank property it is not altered
* NOTE: the function mutates the provided array
*
* @param array The original array
* @param rank The rank to apply to array elements
* @return rankedArray The original array with newly ranked elements
*/
function rankArrayElements(array, rank) {
if (!Array.isArray(array) || !numberIsFinite(rank))
return array;
array.forEach(function(el) {
// only apply ranking on objects {} in array
if (!el || typeof el != 'object' || Array.isArray(el))
return;
// property rank is already defined for array element
if (el.__rank)
return;
// define rank property as non-enumerable and read-only
Object.defineProperty(el, '__rank', {
writable: false,
enumerable: false,
configurable: false,
value: rank,
});
});
return array;
}
/**
* Define an non-enumerable __cachedRelations property
* @param {Object} obj The obj to receive the __cachedRelations
@ -425,48 +613,46 @@ function defineCachedRelations(obj) {
writable: true,
enumerable: false,
configurable: true,
value: {}
value: {},
});
}
}
/**
* Check if the argument is plain object
* @param {*) obj The obj value
* @param {*} obj The obj value
* @returns {boolean}
*/
function isPlainObject(obj) {
return (typeof obj === 'object') && (obj !== null)
&& (obj.constructor === Object);
return (typeof obj === 'object') && (obj !== null) &&
(obj.constructor === Object);
}
function sortObjectsByIds(idName, ids, objects, strict) {
ids = ids.map(function(id) {
return (typeof id === 'object') ? String(id) : id;
return (typeof id === 'object') ? String(id) : id;
});
var indexOf = function(x) {
var isObj = (typeof x[idName] === 'object'); // ObjectID
var id = isObj ? String(x[idName]) : x[idName];
const indexOf = function(x) {
const isObj = (typeof x[idName] === 'object'); // ObjectID
const id = isObj ? String(x[idName]) : x[idName];
return ids.indexOf(id);
};
var heading = [];
var tailing = [];
const heading = [];
const tailing = [];
objects.forEach(function(x) {
if (typeof x === 'object') {
var idx = indexOf(x);
const idx = indexOf(x);
if (strict && idx === -1) return;
idx === -1 ? tailing.push(x) : heading.push(x);
}
});
heading.sort(function(x, y) {
var a = indexOf(x);
var b = indexOf(y);
const a = indexOf(x);
const b = indexOf(y);
if (a === -1 || b === -1) return 1; // last
if (a === b) return 0;
if (a > b) return 1;
@ -474,21 +660,12 @@ function sortObjectsByIds(idName, ids, objects, strict) {
});
return heading.concat(tailing);
};
}
function createPromiseCallback() {
var cb;
if (!global.Promise) {
cb = function(){};
cb.promise = {};
Object.defineProperty(cb.promise, 'then', { get: throwPromiseNotDefined });
Object.defineProperty(cb.promise, 'catch', { get: throwPromiseNotDefined });
return cb;
}
var promise = new Promise(function (resolve, reject) {
cb = function (err, data) {
let cb;
const promise = new Promise(function(resolve, reject) {
cb = function(err, data) {
if (err) return reject(err);
return resolve(data);
};
@ -497,10 +674,10 @@ function createPromiseCallback() {
return cb;
}
function throwPromiseNotDefined() {
throw new Error(
'Your Node runtime does support ES6 Promises. ' +
'Set "global.Promise" to your preferred implementation of promises.');
function isBsonType(value) {
// bson@1.x stores _bsontype on ObjectID instance, bson@4.x on prototype
return value.hasOwnProperty('_bsontype') ||
value.constructor.prototype.hasOwnProperty('_bsontype');
}
/**
@ -509,13 +686,16 @@ function throwPromiseNotDefined() {
* @returns {Array} an array with unique items
*/
function uniq(a) {
var uniqArray = [];
const uniqArray = [];
if (!a) {
return uniqArray;
}
assert(Array.isArray(a), 'array argument is required');
for (var i = 0, n = a.length; i < n; i++) {
if (a.indexOf(a[i]) === i) {
const comparableA = a.map(
item => isBsonType(item) ? item.toString() : item,
);
for (let i = 0, n = comparableA.length; i < n; i++) {
if (comparableA.indexOf(comparableA[i]) === i) {
uniqArray.push(a[i]);
}
}
@ -528,12 +708,12 @@ function uniq(a) {
* @returns {Object} A RegExp object
*/
function toRegExp(regex) {
var isString = typeof regex === 'string';
var isRegExp = regex instanceof RegExp;
const isString = typeof regex === 'string';
const isRegExp = regex instanceof RegExp;
if (!(isString || isRegExp))
return new Error('Invalid argument, must be a string, regex literal, or ' +
'RegExp object');
return new Error(g.f('Invalid argument, must be a string, {{regex}} literal, or ' +
'{{RegExp}} object'));
if (isRegExp)
return regex;
@ -542,20 +722,20 @@ function toRegExp(regex) {
return new RegExp(regex);
// only accept i, g, or m as valid regex flags
var flags = regex.split('/').pop().split('');
var validFlags = ['i', 'g', 'm'];
var invalidFlags = [];
const flags = regex.split('/').pop().split('');
const validFlags = ['i', 'g', 'm'];
const invalidFlags = [];
flags.forEach(function(flag) {
if (validFlags.indexOf(flag) === -1)
invalidFlags.push(flag);
});
var hasInvalidFlags = invalidFlags.length > 0;
const hasInvalidFlags = invalidFlags.length > 0;
if (hasInvalidFlags)
return new Error('Invalid regex flags: ' + invalidFlags);
return new Error(g.f('Invalid {{regex}} flags: %s', invalidFlags));
// strip regex delimiter forward slashes
var expression = regex.substr(1, regex.lastIndexOf('/') - 1);
const expression = regex.substr(1, regex.lastIndexOf('/') - 1);
return new RegExp(expression, flags.join(''));
}
@ -593,9 +773,123 @@ function findIndexOf(arr, target, isEqual) {
return arr.indexOf(target);
}
for (var i = 0; i < arr.length; i++) {
for (let i = 0; i < arr.length; i++) {
if (isEqual(arr[i], target)) { return i; }
};
}
return -1;
}
/**
* Returns an object that queries targetIds.
* @param {Array} The array of targetData
* @param {String} The Id property name of target model
* @returns {Object} The object that queries targetIds
*/
function collectTargetIds(targetData, idPropertyName) {
const targetIds = [];
for (let i = 0; i < targetData.length; i++) {
const targetId = targetData[i][idPropertyName];
targetIds.push(targetId);
}
const IdQuery = {
inq: uniq(targetIds),
};
return IdQuery;
}
/**
* Find the idKey of a Model.
* @param {ModelConstructor} m - Model Constructor
* @returns {String}
*/
function idName(m) {
return m.definition.idName() || 'id';
}
/**
* Check a list of IDs to see if there are any duplicates.
*
* @param {Array} The array of IDs to check
* @returns {boolean} If any duplicates were found
*/
function idsHaveDuplicates(ids) {
// use Set if available and all ids are of string or number type
let hasDuplicates = undefined;
let i, j;
if (typeof Set === 'function') {
const uniqueIds = new Set();
for (i = 0; i < ids.length; ++i) {
const idType = typeof ids[i];
if (idType === 'string' || idType === 'number') {
if (uniqueIds.has(ids[i])) {
hasDuplicates = true;
break;
} else {
uniqueIds.add(ids[i]);
}
} else {
// ids are not all string/number that can be checked via Set, stop and do the slow test
break;
}
}
if (hasDuplicates === undefined && uniqueIds.size === ids.length) {
hasDuplicates = false;
}
}
if (hasDuplicates === undefined) {
// fast check was inconclusive or unavailable, do the slow check
// can still optimize this by doing 1/2 N^2 instead of the full N^2
for (i = 0; i < ids.length && hasDuplicates === undefined; ++i) {
for (j = 0; j < i; ++j) {
if (idEquals(ids[i], ids[j])) {
hasDuplicates = true;
break;
}
}
}
}
return hasDuplicates === true;
}
function isClass(fn) {
return fn && fn.toString().startsWith('class ');
}
/**
* Accept an element, and attach the __parent property to it, unless no object given, while also
* making sure to check for already created properties
*
* @param {object} element
* @param {Model} parent
*/
function applyParentProperty(element, parent) {
assert.strictEqual(typeof element, 'object', 'Non object element given to assign parent');
const {constructor: {modelBuilder: {settings: builderSettings} = {}} = {}} = element;
if (!builderSettings || !builderSettings[BUILDER_PARENT_SETTING]) {
// parentRef flag not enabled on ModelBuilder settings
return;
}
if (element.hasOwnProperty(PARENT_PROPERTY_NAME)) {
// property already created on model, just assign
const existingParent = element[PARENT_PROPERTY_NAME];
if (existingParent && existingParent !== parent) {
// parent re-assigned (child model assigned to other model instance)
g.warn('Re-assigning child model instance to another parent than the original!\n' +
'Although supported, this is not a recommended practice: ' +
`${element.constructor.name} -> ${parent.constructor.name}\n` +
'You should create an independent copy of the child model using `new Model(CHILD)` OR ' +
'`new Model(CHILD.toJSON())` and assign to new parent');
}
element[PARENT_PROPERTY_NAME] = parent;
} else {
// first time defining the property on the element
Object.defineProperty(element, PARENT_PROPERTY_NAME, {
value: parent,
writable: true,
enumerable: false,
configurable: false,
});
}
}

View File

@ -1,5 +1,13 @@
var util = require('util');
var extend = util._extend;
// Copyright IBM Corp. 2013,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
const g = require('strong-globalize')();
const util = require('util');
const extend = util._extend;
/*!
* Module exports
@ -24,6 +32,7 @@ function Validatable() {
/**
* Validate presence of one or more specified properties.
*
* Requires a model to include a property to be considered valid; fails when validated field is blank.
*
* For example, validate presence of title
@ -40,34 +49,43 @@ function Validatable() {
* ```
*
* @param {String} propertyName One or more property names.
* @options {Object} errMsg Optional custom error message. Default is "can't be blank"
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
Validatable.validatesPresenceOf = getConfigurator('presence');
/**
* Validate absence of one or more specified properties.
* A model should not include a property to be considered valid; fails when validated field not blank.
*
* A model should not include a property to be considered valid; fails when validated field is not blank.
*
* For example, validate absence of reserved
* ```
* Post.validatesAbsenceOf('reserved', { unless: 'special' });
* ```
*
* @param {String} propertyName One or more property names.
* @options {Object} errMsg Optional custom error message. Default is "can't be set"
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
Validatable.validatesAbsenceOf = getConfigurator('absence');
/**
* Validate length. Require a property length to be within a specified range.
* Three kinds of validations: min, max, is.
* Validate length.
*
* Require a property length to be within a specified range.
*
* There are three kinds of validations: min, max, is.
*
* Default error messages:
*
* - min: too short
* - max: too long
* - is: length is wrong
* - is: length is wrong
*
* Example: length validations
* ```
@ -81,36 +99,42 @@ Validatable.validatesAbsenceOf = getConfigurator('absence');
* User.validatesLengthOf('password', {min: 7, message: {min: 'too weak'}});
* User.validatesLengthOf('state', {is: 2, message: {is: 'is not valid state name'}});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options See below.
* @options {Object} options Configuration parameters; see below.
* @property {Number} is Value that property must equal to validate.
* @property {Number} min Value that property must be less than to be valid.
* @property {Number} max Value that property must be less than to be valid.
* @property {Object} message Optional Object with string properties for custom error message for each validation: is, min, or max
* @property {Object} message Optional object with string properties for custom error message for each validation: is, min, or max.
*/
Validatable.validatesLengthOf = getConfigurator('length');
/**
* Validate numericality. Requires a value for property to be either an integer or number.
* Validate numericality.
*
* Requires a value for property to be either an integer or number.
*
* Example
* ```
* User.validatesNumericalityOf('age', { message: { number: '...' }});
* User.validatesNumericalityOf('age', {int: true, message: { int: '...' }});
* User.validatesNumericalityOf('age', { message: { number: 'is not a number' }});
* User.validatesNumericalityOf('age', {int: true, message: { int: 'is not an integer' }});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options See below.
* @options {Object} options Configuration parameters; see below.
* @property {Boolean} int If true, then property must be an integer to be valid.
* @property {Object} message Optional object with string properties for 'int' for integer validation. Default error messages:
*
* @property {Boolean} allowBlank Allow property to be blank.
* @property {Boolean} allowNull Allow property to be null.
* @property {Object} message Optional object with string properties for 'int' for integer validation. Default error messages:
* - number: is not a number
* - int: is not an integer
*/
Validatable.validatesNumericalityOf = getConfigurator('numericality');
/**
* Validate inclusion in set. Require a value for property to be in the specified array.
* Validate inclusion in set.
*
* Require a value for property to be in the specified array.
*
* Example:
* ```
@ -121,34 +145,41 @@ Validatable.validatesNumericalityOf = getConfigurator('numericality');
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options
* @property {Array} inArray Property must match one of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid. Default error message: "is not included in the list".
* @options {Object} options Configuration parameters; see below.
* @property {Array} in Property must match one of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid.
* Default error message: "is not included in the list".
* @property {Boolean} allowNull Whether null values are allowed.
*/
Validatable.validatesInclusionOf = getConfigurator('inclusion');
/**
* Validate exclusion. Require a property value not be in the specified array.
* Validate exclusion in a set.
*
* Require a property value not be in the specified array.
*
* Example: `Company.validatesExclusionOf('domain', {in: ['www', 'admin']});`
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options
* @property {Array} inArray Property must match one of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid. Default error message: "is reserved".
* @options {Object} options Configuration parameters; see below.
* @property {Array} in Property must not match any of the values in the array to be valid.
* @property {String} message Optional error message if property is not valid. Default error message: "is reserved".
* @property {Boolean} allowNull Whether null values are allowed.
*/
Validatable.validatesExclusionOf = getConfigurator('exclusion');
/**
* Validate format. Require a model to include a property that matches the given format.
* Validate format.
*
* Require a model to include a property that matches the given format. Example:
* `User.validatesFormat('name', {with: /\w+/});`
* Require a model to include a property that matches the given format.
*
* Example: `User.validatesFormatOf('name', {with: /\w+/});`
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options
* @options {Object} options Configuration parameters; see below.
* @property {RegExp} with Regular expression to validate format.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
Validatable.validatesFormatOf = getConfigurator('format');
@ -156,7 +187,7 @@ Validatable.validatesFormatOf = getConfigurator('format');
* Validate using custom validation function.
*
* Example:
*
*```javascript
* User.validate('name', customValidator, {message: 'Bad name'});
* function customValidator(err) {
* if (this.name === 'bad') err();
@ -165,18 +196,19 @@ Validatable.validatesFormatOf = getConfigurator('format');
* user.isValid(); // true
* user.name = 'bad';
* user.isValid(); // false
* ```
*
* @param {String} propertyName Property name to validate.
* @param {Function} validatorFn Custom validation function.
* @options {Object} Options See below.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @options {Object} options Configuration parameters; see below.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
Validatable.validate = getConfigurator('custom');
/**
* Validate using custom asynchronous validation function.
*
*
* Example:
*```js
* User.validateAsync('name', customValidator, {message: 'Bad name'});
@ -196,16 +228,19 @@ Validatable.validate = getConfigurator('custom');
* user.isValid(function (isValid) {
* isValid; // false
* })
*```
* ```
*
* @param {String} propertyName Property name to validate.
* @param {Function} validatorFn Custom validation function.
* @options {Object} Options See below
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @options {Object} options Configuration parameters; see below.
* @property {String} message Optional error message if property is not valid. Default error message: " is invalid".
* @property {Boolean} allowNull Whether null values are allowed.
*/
Validatable.validateAsync = getConfigurator('custom', {async: true});
/**
* Validate uniqueness. Ensure the value for property is unique in the collection of models.
* Validate uniqueness of the value for a property in the collection of models.
*
* Not available for all connectors. Currently supported with these connectors:
* - In Memory
* - Oracle
@ -219,21 +254,39 @@ Validatable.validateAsync = getConfigurator('custom', {async: true});
* // The login must be unique within each Site.
* SiteUser.validateUniquenessOf('login', { scopedTo: ['siteId'] });
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} Options See below.
* @options {Object} options Configuration parameters; see below.
* @property {RegExp} with Regular expression to validate format.
* @property {Array.<String>} scopedTo List of properties defining the scope.
* @property {String} message Optional error message if property is not valid. Default error message: "is not unique".
* @property {String} message Optional error message if property is not valid. Default error message: "is not unique".
* @property {Boolean} allowNull Whether null values are allowed.
* @property {String} ignoreCase Make the validation case insensitive.
* @property {String} if Validate only if `if` exists.
* @property {String} unless Validate only if `unless` exists.
*/
Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true});
/**
* Validate if a value for a property is a Date.
*
* Example
* ```
* User.validatesDateOf('today', {message: 'today is not a date!'});
* ```
*
* @param {String} propertyName Property name to validate.
* @options {Object} options Configuration parameters; see below.
* @property {String} message Error message to use instead of default.
*/
Validatable.validatesDateOf = getConfigurator('date');
// implementation of validators
/*!
* Presence validator
*/
function validatePresence(attr, conf, err) {
function validatePresence(attr, conf, err, options) {
if (blank(this[attr])) {
err();
}
@ -242,7 +295,7 @@ function validatePresence(attr, conf, err) {
/*!
* Absence validator
*/
function validateAbsence(attr, conf, err) {
function validateAbsence(attr, conf, err, options) {
if (!blank(this[attr])) {
err();
}
@ -251,10 +304,10 @@ function validateAbsence(attr, conf, err) {
/*!
* Length validator
*/
function validateLength(attr, conf, err) {
function validateLength(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
var len = this[attr].length;
const len = this[attr].length;
if (conf.min && len < conf.min) {
err('min');
}
@ -269,10 +322,10 @@ function validateLength(attr, conf, err) {
/*!
* Numericality validator
*/
function validateNumericality(attr, conf, err) {
function validateNumericality(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (typeof this[attr] !== 'number') {
if (typeof this[attr] !== 'number' || isNaN(this[attr])) {
return err('number');
}
if (conf.int && this[attr] !== Math.round(this[attr])) {
@ -283,33 +336,34 @@ function validateNumericality(attr, conf, err) {
/*!
* Inclusion validator
*/
function validateInclusion(attr, conf, err) {
function validateInclusion(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (!~conf.in.indexOf(this[attr])) {
err()
err();
}
}
/*!
* Exclusion validator
*/
function validateExclusion(attr, conf, err) {
function validateExclusion(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (~conf.in.indexOf(this[attr])) {
err()
err();
}
}
/*!
* Format validator
*/
function validateFormat(attr, conf, err) {
function validateFormat(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (typeof this[attr] === 'string') {
if (!this[attr].match(conf['with'])) {
if (typeof this[attr] === 'string' || typeof this[attr] === 'number') {
const regex = new RegExp(conf['with']);
if (!regex.test(this[attr])) {
err();
}
} else {
@ -320,45 +374,89 @@ function validateFormat(attr, conf, err) {
/*!
* Custom validator
*/
function validateCustom(attr, conf, err, done) {
conf.customValidator.call(this, err, done);
function validateCustom(attr, conf, err, options, done) {
if (typeof options === 'function') {
done = options;
options = {};
}
if (!done) {
// called from a sync validator, stick options on end
conf.customValidator.call(this, err, options);
} else {
if (conf.customValidator.length === 3) {
// if they declared the validator with 3 args, they are expecting options
conf.customValidator.call(this, err, options, done);
} else {
// otherwise just pass the expected two (no context)
conf.customValidator.call(this, err, done);
}
}
}
function escapeStringRegexp(str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
const matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
return str.replace(matchOperatorsRe, '\\$&');
}
/*!
* Uniqueness validator
*/
function validateUniqueness(attr, conf, err, done) {
function validateUniqueness(attr, conf, err, options, done) {
if (typeof options === 'function') {
done = options;
options = {};
}
if (blank(this[attr])) {
return process.nextTick(done);
}
var cond = {where: {}};
cond.where[attr] = this[attr];
const cond = {where: {}};
if (conf && conf.ignoreCase) {
cond.where[attr] = new RegExp('^' + escapeStringRegexp(this[attr]) + '$', 'i');
} else {
cond.where[attr] = this[attr];
}
if (conf && conf.scopedTo) {
conf.scopedTo.forEach(function(k) {
var val = this[k];
const val = this[k];
if (val !== undefined)
cond.where[k] = this[k];
}, this);
}
var idName = this.constructor.definition.idName();
var isNewRecord = this.isNewRecord();
this.constructor.find(cond, function (error, found) {
const idName = this.constructor.definition.idName();
const isNewRecord = this.isNewRecord();
this.constructor.find(cond, options, function(error, found) {
if (error) {
err(error);
} else if (found.length > 1) {
err();
} else if (found.length === 1 && idName === attr && isNewRecord) {
err();
} else if (found.length === 1 && (!this.id || !found[0].id || found[0].id.toString() != this.id.toString())) {
} else if (found.length === 1 && (
!this.id || !found[0].id || found[0].id.toString() != this.id.toString()
)) {
err();
}
done();
}.bind(this));
}
var validators = {
/*!
* Date validator
*/
function validateDate(attr, conf, err) {
if (this[attr] === null || this[attr] === undefined) return;
const date = new Date(this[attr]);
if (isNaN(date.getTime())) return err();
}
const validators = {
presence: validatePresence,
absence: validateAbsence,
length: validateLength,
@ -367,12 +465,13 @@ var validators = {
exclusion: validateExclusion,
format: validateFormat,
custom: validateCustom,
uniqueness: validateUniqueness
uniqueness: validateUniqueness,
date: validateDate,
};
function getConfigurator(name, opts) {
return function () {
var args = Array.prototype.slice.call(arguments);
return function() {
const args = Array.prototype.slice.call(arguments);
args[1] = args[1] || {};
configure(this, name, args, opts);
};
@ -387,15 +486,15 @@ function getConfigurator(name, opts) {
* NOTE: This method can be called as synchronous only when no asynchronous validation is
* configured. It's strongly recommended to run all validations as asyncronous.
*
* Example: ExpressJS controller: render user if valid, show flash otherwise
* ```
* Example: ExpressJS controller - render user if valid, show flash otherwise
* ```javascript
* user.isValid(function (valid) {
* if (valid) res.render({user: user});
* else res.flash('error', 'User is not valid'), console.log(user.errors), res.redirect('/users');
* });
* ```
* Another example:
* ```
* ```javascript
* user.isValid(function (valid) {
* if (!valid) {
* console.log(user.errors);
@ -407,22 +506,26 @@ function getConfigurator(name, opts) {
* }
* });
* ```
* @param {Function} callback called with (valid)
* @callback {Function} callback Called with (valid).
* @param {Object} data Data to be validated.
* @param {Object} options Options to be specified upon validation.
* @returns {Boolean} True if no asynchronous validation is configured and all properties pass validation.
*/
Validatable.prototype.isValid = function (callback, data) {
var valid = true, inst = this, wait = 0, async = false;
var validations = this.constructor.validations;
Validatable.prototype.isValid = function(callback, data, options) {
options = options || {};
let valid = true, wait = 0, async = false;
const inst = this;
const validations = this.constructor.validations;
var reportDiscardedProperties = this.__strict === 'validate' &&
const reportDiscardedProperties = this.__strict &&
this.__unknownProperties && this.__unknownProperties.length;
// exit with success when no errors
if (typeof validations !== 'object' && !reportDiscardedProperties) {
cleanErrors(this);
if (callback) {
this.trigger('validate', function (validationsDone) {
validationsDone.call(inst, function () {
this.trigger('validate', function(validationsDone) {
validationsDone.call(inst, function() {
callback(valid);
});
}, data, callback);
@ -433,26 +536,26 @@ Validatable.prototype.isValid = function (callback, data) {
Object.defineProperty(this, 'errors', {
enumerable: false,
configurable: true,
value: new Errors
value: new Errors,
});
this.trigger('validate', function (validationsDone) {
var inst = this,
asyncFail = false;
this.trigger('validate', function(validationsDone) {
const inst = this;
let asyncFail = false;
var attrs = Object.keys(validations || {});
const attrs = Object.keys(validations || {});
attrs.forEach(function(attr) {
var attrValidations = validations[attr] || [];
const attrValidations = validations[attr] || [];
attrValidations.forEach(function(v) {
if (v.options && v.options.async) {
async = true;
wait += 1;
process.nextTick(function () {
validationFailed(inst, attr, v, done);
process.nextTick(function() {
validationFailed(inst, attr, v, options, done);
});
} else {
if (validationFailed(inst, attr, v)) {
if (validationFailed(inst, attr, v, options)) {
valid = false;
}
}
@ -460,17 +563,17 @@ Validatable.prototype.isValid = function (callback, data) {
});
if (reportDiscardedProperties) {
for (var ix in inst.__unknownProperties) {
var key = inst.__unknownProperties[ix];
var code = 'unknown-property';
var msg = defaultMessages[code];
for (const ix in inst.__unknownProperties) {
const key = inst.__unknownProperties[ix];
const code = 'unknown-property';
const msg = defaultMessages[code];
inst.errors.add(key, msg, code);
valid = false;
}
}
if (!async) {
validationsDone.call(inst, function () {
validationsDone.call(inst, function() {
if (valid) cleanErrors(inst);
if (callback) {
callback(valid);
@ -481,7 +584,7 @@ Validatable.prototype.isValid = function (callback, data) {
function done(fail) {
asyncFail = asyncFail || fail;
if (--wait === 0) {
validationsDone.call(inst, function () {
validationsDone.call(inst, function() {
if (valid && !asyncFail) cleanErrors(inst);
if (callback) {
callback(valid && !asyncFail);
@ -489,7 +592,6 @@ Validatable.prototype.isValid = function (callback, data) {
});
}
}
}, data, callback);
if (async) {
@ -499,37 +601,41 @@ Validatable.prototype.isValid = function (callback, data) {
} else {
return valid;
}
};
function cleanErrors(inst) {
Object.defineProperty(inst, 'errors', {
enumerable: false,
configurable: true,
value: false
value: false,
});
}
function validationFailed(inst, attr, conf, cb) {
var opts = conf.options || {};
function validationFailed(inst, attr, conf, options, cb) {
const opts = conf.options || {};
if (typeof options === 'function') {
cb = options;
options = {};
}
if (typeof attr !== 'string') return false;
// here we should check skip validation conditions (if, unless)
// that can be specified in conf
if (skipValidation(inst, conf, 'if')
|| skipValidation(inst, conf, 'unless')) {
if (skipValidation(inst, conf, 'if') ||
skipValidation(inst, conf, 'unless')) {
if (cb) cb(false);
return false;
}
var fail = false;
var validator = validators[conf.validation];
var validatorArguments = [];
let fail = false;
const validator = validators[conf.validation];
const validatorArguments = [];
validatorArguments.push(attr);
validatorArguments.push(conf);
validatorArguments.push(function onerror(kind) {
var message, code = conf.code || conf.validation;
let message, code = conf.code || conf.validation;
if (conf.message) {
message = conf.message;
}
@ -553,8 +659,9 @@ function validationFailed(inst, attr, conf, cb) {
if (kind !== false) inst.errors.add(attr, message, code);
fail = true;
});
validatorArguments.push(options);
if (cb) {
validatorArguments.push(function () {
validatorArguments.push(function() {
cb(fail);
});
}
@ -563,7 +670,7 @@ function validationFailed(inst, attr, conf, cb) {
}
function skipValidation(inst, conf, kind) {
var doValidate = true;
let doValidate = true;
if (typeof conf[kind] === 'function') {
doValidate = conf[kind].call(inst);
if (kind === 'unless') doValidate = !doValidate;
@ -581,38 +688,50 @@ function skipValidation(inst, conf, kind) {
return !doValidate;
}
var defaultMessages = {
const defaultMessages = {
presence: 'can\'t be blank',
absence: 'can\'t be set',
'unknown-property': 'is not defined in the model',
length: {
min: 'too short',
max: 'too long',
is: 'length is wrong'
is: 'length is wrong',
},
common: {
blank: 'is blank',
'null': 'is null'
'null': 'is null',
},
numericality: {
'int': 'is not an integer',
'number': 'is not a number'
'number': 'is not a number',
},
inclusion: 'is not included in the list',
exclusion: 'is reserved',
uniqueness: 'is not unique'
uniqueness: 'is not unique',
date: 'is not a valid date',
};
/**
* Checks if attribute is undefined or null. Calls err function with 'blank' or 'null'.
* See defaultMessages. You can affect this behaviour with conf.allowBlank and conf.allowNull.
* @private
* @param {String} attr Property name of attribute
* @param {Object} conf conf object for validator
* @param {Function} err
* @return {Boolean} returns true if attribute is null or blank
*/
function nullCheck(attr, conf, err) {
if (this[attr] == null) {
if (!conf.allowNull) {
err('null');
// First determine if attribute is defined
if (typeof this[attr] === 'undefined' || this[attr] === '') {
if (!conf.allowBlank) {
err('blank');
}
return true;
} else {
if (blank(this[attr])) {
if (!conf.allowBlank) {
err('blank');
// Now check if attribute is null
if (this[attr] === null) {
if (!conf.allowNull) {
err('null');
}
return true;
}
@ -642,11 +761,11 @@ function configure(cls, validation, args, opts) {
writable: true,
configurable: true,
enumerable: false,
value: {}
value: {},
});
}
args = [].slice.call(args);
var conf;
let conf;
if (typeof args[args.length - 1] === 'object') {
conf = args.pop();
} else {
@ -656,9 +775,9 @@ function configure(cls, validation, args, opts) {
conf.customValidator = args.pop();
}
conf.validation = validation;
args.forEach(function (attr) {
args.forEach(function(attr) {
if (typeof attr === 'string') {
var validation = extend({}, conf);
const validation = extend({}, conf);
validation.options = opts || {};
cls.validations[attr] = cls.validations[attr] || [];
cls.validations[attr].push(validation);
@ -670,11 +789,11 @@ function Errors() {
Object.defineProperty(this, 'codes', {
enumerable: false,
configurable: true,
value: {}
value: {},
});
}
Errors.prototype.add = function (field, message, code) {
Errors.prototype.add = function(field, message, code) {
code = code || 'invalid';
if (!this[field]) {
this[field] = [];
@ -685,8 +804,8 @@ Errors.prototype.add = function (field, message, code) {
};
function ErrorCodes(messages) {
var c = this;
Object.keys(messages).forEach(function (field) {
const c = this;
Object.keys(messages).forEach(function(field) {
c[field] = messages[field].codes;
});
}
@ -736,21 +855,23 @@ function ErrorCodes(messages) {
* }
*
* // This line shows how to create a ValidationError
* err = new ValidationError(model);
* var err = new MyModel.ValidationError(model);
* callback(err);
* }
* ```
*
* @private
*/
function ValidationError(obj) {
if (!(this instanceof ValidationError)) return new ValidationError(obj);
this.name = 'ValidationError';
var context = obj && obj.constructor && obj.constructor.modelName;
this.message = util.format(
const context = obj && obj.constructor && obj.constructor.modelName;
this.message = g.f(
'The %s instance is not valid. Details: %s.',
context ? '`' + context + '`' : 'model',
formatErrors(obj.errors, obj.toJSON()) || '(unknown)'
context ? '`' + context + '`' : 'model',
formatErrors(obj.errors, obj.toJSON()) || '(unknown)',
);
this.statusCode = 422;
@ -758,7 +879,7 @@ function ValidationError(obj) {
this.details = {
context: context,
codes: obj.errors && obj.errors.codes,
messages: obj.errors
messages: obj.errors,
};
if (Error.captureStackTrace) {
@ -774,20 +895,20 @@ function ValidationError(obj) {
util.inherits(ValidationError, Error);
var errorHasStackProperty = !!(new Error).stack;
const errorHasStackProperty = !!(new Error).stack;
ValidationError.maxPropertyStringLength = 32;
function formatErrors(errors, propertyValues) {
var DELIM = '; ';
const DELIM = '; ';
errors = errors || {};
return Object.getOwnPropertyNames(errors)
.filter(function(propertyName) {
return Array.isArray(errors[propertyName]);
})
.map(function(propertyName) {
var messages = errors[propertyName];
var propertyValue = propertyValues[propertyName];
const messages = errors[propertyName];
const propertyValue = propertyValues[propertyName];
return messages.map(function(msg) {
return formatPropertyError(propertyName, propertyValue, msg);
}).join(DELIM);
@ -796,19 +917,19 @@ function formatErrors(errors, propertyValues) {
}
function formatPropertyError(propertyName, propertyValue, errorMessage) {
var formattedValue;
var valueType = typeof propertyValue;
let formattedValue;
const valueType = typeof propertyValue;
if (valueType === 'string') {
formattedValue = JSON.stringify(truncatePropertyString(propertyValue));
} else if (propertyValue instanceof Date) {
formattedValue = propertyValue.toISOString();
formattedValue = isNaN(propertyValue.getTime()) ? propertyValue.toString() : propertyValue.toISOString();
} else if (valueType === 'object') {
// objects and arrays
formattedValue = util.inspect(propertyValue, {
showHidden: false,
color: false,
// show top-level object properties only
depth: Array.isArray(propertyValue) ? 1 : 0
depth: Array.isArray(propertyValue) ? 1 : 0,
});
formattedValue = truncatePropertyString(formattedValue);
} else {
@ -819,13 +940,13 @@ function formatPropertyError(propertyName, propertyValue, errorMessage) {
}
function truncatePropertyString(value) {
var len = ValidationError.maxPropertyStringLength;
let len = ValidationError.maxPropertyStringLength;
if (value.length <= len) return value;
// preserve few last characters like `}` or `]`, but no more than 3
// this way the last `} ]` in the array of objects is included in the message
var tail;
var m = value.match(/([ \t})\]]+)$/);
let tail;
const m = value.match(/([ \t})\]]+)$/);
if (m) {
tail = m[1].slice(-3);
len -= tail.length;
@ -834,5 +955,5 @@ function truncatePropertyString(value) {
len -= 3;
}
return value.slice(0, len-4) + '...' + tail;
return value.slice(0, len - 4) + '...' + tail;
}

6978
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
{
"name": "loopback-datasource-juggler",
"version": "2.44.0",
"description": "LoopBack DataSoure Juggler",
"version": "5.0.9",
"publishConfig": {
"export-tests": true
},
"description": "LoopBack DataSource Juggler",
"keywords": [
"StrongLoop",
"LoopBack",
@ -11,37 +14,56 @@
"Juggler",
"ORM"
],
"author": "IBM Corp.",
"engines": {
"node": ">=18"
},
"repository": {
"type": "git",
"url": "https://github.com/strongloop/loopback-datasource-juggler"
"url": "https://github.com/loopbackio/loopback-datasource-juggler"
},
"main": "index.js",
"types": "index.d.ts",
"browser": {
"depd": "./lib/browser.depd.js"
},
"scripts": {
"clean": "make clean",
"help": "make help",
"refresh": "make refresh",
"test": "make test"
"lint": "eslint .",
"build": "npm run build-ts-types",
"build-ts-types": "tsc -p tsconfig.json --outDir dist",
"pretest": "npm run build",
"test": "nyc mocha",
"posttest": "npm run lint"
},
"engines": [
"node >= 0.6"
],
"devDependencies": {
"bluebird": "^2.9.9",
"mocha": "^2.1.0",
"should": "^5.0.0"
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@types/node": "^10.17.60",
"async-iterators": "^0.2.2",
"bson": "^4.7.2",
"eslint": "^8.57.0",
"eslint-config-loopback": "^13.1.0",
"eslint-plugin-mocha": "^10.4.3",
"loopback-connector-throwing": "file:./test/fixtures/loopback-connector-throwing",
"mocha": "^10.4.0",
"nyc": "^15.1.0",
"should": "^13.2.3",
"typescript": "^5.4.5"
},
"dependencies": {
"async": "~1.0.0",
"debug": "^2.1.1",
"depd": "^1.0.0",
"inflection": "^1.6.0",
"loopback-connector": "^2.1.0",
"node-uuid": "^1.4.2",
"qs": "^3.1.0",
"traverse": "^0.6.6"
"async": "^3.2.5",
"change-case": "^4.1.2",
"debug": "^4.3.4",
"depd": "^2.0.0",
"inflection": "^3.0.0",
"lodash": "^4.17.21",
"loopback-connector": "^6.1.5",
"minimatch": "^9.0.4",
"nanoid": "^3.3.7",
"qs": "^6.12.1",
"strong-globalize": "^6.0.6",
"traverse": "^0.6.9",
"uuid": "^9.0.1"
},
"license": "MIT"
}

5
renovate.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": [
"github>loopbackio/cicd//shared-configs/renovate/base"
]
}

View File

@ -1,5 +0,0 @@
#!/bin/sh
# travis-ci.org now provides neo4j server but it is not started on boot
which neo4j && sudo neo4j start
sleep 5

View File

@ -1,3 +1,10 @@
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
/*
* Describe context objects of operation hooks in comprehensive HTML table.
* Usage:
@ -5,64 +12,85 @@
* $ open hooks.hml
*
*/
var Promise = global.Promise = require('bluebird');
var DataSource = require('../').DataSource;
var Memory = require('../lib/connectors/memory').Memory;
const Promise = global.Promise = require('bluebird');
const DataSource = require('../').DataSource;
const Memory = require('../lib/connectors/memory').Memory;
var HOOK_NAMES = [
const HOOK_NAMES = [
'access',
'before save', 'persist', 'after save',
'before delete', 'after delete'
'before save', 'persist', 'loaded', 'after save',
'before delete', 'after delete',
];
var dataSources = [
const dataSources = [
createOptimizedDataSource(),
createUnoptimizedDataSource()
createUnoptimizedDataSource(),
];
var observedContexts = [];
var lastId = 0;
const observedContexts = [];
let lastId = 0;
Promise.onPossiblyUnhandledRejection(function(err) {
console.error('POSSIBLY UNHANDLED REJECTION', err.stack);
});
var operations = [
/* eslint-disable camelcase */
const operations = [
function find(ds) {
return ds.TestModel.find({ where: { id: '1' } });
return ds.TestModel.find({where: {id: '1'}});
},
function count(ds) {
return ds.TestModel.count({ id: ds.existingInstance.id });
return ds.TestModel.count({id: ds.existingInstance.id});
},
function create(ds) {
return ds.TestModel.create({ name: 'created' });
return ds.TestModel.create({name: 'created'});
},
function findOrCreate_found(ds) {
return ds.TestModel.findOrCreate(
{ where: { name: ds.existingInstance.name } },
{ name: ds.existingInstance.name });
{where: {name: ds.existingInstance.name}},
{name: ds.existingInstance.name},
);
},
function findOrCreate_create(ds) {
return ds.TestModel.findOrCreate(
{ where: { name: 'new-record' } },
{ name: 'new-record' });
{where: {name: 'new-record'}},
{name: 'new-record'},
);
},
function updateOrCreate_create(ds) {
return ds.TestModel.updateOrCreate({ id: 'not-found', name: 'not found' });
return ds.TestModel.updateOrCreate({id: 'not-found', name: 'not found'});
},
function updateOrCreate_update(ds) {
return ds.TestModel.updateOrCreate(
{ id: ds.existingInstance.id, name: 'new name' });
{id: ds.existingInstance.id, name: 'new name'},
);
},
function replaceOrCreate_create(ds) {
return ds.TestModel.replaceOrCreate({id: 'not-found', name: 'not found'});
},
function replaceOrCreate_update(ds) {
return ds.TestModel.replaceOrCreate(
{id: ds.existingInstance.id, name: 'new name'},
);
},
function replaceById(ds) {
return ds.TestModel.replaceById(
ds.existingInstance.id,
{name: 'new name'},
);
},
function updateAll(ds) {
return ds.TestModel.updateAll({ name: 'searched' }, { name: 'updated' });
return ds.TestModel.updateAll({name: 'searched'}, {name: 'updated'});
},
function prototypeSave(ds) {
@ -71,7 +99,7 @@ var operations = [
},
function prototypeUpdateAttributes(ds) {
return ds.existingInstance.updateAttributes({ name: 'changed' });
return ds.existingInstance.updateAttributes({name: 'changed'});
},
function prototypeDelete(ds) {
@ -79,51 +107,42 @@ var operations = [
},
function deleteAll(ds) {
return ds.TestModel.deleteAll({ name: ds.existingInstance.name });
return ds.TestModel.deleteAll({name: ds.existingInstance.name});
},
];
/* eslint-enable camelcase */
var p = setupTestModels();
let p = setupTestModels();
operations.forEach(function(op) {
p = p.then(runner(op));
});
p.then(report, console.error);
p.then(report, function(err) { console.error(err.stack); });
function createOptimizedDataSource() {
var ds = new DataSource({ connector: Memory });
const ds = new DataSource({connector: Memory});
ds.name = 'Optimized';
ds.connector.findOrCreate = function (model, query, data, callback) {
this.all(model, query, {}, function (err, list) {
if (err || (list && list[0])) return callback(err, list && list[0], false);
this.create(model, data, {}, function (err) {
callback(err, data, true);
});
}.bind(this));
};
return ds;
}
function createUnoptimizedDataSource() {
var ds = new DataSource({ connector: Memory });
const ds = new DataSource({connector: Memory});
ds.name = 'Unoptimized';
// disable optimized methods
ds.connector.updateOrCreate = false;
ds.connector.findOrCreate = false;
ds.connector.replaceOrCreate = false;
return ds;
}
function setupTestModels() {
dataSources.forEach(function setupOnDataSource(ds) {
var TestModel = ds.TestModel = ds.createModel('TestModel', {
id: { type: String, id: true, default: uid },
name: { type: String, required: true },
extra: { type: String, required: false }
const TestModel = ds.TestModel = ds.createModel('TestModel', {
id: {type: String, id: true, default: uid},
name: {type: String, required: true},
extra: {type: String, required: false},
});
});
return Promise.resolve();
@ -136,7 +155,7 @@ function uid() {
function runner(fn) {
return function() {
var res = Promise.resolve();
let res = Promise.resolve();
dataSources.forEach(function(ds) {
res = res.then(function() {
return resetStorage(ds);
@ -144,7 +163,7 @@ function runner(fn) {
observedContexts.push({
operation: fn.name,
connector: ds.name,
hooks: {}
hooks: {},
});
return fn(ds);
});
@ -154,26 +173,26 @@ function runner(fn) {
}
function resetStorage(ds) {
var TestModel = ds.TestModel;
const TestModel = ds.TestModel;
HOOK_NAMES.forEach(function(hook) {
TestModel.clearObservers(hook);
});
return TestModel.deleteAll()
.then(function() {
return TestModel.create({ name: 'first' })
return TestModel.create({name: 'first'});
})
.then(function(instance) {
// Look it up from DB so that default values are retrieved
return TestModel.findById(instance.id)
return TestModel.findById(instance.id);
})
.then(function(instance) {
ds.existingInstance = instance;
return TestModel.create({ name: 'second' });
return TestModel.create({name: 'second'});
})
.then(function() {
HOOK_NAMES.forEach(function(hook) {
TestModel.observe(hook, function(ctx, next) {
var row = observedContexts[observedContexts.length-1];
const row = observedContexts[observedContexts.length - 1];
row.hooks[hook] = Object.keys(ctx);
next();
});
@ -182,7 +201,7 @@ function resetStorage(ds) {
}
function report() {
console.log('<style>')
console.log('<style>');
console.log('td { font-family: "monospace": }');
console.log('td, th {');
console.log(' vertical-align: text-top;');
@ -193,7 +212,7 @@ function report() {
// merge rows where Optimized and Unoptimized produce the same context
observedContexts.forEach(function(row, ix) {
if (!ix) return;
var last = observedContexts[ix-1];
const last = observedContexts[ix - 1];
if (row.operation != last.operation) return;
if (JSON.stringify(row.hooks) !== JSON.stringify(last.hooks)) return;
last.merge = true;
@ -207,11 +226,11 @@ function report() {
observedContexts.forEach(function(row) {
if (row.skip) return;
var caption = row.operation;
let caption = row.operation;
if (!row.merge) caption += ' (' + row.connector + ')';
console.log('<tr><th>' + caption + '</th>');
HOOK_NAMES.forEach(function(h) {
var text = row.hooks[h] ? row.hooks[h].join('<br/>') : '';
const text = row.hooks[h] ? row.hooks[h].join('<br/>') : '';
console.log(' <td>' + text + '</td>');
});
console.log('</tr>');

@ -1 +0,0 @@
Subproject commit b41facc8505e4516161452239a25711413711373

View File

@ -1,39 +1,46 @@
var should = require('./init.js');
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
var jdb = require('../');
var DataSource = jdb.DataSource;
'use strict';
var ds, Item, Variant;
describe('Datasource-specific field types for foreign keys', function () {
before(function () {
const should = require('./init.js');
const jdb = require('../');
const DataSource = jdb.DataSource;
let ds, Item, Variant;
describe('Datasource-specific field types for foreign keys', function() {
before(function() {
ds = new DataSource('memory');
Item = ds.define('Item', {
"myProp": {
"id": true,
"type": "string",
"memory": {
"dataType": "string"
}
}
myProp: {
id: true,
type: 'string',
memory: {
dataType: 'string',
},
},
});
Variant = ds.define('Variant', {}, {
relations: {
"item": {
"type": "belongsTo",
"as": "item",
"model": "Item",
"foreignKey": "myProp"
}
}
item: {
type: 'belongsTo',
as: 'item',
model: 'Item',
foreignKey: 'myProp',
},
},
});
});
it('should create foreign key with database-specific field type', function (done) {
var VariantDefinition = ds.getModelDefinition('Variant');
it('should create foreign key with database-specific field type', function(done) {
const VariantDefinition = ds.getModelDefinition('Variant');
should.exist(VariantDefinition);
should.exist(VariantDefinition.properties.myProp.memory);
should.exist(VariantDefinition.properties.myProp.memory.dataType);
VariantDefinition.properties.myProp.memory.dataType.should.be.equal("string");
VariantDefinition.properties.myProp.memory.dataType.should.be.equal('string');
done();
});
})

Some files were not shown because too many files have changed in this diff Show More