@saltcorn/data 0.6.2-beta.1 → 0.6.2-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-plugin/actions.d.ts +141 -0
- package/dist/base-plugin/actions.d.ts.map +1 -0
- package/dist/base-plugin/actions.js +551 -0
- package/dist/base-plugin/actions.js.map +1 -0
- package/dist/base-plugin/base.test.d.ts +2 -0
- package/dist/base-plugin/base.test.d.ts.map +1 -0
- package/dist/base-plugin/base.test.js +15 -0
- package/dist/base-plugin/base.test.js.map +1 -0
- package/dist/base-plugin/fieldviews.d.ts +25 -0
- package/dist/base-plugin/fieldviews.d.ts.map +1 -0
- package/dist/base-plugin/fieldviews.js +159 -0
- package/dist/base-plugin/fieldviews.js.map +1 -0
- package/dist/base-plugin/fileviews.d.ts +52 -0
- package/dist/base-plugin/fileviews.d.ts.map +1 -0
- package/dist/base-plugin/fileviews.js +59 -0
- package/dist/base-plugin/fileviews.js.map +1 -0
- package/dist/base-plugin/index.d.ts +524 -0
- package/dist/base-plugin/index.d.ts.map +1 -0
- package/{base-plugin → dist/base-plugin}/index.js +22 -24
- package/dist/base-plugin/index.js.map +1 -0
- package/dist/base-plugin/types.d.ts +383 -0
- package/dist/base-plugin/types.d.ts.map +1 -0
- package/dist/base-plugin/types.js +1080 -0
- package/dist/base-plugin/types.js.map +1 -0
- package/dist/base-plugin/viewtemplates/edit.d.ts +116 -0
- package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/edit.js +561 -0
- package/dist/base-plugin/viewtemplates/edit.js.map +1 -0
- package/dist/base-plugin/viewtemplates/feed.d.ts +73 -0
- package/dist/base-plugin/viewtemplates/feed.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/feed.js +348 -0
- package/dist/base-plugin/viewtemplates/feed.js.map +1 -0
- package/dist/base-plugin/viewtemplates/filter.d.ts +46 -0
- package/dist/base-plugin/viewtemplates/filter.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/filter.js +267 -0
- package/dist/base-plugin/viewtemplates/filter.js.map +1 -0
- package/dist/base-plugin/viewtemplates/list.d.ts +99 -0
- package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/list.js +471 -0
- package/dist/base-plugin/viewtemplates/list.js.map +1 -0
- package/dist/base-plugin/viewtemplates/listshowlist.d.ts +41 -0
- package/dist/base-plugin/viewtemplates/listshowlist.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/listshowlist.js +248 -0
- package/dist/base-plugin/viewtemplates/listshowlist.js.map +1 -0
- package/dist/base-plugin/viewtemplates/room.d.ts +140 -0
- package/dist/base-plugin/viewtemplates/room.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/room.js +469 -0
- package/dist/base-plugin/viewtemplates/room.js.map +1 -0
- package/dist/base-plugin/viewtemplates/show.d.ts +101 -0
- package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/show.js +562 -0
- package/dist/base-plugin/viewtemplates/show.js.map +1 -0
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts +108 -0
- package/dist/base-plugin/viewtemplates/viewable_fields.d.ts.map +1 -0
- package/dist/base-plugin/viewtemplates/viewable_fields.js +563 -0
- package/dist/base-plugin/viewtemplates/viewable_fields.js.map +1 -0
- package/dist/contracts.d.ts +49 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +212 -0
- package/dist/contracts.js.map +1 -0
- package/dist/coverage/lcov-report/block-navigation.d.ts +2 -0
- package/dist/coverage/lcov-report/block-navigation.d.ts.map +1 -0
- package/dist/coverage/lcov-report/block-navigation.js +66 -0
- package/dist/coverage/lcov-report/block-navigation.js.map +1 -0
- package/dist/coverage/lcov-report/prettify.d.ts +1 -0
- package/dist/coverage/lcov-report/prettify.d.ts.map +1 -0
- package/dist/coverage/lcov-report/prettify.js +478 -0
- package/dist/coverage/lcov-report/prettify.js.map +1 -0
- package/dist/coverage/lcov-report/sorter.d.ts +2 -0
- package/dist/coverage/lcov-report/sorter.d.ts.map +1 -0
- package/dist/coverage/lcov-report/sorter.js +141 -0
- package/dist/coverage/lcov-report/sorter.js.map +1 -0
- package/dist/db/connect.d.ts +40 -0
- package/dist/db/connect.d.ts.map +1 -0
- package/dist/db/connect.js +150 -0
- package/dist/db/connect.js.map +1 -0
- package/dist/db/db.test.d.ts +2 -0
- package/dist/db/db.test.d.ts.map +1 -0
- package/dist/db/db.test.js +28 -0
- package/dist/db/db.test.js.map +1 -0
- package/dist/db/fixtures.d.ts +8 -0
- package/dist/db/fixtures.d.ts.map +1 -0
- package/dist/db/fixtures.js +300 -0
- package/dist/db/fixtures.js.map +1 -0
- package/dist/db/index.d.ts +3 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +41 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/reset_schema.d.ts +13 -0
- package/dist/db/reset_schema.d.ts.map +1 -0
- package/{db → dist/db}/reset_schema.js +45 -55
- package/dist/db/reset_schema.js.map +1 -0
- package/dist/db/state.d.ts +56 -0
- package/dist/db/state.d.ts.map +1 -0
- package/dist/db/state.js +608 -0
- package/dist/db/state.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.js → dist/index.js} +2 -1
- package/dist/index.js.map +1 -0
- package/dist/migrate.d.ts +12 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +94 -0
- package/dist/migrate.js.map +1 -0
- package/dist/migrations/202005141503.d.ts +2 -0
- package/dist/migrations/202005141503.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202005141503.js +2 -1
- package/dist/migrations/202005141503.js.map +1 -0
- package/dist/migrations/202005241712.d.ts +2 -0
- package/dist/migrations/202005241712.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202005241712.js +2 -1
- package/dist/migrations/202005241712.js.map +1 -0
- package/dist/migrations/202005251037.d.ts +2 -0
- package/dist/migrations/202005251037.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202005251037.js +2 -1
- package/dist/migrations/202005251037.js.map +1 -0
- package/dist/migrations/202005282134.d.ts +2 -0
- package/dist/migrations/202005282134.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202005282134.js +2 -1
- package/dist/migrations/202005282134.js.map +1 -0
- package/dist/migrations/202006022156.d.ts +2 -0
- package/dist/migrations/202006022156.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202006022156.js +2 -1
- package/dist/migrations/202006022156.js.map +1 -0
- package/dist/migrations/202006051507.d.ts +2 -0
- package/dist/migrations/202006051507.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202006051507.js +2 -1
- package/dist/migrations/202006051507.js.map +1 -0
- package/dist/migrations/202006240906.d.ts +2 -0
- package/dist/migrations/202006240906.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202006240906.js +2 -1
- package/dist/migrations/202006240906.js.map +1 -0
- package/dist/migrations/202007091707.d.ts +2 -0
- package/dist/migrations/202007091707.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202007091707.js +2 -1
- package/dist/migrations/202007091707.js.map +1 -0
- package/dist/migrations/202007202144.d.ts +2 -0
- package/dist/migrations/202007202144.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202007202144.js +2 -1
- package/dist/migrations/202007202144.js.map +1 -0
- package/dist/migrations/202008031500.d.ts +2 -0
- package/dist/migrations/202008031500.d.ts.map +1 -0
- package/dist/migrations/202008031500.js +4 -0
- package/dist/migrations/202008031500.js.map +1 -0
- package/dist/migrations/202008051415.d.ts +2 -0
- package/dist/migrations/202008051415.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202008051415.js +2 -1
- package/dist/migrations/202008051415.js.map +1 -0
- package/dist/migrations/202008121149.d.ts +3 -0
- package/dist/migrations/202008121149.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202008121149.js +2 -2
- package/dist/migrations/202008121149.js.map +1 -0
- package/dist/migrations/202009112140.d.ts +3 -0
- package/dist/migrations/202009112140.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202009112140.js +2 -2
- package/dist/migrations/202009112140.js.map +1 -0
- package/dist/migrations/202009181655.d.ts +2 -0
- package/dist/migrations/202009181655.d.ts.map +1 -0
- package/dist/migrations/202009181655.js +7 -0
- package/dist/migrations/202009181655.js.map +1 -0
- package/dist/migrations/202009221105.d.ts +2 -0
- package/dist/migrations/202009221105.d.ts.map +1 -0
- package/dist/migrations/202009221105.js +4 -0
- package/dist/migrations/202009221105.js.map +1 -0
- package/dist/migrations/202009231331.d.ts +2 -0
- package/dist/migrations/202009231331.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202009231331.js +2 -1
- package/dist/migrations/202009231331.js.map +1 -0
- package/dist/migrations/202009301531.d.ts +2 -0
- package/dist/migrations/202009301531.d.ts.map +1 -0
- package/dist/migrations/202009301531.js +8 -0
- package/dist/migrations/202009301531.js.map +1 -0
- package/dist/migrations/202010231444.d.ts +2 -0
- package/dist/migrations/202010231444.d.ts.map +1 -0
- package/dist/migrations/202010231444.js +4 -0
- package/dist/migrations/202010231444.js.map +1 -0
- package/dist/migrations/202010251412.d.ts +2 -0
- package/dist/migrations/202010251412.d.ts.map +1 -0
- package/dist/migrations/202010251412.js +10 -0
- package/dist/migrations/202010251412.js.map +1 -0
- package/dist/migrations/202011021749.d.ts +2 -0
- package/dist/migrations/202011021749.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202011021749.js +2 -1
- package/dist/migrations/202011021749.js.map +1 -0
- package/dist/migrations/202011051353.d.ts +2 -0
- package/dist/migrations/202011051353.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202011051353.js +2 -1
- package/dist/migrations/202011051353.js.map +1 -0
- package/dist/migrations/202011111127.d.ts +2 -0
- package/dist/migrations/202011111127.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202011111127.js +2 -1
- package/dist/migrations/202011111127.js.map +1 -0
- package/dist/migrations/202012011203.d.ts +2 -0
- package/dist/migrations/202012011203.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202012011203.js +2 -1
- package/dist/migrations/202012011203.js.map +1 -0
- package/dist/migrations/202012100841.d.ts +2 -0
- package/dist/migrations/202012100841.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202012100841.js +2 -1
- package/dist/migrations/202012100841.js.map +1 -0
- package/dist/migrations/202012281835.d.ts +2 -0
- package/dist/migrations/202012281835.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202012281835.js +2 -1
- package/dist/migrations/202012281835.js.map +1 -0
- package/dist/migrations/202101061051.d.ts +2 -0
- package/dist/migrations/202101061051.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202101061051.js +2 -1
- package/dist/migrations/202101061051.js.map +1 -0
- package/dist/migrations/202101141128.d.ts +2 -0
- package/dist/migrations/202101141128.d.ts.map +1 -0
- package/dist/migrations/202101141128.js +4 -0
- package/dist/migrations/202101141128.js.map +1 -0
- package/dist/migrations/202102091312.d.ts +3 -0
- package/dist/migrations/202102091312.d.ts.map +1 -0
- package/dist/migrations/202102091312.js +19 -0
- package/dist/migrations/202102091312.js.map +1 -0
- package/dist/migrations/202102101624.d.ts +2 -0
- package/dist/migrations/202102101624.d.ts.map +1 -0
- package/dist/migrations/202102101624.js +7 -0
- package/dist/migrations/202102101624.js.map +1 -0
- package/dist/migrations/202102172148.d.ts +2 -0
- package/dist/migrations/202102172148.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202102172148.js +2 -2
- package/dist/migrations/202102172148.js.map +1 -0
- package/dist/migrations/202102261650.d.ts +2 -0
- package/dist/migrations/202102261650.d.ts.map +1 -0
- package/dist/migrations/202102261650.js +7 -0
- package/dist/migrations/202102261650.js.map +1 -0
- package/dist/migrations/202106102347.d.ts +2 -0
- package/dist/migrations/202106102347.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106102347.js +2 -3
- package/dist/migrations/202106102347.js.map +1 -0
- package/dist/migrations/202106112120.d.ts +2 -0
- package/dist/migrations/202106112120.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106112120.js +2 -3
- package/dist/migrations/202106112120.js.map +1 -0
- package/dist/migrations/202106120012.d.ts +2 -0
- package/dist/migrations/202106120012.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106120012.js +2 -3
- package/dist/migrations/202106120012.js.map +1 -0
- package/dist/migrations/202106120220.d.ts +2 -0
- package/dist/migrations/202106120220.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106120220.js +2 -4
- package/dist/migrations/202106120220.js.map +1 -0
- package/dist/migrations/202106121701.d.ts +2 -0
- package/dist/migrations/202106121701.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106121701.js +2 -3
- package/dist/migrations/202106121701.js.map +1 -0
- package/dist/migrations/202106121703.d.ts +3 -0
- package/dist/migrations/202106121703.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202106121703.js +2 -3
- package/dist/migrations/202106121703.js.map +1 -0
- package/dist/migrations/202106251126.d.ts +2 -0
- package/dist/migrations/202106251126.d.ts.map +1 -0
- package/dist/migrations/202106251126.js +6 -0
- package/dist/migrations/202106251126.js.map +1 -0
- package/dist/migrations/202107281619.d.ts +2 -0
- package/dist/migrations/202107281619.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202107281619.js +2 -1
- package/dist/migrations/202107281619.js.map +1 -0
- package/dist/migrations/202107302158.d.ts +3 -0
- package/dist/migrations/202107302158.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202107302158.js +2 -3
- package/dist/migrations/202107302158.js.map +1 -0
- package/dist/migrations/202108022257.d.ts +2 -0
- package/dist/migrations/202108022257.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202108022257.js +3 -4
- package/dist/migrations/202108022257.js.map +1 -0
- package/dist/migrations/202109201624.d.ts +2 -0
- package/dist/migrations/202109201624.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202109201624.js +2 -1
- package/dist/migrations/202109201624.js.map +1 -0
- package/dist/migrations/202109301031.d.ts +3 -0
- package/dist/migrations/202109301031.d.ts.map +1 -0
- package/{migrations → dist/migrations}/202109301031.js +2 -2
- package/dist/migrations/202109301031.js.map +1 -0
- package/dist/migrations/202111290253.d.ts +3 -0
- package/dist/migrations/202111290253.d.ts.map +1 -0
- package/dist/migrations/202111290253.js +5 -0
- package/dist/migrations/202111290253.js.map +1 -0
- package/dist/models/backup.d.ts +22 -0
- package/dist/models/backup.d.ts.map +1 -0
- package/{models → dist/models}/backup.js +95 -192
- package/dist/models/backup.js.map +1 -0
- package/dist/models/config.d.ts +177 -0
- package/dist/models/config.d.ts.map +1 -0
- package/dist/models/config.js +683 -0
- package/dist/models/config.js.map +1 -0
- package/dist/models/crash.d.ts +74 -0
- package/dist/models/crash.d.ts.map +1 -0
- package/dist/models/crash.js +118 -0
- package/dist/models/crash.js.map +1 -0
- package/dist/models/discovery.d.ts +28 -0
- package/dist/models/discovery.d.ts.map +1 -0
- package/dist/models/discovery.js +163 -0
- package/dist/models/discovery.js.map +1 -0
- package/dist/models/email.d.ts +16 -0
- package/dist/models/email.d.ts.map +1 -0
- package/dist/models/email.js +90 -0
- package/dist/models/email.js.map +1 -0
- package/dist/models/eventlog.d.ts +77 -0
- package/dist/models/eventlog.d.ts.map +1 -0
- package/dist/models/eventlog.js +132 -0
- package/dist/models/eventlog.js.map +1 -0
- package/dist/models/expression.d.ts +54 -0
- package/dist/models/expression.d.ts.map +1 -0
- package/dist/models/expression.js +274 -0
- package/dist/models/expression.js.map +1 -0
- package/dist/models/field.d.ts +217 -0
- package/dist/models/field.d.ts.map +1 -0
- package/dist/models/field.js +619 -0
- package/dist/models/field.js.map +1 -0
- package/dist/models/fieldrepeat.d.ts +49 -0
- package/dist/models/fieldrepeat.d.ts.map +1 -0
- package/dist/models/fieldrepeat.js +88 -0
- package/dist/models/fieldrepeat.js.map +1 -0
- package/dist/models/file.d.ts +122 -0
- package/dist/models/file.d.ts.map +1 -0
- package/dist/models/file.js +224 -0
- package/dist/models/file.js.map +1 -0
- package/dist/models/form.d.ts +82 -0
- package/dist/models/form.d.ts.map +1 -0
- package/dist/models/form.js +163 -0
- package/dist/models/form.js.map +1 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -0
- package/{models → dist/models}/index.js +42 -42
- package/dist/models/index.js.map +1 -0
- package/dist/models/layout.d.ts +34 -0
- package/dist/models/layout.d.ts.map +1 -0
- package/dist/models/layout.js +153 -0
- package/dist/models/layout.js.map +1 -0
- package/dist/models/library.d.ts +50 -0
- package/dist/models/library.d.ts.map +1 -0
- package/dist/models/library.js +129 -0
- package/dist/models/library.js.map +1 -0
- package/dist/models/pack.d.ts +89 -0
- package/dist/models/pack.d.ts.map +1 -0
- package/dist/models/pack.js +383 -0
- package/dist/models/pack.js.map +1 -0
- package/dist/models/page.d.ts +101 -0
- package/dist/models/page.d.ts.map +1 -0
- package/dist/models/page.js +223 -0
- package/dist/models/page.js.map +1 -0
- package/dist/models/plugin.d.ts +100 -0
- package/dist/models/plugin.d.ts.map +1 -0
- package/dist/models/plugin.js +204 -0
- package/dist/models/plugin.js.map +1 -0
- package/dist/models/random.d.ts +24 -0
- package/dist/models/random.d.ts.map +1 -0
- package/dist/models/random.js +186 -0
- package/dist/models/random.js.map +1 -0
- package/dist/models/role.d.ts +42 -0
- package/dist/models/role.d.ts.map +1 -0
- package/dist/models/role.js +64 -0
- package/dist/models/role.js.map +1 -0
- package/dist/models/scheduler.d.ts +18 -0
- package/dist/models/scheduler.d.ts.map +1 -0
- package/dist/models/scheduler.js +159 -0
- package/dist/models/scheduler.js.map +1 -0
- package/dist/models/table.d.ts +326 -0
- package/dist/models/table.d.ts.map +1 -0
- package/dist/models/table.js +1006 -0
- package/dist/models/table.js.map +1 -0
- package/dist/models/table_constraints.d.ts +69 -0
- package/dist/models/table_constraints.d.ts.map +1 -0
- package/dist/models/table_constraints.js +118 -0
- package/dist/models/table_constraints.js.map +1 -0
- package/dist/models/tenant.d.ts +55 -0
- package/dist/models/tenant.d.ts.map +1 -0
- package/{models → dist/models}/tenant.js +40 -63
- package/dist/models/tenant.js.map +1 -0
- package/dist/models/trigger.d.ts +133 -0
- package/dist/models/trigger.d.ts.map +1 -0
- package/dist/models/trigger.js +292 -0
- package/dist/models/trigger.js.map +1 -0
- package/dist/models/user.d.ts +235 -0
- package/dist/models/user.d.ts.map +1 -0
- package/dist/models/user.js +434 -0
- package/dist/models/user.js.map +1 -0
- package/dist/models/view.d.ts +204 -0
- package/dist/models/view.d.ts.map +1 -0
- package/dist/models/view.js +497 -0
- package/dist/models/view.js.map +1 -0
- package/dist/models/workflow.d.ts +48 -0
- package/dist/models/workflow.d.ts.map +1 -0
- package/dist/models/workflow.js +190 -0
- package/dist/models/workflow.js.map +1 -0
- package/dist/plugin-helper.d.ts +145 -0
- package/dist/plugin-helper.d.ts.map +1 -0
- package/dist/plugin-helper.js +1158 -0
- package/dist/plugin-helper.js.map +1 -0
- package/dist/plugin-testing.d.ts +3 -0
- package/dist/plugin-testing.d.ts.map +1 -0
- package/dist/plugin-testing.js +120 -0
- package/dist/plugin-testing.js.map +1 -0
- package/dist/tests/actions.test.d.ts +2 -0
- package/dist/tests/actions.test.d.ts.map +1 -0
- package/dist/tests/actions.test.js +205 -0
- package/dist/tests/actions.test.js.map +1 -0
- package/dist/tests/auxtest.test.d.ts +2 -0
- package/dist/tests/auxtest.test.d.ts.map +1 -0
- package/dist/tests/auxtest.test.js +48 -0
- package/dist/tests/auxtest.test.js.map +1 -0
- package/dist/tests/backup.test.d.ts +2 -0
- package/dist/tests/backup.test.d.ts.map +1 -0
- package/dist/tests/backup.test.js +88 -0
- package/dist/tests/backup.test.js.map +1 -0
- package/dist/tests/calc.test.d.ts +2 -0
- package/dist/tests/calc.test.d.ts.map +1 -0
- package/dist/tests/calc.test.js +231 -0
- package/dist/tests/calc.test.js.map +1 -0
- package/dist/tests/config.test.d.ts +2 -0
- package/dist/tests/config.test.d.ts.map +1 -0
- package/dist/tests/config.test.js +83 -0
- package/dist/tests/config.test.js.map +1 -0
- package/dist/tests/discover.test.d.ts +2 -0
- package/dist/tests/discover.test.d.ts.map +1 -0
- package/dist/tests/discover.test.js +106 -0
- package/dist/tests/discover.test.js.map +1 -0
- package/dist/tests/exact_views.test.d.ts +2 -0
- package/dist/tests/exact_views.test.d.ts.map +1 -0
- package/dist/tests/exact_views.test.js +511 -0
- package/dist/tests/exact_views.test.js.map +1 -0
- package/dist/tests/field.test.d.ts +2 -0
- package/dist/tests/field.test.d.ts.map +1 -0
- package/dist/tests/field.test.js +237 -0
- package/dist/tests/field.test.js.map +1 -0
- package/dist/tests/form.test.d.ts +2 -0
- package/dist/tests/form.test.d.ts.map +1 -0
- package/dist/tests/form.test.js +191 -0
- package/dist/tests/form.test.js.map +1 -0
- package/dist/tests/mocks.d.ts +111 -0
- package/dist/tests/mocks.d.ts.map +1 -0
- package/dist/tests/mocks.js +165 -0
- package/dist/tests/mocks.js.map +1 -0
- package/dist/tests/models.test.d.ts +2 -0
- package/dist/tests/models.test.d.ts.map +1 -0
- package/dist/tests/models.test.js +210 -0
- package/dist/tests/models.test.js.map +1 -0
- package/dist/tests/pack.test.d.ts +2 -0
- package/dist/tests/pack.test.d.ts.map +1 -0
- package/dist/tests/pack.test.js +331 -0
- package/dist/tests/pack.test.js.map +1 -0
- package/dist/tests/plugin.test.d.ts +2 -0
- package/dist/tests/plugin.test.d.ts.map +1 -0
- package/dist/tests/plugin.test.js +53 -0
- package/dist/tests/plugin.test.js.map +1 -0
- package/dist/tests/random.test.d.ts +2 -0
- package/dist/tests/random.test.d.ts.map +1 -0
- package/dist/tests/random.test.js +138 -0
- package/dist/tests/random.test.js.map +1 -0
- package/dist/tests/table.test.d.ts +2 -0
- package/dist/tests/table.test.d.ts.map +1 -0
- package/dist/tests/table.test.js +1048 -0
- package/dist/tests/table.test.js.map +1 -0
- package/dist/tests/tenant.test.d.ts +2 -0
- package/dist/tests/tenant.test.d.ts.map +1 -0
- package/dist/tests/tenant.test.js +45 -0
- package/dist/tests/tenant.test.js.map +1 -0
- package/dist/tests/user.test.d.ts +2 -0
- package/dist/tests/user.test.d.ts.map +1 -0
- package/dist/tests/user.test.js +190 -0
- package/dist/tests/user.test.js.map +1 -0
- package/dist/tests/view.test.d.ts +2 -0
- package/dist/tests/view.test.d.ts.map +1 -0
- package/dist/tests/view.test.js +238 -0
- package/dist/tests/view.test.js.map +1 -0
- package/dist/tests/workflow.test.d.ts +2 -0
- package/dist/tests/workflow.test.d.ts.map +1 -0
- package/dist/tests/workflow.test.js +115 -0
- package/dist/tests/workflow.test.js.map +1 -0
- package/dist/tsconfig.ref.tsbuildinfo +1 -0
- package/dist/utils.d.ts +26 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +124 -0
- package/dist/utils.js.map +1 -0
- package/package.json +32 -8
- package/base-plugin/actions.js +0 -629
- package/base-plugin/base.test.js +0 -15
- package/base-plugin/fieldviews.js +0 -197
- package/base-plugin/fileviews.js +0 -65
- package/base-plugin/types.js +0 -1154
- package/base-plugin/viewtemplates/edit.js +0 -672
- package/base-plugin/viewtemplates/feed.js +0 -434
- package/base-plugin/viewtemplates/filter.js +0 -358
- package/base-plugin/viewtemplates/list.js +0 -575
- package/base-plugin/viewtemplates/listshowlist.js +0 -292
- package/base-plugin/viewtemplates/room.js +0 -652
- package/base-plugin/viewtemplates/show.js +0 -689
- package/base-plugin/viewtemplates/viewable_fields.js +0 -714
- package/contracts.js +0 -311
- package/db/connect.js +0 -151
- package/db/db.test.js +0 -33
- package/db/fixtures.js +0 -303
- package/db/index.js +0 -63
- package/db/state.js +0 -674
- package/migrate.js +0 -99
- package/migrations/202008031500.js +0 -4
- package/migrations/202009181655.js +0 -6
- package/migrations/202009221105.js +0 -4
- package/migrations/202009301531.js +0 -7
- package/migrations/202010231444.js +0 -4
- package/migrations/202010251412.js +0 -9
- package/migrations/202101141128.js +0 -4
- package/migrations/202102091312.js +0 -19
- package/migrations/202102101624.js +0 -5
- package/migrations/202102261650.js +0 -6
- package/migrations/202106251126.js +0 -5
- package/models/config.js +0 -680
- package/models/crash.js +0 -126
- package/models/discovery.js +0 -195
- package/models/email.js +0 -92
- package/models/eventlog.js +0 -146
- package/models/expression.js +0 -276
- package/models/field.js +0 -746
- package/models/fieldrepeat.js +0 -96
- package/models/file.js +0 -234
- package/models/form.js +0 -169
- package/models/layout.js +0 -146
- package/models/library.js +0 -135
- package/models/pack.js +0 -466
- package/models/page.js +0 -255
- package/models/plugin.js +0 -219
- package/models/random.js +0 -206
- package/models/role.js +0 -94
- package/models/scheduler.js +0 -163
- package/models/table.js +0 -1211
- package/models/table_constraints.js +0 -133
- package/models/trigger.js +0 -327
- package/models/user.js +0 -503
- package/models/view.js +0 -622
- package/models/workflow.js +0 -205
- package/plugin-helper.js +0 -1311
- package/plugin-testing.js +0 -124
- package/tests/actions.test.js +0 -232
- package/tests/auxtest.test.js +0 -52
- package/tests/backup.test.js +0 -92
- package/tests/calc.test.js +0 -243
- package/tests/config.test.js +0 -91
- package/tests/discover.test.js +0 -114
- package/tests/exact_views.test.js +0 -526
- package/tests/field.test.js +0 -253
- package/tests/form.test.js +0 -198
- package/tests/mocks.js +0 -173
- package/tests/models.test.js +0 -221
- package/tests/pack.test.js +0 -350
- package/tests/plugin.test.js +0 -59
- package/tests/random.test.js +0 -154
- package/tests/table.test.js +0 -1091
- package/tests/tenant.test.js +0 -56
- package/tests/user.test.js +0 -196
- package/tests/view.test.js +0 -251
- package/tests/workflow.test.js +0 -119
- package/utils.js +0 -137
package/models/table.js
DELETED
|
@@ -1,1211 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Table Database Access Layer
|
|
3
|
-
* @category saltcorn-data
|
|
4
|
-
* @module models/table
|
|
5
|
-
* @subcategory models
|
|
6
|
-
*/
|
|
7
|
-
const db = require("../db");
|
|
8
|
-
const {
|
|
9
|
-
sqlsanitize,
|
|
10
|
-
mkWhere,
|
|
11
|
-
mkSelectOptions,
|
|
12
|
-
} = require("@saltcorn/db-common/internal.js");
|
|
13
|
-
const Field = require("./field");
|
|
14
|
-
const Trigger = require("./trigger");
|
|
15
|
-
const {
|
|
16
|
-
apply_calculated_fields,
|
|
17
|
-
apply_calculated_fields_stored,
|
|
18
|
-
recalculate_for_stored,
|
|
19
|
-
get_expression_function,
|
|
20
|
-
} = require("./expression");
|
|
21
|
-
const { contract, is } = require("contractis");
|
|
22
|
-
const { is_table_query } = require("../contracts");
|
|
23
|
-
const csvtojson = require("csvtojson");
|
|
24
|
-
const moment = require("moment");
|
|
25
|
-
const fs = require("fs");
|
|
26
|
-
const {
|
|
27
|
-
InvalidConfiguration,
|
|
28
|
-
InvalidAdminAction,
|
|
29
|
-
satisfies,
|
|
30
|
-
structuredClone,
|
|
31
|
-
getLines,
|
|
32
|
-
} = require("../utils");
|
|
33
|
-
/**
|
|
34
|
-
* Transponce Objects
|
|
35
|
-
* TODO more detailed explanation
|
|
36
|
-
* TODO refactor - move to object util module?
|
|
37
|
-
* @param objs
|
|
38
|
-
* @returns {object}
|
|
39
|
-
*/
|
|
40
|
-
const transposeObjects = (objs) => {
|
|
41
|
-
const keys = new Set();
|
|
42
|
-
for (const o of objs) {
|
|
43
|
-
Object.keys(o).forEach((k) => keys.add(k));
|
|
44
|
-
}
|
|
45
|
-
const res = {};
|
|
46
|
-
keys.forEach((k) => {
|
|
47
|
-
res[k] = [];
|
|
48
|
-
});
|
|
49
|
-
for (const o of objs) {
|
|
50
|
-
keys.forEach((k) => {
|
|
51
|
-
res[k].push(o[k]);
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
return res;
|
|
55
|
-
};
|
|
56
|
-
// todo support also other date formats https://momentjs.com/docs/
|
|
57
|
-
const dateFormats = [moment.ISO_8601];
|
|
58
|
-
// todo refactor - move to separated data utils module?
|
|
59
|
-
/**
|
|
60
|
-
* Is Valid Date of format moment.ISO_8601,
|
|
61
|
-
* example 2010-01-01T05:06:07
|
|
62
|
-
*
|
|
63
|
-
* @param date
|
|
64
|
-
* @returns {boolean}
|
|
65
|
-
*/
|
|
66
|
-
const isDate = function (date) {
|
|
67
|
-
return moment(date, dateFormats, true).isValid();
|
|
68
|
-
};
|
|
69
|
-
// todo resolve database specific
|
|
70
|
-
/**
|
|
71
|
-
* Normalise specific error message according db specific
|
|
72
|
-
* @param msg
|
|
73
|
-
* @returns {string}
|
|
74
|
-
*/
|
|
75
|
-
// todo refactor
|
|
76
|
-
const normalise_error_message = (msg) =>
|
|
77
|
-
db.isSQLite
|
|
78
|
-
? msg.replace(
|
|
79
|
-
/SQLITE_CONSTRAINT: UNIQUE constraint failed: (.*?)\.(.*?)/,
|
|
80
|
-
"Duplicate value for unique field: $2"
|
|
81
|
-
)
|
|
82
|
-
: msg.replace(
|
|
83
|
-
/duplicate key value violates unique constraint "(.*?)_(.*?)_unique"/,
|
|
84
|
-
"Duplicate value for unique field: $2"
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Table class
|
|
89
|
-
* @category saltcorn-data
|
|
90
|
-
*/
|
|
91
|
-
class Table {
|
|
92
|
-
/**
|
|
93
|
-
* Table constructor
|
|
94
|
-
* @param {object} o
|
|
95
|
-
*/
|
|
96
|
-
constructor(o) {
|
|
97
|
-
this.name = o.name;
|
|
98
|
-
this.id = o.id;
|
|
99
|
-
this.min_role_read = o.min_role_read;
|
|
100
|
-
this.min_role_write = o.min_role_write;
|
|
101
|
-
this.ownership_field_id = o.ownership_field_id;
|
|
102
|
-
this.ownership_formula = o.ownership_formula;
|
|
103
|
-
this.versioned = !!o.versioned;
|
|
104
|
-
this.external = false;
|
|
105
|
-
this.description = o.description;
|
|
106
|
-
if (o.fields) this.fields = o.fields.map((f) => new Field(f));
|
|
107
|
-
contract.class(this);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
* Find one Table
|
|
113
|
-
* @param where - where condition
|
|
114
|
-
* @returns {*|Table|null} table or null
|
|
115
|
-
*/
|
|
116
|
-
static findOne(where) {
|
|
117
|
-
if (
|
|
118
|
-
where &&
|
|
119
|
-
((where.constructor && where.constructor.name === "Table") ||
|
|
120
|
-
where.getRows)
|
|
121
|
-
)
|
|
122
|
-
return where;
|
|
123
|
-
if (typeof where === "string") return Table.findOne({ name: where });
|
|
124
|
-
if (typeof where === "number") return Table.findOne({ id: where });
|
|
125
|
-
if (where.name) {
|
|
126
|
-
const { getState } = require("../db/state");
|
|
127
|
-
const extTable = getState().external_tables[where.name];
|
|
128
|
-
if (extTable) return extTable;
|
|
129
|
-
}
|
|
130
|
-
const { getState } = require("../db/state");
|
|
131
|
-
const tbl = getState().tables.find(
|
|
132
|
-
where.id
|
|
133
|
-
? (v) => v.id === +where.id
|
|
134
|
-
: where.name
|
|
135
|
-
? (v) => v.name === where.name
|
|
136
|
-
: satisfies(where)
|
|
137
|
-
);
|
|
138
|
-
return tbl ? new Table(structuredClone(tbl)) : null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Find Tables
|
|
143
|
-
* @param where - where condition
|
|
144
|
-
* @param selectopts - options
|
|
145
|
-
* @returns {Promise<Table[]>} table list
|
|
146
|
-
*/
|
|
147
|
-
static async find(where, selectopts = { orderBy: "name", nocase: true }) {
|
|
148
|
-
if (selectopts.cached) {
|
|
149
|
-
const { getState } = require("../db/state");
|
|
150
|
-
return getState().tables.map((t) => new Table(t));
|
|
151
|
-
}
|
|
152
|
-
const tbls = await db.select("_sc_tables", where, selectopts);
|
|
153
|
-
|
|
154
|
-
return tbls.map((t) => new Table(t));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Find Tables including external tables
|
|
159
|
-
* @param where0
|
|
160
|
-
* @param selectopts
|
|
161
|
-
* @returns {Promise<object[]>}
|
|
162
|
-
*/
|
|
163
|
-
static async find_with_external(
|
|
164
|
-
where0 = {},
|
|
165
|
-
selectopts = { orderBy: "name", nocase: true }
|
|
166
|
-
) {
|
|
167
|
-
const { external, ...where } = where0;
|
|
168
|
-
let externals = [],
|
|
169
|
-
dbs = [];
|
|
170
|
-
if (external !== false) {
|
|
171
|
-
//do include externals
|
|
172
|
-
const { getState } = require("../db/state");
|
|
173
|
-
externals = Object.values(getState().external_tables);
|
|
174
|
-
}
|
|
175
|
-
if (external !== true) {
|
|
176
|
-
//do include db tables
|
|
177
|
-
const tbls = await db.select("_sc_tables", where, selectopts);
|
|
178
|
-
dbs = tbls.map((t) => new Table(t));
|
|
179
|
-
}
|
|
180
|
-
return [...dbs, ...externals];
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Get owner column name
|
|
185
|
-
* @param fields - fields list
|
|
186
|
-
* @returns {null|*} null or owner column name
|
|
187
|
-
*/
|
|
188
|
-
owner_fieldname_from_fields(fields) {
|
|
189
|
-
if (!this.ownership_field_id) return null;
|
|
190
|
-
const field = fields.find((f) => f.id === this.ownership_field_id);
|
|
191
|
-
return field.name;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Get owner column name
|
|
196
|
-
* @returns {Promise<string|null|*>}
|
|
197
|
-
*/
|
|
198
|
-
owner_fieldname() {
|
|
199
|
-
if (this.name === "users") return "id";
|
|
200
|
-
if (!this.ownership_field_id) return null;
|
|
201
|
-
return this.owner_fieldname_from_fields(this.fields);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Check if user is owner of row
|
|
206
|
-
* @param user - user
|
|
207
|
-
* @param row - table row
|
|
208
|
-
* @returns {Promise<string|null|*|boolean>}
|
|
209
|
-
*/
|
|
210
|
-
is_owner(user, row) {
|
|
211
|
-
if (!user) return false;
|
|
212
|
-
if (this.ownership_formula) {
|
|
213
|
-
const f = get_expression_function(this.ownership_formula, this.fields);
|
|
214
|
-
return f(row, user);
|
|
215
|
-
}
|
|
216
|
-
const field_name = this.owner_fieldname();
|
|
217
|
-
return field_name && row[field_name] === user.id;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Create table
|
|
222
|
-
* @param name - table name
|
|
223
|
-
* @param options - table fields
|
|
224
|
-
* @returns {Promise<Table>} table
|
|
225
|
-
*/
|
|
226
|
-
static async create(name, options = {}) {
|
|
227
|
-
const schema = db.getTenantSchemaPrefix();
|
|
228
|
-
// create table in database
|
|
229
|
-
await db.query(
|
|
230
|
-
`create table ${schema}"${sqlsanitize(name)}" (id ${
|
|
231
|
-
db.isSQLite ? "integer" : "serial"
|
|
232
|
-
} primary key)`
|
|
233
|
-
);
|
|
234
|
-
// populate table definition row
|
|
235
|
-
const tblrow = {
|
|
236
|
-
name,
|
|
237
|
-
versioned: options.versioned || false,
|
|
238
|
-
min_role_read: options.min_role_read || 1,
|
|
239
|
-
min_role_write: options.min_role_write || 1,
|
|
240
|
-
ownership_field_id: options.ownership_field_id,
|
|
241
|
-
ownership_formula: options.ownership_formula,
|
|
242
|
-
description: options.description || "",
|
|
243
|
-
};
|
|
244
|
-
// insert table defintion into _sc_tables
|
|
245
|
-
const id = await db.insert("_sc_tables", tblrow);
|
|
246
|
-
// add primary key columnt ID
|
|
247
|
-
await db.query(
|
|
248
|
-
`insert into ${schema}_sc_fields(table_id, name, label, type, attributes, required, is_unique,primary_key)
|
|
249
|
-
values($1,'id','ID','Integer', '{}', true, true, true)`,
|
|
250
|
-
[id]
|
|
251
|
-
);
|
|
252
|
-
// create table
|
|
253
|
-
const table = new Table({ ...tblrow, id });
|
|
254
|
-
// create table history
|
|
255
|
-
if (table.versioned) await table.create_history_table();
|
|
256
|
-
// refresh tables cache
|
|
257
|
-
await require("../db/state").getState().refresh_tables();
|
|
258
|
-
|
|
259
|
-
return table;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Drop current table
|
|
264
|
-
* @returns {Promise<void>}
|
|
265
|
-
*/
|
|
266
|
-
async delete(only_forget = false) {
|
|
267
|
-
const schema = db.getTenantSchemaPrefix();
|
|
268
|
-
const is_sqlite = db.isSQLite;
|
|
269
|
-
await this.update({ ownership_field_id: null });
|
|
270
|
-
const client = is_sqlite ? db : await db.getClient();
|
|
271
|
-
await client.query(`BEGIN`);
|
|
272
|
-
try {
|
|
273
|
-
if (!only_forget)
|
|
274
|
-
await client.query(
|
|
275
|
-
`drop table if exists ${schema}"${sqlsanitize(this.name)}"`
|
|
276
|
-
);
|
|
277
|
-
await client.query(
|
|
278
|
-
`delete FROM ${schema}_sc_fields WHERE table_id = $1`,
|
|
279
|
-
[this.id]
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
await client.query(`delete FROM ${schema}_sc_tables WHERE id = $1`, [
|
|
283
|
-
this.id,
|
|
284
|
-
]);
|
|
285
|
-
if (this.versioned)
|
|
286
|
-
await client.query(
|
|
287
|
-
`drop table if exists ${schema}"${sqlsanitize(this.name)}__history"`
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
await client.query(`COMMIT`);
|
|
291
|
-
} catch (e) {
|
|
292
|
-
await client.query(`ROLLBACK`);
|
|
293
|
-
if (!is_sqlite) client.release(true);
|
|
294
|
-
throw e;
|
|
295
|
-
}
|
|
296
|
-
if (!is_sqlite) client.release(true);
|
|
297
|
-
await require("../db/state").getState().refresh_tables();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/***
|
|
301
|
-
* get Table SQL Name
|
|
302
|
-
* @type {string}
|
|
303
|
-
*/
|
|
304
|
-
get sql_name() {
|
|
305
|
-
return `${db.getTenantSchemaPrefix()}"${sqlsanitize(this.name)}"`;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Delete rows from table
|
|
310
|
-
* @param where - condition
|
|
311
|
-
* @returns {Promise<void>}
|
|
312
|
-
*/
|
|
313
|
-
async deleteRows(where) {
|
|
314
|
-
// get triggers on delete
|
|
315
|
-
const triggers = await Trigger.getTableTriggers("Delete", this);
|
|
316
|
-
if (triggers.length > 0) {
|
|
317
|
-
const rows = await this.getRows(where);
|
|
318
|
-
for (const trigger of triggers) {
|
|
319
|
-
for (const row of rows) {
|
|
320
|
-
// run triggers on delete
|
|
321
|
-
await trigger.run(row);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
await db.deleteWhere(this.name, where);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Returns row with only fields that can be read from db (readFromDB flag)
|
|
330
|
-
* @param row
|
|
331
|
-
* @returns {*}
|
|
332
|
-
*/
|
|
333
|
-
readFromDB(row) {
|
|
334
|
-
for (const f of this.fields) {
|
|
335
|
-
if (f.type && f.type.readFromDB)
|
|
336
|
-
row[f.name] = f.type.readFromDB(row[f.name]);
|
|
337
|
-
}
|
|
338
|
-
return row;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Get one row from table in db
|
|
343
|
-
* @param where
|
|
344
|
-
* @returns {Promise<null|*>}
|
|
345
|
-
*/
|
|
346
|
-
async getRow(where = {}) {
|
|
347
|
-
await this.getFields();
|
|
348
|
-
const row = await db.selectMaybeOne(this.name, where);
|
|
349
|
-
if (!row) return null;
|
|
350
|
-
return apply_calculated_fields([this.readFromDB(row)], this.fields)[0];
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Get rows from Table in db
|
|
355
|
-
* @param where
|
|
356
|
-
* @param selopts
|
|
357
|
-
* @returns {Promise<void>}
|
|
358
|
-
*/
|
|
359
|
-
async getRows(where = {}, selopts) {
|
|
360
|
-
await this.getFields();
|
|
361
|
-
const rows = await db.select(this.name, where, selopts);
|
|
362
|
-
return apply_calculated_fields(
|
|
363
|
-
rows.map((r) => this.readFromDB(r)),
|
|
364
|
-
this.fields
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Count amount of rows in db table
|
|
370
|
-
* @param where
|
|
371
|
-
* @returns {Promise<number>}
|
|
372
|
-
*/
|
|
373
|
-
async countRows(where) {
|
|
374
|
-
return await db.count(this.name, where);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Return distinct Values for column in table
|
|
379
|
-
* ????
|
|
380
|
-
* @param fieldnm
|
|
381
|
-
* @returns {Promise<Object[]>}
|
|
382
|
-
*/
|
|
383
|
-
async distinctValues(fieldnm) {
|
|
384
|
-
const res = await db.query(
|
|
385
|
-
`select distinct "${db.sqlsanitize(fieldnm)}" from ${this.sql_name}`
|
|
386
|
-
);
|
|
387
|
-
return res.rows.map((r) => r[fieldnm]);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Update row
|
|
392
|
-
* @param v_in - colums with values to update
|
|
393
|
-
* @param id - id value
|
|
394
|
-
* @param _userid - user id
|
|
395
|
-
* @returns {Promise<void>}
|
|
396
|
-
*/
|
|
397
|
-
async updateRow(v_in, id, _userid) {
|
|
398
|
-
let existing;
|
|
399
|
-
let v;
|
|
400
|
-
const fields = await this.getFields();
|
|
401
|
-
const pk_name = this.pk_name;
|
|
402
|
-
if (fields.some((f) => f.calculated && f.stored)) {
|
|
403
|
-
existing = await db.selectOne(this.name, { [pk_name]: id });
|
|
404
|
-
v = await apply_calculated_fields_stored(
|
|
405
|
-
{ ...existing, ...v_in },
|
|
406
|
-
this.fields
|
|
407
|
-
);
|
|
408
|
-
} else v = v_in;
|
|
409
|
-
if (this.versioned) {
|
|
410
|
-
if (!existing)
|
|
411
|
-
existing = await db.selectOne(this.name, { [pk_name]: id });
|
|
412
|
-
await db.insert(this.name + "__history", {
|
|
413
|
-
...existing,
|
|
414
|
-
...v,
|
|
415
|
-
[pk_name]: id,
|
|
416
|
-
_version: {
|
|
417
|
-
next_version_by_id: +id,
|
|
418
|
-
},
|
|
419
|
-
_time: new Date(),
|
|
420
|
-
_userid,
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
await db.update(this.name, v, id, { pk_name });
|
|
424
|
-
if (typeof existing === "undefined") {
|
|
425
|
-
const triggers = await Trigger.getTableTriggers("Update", this);
|
|
426
|
-
if (triggers.length > 0)
|
|
427
|
-
existing = await db.selectOne(this.name, { [pk_name]: id });
|
|
428
|
-
}
|
|
429
|
-
const newRow = { ...existing, ...v, [pk_name]: id };
|
|
430
|
-
await Trigger.runTableTriggers("Update", this, newRow);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Try to Update row
|
|
435
|
-
* @param v
|
|
436
|
-
* @param id
|
|
437
|
-
* @param _userid
|
|
438
|
-
* @returns {Promise<{error}|{success: boolean}>}
|
|
439
|
-
*/
|
|
440
|
-
async tryUpdateRow(v, id, _userid) {
|
|
441
|
-
try {
|
|
442
|
-
await this.updateRow(v, id, _userid);
|
|
443
|
-
return { success: true };
|
|
444
|
-
} catch (e) {
|
|
445
|
-
return { error: normalise_error_message(e.message) };
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* ????
|
|
451
|
-
* @param id
|
|
452
|
-
* @param field_name
|
|
453
|
-
* @returns {Promise<void>}
|
|
454
|
-
*/
|
|
455
|
-
async toggleBool(id, field_name) {
|
|
456
|
-
const schema = db.getTenantSchemaPrefix();
|
|
457
|
-
await db.query(
|
|
458
|
-
`update ${schema}"${sqlsanitize(this.name)}" set "${sqlsanitize(
|
|
459
|
-
field_name
|
|
460
|
-
)}"=NOT coalesce("${sqlsanitize(field_name)}", false) where id=$1`,
|
|
461
|
-
[id]
|
|
462
|
-
);
|
|
463
|
-
const triggers = await Trigger.getTableTriggers("Update", this);
|
|
464
|
-
if (triggers.length > 0) {
|
|
465
|
-
const row = await this.getRow({ id });
|
|
466
|
-
for (const trigger of triggers) {
|
|
467
|
-
await trigger.run(row);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* Get primary key field
|
|
474
|
-
* @type {string}
|
|
475
|
-
*/
|
|
476
|
-
get pk_name() {
|
|
477
|
-
return this.fields.find((f) => f.primary_key).name;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Insert row
|
|
482
|
-
* @param v_in
|
|
483
|
-
* @param _userid
|
|
484
|
-
* @returns {Promise<*>}
|
|
485
|
-
*/
|
|
486
|
-
async insertRow(v_in, _userid) {
|
|
487
|
-
await this.getFields();
|
|
488
|
-
const v = await apply_calculated_fields_stored(v_in, this.fields);
|
|
489
|
-
const pk_name = this.pk_name;
|
|
490
|
-
const id = await db.insert(this.name, v, { pk_name });
|
|
491
|
-
if (this.versioned)
|
|
492
|
-
await db.insert(this.name + "__history", {
|
|
493
|
-
...v,
|
|
494
|
-
[pk_name]: id,
|
|
495
|
-
_version: 1,
|
|
496
|
-
_userid,
|
|
497
|
-
_time: new Date(),
|
|
498
|
-
});
|
|
499
|
-
Trigger.runTableTriggers("Insert", this, { [pk_name]: id, ...v });
|
|
500
|
-
return id;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Try to Insert row
|
|
505
|
-
* @param v
|
|
506
|
-
* @param _userid
|
|
507
|
-
* @returns {Promise<{error}|{success: *}>}
|
|
508
|
-
*/
|
|
509
|
-
async tryInsertRow(v, _userid) {
|
|
510
|
-
try {
|
|
511
|
-
const id = await this.insertRow(v, _userid);
|
|
512
|
-
return { success: id };
|
|
513
|
-
} catch (e) {
|
|
514
|
-
return { error: normalise_error_message(e.message) };
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Get Fields list for table
|
|
520
|
-
* @returns {Promise<Field[]>}
|
|
521
|
-
*/
|
|
522
|
-
async getFields() {
|
|
523
|
-
if (!this.fields) {
|
|
524
|
-
this.fields = await Field.find({ table_id: this.id }, { orderBy: "id" });
|
|
525
|
-
}
|
|
526
|
-
return this.fields;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
/**
|
|
530
|
-
* Create history table
|
|
531
|
-
* @returns {Promise<void>}
|
|
532
|
-
*/
|
|
533
|
-
// todo create function that returns history table name for table
|
|
534
|
-
async create_history_table() {
|
|
535
|
-
const schemaPrefix = db.getTenantSchemaPrefix();
|
|
536
|
-
|
|
537
|
-
const fields = await this.getFields();
|
|
538
|
-
const flds = fields.map(
|
|
539
|
-
(f) => `,"${sqlsanitize(f.name)}" ${f.sql_bare_type}`
|
|
540
|
-
);
|
|
541
|
-
const pk = fields.find((f) => f.primary_key).name;
|
|
542
|
-
|
|
543
|
-
// create history table
|
|
544
|
-
await db.query(
|
|
545
|
-
`create table ${schemaPrefix}"${sqlsanitize(this.name)}__history" (
|
|
546
|
-
_version integer,
|
|
547
|
-
_time timestamp,
|
|
548
|
-
_userid integer
|
|
549
|
-
${flds.join("")}
|
|
550
|
-
,PRIMARY KEY("${pk}", _version)
|
|
551
|
-
);`
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* Drop history table
|
|
557
|
-
* @returns {Promise<void>}
|
|
558
|
-
*/
|
|
559
|
-
async drop_history_table() {
|
|
560
|
-
const schemaPrefix = db.getTenantSchemaPrefix();
|
|
561
|
-
|
|
562
|
-
await db.query(`
|
|
563
|
-
drop table ${schemaPrefix}"${sqlsanitize(this.name)}__history";`);
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* Rename table
|
|
568
|
-
* @param new_name
|
|
569
|
-
* @returns {Promise<void>}
|
|
570
|
-
*/
|
|
571
|
-
async rename(new_name) {
|
|
572
|
-
//in transaction
|
|
573
|
-
if (db.isSQLite)
|
|
574
|
-
throw new InvalidAdminAction("Cannot rename table on SQLite");
|
|
575
|
-
const schemaPrefix = db.getTenantSchemaPrefix();
|
|
576
|
-
|
|
577
|
-
const client = await db.getClient();
|
|
578
|
-
await client.query(`BEGIN`);
|
|
579
|
-
try {
|
|
580
|
-
//rename table
|
|
581
|
-
await db.query(
|
|
582
|
-
`alter table ${schemaPrefix}"${sqlsanitize(
|
|
583
|
-
this.name
|
|
584
|
-
)}" rename to "${sqlsanitize(new_name)}";`
|
|
585
|
-
);
|
|
586
|
-
//change refs
|
|
587
|
-
await db.query(
|
|
588
|
-
`update ${schemaPrefix}_sc_fields set reftable_name=$1 where reftable_name=$2`,
|
|
589
|
-
[sqlsanitize(new_name), sqlsanitize(this.name)]
|
|
590
|
-
);
|
|
591
|
-
//rename history
|
|
592
|
-
if (this.versioned)
|
|
593
|
-
await db.query(
|
|
594
|
-
`alter table ${schemaPrefix}"${sqlsanitize(
|
|
595
|
-
this.name
|
|
596
|
-
)}__history" rename to "${sqlsanitize(new_name)}__history";`
|
|
597
|
-
);
|
|
598
|
-
//1. change record
|
|
599
|
-
await this.update({ name: new_name });
|
|
600
|
-
await client.query(`COMMIT`);
|
|
601
|
-
} catch (e) {
|
|
602
|
-
await client.query(`ROLLBACK`);
|
|
603
|
-
client.release(true);
|
|
604
|
-
throw e;
|
|
605
|
-
}
|
|
606
|
-
client.release(true);
|
|
607
|
-
await require("../db/state").getState().refresh_tables();
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
* Update Table description in _sc_table
|
|
612
|
-
* Also creates / drops history table for table
|
|
613
|
-
* @param new_table_rec
|
|
614
|
-
* @returns {Promise<void>}
|
|
615
|
-
*/
|
|
616
|
-
async update(new_table_rec) {
|
|
617
|
-
if (new_table_rec.ownership_field_id === "")
|
|
618
|
-
delete new_table_rec.ownership_field_id;
|
|
619
|
-
const existing = await Table.findOne({ id: this.id });
|
|
620
|
-
const { external, fields, ...upd_rec } = new_table_rec;
|
|
621
|
-
await db.update("_sc_tables", upd_rec, this.id);
|
|
622
|
-
await require("../db/state").getState().refresh_tables();
|
|
623
|
-
|
|
624
|
-
const new_table = await Table.findOne({ id: this.id });
|
|
625
|
-
|
|
626
|
-
if (new_table.versioned && !existing.versioned) {
|
|
627
|
-
await new_table.create_history_table();
|
|
628
|
-
} else if (!new_table.versioned && existing.versioned) {
|
|
629
|
-
await new_table.drop_history_table();
|
|
630
|
-
}
|
|
631
|
-
Object.assign(this, new_table_rec);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Get table history data
|
|
636
|
-
* @param id
|
|
637
|
-
* @returns {Promise<*>}
|
|
638
|
-
*/
|
|
639
|
-
async get_history(id) {
|
|
640
|
-
return await db.select(
|
|
641
|
-
`${sqlsanitize(this.name)}__history`,
|
|
642
|
-
{ id },
|
|
643
|
-
{ orderBy: "_version" }
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Enable constraints
|
|
649
|
-
* @returns {Promise<void>}
|
|
650
|
-
*/
|
|
651
|
-
async enable_fkey_constraints() {
|
|
652
|
-
const fields = await this.getFields();
|
|
653
|
-
for (const f of fields) await f.enable_fkey_constraint(this);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
/**
|
|
657
|
-
* Table Create from CSV
|
|
658
|
-
* @param name
|
|
659
|
-
* @param filePath
|
|
660
|
-
* @returns {Promise<{error: string}|{error: string}|{error: string}|{error: string}|{error: string}|{success: string}|{error: (string|string|*)}>}
|
|
661
|
-
*/
|
|
662
|
-
static async create_from_csv(name, filePath) {
|
|
663
|
-
let rows;
|
|
664
|
-
try {
|
|
665
|
-
const s = await getLines(filePath, 500);
|
|
666
|
-
rows = await csvtojson().fromString(s); // todo agrument type unknown
|
|
667
|
-
} catch (e) {
|
|
668
|
-
return { error: `Error processing CSV file` };
|
|
669
|
-
}
|
|
670
|
-
const rowsTr = transposeObjects(rows);
|
|
671
|
-
const table = await Table.create(name);
|
|
672
|
-
for (const [k, vs] of Object.entries(rowsTr)) {
|
|
673
|
-
const required = vs.every((v) => v !== "");
|
|
674
|
-
const nonEmpties = vs.filter((v) => v !== "");
|
|
675
|
-
const isBools = "true false yes no on off y n t f".split(" ");
|
|
676
|
-
let type;
|
|
677
|
-
if (
|
|
678
|
-
nonEmpties.every((v) =>
|
|
679
|
-
//https://www.postgresql.org/docs/11/datatype-boolean.html
|
|
680
|
-
|
|
681
|
-
isBools.includes(v && v.toLowerCase && v.toLowerCase())
|
|
682
|
-
)
|
|
683
|
-
)
|
|
684
|
-
type = "Bool";
|
|
685
|
-
else if (nonEmpties.every((v) => !isNaN(v)))
|
|
686
|
-
if (nonEmpties.every((v) => Number.isSafeInteger(+v))) type = "Integer";
|
|
687
|
-
else type = "Float";
|
|
688
|
-
else if (nonEmpties.every((v) => isDate(v))) type = "Date";
|
|
689
|
-
else type = "String";
|
|
690
|
-
const label = (k.charAt(0).toUpperCase() + k.slice(1)).replace(/_/g, " ");
|
|
691
|
-
|
|
692
|
-
//can fail here if: non integer i d, duplicate headers, invalid name
|
|
693
|
-
const fld = new Field({
|
|
694
|
-
name: Field.labelToName(k),
|
|
695
|
-
required,
|
|
696
|
-
type,
|
|
697
|
-
table,
|
|
698
|
-
label,
|
|
699
|
-
});
|
|
700
|
-
if (db.sqlsanitize(k.toLowerCase()) === "id") {
|
|
701
|
-
if (type !== "Integer") {
|
|
702
|
-
await table.delete();
|
|
703
|
-
return { error: `Columns named "id" must have only integers` };
|
|
704
|
-
}
|
|
705
|
-
if (!required) {
|
|
706
|
-
await table.delete();
|
|
707
|
-
return { error: `Columns named "id" must not have missing values` };
|
|
708
|
-
}
|
|
709
|
-
continue;
|
|
710
|
-
}
|
|
711
|
-
if (db.sqlsanitize(fld.name) === "") {
|
|
712
|
-
await table.delete();
|
|
713
|
-
return {
|
|
714
|
-
error: `Invalid column name ${k} - Use A-Z, a-z, 0-9, _ only`,
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
try {
|
|
718
|
-
await Field.create(fld);
|
|
719
|
-
} catch (e) {
|
|
720
|
-
await table.delete();
|
|
721
|
-
return { error: `Error in header ${k}: ${e.message}` };
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
const parse_res = await table.import_csv_file(filePath);
|
|
725
|
-
if (parse_res.error) {
|
|
726
|
-
await table.delete();
|
|
727
|
-
return { error: parse_res.error };
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
parse_res.table = table;
|
|
731
|
-
await require("../db/state").getState().refresh_tables();
|
|
732
|
-
|
|
733
|
-
return parse_res;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
* Import CSV file to existing table
|
|
738
|
-
* @param filePath
|
|
739
|
-
* @param recalc_stored
|
|
740
|
-
* @param skip_first_data_row
|
|
741
|
-
* @returns {Promise<{error: string}|{success: string}>}
|
|
742
|
-
*/
|
|
743
|
-
async import_csv_file(filePath, recalc_stored, skip_first_data_row) {
|
|
744
|
-
let headers;
|
|
745
|
-
const { readStateStrict } = require("../plugin-helper");
|
|
746
|
-
try {
|
|
747
|
-
const s = await getLines(filePath, 1);
|
|
748
|
-
[headers] = await csvtojson({
|
|
749
|
-
output: "csv",
|
|
750
|
-
noheader: true,
|
|
751
|
-
}).fromString(s); // todo agrument type unknown
|
|
752
|
-
} catch (e) {
|
|
753
|
-
return { error: `Error processing CSV file` };
|
|
754
|
-
}
|
|
755
|
-
const fields = (await this.getFields()).filter((f) => !f.calculated);
|
|
756
|
-
const okHeaders = {};
|
|
757
|
-
const pk_name = this.pk_name;
|
|
758
|
-
const renames = [];
|
|
759
|
-
for (const f of fields) {
|
|
760
|
-
if (headers.includes(f.name)) okHeaders[f.name] = f;
|
|
761
|
-
else if (headers.includes(f.label)) {
|
|
762
|
-
okHeaders[f.label] = f;
|
|
763
|
-
renames.push({ from: f.label, to: f.name });
|
|
764
|
-
} else if (f.required && !f.primary_key)
|
|
765
|
-
return { error: `Required field missing: ${f.label}` };
|
|
766
|
-
}
|
|
767
|
-
const fieldNames = headers.map((hnm) => {
|
|
768
|
-
if (okHeaders[hnm]) return okHeaders[hnm].name;
|
|
769
|
-
});
|
|
770
|
-
// also id
|
|
771
|
-
if (headers.includes(`id`)) okHeaders.id = { type: "Integer" };
|
|
772
|
-
const colRe = new RegExp(`(${Object.keys(okHeaders).join("|")})`);
|
|
773
|
-
|
|
774
|
-
let i = 1;
|
|
775
|
-
let rejects = 0;
|
|
776
|
-
const client = db.isSQLite ? db : await db.getClient();
|
|
777
|
-
|
|
778
|
-
const stats = await fs.promises.stat(filePath);
|
|
779
|
-
const fileSizeInMegabytes = stats.size / (1024 * 1024);
|
|
780
|
-
|
|
781
|
-
await client.query("BEGIN");
|
|
782
|
-
|
|
783
|
-
const readStream = fs.createReadStream(filePath);
|
|
784
|
-
|
|
785
|
-
try {
|
|
786
|
-
if (db.copyFrom && fileSizeInMegabytes > 1) {
|
|
787
|
-
let theError;
|
|
788
|
-
|
|
789
|
-
const copyres = await db
|
|
790
|
-
.copyFrom(readStream, this.name, fieldNames, client)
|
|
791
|
-
.catch((cate) => {
|
|
792
|
-
theError = cate;
|
|
793
|
-
});
|
|
794
|
-
if (theError || (copyres && copyres.error)) {
|
|
795
|
-
theError = theError || copyres.error;
|
|
796
|
-
return {
|
|
797
|
-
error: `Error processing CSV file: ${
|
|
798
|
-
!theError
|
|
799
|
-
? theError
|
|
800
|
-
: theError.error || theError.message || theError
|
|
801
|
-
}`,
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
} else {
|
|
805
|
-
await new Promise((resolve, reject) => {
|
|
806
|
-
csvtojson({
|
|
807
|
-
includeColumns: colRe,
|
|
808
|
-
})
|
|
809
|
-
.fromStream(readStream)
|
|
810
|
-
.subscribe(
|
|
811
|
-
async (rec) => {
|
|
812
|
-
i += 1;
|
|
813
|
-
if (skip_first_data_row && i === 2) return;
|
|
814
|
-
try {
|
|
815
|
-
renames.forEach(({ from, to }) => {
|
|
816
|
-
rec[to] = rec[from];
|
|
817
|
-
delete rec[from];
|
|
818
|
-
});
|
|
819
|
-
const rowOk = readStateStrict(rec, fields);
|
|
820
|
-
if (rowOk)
|
|
821
|
-
await db.insert(this.name, rec, {
|
|
822
|
-
noid: true,
|
|
823
|
-
client,
|
|
824
|
-
pk_name,
|
|
825
|
-
});
|
|
826
|
-
else rejects += 1;
|
|
827
|
-
} catch (e) {
|
|
828
|
-
await client.query("ROLLBACK");
|
|
829
|
-
|
|
830
|
-
if (!db.isSQLite) await client.release(true);
|
|
831
|
-
reject({ error: `${e.message} in row ${i}` });
|
|
832
|
-
}
|
|
833
|
-
},
|
|
834
|
-
(err) => {
|
|
835
|
-
reject({ error: !err ? err : err.message || err });
|
|
836
|
-
},
|
|
837
|
-
() => {
|
|
838
|
-
resolve();
|
|
839
|
-
}
|
|
840
|
-
);
|
|
841
|
-
});
|
|
842
|
-
readStream.destroy();
|
|
843
|
-
}
|
|
844
|
-
} catch (e) {
|
|
845
|
-
return {
|
|
846
|
-
error: `Error processing CSV file: ${
|
|
847
|
-
!e ? e : e.error || e.message || e
|
|
848
|
-
}`,
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
await client.query("COMMIT");
|
|
853
|
-
|
|
854
|
-
if (!db.isSQLite) await client.release(true);
|
|
855
|
-
const pk = fields.find((f) => f.primary_key);
|
|
856
|
-
if (db.reset_sequence && pk.type.name === "Integer")
|
|
857
|
-
await db.reset_sequence(this.name);
|
|
858
|
-
|
|
859
|
-
if (recalc_stored && this.fields.some((f) => f.calculated && f.stored)) {
|
|
860
|
-
await recalculate_for_stored(this);
|
|
861
|
-
}
|
|
862
|
-
return {
|
|
863
|
-
success:
|
|
864
|
-
`Imported ${i > 1 ? i - 1 - rejects : ""} rows into table ${
|
|
865
|
-
this.name
|
|
866
|
-
}` + (rejects ? `. Rejected ${rejects} rows.` : ""),
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
/**
|
|
871
|
-
* Import JSON table description
|
|
872
|
-
* @param filePath
|
|
873
|
-
* @param skip_first_data_row
|
|
874
|
-
* @returns {Promise<{error: string}|{success: string}>}
|
|
875
|
-
*/
|
|
876
|
-
async import_json_file(filePath, skip_first_data_row) {
|
|
877
|
-
// todo argument type buffer is not assignable for type String...
|
|
878
|
-
const file_rows = JSON.parse(await fs.promises.readFile(filePath));
|
|
879
|
-
const fields = await this.getFields();
|
|
880
|
-
const pk_name = this.pk_name;
|
|
881
|
-
const { readState } = require("../plugin-helper");
|
|
882
|
-
|
|
883
|
-
let i = 1;
|
|
884
|
-
const client = db.isSQLite ? db : await db.getClient();
|
|
885
|
-
await client.query("BEGIN");
|
|
886
|
-
for (const rec of file_rows) {
|
|
887
|
-
i += 1;
|
|
888
|
-
if (skip_first_data_row && i === 2) continue;
|
|
889
|
-
fields
|
|
890
|
-
.filter((f) => f.calculated && !f.stored)
|
|
891
|
-
.forEach((f) => {
|
|
892
|
-
if (typeof rec[f.name] !== "undefined") {
|
|
893
|
-
delete rec[f.name];
|
|
894
|
-
}
|
|
895
|
-
});
|
|
896
|
-
try {
|
|
897
|
-
readState(rec, fields);
|
|
898
|
-
await db.insert(this.name, rec, { noid: true, client, pk_name });
|
|
899
|
-
} catch (e) {
|
|
900
|
-
await client.query("ROLLBACK");
|
|
901
|
-
|
|
902
|
-
if (!db.isSQLite) await client.release(true);
|
|
903
|
-
return { error: `${e.message} in row ${i}` };
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
await client.query("COMMIT");
|
|
907
|
-
if (!db.isSQLite) await client.release(true);
|
|
908
|
-
const pk = fields.find((f) => f.primary_key);
|
|
909
|
-
if (db.reset_sequence && pk.type.name === "Integer")
|
|
910
|
-
await db.reset_sequence(this.name);
|
|
911
|
-
|
|
912
|
-
return {
|
|
913
|
-
success: `Imported ${file_rows.length} rows into table ${this.name}`,
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Get parent relations for table
|
|
919
|
-
* @param allow_double
|
|
920
|
-
* @returns {Promise<{parent_relations: object[], parent_field_list: object[]}>}
|
|
921
|
-
*/
|
|
922
|
-
async get_parent_relations(allow_double) {
|
|
923
|
-
const fields = await this.getFields();
|
|
924
|
-
let parent_relations = [];
|
|
925
|
-
let parent_field_list = [];
|
|
926
|
-
for (const f of fields) {
|
|
927
|
-
if (f.is_fkey && f.type !== "File") {
|
|
928
|
-
const table = await Table.findOne({ name: f.reftable_name });
|
|
929
|
-
await table.getFields();
|
|
930
|
-
for (const pf of table.fields.filter(
|
|
931
|
-
(f) => !f.calculated || f.stored
|
|
932
|
-
)) {
|
|
933
|
-
parent_field_list.push(`${f.name}.${pf.name}`);
|
|
934
|
-
if (pf.is_fkey && pf.type !== "File" && allow_double) {
|
|
935
|
-
const table1 = await Table.findOne({ name: pf.reftable_name });
|
|
936
|
-
await table1.getFields();
|
|
937
|
-
for (const gpf of table1.fields.filter(
|
|
938
|
-
(f) => !f.calculated || f.stored
|
|
939
|
-
)) {
|
|
940
|
-
parent_field_list.push(`${f.name}.${pf.name}.${gpf.name}`);
|
|
941
|
-
}
|
|
942
|
-
parent_relations.push({ key_field: pf, through: f, table: table1 });
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
parent_relations.push({ key_field: f, table });
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
return { parent_relations, parent_field_list };
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
/**
|
|
952
|
-
* Get child relations for table
|
|
953
|
-
* @returns {Promise<{child_relations: object[], child_field_list: object[]}>}
|
|
954
|
-
*/
|
|
955
|
-
async get_child_relations() {
|
|
956
|
-
const cfields = await Field.find({ reftable_name: this.name });
|
|
957
|
-
let child_relations = [];
|
|
958
|
-
let child_field_list = [];
|
|
959
|
-
for (const f of cfields) {
|
|
960
|
-
if (f.is_fkey) {
|
|
961
|
-
const table = await Table.findOne({ id: f.table_id });
|
|
962
|
-
child_field_list.push(`${table.name}.${f.name}`);
|
|
963
|
-
await table.getFields();
|
|
964
|
-
child_relations.push({ key_field: f, table });
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
return { child_relations, child_field_list };
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
/**
|
|
971
|
-
*
|
|
972
|
-
* @param opts
|
|
973
|
-
* @returns {Promise<{values, sql: string}>}
|
|
974
|
-
*/
|
|
975
|
-
async getJoinedQuery(opts = {}) {
|
|
976
|
-
const fields = await this.getFields();
|
|
977
|
-
let fldNms = [];
|
|
978
|
-
let joinq = "";
|
|
979
|
-
let joinTables = [];
|
|
980
|
-
let joinFields = opts.joinFields || [];
|
|
981
|
-
const schema = db.getTenantSchemaPrefix();
|
|
982
|
-
|
|
983
|
-
fields
|
|
984
|
-
.filter((f) => f.type === "File")
|
|
985
|
-
.forEach((f) => {
|
|
986
|
-
joinFields[`${f.name}__filename`] = {
|
|
987
|
-
ref: f.name,
|
|
988
|
-
reftable: "_sc_files",
|
|
989
|
-
target: `filename`,
|
|
990
|
-
};
|
|
991
|
-
});
|
|
992
|
-
for (const [fldnm, { ref, target, through }] of Object.entries(
|
|
993
|
-
joinFields
|
|
994
|
-
)) {
|
|
995
|
-
const reffield = fields.find((f) => f.name === ref);
|
|
996
|
-
if (!reffield)
|
|
997
|
-
throw new InvalidConfiguration(
|
|
998
|
-
`Key field ${ref} not found in table ${this.name}`
|
|
999
|
-
);
|
|
1000
|
-
const reftable = reffield.reftable_name;
|
|
1001
|
-
if (!reftable)
|
|
1002
|
-
throw new InvalidConfiguration(`Field ${ref} is not a key field`);
|
|
1003
|
-
const jtNm = `${sqlsanitize(reftable)}_jt_${sqlsanitize(ref)}`;
|
|
1004
|
-
if (!joinTables.includes(jtNm)) {
|
|
1005
|
-
joinTables.push(jtNm);
|
|
1006
|
-
joinq += ` left join ${schema}"${sqlsanitize(
|
|
1007
|
-
reftable
|
|
1008
|
-
)}" ${jtNm} on ${jtNm}."${reffield.refname}"=a."${sqlsanitize(ref)}"`;
|
|
1009
|
-
}
|
|
1010
|
-
if (through) {
|
|
1011
|
-
const throughTable = await Table.findOne({
|
|
1012
|
-
name: reffield.reftable_name,
|
|
1013
|
-
});
|
|
1014
|
-
if (!throughTable)
|
|
1015
|
-
throw new InvalidConfiguration(
|
|
1016
|
-
`Join-through table ${reffield.reftable_name} not found`
|
|
1017
|
-
);
|
|
1018
|
-
const throughTableFields = await throughTable.getFields();
|
|
1019
|
-
const throughRefField = throughTableFields.find(
|
|
1020
|
-
(f) => f.name === through
|
|
1021
|
-
);
|
|
1022
|
-
if (!throughRefField)
|
|
1023
|
-
throw new InvalidConfiguration(
|
|
1024
|
-
`Reference field field ${through} not found in table ${throughTable.name}`
|
|
1025
|
-
);
|
|
1026
|
-
const finalTable = throughRefField.reftable_name;
|
|
1027
|
-
const jtNm1 = `${sqlsanitize(reftable)}_jt_${sqlsanitize(
|
|
1028
|
-
through
|
|
1029
|
-
)}_jt_${sqlsanitize(ref)}`;
|
|
1030
|
-
if (!joinTables.includes(jtNm1)) {
|
|
1031
|
-
joinTables.push(jtNm1);
|
|
1032
|
-
joinq += ` left join ${schema}"${sqlsanitize(
|
|
1033
|
-
finalTable
|
|
1034
|
-
)}" ${jtNm1} on ${jtNm1}.id=${jtNm}."${sqlsanitize(through)}"`;
|
|
1035
|
-
}
|
|
1036
|
-
fldNms.push(`${jtNm1}.${sqlsanitize(target)} as ${sqlsanitize(fldnm)}`);
|
|
1037
|
-
} else {
|
|
1038
|
-
fldNms.push(`${jtNm}.${sqlsanitize(target)} as ${sqlsanitize(fldnm)}`);
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
for (const f of fields.filter((f) => !f.calculated || f.stored)) {
|
|
1042
|
-
fldNms.push(`a."${sqlsanitize(f.name)}"`);
|
|
1043
|
-
}
|
|
1044
|
-
Object.entries(opts.aggregations || {}).forEach(
|
|
1045
|
-
([fldnm, { table, ref, field, where, aggregate, subselect }]) => {
|
|
1046
|
-
if (aggregate.startsWith("Latest ")) {
|
|
1047
|
-
const dateField = aggregate.replace("Latest ", "");
|
|
1048
|
-
fldNms.push(
|
|
1049
|
-
`(select "${sqlsanitize(field)}" from ${schema}"${sqlsanitize(
|
|
1050
|
-
table
|
|
1051
|
-
)}" where ${dateField}=(select max(${dateField}) from ${schema}"${sqlsanitize(
|
|
1052
|
-
table
|
|
1053
|
-
)}" where "${sqlsanitize(ref)}"=a.id${
|
|
1054
|
-
where ? ` and ${where}` : ""
|
|
1055
|
-
}) and "${sqlsanitize(ref)}"=a.id) ${sqlsanitize(fldnm)}`
|
|
1056
|
-
);
|
|
1057
|
-
} else if (subselect)
|
|
1058
|
-
fldNms.push(
|
|
1059
|
-
`(select ${sqlsanitize(aggregate)}(${
|
|
1060
|
-
field ? `"${sqlsanitize(field)}"` : "*"
|
|
1061
|
-
}) from ${schema}"${sqlsanitize(table)}" where ${sqlsanitize(
|
|
1062
|
-
ref
|
|
1063
|
-
)} in (select "${subselect.field}" from ${schema}"${
|
|
1064
|
-
subselect.table.name
|
|
1065
|
-
}" where "${subselect.whereField}"=a.id)) ${sqlsanitize(fldnm)}`
|
|
1066
|
-
);
|
|
1067
|
-
else
|
|
1068
|
-
fldNms.push(
|
|
1069
|
-
`(select ${sqlsanitize(aggregate)}(${
|
|
1070
|
-
field ? `"${sqlsanitize(field)}"` : "*"
|
|
1071
|
-
}) from ${schema}"${sqlsanitize(table)}" where "${sqlsanitize(
|
|
1072
|
-
ref
|
|
1073
|
-
)}"=a.id${where ? ` and ${where}` : ""}) ${sqlsanitize(fldnm)}`
|
|
1074
|
-
);
|
|
1075
|
-
}
|
|
1076
|
-
);
|
|
1077
|
-
|
|
1078
|
-
let whereObj = {};
|
|
1079
|
-
if (opts.where) {
|
|
1080
|
-
Object.keys(opts.where).forEach((k) => {
|
|
1081
|
-
if (k === "_fts") whereObj[k] = { table: "a", ...opts.where[k] };
|
|
1082
|
-
else whereObj[`a."${k}"`] = opts.where[k];
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
const { where, values } = mkWhere(whereObj, db.isSQLite);
|
|
1086
|
-
const selectopts = {
|
|
1087
|
-
limit: opts.limit,
|
|
1088
|
-
orderBy:
|
|
1089
|
-
opts.orderBy &&
|
|
1090
|
-
(opts.orderBy.distance ? opts.orderBy : "a." + opts.orderBy),
|
|
1091
|
-
orderDesc: opts.orderDesc,
|
|
1092
|
-
offset: opts.offset,
|
|
1093
|
-
};
|
|
1094
|
-
|
|
1095
|
-
const sql = `SELECT ${fldNms.join()} FROM ${schema}"${sqlsanitize(
|
|
1096
|
-
this.name
|
|
1097
|
-
)}" a ${joinq} ${where} ${mkSelectOptions(selectopts)}`;
|
|
1098
|
-
return { sql, values };
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
/**
|
|
1102
|
-
* @param {object} [opts = {}]
|
|
1103
|
-
* @returns {Promise<object[]>}
|
|
1104
|
-
*/
|
|
1105
|
-
async getJoinedRows(opts = {}) {
|
|
1106
|
-
const fields = await this.getFields();
|
|
1107
|
-
|
|
1108
|
-
const { sql, values } = await this.getJoinedQuery(opts);
|
|
1109
|
-
const res = await db.query(sql, values);
|
|
1110
|
-
|
|
1111
|
-
return apply_calculated_fields(res.rows, fields);
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
/**
|
|
1116
|
-
* Table contract
|
|
1117
|
-
* @type {{variables: {name: ((function(*=): *)|*)}, methods: {updateRow: ((function(*=): *)|*), get_history: ((function(*=): *)|*), tryUpdateRow: ((function(*=): *)|*), deleteRows: ((function(*=): *)|*), update: ((function(*=): *)|*), getRows: ((function(*=): *)|*), getRow: ((function(*=): *)|*), delete: ((function(*=): *)|*), get_parent_relations: ((function(*=): *)|*), get_child_relations: ((function(*=): *)|*), tryInsertRow: ((function(*=): *)|*), getFields: ((function(*=): *)|*), insertRow: ((function(*=): *)|*), toggleBool: ((function(*=): *)|*), getJoinedRows: ((function(*=): *)|*), countRows: ((function(*=): *)|*), distinctValues: ((function(*=): *)|*), sql_name: ((function(*=): *)|*), import_csv_file: ((function(*=): *)|*)}, static_methods: {find: ((function(*=): *)|*), create_from_csv: ((function(*=): *)|*), findOne: ((function(*=): *)|*), find_with_external: ((function(*=): *)|*), create: ((function(*=): *)|*)}, constructs: {name: ((function(*=): *)|*)}}}
|
|
1118
|
-
*/
|
|
1119
|
-
Table.contract = {
|
|
1120
|
-
constructs: { name: is.str },
|
|
1121
|
-
variables: { name: is.str },
|
|
1122
|
-
methods: {
|
|
1123
|
-
delete: is.fun([], is.promise(is.eq(undefined))),
|
|
1124
|
-
update: is.fun(is.obj(), is.promise(is.eq(undefined))),
|
|
1125
|
-
deleteRows: is.fun(is.obj(), is.promise(is.eq(undefined))),
|
|
1126
|
-
getRow: is.fun(is.maybe(is.obj()), is.promise(is.maybe(is.obj()))),
|
|
1127
|
-
getRows: is.fun(is.maybe(is.obj()), is.promise(is.array(is.obj()))),
|
|
1128
|
-
countRows: is.fun(is.maybe(is.obj()), is.promise(is.posint)),
|
|
1129
|
-
updateRow: is.fun([is.obj(), is.any], is.promise(is.eq(undefined))),
|
|
1130
|
-
toggleBool: is.fun([is.any, is.str], is.promise(is.eq(undefined))),
|
|
1131
|
-
insertRow: is.fun(is.obj(), is.promise(is.any)),
|
|
1132
|
-
get_history: is.fun(is.posint, is.promise(is.array(is.obj()))),
|
|
1133
|
-
distinctValues: is.fun(is.str, is.promise(is.array(is.any))),
|
|
1134
|
-
tryInsertRow: is.fun(
|
|
1135
|
-
[is.obj(), is.maybe(is.posint)],
|
|
1136
|
-
is.promise(is.or(is.obj({ error: is.str }), is.obj({ success: is.any })))
|
|
1137
|
-
),
|
|
1138
|
-
tryUpdateRow: is.fun(
|
|
1139
|
-
[is.obj(), is.any, is.maybe(is.posint)],
|
|
1140
|
-
is.promise(
|
|
1141
|
-
is.or(is.obj({ error: is.str }), is.obj({ success: is.eq(true) }))
|
|
1142
|
-
)
|
|
1143
|
-
),
|
|
1144
|
-
sql_name: is.getter(is.str),
|
|
1145
|
-
getFields: is.fun([], is.promise(is.array(is.class("Field")))),
|
|
1146
|
-
get_parent_relations: is.fun(
|
|
1147
|
-
[],
|
|
1148
|
-
is.promise(
|
|
1149
|
-
is.obj({
|
|
1150
|
-
parent_relations: is.array(
|
|
1151
|
-
is.obj({
|
|
1152
|
-
key_field: is.class("Field"),
|
|
1153
|
-
table: is.class("Table"),
|
|
1154
|
-
})
|
|
1155
|
-
),
|
|
1156
|
-
parent_field_list: is.array(is.str),
|
|
1157
|
-
})
|
|
1158
|
-
)
|
|
1159
|
-
),
|
|
1160
|
-
get_child_relations: is.fun(
|
|
1161
|
-
[],
|
|
1162
|
-
is.promise(
|
|
1163
|
-
is.obj({
|
|
1164
|
-
child_relations: is.array(
|
|
1165
|
-
is.obj({
|
|
1166
|
-
key_field: is.class("Field"),
|
|
1167
|
-
table: is.class("Table"),
|
|
1168
|
-
})
|
|
1169
|
-
),
|
|
1170
|
-
child_field_list: is.array(is.str),
|
|
1171
|
-
})
|
|
1172
|
-
)
|
|
1173
|
-
),
|
|
1174
|
-
import_csv_file: is.fun(
|
|
1175
|
-
is.str,
|
|
1176
|
-
is.promise(is.or(is.obj({ success: is.str }), is.obj({ error: is.str })))
|
|
1177
|
-
),
|
|
1178
|
-
getJoinedRows: is.fun(
|
|
1179
|
-
is.maybe(is_table_query),
|
|
1180
|
-
is.promise(is.array(is.obj({})))
|
|
1181
|
-
),
|
|
1182
|
-
},
|
|
1183
|
-
static_methods: {
|
|
1184
|
-
find: is.fun(
|
|
1185
|
-
[is.maybe(is.obj()), is.maybe(is.obj())],
|
|
1186
|
-
is.promise(is.array(is.class("Table")))
|
|
1187
|
-
),
|
|
1188
|
-
find_with_external: is.fun(
|
|
1189
|
-
[is.maybe(is.obj()), is.maybe(is.obj())],
|
|
1190
|
-
is.promise(
|
|
1191
|
-
is.array(is.or(is.class("Table"), is.obj({ external: is.eq(true) })))
|
|
1192
|
-
)
|
|
1193
|
-
),
|
|
1194
|
-
findOne: is.fun(
|
|
1195
|
-
is.or(is.obj(), is.str, is.posint),
|
|
1196
|
-
is.maybe(is.or(is.class("Table"), is.obj({ external: is.eq(true) })))
|
|
1197
|
-
),
|
|
1198
|
-
create: is.fun(is.str, is.promise(is.class("Table"))),
|
|
1199
|
-
create_from_csv: is.fun(
|
|
1200
|
-
[is.str, is.str],
|
|
1201
|
-
is.promise(
|
|
1202
|
-
is.or(
|
|
1203
|
-
is.obj({ success: is.str, table: is.class("Table") }),
|
|
1204
|
-
is.obj({ error: is.str })
|
|
1205
|
-
)
|
|
1206
|
-
)
|
|
1207
|
-
),
|
|
1208
|
-
//update: is.fun([is.posint, is.obj({})], is.promise(is.eq(undefined)))
|
|
1209
|
-
},
|
|
1210
|
-
};
|
|
1211
|
-
module.exports = Table;
|