@rebasepro/server-core 0.0.1-canary.4d4fb3e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/README.md +40 -0
- package/build-errors.txt +52 -0
- package/coverage/clover.xml +3739 -0
- package/coverage/coverage-final.json +31 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +266 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/src/api/ast-schema-editor.ts.html +952 -0
- package/coverage/lcov-report/src/api/errors.ts.html +472 -0
- package/coverage/lcov-report/src/api/graphql/graphql-schema-generator.ts.html +1069 -0
- package/coverage/lcov-report/src/api/graphql/index.html +116 -0
- package/coverage/lcov-report/src/api/index.html +176 -0
- package/coverage/lcov-report/src/api/openapi-generator.ts.html +565 -0
- package/coverage/lcov-report/src/api/rest/api-generator.ts.html +994 -0
- package/coverage/lcov-report/src/api/rest/index.html +131 -0
- package/coverage/lcov-report/src/api/rest/query-parser.ts.html +550 -0
- package/coverage/lcov-report/src/api/schema-editor-routes.ts.html +202 -0
- package/coverage/lcov-report/src/api/server.ts.html +823 -0
- package/coverage/lcov-report/src/auth/admin-routes.ts.html +973 -0
- package/coverage/lcov-report/src/auth/index.html +176 -0
- package/coverage/lcov-report/src/auth/jwt.ts.html +574 -0
- package/coverage/lcov-report/src/auth/middleware.ts.html +745 -0
- package/coverage/lcov-report/src/auth/password.ts.html +310 -0
- package/coverage/lcov-report/src/auth/services.ts.html +2074 -0
- package/coverage/lcov-report/src/collections/index.html +116 -0
- package/coverage/lcov-report/src/collections/loader.ts.html +232 -0
- package/coverage/lcov-report/src/db/auth-schema.ts.html +523 -0
- package/coverage/lcov-report/src/db/data-transformer.ts.html +1753 -0
- package/coverage/lcov-report/src/db/entityService.ts.html +700 -0
- package/coverage/lcov-report/src/db/index.html +146 -0
- package/coverage/lcov-report/src/db/services/EntityFetchService.ts.html +4048 -0
- package/coverage/lcov-report/src/db/services/EntityPersistService.ts.html +883 -0
- package/coverage/lcov-report/src/db/services/RelationService.ts.html +3121 -0
- package/coverage/lcov-report/src/db/services/entity-helpers.ts.html +442 -0
- package/coverage/lcov-report/src/db/services/index.html +176 -0
- package/coverage/lcov-report/src/db/services/index.ts.html +124 -0
- package/coverage/lcov-report/src/generate-drizzle-schema-logic.ts.html +1960 -0
- package/coverage/lcov-report/src/index.html +116 -0
- package/coverage/lcov-report/src/services/driver-registry.ts.html +631 -0
- package/coverage/lcov-report/src/services/index.html +131 -0
- package/coverage/lcov-report/src/services/postgresDataDriver.ts.html +3025 -0
- package/coverage/lcov-report/src/storage/LocalStorageController.ts.html +1189 -0
- package/coverage/lcov-report/src/storage/S3StorageController.ts.html +970 -0
- package/coverage/lcov-report/src/storage/index.html +161 -0
- package/coverage/lcov-report/src/storage/storage-registry.ts.html +646 -0
- package/coverage/lcov-report/src/storage/types.ts.html +451 -0
- package/coverage/lcov-report/src/utils/drizzle-conditions.ts.html +3082 -0
- package/coverage/lcov-report/src/utils/index.html +116 -0
- package/coverage/lcov.info +7179 -0
- package/dist/common/src/collections/CollectionRegistry.d.ts +48 -0
- package/dist/common/src/collections/index.d.ts +1 -0
- package/dist/common/src/data/buildRebaseData.d.ts +14 -0
- package/dist/common/src/index.d.ts +3 -0
- package/dist/common/src/util/builders.d.ts +57 -0
- package/dist/common/src/util/callbacks.d.ts +6 -0
- package/dist/common/src/util/collections.d.ts +11 -0
- package/dist/common/src/util/common.d.ts +2 -0
- package/dist/common/src/util/conditions.d.ts +26 -0
- package/dist/common/src/util/entities.d.ts +36 -0
- package/dist/common/src/util/enums.d.ts +3 -0
- package/dist/common/src/util/index.d.ts +16 -0
- package/dist/common/src/util/navigation_from_path.d.ts +34 -0
- package/dist/common/src/util/navigation_utils.d.ts +20 -0
- package/dist/common/src/util/parent_references_from_path.d.ts +6 -0
- package/dist/common/src/util/paths.d.ts +14 -0
- package/dist/common/src/util/permissions.d.ts +5 -0
- package/dist/common/src/util/references.d.ts +2 -0
- package/dist/common/src/util/relations.d.ts +12 -0
- package/dist/common/src/util/resolutions.d.ts +72 -0
- package/dist/common/src/util/storage.d.ts +24 -0
- package/dist/index-BeMqpmfQ.js +239 -0
- package/dist/index-BeMqpmfQ.js.map +1 -0
- package/dist/index-bl4J3lNb.js +55823 -0
- package/dist/index-bl4J3lNb.js.map +1 -0
- package/dist/index.es.js +58 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +56062 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/server-core/src/api/ast-schema-editor.d.ts +21 -0
- package/dist/server-core/src/api/collections_for_test/callbacks_test_collection.d.ts +2 -0
- package/dist/server-core/src/api/errors.d.ts +35 -0
- package/dist/server-core/src/api/graphql/graphql-schema-generator.d.ts +35 -0
- package/dist/server-core/src/api/graphql/index.d.ts +1 -0
- package/dist/server-core/src/api/index.d.ts +9 -0
- package/dist/server-core/src/api/openapi-generator.d.ts +2 -0
- package/dist/server-core/src/api/rest/api-generator.d.ts +64 -0
- package/dist/server-core/src/api/rest/index.d.ts +1 -0
- package/dist/server-core/src/api/rest/query-parser.d.ts +9 -0
- package/dist/server-core/src/api/schema-editor-routes.d.ts +3 -0
- package/dist/server-core/src/api/server.d.ts +40 -0
- package/dist/server-core/src/api/types.d.ts +90 -0
- package/dist/server-core/src/auth/admin-routes.d.ts +7 -0
- package/dist/server-core/src/auth/google-oauth.d.ts +20 -0
- package/dist/server-core/src/auth/index.d.ts +12 -0
- package/dist/server-core/src/auth/interfaces.d.ts +270 -0
- package/dist/server-core/src/auth/jwt.d.ts +42 -0
- package/dist/server-core/src/auth/middleware.d.ts +56 -0
- package/dist/server-core/src/auth/password.d.ts +22 -0
- package/dist/server-core/src/auth/rate-limiter.d.ts +31 -0
- package/dist/server-core/src/auth/routes.d.ts +17 -0
- package/dist/server-core/src/bootstrappers/index.d.ts +0 -0
- package/dist/server-core/src/collections/BackendCollectionRegistry.d.ts +13 -0
- package/dist/server-core/src/collections/loader.d.ts +5 -0
- package/dist/server-core/src/db/interfaces.d.ts +18 -0
- package/dist/server-core/src/email/index.d.ts +6 -0
- package/dist/server-core/src/email/smtp-email-service.d.ts +25 -0
- package/dist/server-core/src/email/templates.d.ts +33 -0
- package/dist/server-core/src/email/types.d.ts +110 -0
- package/dist/server-core/src/functions/function-loader.d.ts +17 -0
- package/dist/server-core/src/functions/function-routes.d.ts +10 -0
- package/dist/server-core/src/functions/index.d.ts +3 -0
- package/dist/server-core/src/history/history-routes.d.ts +23 -0
- package/dist/server-core/src/history/index.d.ts +1 -0
- package/dist/server-core/src/index.d.ts +24 -0
- package/dist/server-core/src/init.d.ts +49 -0
- package/dist/server-core/src/serve-spa.d.ts +30 -0
- package/dist/server-core/src/services/driver-registry.d.ts +78 -0
- package/dist/server-core/src/storage/LocalStorageController.d.ts +46 -0
- package/dist/server-core/src/storage/S3StorageController.d.ts +36 -0
- package/dist/server-core/src/storage/index.d.ts +18 -0
- package/dist/server-core/src/storage/routes.d.ts +38 -0
- package/dist/server-core/src/storage/storage-registry.d.ts +78 -0
- package/dist/server-core/src/storage/types.d.ts +91 -0
- package/dist/server-core/src/types/index.d.ts +11 -0
- package/dist/server-core/src/utils/logging.d.ts +9 -0
- package/dist/server-core/src/utils/sql.d.ts +27 -0
- package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
- package/dist/types/src/controllers/auth.d.ts +117 -0
- package/dist/types/src/controllers/client.d.ts +58 -0
- package/dist/types/src/controllers/collection_registry.d.ts +44 -0
- package/dist/types/src/controllers/customization_controller.d.ts +54 -0
- package/dist/types/src/controllers/data.d.ts +141 -0
- package/dist/types/src/controllers/data_driver.d.ts +168 -0
- package/dist/types/src/controllers/database_admin.d.ts +11 -0
- package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
- package/dist/types/src/controllers/effective_role.d.ts +4 -0
- package/dist/types/src/controllers/index.d.ts +17 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
- package/dist/types/src/controllers/navigation.d.ts +213 -0
- package/dist/types/src/controllers/registry.d.ts +51 -0
- package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
- package/dist/types/src/controllers/side_entity_controller.d.ts +89 -0
- package/dist/types/src/controllers/snackbar.d.ts +24 -0
- package/dist/types/src/controllers/storage.d.ts +173 -0
- package/dist/types/src/index.d.ts +4 -0
- package/dist/types/src/rebase_context.d.ts +101 -0
- package/dist/types/src/types/backend.d.ts +533 -0
- package/dist/types/src/types/builders.d.ts +14 -0
- package/dist/types/src/types/chips.d.ts +5 -0
- package/dist/types/src/types/collections.d.ts +812 -0
- package/dist/types/src/types/data_source.d.ts +64 -0
- package/dist/types/src/types/entities.d.ts +145 -0
- package/dist/types/src/types/entity_actions.d.ts +98 -0
- package/dist/types/src/types/entity_callbacks.d.ts +173 -0
- package/dist/types/src/types/entity_link_builder.d.ts +7 -0
- package/dist/types/src/types/entity_overrides.d.ts +9 -0
- package/dist/types/src/types/entity_views.d.ts +61 -0
- package/dist/types/src/types/export_import.d.ts +21 -0
- package/dist/types/src/types/index.d.ts +22 -0
- package/dist/types/src/types/locales.d.ts +4 -0
- package/dist/types/src/types/modify_collections.d.ts +5 -0
- package/dist/types/src/types/plugins.d.ts +225 -0
- package/dist/types/src/types/properties.d.ts +1091 -0
- package/dist/types/src/types/property_config.d.ts +70 -0
- package/dist/types/src/types/relations.d.ts +336 -0
- package/dist/types/src/types/slots.d.ts +228 -0
- package/dist/types/src/types/translations.d.ts +826 -0
- package/dist/types/src/types/user_management_delegate.d.ts +120 -0
- package/dist/types/src/types/websockets.d.ts +78 -0
- package/dist/types/src/users/index.d.ts +2 -0
- package/dist/types/src/users/roles.d.ts +22 -0
- package/dist/types/src/users/user.d.ts +46 -0
- package/history_diff.log +385 -0
- package/jest.config.cjs +16 -0
- package/package.json +86 -0
- package/scratch.ts +8 -0
- package/src/api/ast-schema-editor.ts +289 -0
- package/src/api/collections_for_test/callbacks_test_collection.ts +57 -0
- package/src/api/errors.ts +155 -0
- package/src/api/graphql/graphql-schema-generator.ts +334 -0
- package/src/api/graphql/index.ts +2 -0
- package/src/api/index.ts +11 -0
- package/src/api/openapi-generator.ts +160 -0
- package/src/api/rest/api-generator.ts +466 -0
- package/src/api/rest/index.ts +2 -0
- package/src/api/rest/query-parser.ts +155 -0
- package/src/api/schema-editor-routes.ts +39 -0
- package/src/api/server.ts +245 -0
- package/src/api/types.ts +90 -0
- package/src/auth/admin-routes.ts +488 -0
- package/src/auth/google-oauth.ts +60 -0
- package/src/auth/index.ts +21 -0
- package/src/auth/interfaces.ts +316 -0
- package/src/auth/jwt.ts +164 -0
- package/src/auth/middleware.ts +235 -0
- package/src/auth/password.ts +75 -0
- package/src/auth/rate-limiter.ts +129 -0
- package/src/auth/routes.ts +730 -0
- package/src/bootstrappers/index.ts +1 -0
- package/src/collections/BackendCollectionRegistry.ts +20 -0
- package/src/collections/loader.ts +49 -0
- package/src/db/interfaces.ts +60 -0
- package/src/email/index.ts +17 -0
- package/src/email/smtp-email-service.ts +88 -0
- package/src/email/templates.ts +301 -0
- package/src/email/types.ts +112 -0
- package/src/functions/function-loader.ts +91 -0
- package/src/functions/function-routes.ts +31 -0
- package/src/functions/index.ts +3 -0
- package/src/history/history-routes.ts +128 -0
- package/src/history/index.ts +2 -0
- package/src/index.ts +56 -0
- package/src/init.ts +309 -0
- package/src/serve-spa.ts +81 -0
- package/src/services/driver-registry.ts +182 -0
- package/src/storage/LocalStorageController.ts +368 -0
- package/src/storage/S3StorageController.ts +295 -0
- package/src/storage/index.ts +32 -0
- package/src/storage/routes.ts +247 -0
- package/src/storage/storage-registry.ts +187 -0
- package/src/storage/types.ts +122 -0
- package/src/types/index.ts +27 -0
- package/src/utils/logging.ts +35 -0
- package/src/utils/sql.ts +38 -0
- package/test/admin-routes.test.ts +591 -0
- package/test/api-generator.test.ts +458 -0
- package/test/ast-schema-editor.test.ts +61 -0
- package/test/auth-middleware-hono.test.ts +321 -0
- package/test/auth-routes.test.ts +868 -0
- package/test/driver-registry.test.ts +280 -0
- package/test/errors-hono.test.ts +133 -0
- package/test/errors.test.ts +150 -0
- package/test/jwt-security.test.ts +173 -0
- package/test/jwt.test.ts +311 -0
- package/test/middleware.test.ts +295 -0
- package/test/password.test.ts +165 -0
- package/test/query-parser.test.ts +258 -0
- package/test/rate-limiter.test.ts +102 -0
- package/test/storage-local.test.ts +278 -0
- package/test/storage-registry.test.ts +280 -0
- package/test/storage-routes.test.ts +218 -0
- package/test/storage-s3.test.ts +301 -0
- package/test-ast.ts +28 -0
- package/test_output.txt +1133 -0
- package/tsconfig.json +49 -0
- package/tsconfig.prod.json +20 -0
- package/vite.config.ts +78 -0
- package/vite.config.ts.timestamp-1775065397568-8a853255edf6e.mjs +46 -0
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for src/db/services/EntityPersistService.ts</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="../../../prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="../../../base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(../../../sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="../../../index.html">All files</a> / <a href="index.html">src/db/services</a> EntityPersistService.ts</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">8.95% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>12/134</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">0% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>0/53</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">11.11% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>1/9</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">8.59% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>11/128</span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
<p class="quiet">
|
|
55
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
+
</p>
|
|
57
|
+
<template id="filterTemplate">
|
|
58
|
+
<div class="quiet">
|
|
59
|
+
Filter:
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
<div class='status-line low'></div>
|
|
65
|
+
<pre><table class="coverage">
|
|
66
|
+
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
+
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
+
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
+
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
+
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
+
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
+
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
+
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
+
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
+
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
+
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
+
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
+
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
+
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
+
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
+
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
+
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
+
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
+
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
+
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
+
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
+
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
+
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
+
<a name='L25'></a><a href='#L25'>25</a>
|
|
91
|
+
<a name='L26'></a><a href='#L26'>26</a>
|
|
92
|
+
<a name='L27'></a><a href='#L27'>27</a>
|
|
93
|
+
<a name='L28'></a><a href='#L28'>28</a>
|
|
94
|
+
<a name='L29'></a><a href='#L29'>29</a>
|
|
95
|
+
<a name='L30'></a><a href='#L30'>30</a>
|
|
96
|
+
<a name='L31'></a><a href='#L31'>31</a>
|
|
97
|
+
<a name='L32'></a><a href='#L32'>32</a>
|
|
98
|
+
<a name='L33'></a><a href='#L33'>33</a>
|
|
99
|
+
<a name='L34'></a><a href='#L34'>34</a>
|
|
100
|
+
<a name='L35'></a><a href='#L35'>35</a>
|
|
101
|
+
<a name='L36'></a><a href='#L36'>36</a>
|
|
102
|
+
<a name='L37'></a><a href='#L37'>37</a>
|
|
103
|
+
<a name='L38'></a><a href='#L38'>38</a>
|
|
104
|
+
<a name='L39'></a><a href='#L39'>39</a>
|
|
105
|
+
<a name='L40'></a><a href='#L40'>40</a>
|
|
106
|
+
<a name='L41'></a><a href='#L41'>41</a>
|
|
107
|
+
<a name='L42'></a><a href='#L42'>42</a>
|
|
108
|
+
<a name='L43'></a><a href='#L43'>43</a>
|
|
109
|
+
<a name='L44'></a><a href='#L44'>44</a>
|
|
110
|
+
<a name='L45'></a><a href='#L45'>45</a>
|
|
111
|
+
<a name='L46'></a><a href='#L46'>46</a>
|
|
112
|
+
<a name='L47'></a><a href='#L47'>47</a>
|
|
113
|
+
<a name='L48'></a><a href='#L48'>48</a>
|
|
114
|
+
<a name='L49'></a><a href='#L49'>49</a>
|
|
115
|
+
<a name='L50'></a><a href='#L50'>50</a>
|
|
116
|
+
<a name='L51'></a><a href='#L51'>51</a>
|
|
117
|
+
<a name='L52'></a><a href='#L52'>52</a>
|
|
118
|
+
<a name='L53'></a><a href='#L53'>53</a>
|
|
119
|
+
<a name='L54'></a><a href='#L54'>54</a>
|
|
120
|
+
<a name='L55'></a><a href='#L55'>55</a>
|
|
121
|
+
<a name='L56'></a><a href='#L56'>56</a>
|
|
122
|
+
<a name='L57'></a><a href='#L57'>57</a>
|
|
123
|
+
<a name='L58'></a><a href='#L58'>58</a>
|
|
124
|
+
<a name='L59'></a><a href='#L59'>59</a>
|
|
125
|
+
<a name='L60'></a><a href='#L60'>60</a>
|
|
126
|
+
<a name='L61'></a><a href='#L61'>61</a>
|
|
127
|
+
<a name='L62'></a><a href='#L62'>62</a>
|
|
128
|
+
<a name='L63'></a><a href='#L63'>63</a>
|
|
129
|
+
<a name='L64'></a><a href='#L64'>64</a>
|
|
130
|
+
<a name='L65'></a><a href='#L65'>65</a>
|
|
131
|
+
<a name='L66'></a><a href='#L66'>66</a>
|
|
132
|
+
<a name='L67'></a><a href='#L67'>67</a>
|
|
133
|
+
<a name='L68'></a><a href='#L68'>68</a>
|
|
134
|
+
<a name='L69'></a><a href='#L69'>69</a>
|
|
135
|
+
<a name='L70'></a><a href='#L70'>70</a>
|
|
136
|
+
<a name='L71'></a><a href='#L71'>71</a>
|
|
137
|
+
<a name='L72'></a><a href='#L72'>72</a>
|
|
138
|
+
<a name='L73'></a><a href='#L73'>73</a>
|
|
139
|
+
<a name='L74'></a><a href='#L74'>74</a>
|
|
140
|
+
<a name='L75'></a><a href='#L75'>75</a>
|
|
141
|
+
<a name='L76'></a><a href='#L76'>76</a>
|
|
142
|
+
<a name='L77'></a><a href='#L77'>77</a>
|
|
143
|
+
<a name='L78'></a><a href='#L78'>78</a>
|
|
144
|
+
<a name='L79'></a><a href='#L79'>79</a>
|
|
145
|
+
<a name='L80'></a><a href='#L80'>80</a>
|
|
146
|
+
<a name='L81'></a><a href='#L81'>81</a>
|
|
147
|
+
<a name='L82'></a><a href='#L82'>82</a>
|
|
148
|
+
<a name='L83'></a><a href='#L83'>83</a>
|
|
149
|
+
<a name='L84'></a><a href='#L84'>84</a>
|
|
150
|
+
<a name='L85'></a><a href='#L85'>85</a>
|
|
151
|
+
<a name='L86'></a><a href='#L86'>86</a>
|
|
152
|
+
<a name='L87'></a><a href='#L87'>87</a>
|
|
153
|
+
<a name='L88'></a><a href='#L88'>88</a>
|
|
154
|
+
<a name='L89'></a><a href='#L89'>89</a>
|
|
155
|
+
<a name='L90'></a><a href='#L90'>90</a>
|
|
156
|
+
<a name='L91'></a><a href='#L91'>91</a>
|
|
157
|
+
<a name='L92'></a><a href='#L92'>92</a>
|
|
158
|
+
<a name='L93'></a><a href='#L93'>93</a>
|
|
159
|
+
<a name='L94'></a><a href='#L94'>94</a>
|
|
160
|
+
<a name='L95'></a><a href='#L95'>95</a>
|
|
161
|
+
<a name='L96'></a><a href='#L96'>96</a>
|
|
162
|
+
<a name='L97'></a><a href='#L97'>97</a>
|
|
163
|
+
<a name='L98'></a><a href='#L98'>98</a>
|
|
164
|
+
<a name='L99'></a><a href='#L99'>99</a>
|
|
165
|
+
<a name='L100'></a><a href='#L100'>100</a>
|
|
166
|
+
<a name='L101'></a><a href='#L101'>101</a>
|
|
167
|
+
<a name='L102'></a><a href='#L102'>102</a>
|
|
168
|
+
<a name='L103'></a><a href='#L103'>103</a>
|
|
169
|
+
<a name='L104'></a><a href='#L104'>104</a>
|
|
170
|
+
<a name='L105'></a><a href='#L105'>105</a>
|
|
171
|
+
<a name='L106'></a><a href='#L106'>106</a>
|
|
172
|
+
<a name='L107'></a><a href='#L107'>107</a>
|
|
173
|
+
<a name='L108'></a><a href='#L108'>108</a>
|
|
174
|
+
<a name='L109'></a><a href='#L109'>109</a>
|
|
175
|
+
<a name='L110'></a><a href='#L110'>110</a>
|
|
176
|
+
<a name='L111'></a><a href='#L111'>111</a>
|
|
177
|
+
<a name='L112'></a><a href='#L112'>112</a>
|
|
178
|
+
<a name='L113'></a><a href='#L113'>113</a>
|
|
179
|
+
<a name='L114'></a><a href='#L114'>114</a>
|
|
180
|
+
<a name='L115'></a><a href='#L115'>115</a>
|
|
181
|
+
<a name='L116'></a><a href='#L116'>116</a>
|
|
182
|
+
<a name='L117'></a><a href='#L117'>117</a>
|
|
183
|
+
<a name='L118'></a><a href='#L118'>118</a>
|
|
184
|
+
<a name='L119'></a><a href='#L119'>119</a>
|
|
185
|
+
<a name='L120'></a><a href='#L120'>120</a>
|
|
186
|
+
<a name='L121'></a><a href='#L121'>121</a>
|
|
187
|
+
<a name='L122'></a><a href='#L122'>122</a>
|
|
188
|
+
<a name='L123'></a><a href='#L123'>123</a>
|
|
189
|
+
<a name='L124'></a><a href='#L124'>124</a>
|
|
190
|
+
<a name='L125'></a><a href='#L125'>125</a>
|
|
191
|
+
<a name='L126'></a><a href='#L126'>126</a>
|
|
192
|
+
<a name='L127'></a><a href='#L127'>127</a>
|
|
193
|
+
<a name='L128'></a><a href='#L128'>128</a>
|
|
194
|
+
<a name='L129'></a><a href='#L129'>129</a>
|
|
195
|
+
<a name='L130'></a><a href='#L130'>130</a>
|
|
196
|
+
<a name='L131'></a><a href='#L131'>131</a>
|
|
197
|
+
<a name='L132'></a><a href='#L132'>132</a>
|
|
198
|
+
<a name='L133'></a><a href='#L133'>133</a>
|
|
199
|
+
<a name='L134'></a><a href='#L134'>134</a>
|
|
200
|
+
<a name='L135'></a><a href='#L135'>135</a>
|
|
201
|
+
<a name='L136'></a><a href='#L136'>136</a>
|
|
202
|
+
<a name='L137'></a><a href='#L137'>137</a>
|
|
203
|
+
<a name='L138'></a><a href='#L138'>138</a>
|
|
204
|
+
<a name='L139'></a><a href='#L139'>139</a>
|
|
205
|
+
<a name='L140'></a><a href='#L140'>140</a>
|
|
206
|
+
<a name='L141'></a><a href='#L141'>141</a>
|
|
207
|
+
<a name='L142'></a><a href='#L142'>142</a>
|
|
208
|
+
<a name='L143'></a><a href='#L143'>143</a>
|
|
209
|
+
<a name='L144'></a><a href='#L144'>144</a>
|
|
210
|
+
<a name='L145'></a><a href='#L145'>145</a>
|
|
211
|
+
<a name='L146'></a><a href='#L146'>146</a>
|
|
212
|
+
<a name='L147'></a><a href='#L147'>147</a>
|
|
213
|
+
<a name='L148'></a><a href='#L148'>148</a>
|
|
214
|
+
<a name='L149'></a><a href='#L149'>149</a>
|
|
215
|
+
<a name='L150'></a><a href='#L150'>150</a>
|
|
216
|
+
<a name='L151'></a><a href='#L151'>151</a>
|
|
217
|
+
<a name='L152'></a><a href='#L152'>152</a>
|
|
218
|
+
<a name='L153'></a><a href='#L153'>153</a>
|
|
219
|
+
<a name='L154'></a><a href='#L154'>154</a>
|
|
220
|
+
<a name='L155'></a><a href='#L155'>155</a>
|
|
221
|
+
<a name='L156'></a><a href='#L156'>156</a>
|
|
222
|
+
<a name='L157'></a><a href='#L157'>157</a>
|
|
223
|
+
<a name='L158'></a><a href='#L158'>158</a>
|
|
224
|
+
<a name='L159'></a><a href='#L159'>159</a>
|
|
225
|
+
<a name='L160'></a><a href='#L160'>160</a>
|
|
226
|
+
<a name='L161'></a><a href='#L161'>161</a>
|
|
227
|
+
<a name='L162'></a><a href='#L162'>162</a>
|
|
228
|
+
<a name='L163'></a><a href='#L163'>163</a>
|
|
229
|
+
<a name='L164'></a><a href='#L164'>164</a>
|
|
230
|
+
<a name='L165'></a><a href='#L165'>165</a>
|
|
231
|
+
<a name='L166'></a><a href='#L166'>166</a>
|
|
232
|
+
<a name='L167'></a><a href='#L167'>167</a>
|
|
233
|
+
<a name='L168'></a><a href='#L168'>168</a>
|
|
234
|
+
<a name='L169'></a><a href='#L169'>169</a>
|
|
235
|
+
<a name='L170'></a><a href='#L170'>170</a>
|
|
236
|
+
<a name='L171'></a><a href='#L171'>171</a>
|
|
237
|
+
<a name='L172'></a><a href='#L172'>172</a>
|
|
238
|
+
<a name='L173'></a><a href='#L173'>173</a>
|
|
239
|
+
<a name='L174'></a><a href='#L174'>174</a>
|
|
240
|
+
<a name='L175'></a><a href='#L175'>175</a>
|
|
241
|
+
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
|
+
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
|
+
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a>
|
|
255
|
+
<a name='L190'></a><a href='#L190'>190</a>
|
|
256
|
+
<a name='L191'></a><a href='#L191'>191</a>
|
|
257
|
+
<a name='L192'></a><a href='#L192'>192</a>
|
|
258
|
+
<a name='L193'></a><a href='#L193'>193</a>
|
|
259
|
+
<a name='L194'></a><a href='#L194'>194</a>
|
|
260
|
+
<a name='L195'></a><a href='#L195'>195</a>
|
|
261
|
+
<a name='L196'></a><a href='#L196'>196</a>
|
|
262
|
+
<a name='L197'></a><a href='#L197'>197</a>
|
|
263
|
+
<a name='L198'></a><a href='#L198'>198</a>
|
|
264
|
+
<a name='L199'></a><a href='#L199'>199</a>
|
|
265
|
+
<a name='L200'></a><a href='#L200'>200</a>
|
|
266
|
+
<a name='L201'></a><a href='#L201'>201</a>
|
|
267
|
+
<a name='L202'></a><a href='#L202'>202</a>
|
|
268
|
+
<a name='L203'></a><a href='#L203'>203</a>
|
|
269
|
+
<a name='L204'></a><a href='#L204'>204</a>
|
|
270
|
+
<a name='L205'></a><a href='#L205'>205</a>
|
|
271
|
+
<a name='L206'></a><a href='#L206'>206</a>
|
|
272
|
+
<a name='L207'></a><a href='#L207'>207</a>
|
|
273
|
+
<a name='L208'></a><a href='#L208'>208</a>
|
|
274
|
+
<a name='L209'></a><a href='#L209'>209</a>
|
|
275
|
+
<a name='L210'></a><a href='#L210'>210</a>
|
|
276
|
+
<a name='L211'></a><a href='#L211'>211</a>
|
|
277
|
+
<a name='L212'></a><a href='#L212'>212</a>
|
|
278
|
+
<a name='L213'></a><a href='#L213'>213</a>
|
|
279
|
+
<a name='L214'></a><a href='#L214'>214</a>
|
|
280
|
+
<a name='L215'></a><a href='#L215'>215</a>
|
|
281
|
+
<a name='L216'></a><a href='#L216'>216</a>
|
|
282
|
+
<a name='L217'></a><a href='#L217'>217</a>
|
|
283
|
+
<a name='L218'></a><a href='#L218'>218</a>
|
|
284
|
+
<a name='L219'></a><a href='#L219'>219</a>
|
|
285
|
+
<a name='L220'></a><a href='#L220'>220</a>
|
|
286
|
+
<a name='L221'></a><a href='#L221'>221</a>
|
|
287
|
+
<a name='L222'></a><a href='#L222'>222</a>
|
|
288
|
+
<a name='L223'></a><a href='#L223'>223</a>
|
|
289
|
+
<a name='L224'></a><a href='#L224'>224</a>
|
|
290
|
+
<a name='L225'></a><a href='#L225'>225</a>
|
|
291
|
+
<a name='L226'></a><a href='#L226'>226</a>
|
|
292
|
+
<a name='L227'></a><a href='#L227'>227</a>
|
|
293
|
+
<a name='L228'></a><a href='#L228'>228</a>
|
|
294
|
+
<a name='L229'></a><a href='#L229'>229</a>
|
|
295
|
+
<a name='L230'></a><a href='#L230'>230</a>
|
|
296
|
+
<a name='L231'></a><a href='#L231'>231</a>
|
|
297
|
+
<a name='L232'></a><a href='#L232'>232</a>
|
|
298
|
+
<a name='L233'></a><a href='#L233'>233</a>
|
|
299
|
+
<a name='L234'></a><a href='#L234'>234</a>
|
|
300
|
+
<a name='L235'></a><a href='#L235'>235</a>
|
|
301
|
+
<a name='L236'></a><a href='#L236'>236</a>
|
|
302
|
+
<a name='L237'></a><a href='#L237'>237</a>
|
|
303
|
+
<a name='L238'></a><a href='#L238'>238</a>
|
|
304
|
+
<a name='L239'></a><a href='#L239'>239</a>
|
|
305
|
+
<a name='L240'></a><a href='#L240'>240</a>
|
|
306
|
+
<a name='L241'></a><a href='#L241'>241</a>
|
|
307
|
+
<a name='L242'></a><a href='#L242'>242</a>
|
|
308
|
+
<a name='L243'></a><a href='#L243'>243</a>
|
|
309
|
+
<a name='L244'></a><a href='#L244'>244</a>
|
|
310
|
+
<a name='L245'></a><a href='#L245'>245</a>
|
|
311
|
+
<a name='L246'></a><a href='#L246'>246</a>
|
|
312
|
+
<a name='L247'></a><a href='#L247'>247</a>
|
|
313
|
+
<a name='L248'></a><a href='#L248'>248</a>
|
|
314
|
+
<a name='L249'></a><a href='#L249'>249</a>
|
|
315
|
+
<a name='L250'></a><a href='#L250'>250</a>
|
|
316
|
+
<a name='L251'></a><a href='#L251'>251</a>
|
|
317
|
+
<a name='L252'></a><a href='#L252'>252</a>
|
|
318
|
+
<a name='L253'></a><a href='#L253'>253</a>
|
|
319
|
+
<a name='L254'></a><a href='#L254'>254</a>
|
|
320
|
+
<a name='L255'></a><a href='#L255'>255</a>
|
|
321
|
+
<a name='L256'></a><a href='#L256'>256</a>
|
|
322
|
+
<a name='L257'></a><a href='#L257'>257</a>
|
|
323
|
+
<a name='L258'></a><a href='#L258'>258</a>
|
|
324
|
+
<a name='L259'></a><a href='#L259'>259</a>
|
|
325
|
+
<a name='L260'></a><a href='#L260'>260</a>
|
|
326
|
+
<a name='L261'></a><a href='#L261'>261</a>
|
|
327
|
+
<a name='L262'></a><a href='#L262'>262</a>
|
|
328
|
+
<a name='L263'></a><a href='#L263'>263</a>
|
|
329
|
+
<a name='L264'></a><a href='#L264'>264</a>
|
|
330
|
+
<a name='L265'></a><a href='#L265'>265</a>
|
|
331
|
+
<a name='L266'></a><a href='#L266'>266</a>
|
|
332
|
+
<a name='L267'></a><a href='#L267'>267</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">3x</span>
|
|
333
|
+
<span class="cline-any cline-neutral"> </span>
|
|
334
|
+
<span class="cline-any cline-neutral"> </span>
|
|
335
|
+
<span class="cline-any cline-neutral"> </span>
|
|
336
|
+
<span class="cline-any cline-yes">3x</span>
|
|
337
|
+
<span class="cline-any cline-yes">3x</span>
|
|
338
|
+
<span class="cline-any cline-yes">3x</span>
|
|
339
|
+
<span class="cline-any cline-neutral"> </span>
|
|
340
|
+
<span class="cline-any cline-neutral"> </span>
|
|
341
|
+
<span class="cline-any cline-neutral"> </span>
|
|
342
|
+
<span class="cline-any cline-neutral"> </span>
|
|
343
|
+
<span class="cline-any cline-neutral"> </span>
|
|
344
|
+
<span class="cline-any cline-neutral"> </span>
|
|
345
|
+
<span class="cline-any cline-yes">3x</span>
|
|
346
|
+
<span class="cline-any cline-yes">3x</span>
|
|
347
|
+
<span class="cline-any cline-yes">3x</span>
|
|
348
|
+
<span class="cline-any cline-neutral"> </span>
|
|
349
|
+
<span class="cline-any cline-neutral"> </span>
|
|
350
|
+
<span class="cline-any cline-neutral"> </span>
|
|
351
|
+
<span class="cline-any cline-neutral"> </span>
|
|
352
|
+
<span class="cline-any cline-neutral"> </span>
|
|
353
|
+
<span class="cline-any cline-neutral"> </span>
|
|
354
|
+
<span class="cline-any cline-neutral"> </span>
|
|
355
|
+
<span class="cline-any cline-yes">3x</span>
|
|
356
|
+
<span class="cline-any cline-neutral"> </span>
|
|
357
|
+
<span class="cline-any cline-neutral"> </span>
|
|
358
|
+
<span class="cline-any cline-neutral"> </span>
|
|
359
|
+
<span class="cline-any cline-yes">73x</span>
|
|
360
|
+
<span class="cline-any cline-yes">73x</span>
|
|
361
|
+
<span class="cline-any cline-yes">73x</span>
|
|
362
|
+
<span class="cline-any cline-neutral"> </span>
|
|
363
|
+
<span class="cline-any cline-neutral"> </span>
|
|
364
|
+
<span class="cline-any cline-neutral"> </span>
|
|
365
|
+
<span class="cline-any cline-neutral"> </span>
|
|
366
|
+
<span class="cline-any cline-neutral"> </span>
|
|
367
|
+
<span class="cline-any cline-neutral"> </span>
|
|
368
|
+
<span class="cline-any cline-neutral"> </span>
|
|
369
|
+
<span class="cline-any cline-no"> </span>
|
|
370
|
+
<span class="cline-any cline-no"> </span>
|
|
371
|
+
<span class="cline-any cline-no"> </span>
|
|
372
|
+
<span class="cline-any cline-no"> </span>
|
|
373
|
+
<span class="cline-any cline-no"> </span>
|
|
374
|
+
<span class="cline-any cline-neutral"> </span>
|
|
375
|
+
<span class="cline-any cline-no"> </span>
|
|
376
|
+
<span class="cline-any cline-no"> </span>
|
|
377
|
+
<span class="cline-any cline-neutral"> </span>
|
|
378
|
+
<span class="cline-any cline-neutral"> </span>
|
|
379
|
+
<span class="cline-any cline-no"> </span>
|
|
380
|
+
<span class="cline-any cline-no"> </span>
|
|
381
|
+
<span class="cline-any cline-neutral"> </span>
|
|
382
|
+
<span class="cline-any cline-no"> </span>
|
|
383
|
+
<span class="cline-any cline-neutral"> </span>
|
|
384
|
+
<span class="cline-any cline-neutral"> </span>
|
|
385
|
+
<span class="cline-any cline-neutral"> </span>
|
|
386
|
+
<span class="cline-any cline-neutral"> </span>
|
|
387
|
+
<span class="cline-any cline-neutral"> </span>
|
|
388
|
+
<span class="cline-any cline-neutral"> </span>
|
|
389
|
+
<span class="cline-any cline-neutral"> </span>
|
|
390
|
+
<span class="cline-any cline-neutral"> </span>
|
|
391
|
+
<span class="cline-any cline-neutral"> </span>
|
|
392
|
+
<span class="cline-any cline-neutral"> </span>
|
|
393
|
+
<span class="cline-any cline-neutral"> </span>
|
|
394
|
+
<span class="cline-any cline-neutral"> </span>
|
|
395
|
+
<span class="cline-any cline-neutral"> </span>
|
|
396
|
+
<span class="cline-any cline-neutral"> </span>
|
|
397
|
+
<span class="cline-any cline-no"> </span>
|
|
398
|
+
<span class="cline-any cline-no"> </span>
|
|
399
|
+
<span class="cline-any cline-neutral"> </span>
|
|
400
|
+
<span class="cline-any cline-no"> </span>
|
|
401
|
+
<span class="cline-any cline-no"> </span>
|
|
402
|
+
<span class="cline-any cline-no"> </span>
|
|
403
|
+
<span class="cline-any cline-no"> </span>
|
|
404
|
+
<span class="cline-any cline-no"> </span>
|
|
405
|
+
<span class="cline-any cline-no"> </span>
|
|
406
|
+
<span class="cline-any cline-neutral"> </span>
|
|
407
|
+
<span class="cline-any cline-no"> </span>
|
|
408
|
+
<span class="cline-any cline-no"> </span>
|
|
409
|
+
<span class="cline-any cline-no"> </span>
|
|
410
|
+
<span class="cline-any cline-no"> </span>
|
|
411
|
+
<span class="cline-any cline-neutral"> </span>
|
|
412
|
+
<span class="cline-any cline-no"> </span>
|
|
413
|
+
<span class="cline-any cline-no"> </span>
|
|
414
|
+
<span class="cline-any cline-neutral"> </span>
|
|
415
|
+
<span class="cline-any cline-neutral"> </span>
|
|
416
|
+
<span class="cline-any cline-no"> </span>
|
|
417
|
+
<span class="cline-any cline-no"> </span>
|
|
418
|
+
<span class="cline-any cline-no"> </span>
|
|
419
|
+
<span class="cline-any cline-neutral"> </span>
|
|
420
|
+
<span class="cline-any cline-neutral"> </span>
|
|
421
|
+
<span class="cline-any cline-no"> </span>
|
|
422
|
+
<span class="cline-any cline-no"> </span>
|
|
423
|
+
<span class="cline-any cline-no"> </span>
|
|
424
|
+
<span class="cline-any cline-no"> </span>
|
|
425
|
+
<span class="cline-any cline-no"> </span>
|
|
426
|
+
<span class="cline-any cline-neutral"> </span>
|
|
427
|
+
<span class="cline-any cline-no"> </span>
|
|
428
|
+
<span class="cline-any cline-neutral"> </span>
|
|
429
|
+
<span class="cline-any cline-neutral"> </span>
|
|
430
|
+
<span class="cline-any cline-neutral"> </span>
|
|
431
|
+
<span class="cline-any cline-neutral"> </span>
|
|
432
|
+
<span class="cline-any cline-neutral"> </span>
|
|
433
|
+
<span class="cline-any cline-no"> </span>
|
|
434
|
+
<span class="cline-any cline-neutral"> </span>
|
|
435
|
+
<span class="cline-any cline-neutral"> </span>
|
|
436
|
+
<span class="cline-any cline-neutral"> </span>
|
|
437
|
+
<span class="cline-any cline-neutral"> </span>
|
|
438
|
+
<span class="cline-any cline-neutral"> </span>
|
|
439
|
+
<span class="cline-any cline-no"> </span>
|
|
440
|
+
<span class="cline-any cline-no"> </span>
|
|
441
|
+
<span class="cline-any cline-no"> </span>
|
|
442
|
+
<span class="cline-any cline-no"> </span>
|
|
443
|
+
<span class="cline-any cline-no"> </span>
|
|
444
|
+
<span class="cline-any cline-no"> </span>
|
|
445
|
+
<span class="cline-any cline-no"> </span>
|
|
446
|
+
<span class="cline-any cline-neutral"> </span>
|
|
447
|
+
<span class="cline-any cline-no"> </span>
|
|
448
|
+
<span class="cline-any cline-no"> </span>
|
|
449
|
+
<span class="cline-any cline-no"> </span>
|
|
450
|
+
<span class="cline-any cline-neutral"> </span>
|
|
451
|
+
<span class="cline-any cline-no"> </span>
|
|
452
|
+
<span class="cline-any cline-no"> </span>
|
|
453
|
+
<span class="cline-any cline-no"> </span>
|
|
454
|
+
<span class="cline-any cline-neutral"> </span>
|
|
455
|
+
<span class="cline-any cline-neutral"> </span>
|
|
456
|
+
<span class="cline-any cline-no"> </span>
|
|
457
|
+
<span class="cline-any cline-neutral"> </span>
|
|
458
|
+
<span class="cline-any cline-neutral"> </span>
|
|
459
|
+
<span class="cline-any cline-no"> </span>
|
|
460
|
+
<span class="cline-any cline-no"> </span>
|
|
461
|
+
<span class="cline-any cline-no"> </span>
|
|
462
|
+
<span class="cline-any cline-no"> </span>
|
|
463
|
+
<span class="cline-any cline-neutral"> </span>
|
|
464
|
+
<span class="cline-any cline-no"> </span>
|
|
465
|
+
<span class="cline-any cline-no"> </span>
|
|
466
|
+
<span class="cline-any cline-no"> </span>
|
|
467
|
+
<span class="cline-any cline-neutral"> </span>
|
|
468
|
+
<span class="cline-any cline-no"> </span>
|
|
469
|
+
<span class="cline-any cline-no"> </span>
|
|
470
|
+
<span class="cline-any cline-neutral"> </span>
|
|
471
|
+
<span class="cline-any cline-no"> </span>
|
|
472
|
+
<span class="cline-any cline-no"> </span>
|
|
473
|
+
<span class="cline-any cline-no"> </span>
|
|
474
|
+
<span class="cline-any cline-neutral"> </span>
|
|
475
|
+
<span class="cline-any cline-neutral"> </span>
|
|
476
|
+
<span class="cline-any cline-neutral"> </span>
|
|
477
|
+
<span class="cline-any cline-neutral"> </span>
|
|
478
|
+
<span class="cline-any cline-neutral"> </span>
|
|
479
|
+
<span class="cline-any cline-no"> </span>
|
|
480
|
+
<span class="cline-any cline-no"> </span>
|
|
481
|
+
<span class="cline-any cline-no"> </span>
|
|
482
|
+
<span class="cline-any cline-no"> </span>
|
|
483
|
+
<span class="cline-any cline-neutral"> </span>
|
|
484
|
+
<span class="cline-any cline-neutral"> </span>
|
|
485
|
+
<span class="cline-any cline-no"> </span>
|
|
486
|
+
<span class="cline-any cline-no"> </span>
|
|
487
|
+
<span class="cline-any cline-no"> </span>
|
|
488
|
+
<span class="cline-any cline-no"> </span>
|
|
489
|
+
<span class="cline-any cline-no"> </span>
|
|
490
|
+
<span class="cline-any cline-neutral"> </span>
|
|
491
|
+
<span class="cline-any cline-neutral"> </span>
|
|
492
|
+
<span class="cline-any cline-neutral"> </span>
|
|
493
|
+
<span class="cline-any cline-no"> </span>
|
|
494
|
+
<span class="cline-any cline-no"> </span>
|
|
495
|
+
<span class="cline-any cline-no"> </span>
|
|
496
|
+
<span class="cline-any cline-neutral"> </span>
|
|
497
|
+
<span class="cline-any cline-no"> </span>
|
|
498
|
+
<span class="cline-any cline-no"> </span>
|
|
499
|
+
<span class="cline-any cline-no"> </span>
|
|
500
|
+
<span class="cline-any cline-no"> </span>
|
|
501
|
+
<span class="cline-any cline-no"> </span>
|
|
502
|
+
<span class="cline-any cline-no"> </span>
|
|
503
|
+
<span class="cline-any cline-neutral"> </span>
|
|
504
|
+
<span class="cline-any cline-neutral"> </span>
|
|
505
|
+
<span class="cline-any cline-neutral"> </span>
|
|
506
|
+
<span class="cline-any cline-neutral"> </span>
|
|
507
|
+
<span class="cline-any cline-neutral"> </span>
|
|
508
|
+
<span class="cline-any cline-no"> </span>
|
|
509
|
+
<span class="cline-any cline-neutral"> </span>
|
|
510
|
+
<span class="cline-any cline-neutral"> </span>
|
|
511
|
+
<span class="cline-any cline-no"> </span>
|
|
512
|
+
<span class="cline-any cline-no"> </span>
|
|
513
|
+
<span class="cline-any cline-no"> </span>
|
|
514
|
+
<span class="cline-any cline-no"> </span>
|
|
515
|
+
<span class="cline-any cline-no"> </span>
|
|
516
|
+
<span class="cline-any cline-no"> </span>
|
|
517
|
+
<span class="cline-any cline-neutral"> </span>
|
|
518
|
+
<span class="cline-any cline-no"> </span>
|
|
519
|
+
<span class="cline-any cline-neutral"> </span>
|
|
520
|
+
<span class="cline-any cline-no"> </span>
|
|
521
|
+
<span class="cline-any cline-neutral"> </span>
|
|
522
|
+
<span class="cline-any cline-neutral"> </span>
|
|
523
|
+
<span class="cline-any cline-no"> </span>
|
|
524
|
+
<span class="cline-any cline-neutral"> </span>
|
|
525
|
+
<span class="cline-any cline-no"> </span>
|
|
526
|
+
<span class="cline-any cline-no"> </span>
|
|
527
|
+
<span class="cline-any cline-neutral"> </span>
|
|
528
|
+
<span class="cline-any cline-no"> </span>
|
|
529
|
+
<span class="cline-any cline-no"> </span>
|
|
530
|
+
<span class="cline-any cline-no"> </span>
|
|
531
|
+
<span class="cline-any cline-no"> </span>
|
|
532
|
+
<span class="cline-any cline-no"> </span>
|
|
533
|
+
<span class="cline-any cline-neutral"> </span>
|
|
534
|
+
<span class="cline-any cline-neutral"> </span>
|
|
535
|
+
<span class="cline-any cline-no"> </span>
|
|
536
|
+
<span class="cline-any cline-neutral"> </span>
|
|
537
|
+
<span class="cline-any cline-no"> </span>
|
|
538
|
+
<span class="cline-any cline-neutral"> </span>
|
|
539
|
+
<span class="cline-any cline-neutral"> </span>
|
|
540
|
+
<span class="cline-any cline-no"> </span>
|
|
541
|
+
<span class="cline-any cline-no"> </span>
|
|
542
|
+
<span class="cline-any cline-no"> </span>
|
|
543
|
+
<span class="cline-any cline-neutral"> </span>
|
|
544
|
+
<span class="cline-any cline-neutral"> </span>
|
|
545
|
+
<span class="cline-any cline-neutral"> </span>
|
|
546
|
+
<span class="cline-any cline-no"> </span>
|
|
547
|
+
<span class="cline-any cline-neutral"> </span>
|
|
548
|
+
<span class="cline-any cline-neutral"> </span>
|
|
549
|
+
<span class="cline-any cline-neutral"> </span>
|
|
550
|
+
<span class="cline-any cline-neutral"> </span>
|
|
551
|
+
<span class="cline-any cline-no"> </span>
|
|
552
|
+
<span class="cline-any cline-no"> </span>
|
|
553
|
+
<span class="cline-any cline-neutral"> </span>
|
|
554
|
+
<span class="cline-any cline-neutral"> </span>
|
|
555
|
+
<span class="cline-any cline-neutral"> </span>
|
|
556
|
+
<span class="cline-any cline-no"> </span>
|
|
557
|
+
<span class="cline-any cline-no"> </span>
|
|
558
|
+
<span class="cline-any cline-neutral"> </span>
|
|
559
|
+
<span class="cline-any cline-neutral"> </span>
|
|
560
|
+
<span class="cline-any cline-neutral"> </span>
|
|
561
|
+
<span class="cline-any cline-no"> </span>
|
|
562
|
+
<span class="cline-any cline-no"> </span>
|
|
563
|
+
<span class="cline-any cline-neutral"> </span>
|
|
564
|
+
<span class="cline-any cline-neutral"> </span>
|
|
565
|
+
<span class="cline-any cline-neutral"> </span>
|
|
566
|
+
<span class="cline-any cline-no"> </span>
|
|
567
|
+
<span class="cline-any cline-no"> </span>
|
|
568
|
+
<span class="cline-any cline-neutral"> </span>
|
|
569
|
+
<span class="cline-any cline-neutral"> </span>
|
|
570
|
+
<span class="cline-any cline-neutral"> </span>
|
|
571
|
+
<span class="cline-any cline-no"> </span>
|
|
572
|
+
<span class="cline-any cline-no"> </span>
|
|
573
|
+
<span class="cline-any cline-neutral"> </span>
|
|
574
|
+
<span class="cline-any cline-neutral"> </span>
|
|
575
|
+
<span class="cline-any cline-no"> </span>
|
|
576
|
+
<span class="cline-any cline-neutral"> </span>
|
|
577
|
+
<span class="cline-any cline-neutral"> </span>
|
|
578
|
+
<span class="cline-any cline-neutral"> </span>
|
|
579
|
+
<span class="cline-any cline-no"> </span>
|
|
580
|
+
<span class="cline-any cline-no"> </span>
|
|
581
|
+
<span class="cline-any cline-no"> </span>
|
|
582
|
+
<span class="cline-any cline-neutral"> </span>
|
|
583
|
+
<span class="cline-any cline-neutral"> </span>
|
|
584
|
+
<span class="cline-any cline-neutral"> </span>
|
|
585
|
+
<span class="cline-any cline-neutral"> </span>
|
|
586
|
+
<span class="cline-any cline-neutral"> </span>
|
|
587
|
+
<span class="cline-any cline-neutral"> </span>
|
|
588
|
+
<span class="cline-any cline-no"> </span>
|
|
589
|
+
<span class="cline-any cline-neutral"> </span>
|
|
590
|
+
<span class="cline-any cline-neutral"> </span>
|
|
591
|
+
<span class="cline-any cline-neutral"> </span>
|
|
592
|
+
<span class="cline-any cline-neutral"> </span>
|
|
593
|
+
<span class="cline-any cline-neutral"> </span>
|
|
594
|
+
<span class="cline-any cline-neutral"> </span>
|
|
595
|
+
<span class="cline-any cline-no"> </span>
|
|
596
|
+
<span class="cline-any cline-neutral"> </span>
|
|
597
|
+
<span class="cline-any cline-neutral"> </span>
|
|
598
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { eq, and } from "drizzle-orm";
|
|
599
|
+
import { AnyPgColumn } from "drizzle-orm/pg-core";
|
|
600
|
+
// import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
601
|
+
import { Entity, EntityCollection, Properties, Relation } from "@rebasepro/types";
|
|
602
|
+
import { getTableName, resolveCollectionRelations } from "@rebasepro/common";
|
|
603
|
+
import { DrizzleConditionBuilder } from "../../utils/drizzle-conditions";
|
|
604
|
+
import {
|
|
605
|
+
getCollectionByPath,
|
|
606
|
+
getTableForCollection,
|
|
607
|
+
getPrimaryKeys,
|
|
608
|
+
parseIdValues,
|
|
609
|
+
buildCompositeId
|
|
610
|
+
} from "./entity-helpers";
|
|
611
|
+
import { sanitizeAndConvertDates, serializeDataToServer } from "../data-transformer";
|
|
612
|
+
import { RelationService } from "./RelationService";
|
|
613
|
+
import { EntityFetchService } from "./EntityFetchService";
|
|
614
|
+
import { DrizzleClient } from "../interfaces";
|
|
615
|
+
import { BackendCollectionRegistry } from "../../collections/BackendCollectionRegistry";
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Service for handling all entity write operations.
|
|
619
|
+
* Handles saving, deleting, and updating entities.
|
|
620
|
+
*/
|
|
621
|
+
export class EntityPersistService {
|
|
622
|
+
private relationService: RelationService;
|
|
623
|
+
private fetchService: EntityFetchService;
|
|
624
|
+
|
|
625
|
+
constructor(private db: DrizzleClient, private registry: BackendCollectionRegistry) {
|
|
626
|
+
this.relationService = new RelationService(db, registry);
|
|
627
|
+
this.fetchService = new EntityFetchService(db, registry);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Delete an entity by ID
|
|
633
|
+
*/
|
|
634
|
+
<span class="fstat-no" title="function not covered" > async </span>deleteEntity(collectionPath: string, entityId: string | number, _databaseId?: string): Promise<void> {
|
|
635
|
+
const collection = <span class="cstat-no" title="statement not covered" >getCollectionByPath(collectionPath, this.registry);</span>
|
|
636
|
+
const table = <span class="cstat-no" title="statement not covered" >getTableForCollection(collection, this.registry);</span>
|
|
637
|
+
const idInfoArray = <span class="cstat-no" title="statement not covered" >getPrimaryKeys(collection, this.registry);</span>
|
|
638
|
+
const idInfo = <span class="cstat-no" title="statement not covered" >idInfoArray[0];</span>
|
|
639
|
+
const idField = <span class="cstat-no" title="statement not covered" >table[idInfo.fieldName as keyof typeof table] as AnyPgColumn;</span>
|
|
640
|
+
|
|
641
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!idField) {</span>
|
|
642
|
+
<span class="cstat-no" title="statement not covered" > throw new Error(`ID field '${idInfo.fieldName}' not found in table for collection '${collectionPath}'`);</span>
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const parsedIdObj = <span class="cstat-no" title="statement not covered" >parseIdValues(entityId, idInfoArray);</span>
|
|
646
|
+
const parsedId = <span class="cstat-no" title="statement not covered" >parsedIdObj[idInfo.fieldName];</span>
|
|
647
|
+
|
|
648
|
+
<span class="cstat-no" title="statement not covered" > await this.db</span>
|
|
649
|
+
.delete(table)
|
|
650
|
+
.where(eq(idField, parsedId));
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Save an entity (create or update)
|
|
655
|
+
*/
|
|
656
|
+
<span class="fstat-no" title="function not covered" > async </span>saveEntity<M extends Record<string, any>>(
|
|
657
|
+
collectionPath: string,
|
|
658
|
+
values: Partial<M>,
|
|
659
|
+
entityId?: string | number,
|
|
660
|
+
databaseId?: string
|
|
661
|
+
): Promise<Entity<M>> {
|
|
662
|
+
// If saving under a nested relation path, resolve the parent and inject FK
|
|
663
|
+
let effectiveCollectionPath = <span class="cstat-no" title="statement not covered" >collectionPath;</span>
|
|
664
|
+
const effectiveValues: Partial<M> = <span class="cstat-no" title="statement not covered" >{ ...values };</span>
|
|
665
|
+
|
|
666
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (collectionPath.includes("/")) {</span>
|
|
667
|
+
const segments = <span class="cstat-no" title="statement not covered" >collectionPath.split("/").filter(Boolean);</span>
|
|
668
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (segments.length >= 3 && segments.length % 2 === 1) {</span>
|
|
669
|
+
const rootSegment = <span class="cstat-no" title="statement not covered" >segments[0];</span>
|
|
670
|
+
let currentCollection = <span class="cstat-no" title="statement not covered" >getCollectionByPath(rootSegment, this.registry);</span>
|
|
671
|
+
let currentEntityId: string | number = <span class="cstat-no" title="statement not covered" >segments[1];</span>
|
|
672
|
+
|
|
673
|
+
<span class="cstat-no" title="statement not covered" > for (let i = <span class="cstat-no" title="statement not covered" >2;</span> i < segments.length; i += 2) {</span>
|
|
674
|
+
const relationKey = <span class="cstat-no" title="statement not covered" >segments[i];</span>
|
|
675
|
+
const resolvedRelations = <span class="cstat-no" title="statement not covered" >resolveCollectionRelations(currentCollection);</span>
|
|
676
|
+
const relation = <span class="cstat-no" title="statement not covered" >resolvedRelations[relationKey];</span>
|
|
677
|
+
|
|
678
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!relation) {</span>
|
|
679
|
+
<span class="cstat-no" title="statement not covered" > throw new Error(`Relation '${relationKey}' not found in collection '${currentCollection.slug || currentCollection.dbPath}'`);</span>
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
<span class="cstat-no" title="statement not covered" > if (i === segments.length - 1) {</span>
|
|
683
|
+
const targetCollection = <span class="cstat-no" title="statement not covered" >relation.target();</span>
|
|
684
|
+
<span class="cstat-no" title="statement not covered" > effectiveCollectionPath = targetCollection.slug ?? targetCollection.dbPath;</span>
|
|
685
|
+
|
|
686
|
+
// Handle many-to-many with junction table
|
|
687
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (relation.cardinality === "many" && relation.through) {</span>
|
|
688
|
+
const parentIdInfoArray = <span class="cstat-no" title="statement not covered" >getPrimaryKeys(currentCollection, this.registry);</span>
|
|
689
|
+
const parentIdInfo = <span class="cstat-no" title="statement not covered" >parentIdInfoArray[0];</span>
|
|
690
|
+
const parsedParentIdObj = <span class="cstat-no" title="statement not covered" >parseIdValues(currentEntityId, parentIdInfoArray);</span>
|
|
691
|
+
const parsedParentId = <span class="cstat-no" title="statement not covered" >parsedParentIdObj[parentIdInfo.fieldName];</span>
|
|
692
|
+
|
|
693
|
+
(<span class="cstat-no" title="statement not covered" >effectiveValues as Record<string, unknown>).__junction_table_info = {</span>
|
|
694
|
+
parentCollection: currentCollection,
|
|
695
|
+
parentId: parsedParentId,
|
|
696
|
+
relation: relation,
|
|
697
|
+
relationKey: relationKey
|
|
698
|
+
};
|
|
699
|
+
<span class="cstat-no" title="statement not covered" > break;</span>
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Find the FK column that should store the parent ID
|
|
703
|
+
let targetColumnName: string;
|
|
704
|
+
|
|
705
|
+
<span class="cstat-no" title="statement not covered" > if (relation.localKey) {</span>
|
|
706
|
+
<span class="cstat-no" title="statement not covered" > targetColumnName = relation.localKey;</span>
|
|
707
|
+
} else <span class="cstat-no" title="statement not covered" >if (relation.foreignKeyOnTarget) {</span>
|
|
708
|
+
<span class="cstat-no" title="statement not covered" > targetColumnName = relation.foreignKeyOnTarget;</span>
|
|
709
|
+
} else <span class="cstat-no" title="statement not covered" >if (relation.joinPath && relation.joinPath.length > 0) {</span>
|
|
710
|
+
const targetTableName = <span class="cstat-no" title="statement not covered" >getTableName(targetCollection);</span>
|
|
711
|
+
const relevantJoinStep = <span class="cstat-no" title="statement not covered" >relation.joinPath.find(<span class="fstat-no" title="function not covered" >joinStep </span>=> <span class="cstat-no" title="statement not covered" >joinStep.table === targetTableName)</span>;</span>
|
|
712
|
+
|
|
713
|
+
<span class="cstat-no" title="statement not covered" > if (relevantJoinStep) {</span>
|
|
714
|
+
const targetColumnNames = <span class="cstat-no" title="statement not covered" >DrizzleConditionBuilder.getColumnNamesFromColumns(relevantJoinStep.on.to);</span>
|
|
715
|
+
<span class="cstat-no" title="statement not covered" > targetColumnName = targetColumnNames[0];</span>
|
|
716
|
+
} else {
|
|
717
|
+
<span class="cstat-no" title="statement not covered" > console.warn(`Could not find specific join step for target table ${targetTableName} in relation '${relationKey}'.`);</span>
|
|
718
|
+
const targetColumnNames = <span class="cstat-no" title="statement not covered" >DrizzleConditionBuilder.getColumnNamesFromColumns(relation.joinPath[0].on.to);</span>
|
|
719
|
+
<span class="cstat-no" title="statement not covered" > targetColumnName = targetColumnNames[0];</span>
|
|
720
|
+
}
|
|
721
|
+
} else {
|
|
722
|
+
<span class="cstat-no" title="statement not covered" > throw new Error(`Relation '${relationKey}' lacks configuration for path-based saving.`);</span>
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
const parentIdInfoArray = <span class="cstat-no" title="statement not covered" >getPrimaryKeys(currentCollection, this.registry);</span>
|
|
726
|
+
const parentIdInfo = <span class="cstat-no" title="statement not covered" >parentIdInfoArray[0];</span>
|
|
727
|
+
const parsedParentIdObj = <span class="cstat-no" title="statement not covered" >parseIdValues(currentEntityId, parentIdInfoArray);</span>
|
|
728
|
+
const parsedParentId = <span class="cstat-no" title="statement not covered" >parsedParentIdObj[parentIdInfo.fieldName];</span>
|
|
729
|
+
|
|
730
|
+
const existingValue = (<span class="cstat-no" title="statement not covered" >effectiveValues as Record<string, unknown>)[targetColumnName];</span>
|
|
731
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (existingValue !== undefined && existingValue !== null && existingValue !== parsedParentId) {</span>
|
|
732
|
+
<span class="cstat-no" title="statement not covered" > console.warn(`Overriding provided value '${existingValue}' for FK '${targetColumnName}' with path parent id '${parsedParentId}'.`);</span>
|
|
733
|
+
}
|
|
734
|
+
(<span class="cstat-no" title="statement not covered" >effectiveValues as Record<string, unknown>)[targetColumnName] = parsedParentId;</span>
|
|
735
|
+
<span class="cstat-no" title="statement not covered" > break;</span>
|
|
736
|
+
} else {
|
|
737
|
+
const nextEntityId = <span class="cstat-no" title="statement not covered" >segments[i + 1];</span>
|
|
738
|
+
<span class="cstat-no" title="statement not covered" > currentCollection = relation.target();</span>
|
|
739
|
+
<span class="cstat-no" title="statement not covered" > currentEntityId = nextEntityId;</span>
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
const collection = <span class="cstat-no" title="statement not covered" >getCollectionByPath(effectiveCollectionPath, this.registry);</span>
|
|
746
|
+
const table = <span class="cstat-no" title="statement not covered" >getTableForCollection(collection, this.registry);</span>
|
|
747
|
+
const idInfoArray = <span class="cstat-no" title="statement not covered" >getPrimaryKeys(collection, this.registry);</span>
|
|
748
|
+
const primaryKeyFields = <span class="cstat-no" title="statement not covered" >idInfoArray.map(<span class="fstat-no" title="function not covered" >info </span>=> <span class="cstat-no" title="statement not covered" >info.fieldName)</span>;</span>
|
|
749
|
+
|
|
750
|
+
// Build an object mapping required for dynamic returning
|
|
751
|
+
const returningKeys: Record<string, AnyPgColumn> = <span class="cstat-no" title="statement not covered" >{};</span>
|
|
752
|
+
<span class="cstat-no" title="statement not covered" > idInfoArray.forEach(<span class="fstat-no" title="function not covered" >info </span>=> {</span>
|
|
753
|
+
const field = <span class="cstat-no" title="statement not covered" >table[info.fieldName as keyof typeof table] as AnyPgColumn;</span>
|
|
754
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!field) <span class="cstat-no" title="statement not covered" >throw new Error(`Primary key field '${info.fieldName}' not found in table for collection '${effectiveCollectionPath}'`);</span></span>
|
|
755
|
+
<span class="cstat-no" title="statement not covered" > returningKeys[info.fieldName] = field;</span>
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
// Separate relations that require special handling
|
|
759
|
+
const relationValues: Record<string, unknown> = <span class="cstat-no" title="statement not covered" >{};</span>
|
|
760
|
+
const otherValues: Partial<M> = <span class="cstat-no" title="statement not covered" >{ ...effectiveValues };</span>
|
|
761
|
+
const resolvedRelations = <span class="cstat-no" title="statement not covered" >resolveCollectionRelations(collection);</span>
|
|
762
|
+
|
|
763
|
+
<span class="cstat-no" title="statement not covered" > for (const key in resolvedRelations) {</span>
|
|
764
|
+
const relation = <span class="cstat-no" title="statement not covered" >resolvedRelations[key];</span>
|
|
765
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (relation && relation.cardinality === "many") {</span>
|
|
766
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (Object.prototype.hasOwnProperty.call(otherValues, key)) {</span>
|
|
767
|
+
<span class="cstat-no" title="statement not covered" > relationValues[key] = otherValues[key as keyof M];</span>
|
|
768
|
+
<span class="cstat-no" title="statement not covered" > delete otherValues[key as keyof M];</span>
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Transform relations to IDs, then sanitize
|
|
774
|
+
const processedData = <span class="cstat-no" title="statement not covered" >serializeDataToServer(otherValues as M, collection.properties as Properties, collection, this.registry);</span>
|
|
775
|
+
|
|
776
|
+
// Extract relation updates before sanitizing
|
|
777
|
+
const inverseRelationUpdates = ((<span class="cstat-no" title="statement not covered" >processedData as Record<string, unknown>).__inverseRelationUpdates as Array<{ relationKey: string; relation: Relation; newValue: unknown; currentEntityId?: string | number; }>) || [];</span>
|
|
778
|
+
const joinPathRelationUpdates = ((<span class="cstat-no" title="statement not covered" >processedData as Record<string, unknown>).__joinPathRelationUpdates as Array<{ relationKey: string; relation: Relation; newTargetId: string | number | null; }>) || [];</span>
|
|
779
|
+
const junctionTableInfo = (<span class="cstat-no" title="statement not covered" >processedData as Record<string, unknown>).__junction_table_info as { parentCollection: EntityCollection<any, any>; parentId: string | number; relation: Relation; relationKey: string; } | undefined;</span>
|
|
780
|
+
<span class="cstat-no" title="statement not covered" > delete (processedData as Record<string, unknown>).__inverseRelationUpdates;</span>
|
|
781
|
+
<span class="cstat-no" title="statement not covered" > delete (processedData as Record<string, unknown>).__joinPathRelationUpdates;</span>
|
|
782
|
+
<span class="cstat-no" title="statement not covered" > delete (processedData as Record<string, unknown>).__junction_table_info;</span>
|
|
783
|
+
|
|
784
|
+
const entityData = <span class="cstat-no" title="statement not covered" >sanitizeAndConvertDates(processedData);</span>
|
|
785
|
+
|
|
786
|
+
const savedId = <span class="cstat-no" title="statement not covered" >await this.db.transaction(<span class="fstat-no" title="function not covered" >async </span>(tx) => {</span>
|
|
787
|
+
let currentId: string | number;
|
|
788
|
+
|
|
789
|
+
<span class="cstat-no" title="statement not covered" > if (entityId) {</span>
|
|
790
|
+
// Update existing entity
|
|
791
|
+
<span class="cstat-no" title="statement not covered" > currentId = entityId; </span>// `entityId` is already the formatted composite or singular string
|
|
792
|
+
const idValues = <span class="cstat-no" title="statement not covered" >parseIdValues(entityId, idInfoArray);</span>
|
|
793
|
+
|
|
794
|
+
let updateQuery = <span class="cstat-no" title="statement not covered" >tx.update(table).set(entityData as Record<string, unknown>);</span>
|
|
795
|
+
const conditions = <span class="cstat-no" title="statement not covered" >[];</span>
|
|
796
|
+
<span class="cstat-no" title="statement not covered" > for (const info of idInfoArray) {</span>
|
|
797
|
+
const field = <span class="cstat-no" title="statement not covered" >table[info.fieldName as keyof typeof table] as AnyPgColumn;</span>
|
|
798
|
+
<span class="cstat-no" title="statement not covered" > conditions.push(eq(field, idValues[info.fieldName]));</span>
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
<span class="cstat-no" title="statement not covered" > await updateQuery.where(and(...conditions));</span>
|
|
802
|
+
} else {
|
|
803
|
+
const dataForInsert = <span class="cstat-no" title="statement not covered" >{ ...(entityData as Record<string, unknown>) };</span>
|
|
804
|
+
|
|
805
|
+
// Strip empty primary keys so the database defaults (e.g. uuid_gen(), auto-increment) can trigger
|
|
806
|
+
<span class="cstat-no" title="statement not covered" > for (const info of idInfoArray) {</span>
|
|
807
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (dataForInsert[info.fieldName] === "" || dataForInsert[info.fieldName] === null || dataForInsert[info.fieldName] === undefined) {</span>
|
|
808
|
+
<span class="cstat-no" title="statement not covered" > delete dataForInsert[info.fieldName];</span>
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
const result = <span class="cstat-no" title="statement not covered" >await tx</span>
|
|
813
|
+
.insert(table)
|
|
814
|
+
.values(dataForInsert)
|
|
815
|
+
.returning(returningKeys);
|
|
816
|
+
|
|
817
|
+
const resultRow = <span class="cstat-no" title="statement not covered" >result[0];</span>
|
|
818
|
+
<span class="cstat-no" title="statement not covered" > currentId = buildCompositeId(resultRow, idInfoArray);</span>
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// Handle inverse relation updates
|
|
822
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (inverseRelationUpdates.length > 0) {</span>
|
|
823
|
+
<span class="cstat-no" title="statement not covered" > await this.relationService.updateInverseRelations(tx, collection, currentId, inverseRelationUpdates);</span>
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Update many-to-many relations
|
|
827
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (Object.keys(relationValues).length > 0) {</span>
|
|
828
|
+
<span class="cstat-no" title="statement not covered" > await this.relationService.updateRelationsUsingJoins(tx, collection, currentId, relationValues);</span>
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// Apply joinPath one-to-one relation updates
|
|
832
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (joinPathRelationUpdates.length > 0) {</span>
|
|
833
|
+
<span class="cstat-no" title="statement not covered" > await this.relationService.updateJoinPathOneToOneRelations(tx, collection, currentId, joinPathRelationUpdates);</span>
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// Handle junction table creation for many-to-many path-based saves
|
|
837
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (junctionTableInfo && !entityId) {</span>
|
|
838
|
+
<span class="cstat-no" title="statement not covered" > await this.relationService.handleJunctionTableCreation(tx, currentId, junctionTableInfo);</span>
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
<span class="cstat-no" title="statement not covered" > return currentId;</span>
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
// Fetch the updated/created entity to return with proper relation objects
|
|
845
|
+
const finalEntity = <span class="cstat-no" title="statement not covered" >await this.fetchService.fetchEntity<M>(collection.dbPath ?? collection.slug, savedId, databaseId);</span>
|
|
846
|
+
<span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!finalEntity) <span class="cstat-no" title="statement not covered" >throw new Error("Could not fetch entity after save.");</span></span>
|
|
847
|
+
<span class="cstat-no" title="statement not covered" > return finalEntity;</span>
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Get the RelationService instance for external use
|
|
852
|
+
*/
|
|
853
|
+
<span class="fstat-no" title="function not covered" > getRelationService(</span>): RelationService {
|
|
854
|
+
<span class="cstat-no" title="statement not covered" > return this.relationService;</span>
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Get the FetchService instance for external use
|
|
859
|
+
*/
|
|
860
|
+
<span class="fstat-no" title="function not covered" > getFetchService(</span>): EntityFetchService {
|
|
861
|
+
<span class="cstat-no" title="statement not covered" > return this.fetchService;</span>
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
</pre></td></tr></table></pre>
|
|
865
|
+
|
|
866
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
867
|
+
</div><!-- /wrapper -->
|
|
868
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
869
|
+
Code coverage generated by
|
|
870
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
871
|
+
at 2026-04-06T04:35:23.770Z
|
|
872
|
+
</div>
|
|
873
|
+
<script src="../../../prettify.js"></script>
|
|
874
|
+
<script>
|
|
875
|
+
window.onload = function () {
|
|
876
|
+
prettyPrint();
|
|
877
|
+
};
|
|
878
|
+
</script>
|
|
879
|
+
<script src="../../../sorter.js"></script>
|
|
880
|
+
<script src="../../../block-navigation.js"></script>
|
|
881
|
+
</body>
|
|
882
|
+
</html>
|
|
883
|
+
|