@dosgato/api 0.0.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/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/access/access.model.d.ts +2 -0
- package/dist/access/access.model.js +14 -0
- package/dist/access/access.model.js.map +1 -0
- package/dist/access/access.resolver.d.ts +15 -0
- package/dist/access/access.resolver.js +133 -0
- package/dist/access/access.resolver.js.map +1 -0
- package/dist/asset/asset.database.d.ts +12 -0
- package/dist/asset/asset.database.js +116 -0
- package/dist/asset/asset.database.js.map +1 -0
- package/dist/asset/asset.model.d.ts +81 -0
- package/dist/asset/asset.model.js +271 -0
- package/dist/asset/asset.model.js.map +1 -0
- package/dist/asset/asset.resolver.d.ts +32 -0
- package/dist/asset/asset.resolver.js +325 -0
- package/dist/asset/asset.resolver.js.map +1 -0
- package/dist/asset/asset.service.d.ts +35 -0
- package/dist/asset/asset.service.js +225 -0
- package/dist/asset/asset.service.js.map +1 -0
- package/dist/assetfolder/assetfolder.database.d.ts +7 -0
- package/dist/assetfolder/assetfolder.database.js +85 -0
- package/dist/assetfolder/assetfolder.database.js.map +1 -0
- package/dist/assetfolder/assetfolder.model.d.ts +56 -0
- package/dist/assetfolder/assetfolder.model.js +160 -0
- package/dist/assetfolder/assetfolder.model.js.map +1 -0
- package/dist/assetfolder/assetfolder.resolver.d.ts +25 -0
- package/dist/assetfolder/assetfolder.resolver.js +255 -0
- package/dist/assetfolder/assetfolder.resolver.js.map +1 -0
- package/dist/assetfolder/assetfolder.service.d.ts +39 -0
- package/dist/assetfolder/assetfolder.service.js +355 -0
- package/dist/assetfolder/assetfolder.service.js.map +1 -0
- package/dist/assetrule/assetrule.database.d.ts +5 -0
- package/dist/assetrule/assetrule.database.js +161 -0
- package/dist/assetrule/assetrule.database.js.map +1 -0
- package/dist/assetrule/assetrule.model.d.ts +71 -0
- package/dist/assetrule/assetrule.model.js +221 -0
- package/dist/assetrule/assetrule.model.js.map +1 -0
- package/dist/assetrule/assetrule.resolver.d.ts +12 -0
- package/dist/assetrule/assetrule.resolver.js +100 -0
- package/dist/assetrule/assetrule.resolver.js.map +1 -0
- package/dist/assetrule/assetrule.service.d.ts +26 -0
- package/dist/assetrule/assetrule.service.js +184 -0
- package/dist/assetrule/assetrule.service.js.map +1 -0
- package/dist/createdb.d.ts +2 -0
- package/dist/createdb.js +541 -0
- package/dist/createdb.js.map +1 -0
- package/dist/data/data.database.d.ts +7 -0
- package/dist/data/data.database.js +265 -0
- package/dist/data/data.database.js.map +1 -0
- package/dist/data/data.indexing.d.ts +2 -0
- package/dist/data/data.indexing.js +23 -0
- package/dist/data/data.indexing.js.map +1 -0
- package/dist/data/data.model.d.ts +69 -0
- package/dist/data/data.model.js +206 -0
- package/dist/data/data.model.js.map +1 -0
- package/dist/data/data.resolver.d.ts +36 -0
- package/dist/data/data.resolver.js +384 -0
- package/dist/data/data.resolver.js.map +1 -0
- package/dist/data/data.service.d.ts +41 -0
- package/dist/data/data.service.js +374 -0
- package/dist/data/data.service.js.map +1 -0
- package/dist/datafolder/datafolder.database.d.ts +7 -0
- package/dist/datafolder/datafolder.database.js +72 -0
- package/dist/datafolder/datafolder.database.js.map +1 -0
- package/dist/datafolder/datafolder.model.d.ts +48 -0
- package/dist/datafolder/datafolder.model.js +139 -0
- package/dist/datafolder/datafolder.model.js.map +1 -0
- package/dist/datafolder/datafolder.resolver.d.ts +24 -0
- package/dist/datafolder/datafolder.resolver.js +243 -0
- package/dist/datafolder/datafolder.resolver.js.map +1 -0
- package/dist/datafolder/datafolder.service.d.ts +32 -0
- package/dist/datafolder/datafolder.service.js +223 -0
- package/dist/datafolder/datafolder.service.js.map +1 -0
- package/dist/dataroot/dataroot.model.d.ts +19 -0
- package/dist/dataroot/dataroot.model.js +72 -0
- package/dist/dataroot/dataroot.model.js.map +1 -0
- package/dist/dataroot/dataroot.resolver.d.ts +11 -0
- package/dist/dataroot/dataroot.resolver.js +87 -0
- package/dist/dataroot/dataroot.resolver.js.map +1 -0
- package/dist/dataroot/dataroot.service.d.ts +12 -0
- package/dist/dataroot/dataroot.service.js +62 -0
- package/dist/dataroot/dataroot.service.js.map +1 -0
- package/dist/datarule/datarule.database.d.ts +5 -0
- package/dist/datarule/datarule.database.js +144 -0
- package/dist/datarule/datarule.database.js.map +1 -0
- package/dist/datarule/datarule.model.d.ts +55 -0
- package/dist/datarule/datarule.model.js +200 -0
- package/dist/datarule/datarule.model.js.map +1 -0
- package/dist/datarule/datarule.resolver.d.ts +13 -0
- package/dist/datarule/datarule.resolver.js +114 -0
- package/dist/datarule/datarule.resolver.js.map +1 -0
- package/dist/datarule/datarule.service.d.ts +27 -0
- package/dist/datarule/datarule.service.js +191 -0
- package/dist/datarule/datarule.service.js.map +1 -0
- package/dist/fixtures.d.ts +1 -0
- package/dist/fixtures.js +697 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/fixturetemplates.d.ts +110 -0
- package/dist/fixturetemplates.js +178 -0
- package/dist/fixturetemplates.js.map +1 -0
- package/dist/globalrule/globalrule.database.d.ts +5 -0
- package/dist/globalrule/globalrule.database.js +65 -0
- package/dist/globalrule/globalrule.database.js.map +1 -0
- package/dist/globalrule/globalrule.model.d.ts +34 -0
- package/dist/globalrule/globalrule.model.js +120 -0
- package/dist/globalrule/globalrule.model.js.map +1 -0
- package/dist/globalrule/globalrule.resolver.d.ts +11 -0
- package/dist/globalrule/globalrule.resolver.js +85 -0
- package/dist/globalrule/globalrule.resolver.js.map +1 -0
- package/dist/globalrule/globalrule.service.d.ts +18 -0
- package/dist/globalrule/globalrule.service.js +111 -0
- package/dist/globalrule/globalrule.service.js.map +1 -0
- package/dist/group/group.database.d.ts +41 -0
- package/dist/group/group.database.js +190 -0
- package/dist/group/group.database.js.map +1 -0
- package/dist/group/group.model.d.ts +19 -0
- package/dist/group/group.model.js +70 -0
- package/dist/group/group.model.js.map +1 -0
- package/dist/group/group.resolver.d.ts +27 -0
- package/dist/group/group.resolver.js +275 -0
- package/dist/group/group.resolver.js.map +1 -0
- package/dist/group/group.service.d.ts +46 -0
- package/dist/group/group.service.js +384 -0
- package/dist/group/group.service.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +88 -0
- package/dist/internal.js +89 -0
- package/dist/internal.js.map +1 -0
- package/dist/migrations.d.ts +2 -0
- package/dist/migrations.js +41 -0
- package/dist/migrations.js.map +1 -0
- package/dist/organization/organization.database.d.ts +2 -0
- package/dist/organization/organization.database.js +16 -0
- package/dist/organization/organization.database.js.map +1 -0
- package/dist/organization/organization.model.d.ts +5 -0
- package/dist/organization/organization.model.js +35 -0
- package/dist/organization/organization.model.js.map +1 -0
- package/dist/organization/organization.resolver.d.ts +6 -0
- package/dist/organization/organization.resolver.js +43 -0
- package/dist/organization/organization.resolver.js.map +1 -0
- package/dist/organization/organization.service.d.ts +12 -0
- package/dist/organization/organization.service.js +35 -0
- package/dist/organization/organization.service.js.map +1 -0
- package/dist/page/page.database.d.ts +10 -0
- package/dist/page/page.database.js +269 -0
- package/dist/page/page.database.js.map +1 -0
- package/dist/page/page.indexing.d.ts +3 -0
- package/dist/page/page.indexing.js +26 -0
- package/dist/page/page.indexing.js.map +1 -0
- package/dist/page/page.migrations.d.ts +13 -0
- package/dist/page/page.migrations.js +55 -0
- package/dist/page/page.migrations.js.map +1 -0
- package/dist/page/page.model.d.ts +88 -0
- package/dist/page/page.model.js +272 -0
- package/dist/page/page.model.js.map +1 -0
- package/dist/page/page.resolver.d.ts +48 -0
- package/dist/page/page.resolver.js +542 -0
- package/dist/page/page.resolver.js.map +1 -0
- package/dist/page/page.service.d.ts +59 -0
- package/dist/page/page.service.js +399 -0
- package/dist/page/page.service.js.map +1 -0
- package/dist/page/page.util.d.ts +3 -0
- package/dist/page/page.util.js +16 -0
- package/dist/page/page.util.js.map +1 -0
- package/dist/page/page.validation.d.ts +2 -0
- package/dist/page/page.validation.js +21 -0
- package/dist/page/page.validation.js.map +1 -0
- package/dist/pagerule/pagerule.database.d.ts +5 -0
- package/dist/pagerule/pagerule.database.js +212 -0
- package/dist/pagerule/pagerule.database.js.map +1 -0
- package/dist/pagerule/pagerule.model.d.ts +71 -0
- package/dist/pagerule/pagerule.model.js +272 -0
- package/dist/pagerule/pagerule.model.js.map +1 -0
- package/dist/pagerule/pagerule.resolver.d.ts +13 -0
- package/dist/pagerule/pagerule.resolver.js +114 -0
- package/dist/pagerule/pagerule.resolver.js.map +1 -0
- package/dist/pagerule/pagerule.service.d.ts +23 -0
- package/dist/pagerule/pagerule.service.js +180 -0
- package/dist/pagerule/pagerule.service.js.map +1 -0
- package/dist/pagetree/pagetree.database.d.ts +13 -0
- package/dist/pagetree/pagetree.database.js +84 -0
- package/dist/pagetree/pagetree.database.js.map +1 -0
- package/dist/pagetree/pagetree.model.d.ts +43 -0
- package/dist/pagetree/pagetree.model.js +146 -0
- package/dist/pagetree/pagetree.model.js.map +1 -0
- package/dist/pagetree/pagetree.resolver.d.ts +23 -0
- package/dist/pagetree/pagetree.resolver.js +238 -0
- package/dist/pagetree/pagetree.resolver.js.map +1 -0
- package/dist/pagetree/pagetree.service.d.ts +25 -0
- package/dist/pagetree/pagetree.service.js +221 -0
- package/dist/pagetree/pagetree.service.js.map +1 -0
- package/dist/role/role.database.d.ts +17 -0
- package/dist/role/role.database.js +74 -0
- package/dist/role/role.database.js.map +1 -0
- package/dist/role/role.model.d.ts +26 -0
- package/dist/role/role.model.js +84 -0
- package/dist/role/role.model.js.map +1 -0
- package/dist/role/role.resolver.d.ts +27 -0
- package/dist/role/role.resolver.js +294 -0
- package/dist/role/role.resolver.js.map +1 -0
- package/dist/role/role.service.d.ts +33 -0
- package/dist/role/role.service.js +265 -0
- package/dist/role/role.service.js.map +1 -0
- package/dist/run.d.ts +1 -0
- package/dist/run.js +29 -0
- package/dist/run.js.map +1 -0
- package/dist/scalars/datetime.d.ts +2 -0
- package/dist/scalars/datetime.js +19 -0
- package/dist/scalars/datetime.js.map +1 -0
- package/dist/scalars/index.d.ts +3 -0
- package/dist/scalars/index.js +4 -0
- package/dist/scalars/index.js.map +1 -0
- package/dist/scalars/jsondata.d.ts +2 -0
- package/dist/scalars/jsondata.js +15 -0
- package/dist/scalars/jsondata.js.map +1 -0
- package/dist/scalars/urlsafestring.d.ts +4 -0
- package/dist/scalars/urlsafestring.js +28 -0
- package/dist/scalars/urlsafestring.js.map +1 -0
- package/dist/site/site.database.d.ts +15 -0
- package/dist/site/site.database.js +164 -0
- package/dist/site/site.database.js.map +1 -0
- package/dist/site/site.model.d.ts +62 -0
- package/dist/site/site.model.js +197 -0
- package/dist/site/site.model.js.map +1 -0
- package/dist/site/site.resolver.d.ts +30 -0
- package/dist/site/site.resolver.js +326 -0
- package/dist/site/site.resolver.js.map +1 -0
- package/dist/site/site.service.d.ts +35 -0
- package/dist/site/site.service.js +199 -0
- package/dist/site/site.service.js.map +1 -0
- package/dist/siterule/siterule.database.d.ts +5 -0
- package/dist/siterule/siterule.database.js +139 -0
- package/dist/siterule/siterule.database.js.map +1 -0
- package/dist/siterule/siterule.model.d.ts +53 -0
- package/dist/siterule/siterule.model.js +203 -0
- package/dist/siterule/siterule.model.js.map +1 -0
- package/dist/siterule/siterule.resolver.d.ts +12 -0
- package/dist/siterule/siterule.resolver.js +100 -0
- package/dist/siterule/siterule.resolver.js.map +1 -0
- package/dist/siterule/siterule.service.d.ts +23 -0
- package/dist/siterule/siterule.service.js +148 -0
- package/dist/siterule/siterule.service.js.map +1 -0
- package/dist/template/template.database.d.ts +15 -0
- package/dist/template/template.database.js +61 -0
- package/dist/template/template.database.js.map +1 -0
- package/dist/template/template.model.d.ts +32 -0
- package/dist/template/template.model.js +124 -0
- package/dist/template/template.model.js.map +1 -0
- package/dist/template/template.resolver.d.ts +22 -0
- package/dist/template/template.resolver.js +216 -0
- package/dist/template/template.resolver.js.map +1 -0
- package/dist/template/template.service.d.ts +27 -0
- package/dist/template/template.service.js +192 -0
- package/dist/template/template.service.js.map +1 -0
- package/dist/templaterule/templaterule.database.d.ts +5 -0
- package/dist/templaterule/templaterule.database.js +80 -0
- package/dist/templaterule/templaterule.database.js.map +1 -0
- package/dist/templaterule/templaterule.model.d.ts +38 -0
- package/dist/templaterule/templaterule.model.js +136 -0
- package/dist/templaterule/templaterule.model.js.map +1 -0
- package/dist/templaterule/templaterule.resolver.d.ts +12 -0
- package/dist/templaterule/templaterule.resolver.js +100 -0
- package/dist/templaterule/templaterule.resolver.js.map +1 -0
- package/dist/templaterule/templaterule.service.d.ts +19 -0
- package/dist/templaterule/templaterule.service.js +123 -0
- package/dist/templaterule/templaterule.service.js.map +1 -0
- package/dist/user/user.database.d.ts +22 -0
- package/dist/user/user.database.js +116 -0
- package/dist/user/user.database.js.map +1 -0
- package/dist/user/user.model.d.ts +42 -0
- package/dist/user/user.model.js +122 -0
- package/dist/user/user.model.js.map +1 -0
- package/dist/user/user.resolver.d.ts +16 -0
- package/dist/user/user.resolver.js +140 -0
- package/dist/user/user.resolver.js.map +1 -0
- package/dist/user/user.service.d.ts +29 -0
- package/dist/user/user.service.js +195 -0
- package/dist/user/user.service.js.map +1 -0
- package/dist/util/authservice.d.ts +28 -0
- package/dist/util/authservice.js +131 -0
- package/dist/util/authservice.js.map +1 -0
- package/dist/util/dates.d.ts +2 -0
- package/dist/util/dates.js +4 -0
- package/dist/util/dates.js.map +1 -0
- package/dist/util/filehandler.d.ts +15 -0
- package/dist/util/filehandler.js +48 -0
- package/dist/util/filehandler.js.map +1 -0
- package/dist/util/index.d.ts +13 -0
- package/dist/util/index.js +26 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/indexing.d.ts +12 -0
- package/dist/util/indexing.js +74 -0
- package/dist/util/indexing.js.map +1 -0
- package/dist/util/migrations.d.ts +15 -0
- package/dist/util/migrations.js +2 -0
- package/dist/util/migrations.js.map +1 -0
- package/dist/util/mutationlogger.d.ts +1 -0
- package/dist/util/mutationlogger.js +9 -0
- package/dist/util/mutationlogger.js.map +1 -0
- package/dist/util/registry.d.ts +25 -0
- package/dist/util/registry.js +66 -0
- package/dist/util/registry.js.map +1 -0
- package/dist/util/rules.d.ts +6 -0
- package/dist/util/rules.js +31 -0
- package/dist/util/rules.js.map +1 -0
- package/dist/util/sharedtypes.d.ts +3 -0
- package/dist/util/sharedtypes.js +2 -0
- package/dist/util/sharedtypes.js.map +1 -0
- package/dist/util/stopwords.d.ts +1 -0
- package/dist/util/stopwords.js +152 -0
- package/dist/util/stopwords.js.map +1 -0
- package/dist/version/version.model.d.ts +11 -0
- package/dist/version/version.model.js +46 -0
- package/dist/version/version.model.js.map +1 -0
- package/dist/version/version.resolver.d.ts +6 -0
- package/dist/version/version.resolver.js +45 -0
- package/dist/version/version.resolver.js.map +1 -0
- package/dist/versionedservice/service.d.ts +148 -0
- package/dist/versionedservice/service.js +547 -0
- package/dist/versionedservice/service.js.map +1 -0
- package/dist/versionedservice/types.d.ts +87 -0
- package/dist/versionedservice/types.js +11 -0
- package/dist/versionedservice/types.js.map +1 -0
- package/package.json +50 -0
- package/readme/DosGato.mwb +0 -0
- package/readme/DosGato.mwb.bak +0 -0
- package/readme/upgradeflow2.png +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Texas State ETC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# dosgato
|
|
2
|
+
## Introduction
|
|
3
|
+
This is a place to record ideas and code for an experimental new CMS for use at Texas State.
|
|
4
|
+
|
|
5
|
+
The core concepts focus on our handling of data and versions, in an effort to preserve editing history, maximize API compatibility, and reduce system downtime.
|
|
6
|
+
|
|
7
|
+
## Definitions
|
|
8
|
+
### Content Object
|
|
9
|
+
A single page or independent chunk of data. These are objects that will be created and edited by CMS editors during the course of creating their content.
|
|
10
|
+
|
|
11
|
+
### Content Version
|
|
12
|
+
Each content object will have a content version that increments each time a user makes a data change. We will maintain a limited version history for the object so that we can restore older versions of the content. An API parameter will allow clients to request a specific historical version of a content object.
|
|
13
|
+
|
|
14
|
+
### Schema Version
|
|
15
|
+
Each content object will have a schema, and a schema version that increments each time we need to alter structure. Each instance of the object will be tagged with the schema version the client was using when the editor saved the object. When returning a content object from the API, we will be able to alter the schema version up or down to match the client performing the request. This allows zero downtime upgrades without risk of corruption due to old clients in the wild.
|
|
16
|
+
|
|
17
|
+
### Migration
|
|
18
|
+
A migration is a block of code that converts a content object from one schema version to another. Typically migrations will be written so that they can both upgrade to and downgrade from a particular schema version. This is called a reversible migration.
|
|
19
|
+
|
|
20
|
+
If a reversible migration is impossible to write, for example when a field is being deleted, we will have a non-reversible migration. All system updates including a non-reversible migration will require downtime, and clients older than that version will cease to function (see Minimum Schema Version below).
|
|
21
|
+
|
|
22
|
+
Deletion of a non-required field might not crash, so we could theoretically avoid downtime, but in those cases we should write a migration downgrade where we set it to a default value.
|
|
23
|
+
|
|
24
|
+
In general we should avoid non-reversible migrations as much as possible, to avoid making older clients incompatible.
|
|
25
|
+
|
|
26
|
+
### Minimum Schema Version
|
|
27
|
+
The earliest schema version after which all migrations are reversible. Each API request will contain the API/Schema version that the client expects, so that it always receives data structured in a way that it can handle. If the requested API version is less than the minimum schema version, the request will be rejected. That client will be required to upgrade (or refresh the page, in the case of an in-browser client).
|
|
28
|
+
|
|
29
|
+
## Upgrade Process
|
|
30
|
+
In order to preserve uptime, we can now follow a specific upgrade flow to avoid downtime:
|
|
31
|
+
* Each update should consist of de-listing from the load balancer, then restarting with the latest docker image.
|
|
32
|
+
* Update API services, one by one, until all are updated.
|
|
33
|
+
* Update Client/UI services, one by one, until all are updated.
|
|
34
|
+
|
|
35
|
+
This diagram illustrates the process.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
As you can see, when the API services are partially upgraded, the upgraded services simply need to downgrade schema versions on the way out to maintain compatibility. When all API services are prepared to serve the next schema version, clients may begin their upgrades.
|
|
40
|
+
|
|
41
|
+
## Miscellaneous
|
|
42
|
+
* No edits on old versions, must restore a version first to bring it to the top
|
|
43
|
+
* Ensure that browser updates all client-side UI resources at the same time
|
|
44
|
+
* Forced refresh is unnecessary
|
|
45
|
+
|
|
46
|
+
* Reading a page
|
|
47
|
+
* retrieve page data
|
|
48
|
+
* rewind to requested content version, if applicable
|
|
49
|
+
* run migrations to update to requested schema version
|
|
50
|
+
* return modified page data
|
|
51
|
+
|
|
52
|
+
* Saving a page
|
|
53
|
+
* accept page from client, tagged with content version and schema version
|
|
54
|
+
* if there is already a content version with a higher number, abort with concurrency error
|
|
55
|
+
* save a new content version exactly as user provided it and tag with the incoming schema version
|
|
56
|
+
|
|
57
|
+
* Restoring a page
|
|
58
|
+
* retrieve page
|
|
59
|
+
* rewind to requested content version
|
|
60
|
+
* save a new content version with page data exactly as it was, tagged with the old schema version
|
|
61
|
+
|
|
62
|
+
* Deleting a page
|
|
63
|
+
* record the date in meta
|
|
64
|
+
* soft delete for 6 months
|
|
65
|
+
|
|
66
|
+
## References
|
|
67
|
+
* https://www.npmjs.com/package/rfc6902
|
|
68
|
+
|
|
69
|
+
## Notes
|
|
70
|
+
* The rendering server may pass a user token along to the API, or may pass a service token for anonymous access.
|
|
71
|
+
* The API should ensure that the service token only receives published/launched page data.
|
|
72
|
+
* Direct asset downloads will also pass through the rendering server.
|
|
73
|
+
* The API should never allow entirely unauthenticated access.
|
|
74
|
+
* Need to think about first-class support for protected pages. Probably a shared secret with the cache boxes.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { ObjectType } from 'type-graphql';
|
|
8
|
+
let Access = class Access {
|
|
9
|
+
};
|
|
10
|
+
Access = __decorate([
|
|
11
|
+
ObjectType()
|
|
12
|
+
], Access);
|
|
13
|
+
export { Access };
|
|
14
|
+
//# sourceMappingURL=access.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.model.js","sourceRoot":"","sources":["../../src/access/access.model.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAGzC,IAAa,MAAM,GAAnB,MAAa,MAAM;CAAG,CAAA;AAAT,MAAM;IADlB,UAAU,EAAE;GACA,MAAM,CAAG;SAAT,MAAM"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Context } from '@txstate-mws/graphql-server';
|
|
2
|
+
import { UrlSafeString } from '../internal.js';
|
|
3
|
+
export declare class AccessResolver {
|
|
4
|
+
access(ctx: Context): Promise<{}>;
|
|
5
|
+
createGroups(ctx: Context): Promise<boolean>;
|
|
6
|
+
viewGroupManager(ctx: Context): Promise<boolean>;
|
|
7
|
+
createRoles(ctx: Context): Promise<boolean>;
|
|
8
|
+
viewRoleManager(ctx: Context): Promise<boolean>;
|
|
9
|
+
createSites(ctx: Context): Promise<boolean>;
|
|
10
|
+
viewPageManager(ctx: Context): Promise<boolean>;
|
|
11
|
+
viewSiteManager(ctx: Context): Promise<boolean>;
|
|
12
|
+
viewAssetManager(ctx: Context): Promise<boolean>;
|
|
13
|
+
viewDataManager(ctx: Context): Promise<boolean>;
|
|
14
|
+
createGlobalData(ctx: Context, type: UrlSafeString): Promise<boolean>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Context } from '@txstate-mws/graphql-server';
|
|
14
|
+
import { Arg, Ctx, FieldResolver, Query, Resolver } from 'type-graphql';
|
|
15
|
+
import { AssetService, DataService, GroupService, PageService, RoleService, UrlSafeString, SiteService, Access } from '../internal.js';
|
|
16
|
+
let AccessResolver = class AccessResolver {
|
|
17
|
+
async access(ctx) {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
async createGroups(ctx) {
|
|
21
|
+
return await ctx.svc(GroupService).mayCreate();
|
|
22
|
+
}
|
|
23
|
+
async viewGroupManager(ctx) {
|
|
24
|
+
return await ctx.svc(GroupService).mayViewManagerUI();
|
|
25
|
+
}
|
|
26
|
+
async createRoles(ctx) {
|
|
27
|
+
return await ctx.svc(RoleService).mayCreate();
|
|
28
|
+
}
|
|
29
|
+
async viewRoleManager(ctx) {
|
|
30
|
+
return await ctx.svc(RoleService).mayViewManagerUI();
|
|
31
|
+
}
|
|
32
|
+
async createSites(ctx) {
|
|
33
|
+
return await ctx.svc(SiteService).mayCreate();
|
|
34
|
+
}
|
|
35
|
+
async viewPageManager(ctx) {
|
|
36
|
+
return await ctx.svc(PageService).mayViewManagerUI();
|
|
37
|
+
}
|
|
38
|
+
async viewSiteManager(ctx) {
|
|
39
|
+
return await ctx.svc(SiteService).mayViewManagerUI();
|
|
40
|
+
}
|
|
41
|
+
async viewAssetManager(ctx) {
|
|
42
|
+
return await ctx.svc(AssetService).mayViewManagerUI();
|
|
43
|
+
}
|
|
44
|
+
async viewDataManager(ctx) {
|
|
45
|
+
return await ctx.svc(DataService).mayViewManagerUI();
|
|
46
|
+
}
|
|
47
|
+
async createGlobalData(ctx, type) {
|
|
48
|
+
return await ctx.svc(DataService).mayCreateGlobal();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
__decorate([
|
|
52
|
+
Query(returns => Access, { description: 'Shows permissions for the currently authenticated user that are not related to a specific resource. Generally each resource has a `permissions` object stating all the things the currently authenticated user can do to or with that resource. This resolver is for determining permissions that are not related to any particular resource, like whether or not they should be able to view the user management interface.' }),
|
|
53
|
+
__param(0, Ctx()),
|
|
54
|
+
__metadata("design:type", Function),
|
|
55
|
+
__metadata("design:paramtypes", [Context]),
|
|
56
|
+
__metadata("design:returntype", Promise)
|
|
57
|
+
], AccessResolver.prototype, "access", null);
|
|
58
|
+
__decorate([
|
|
59
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create groups.' }),
|
|
60
|
+
__param(0, Ctx()),
|
|
61
|
+
__metadata("design:type", Function),
|
|
62
|
+
__metadata("design:paramtypes", [Context]),
|
|
63
|
+
__metadata("design:returntype", Promise)
|
|
64
|
+
], AccessResolver.prototype, "createGroups", null);
|
|
65
|
+
__decorate([
|
|
66
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create or edit one or more groups and should therefore see the group management UI.' }),
|
|
67
|
+
__param(0, Ctx()),
|
|
68
|
+
__metadata("design:type", Function),
|
|
69
|
+
__metadata("design:paramtypes", [Context]),
|
|
70
|
+
__metadata("design:returntype", Promise)
|
|
71
|
+
], AccessResolver.prototype, "viewGroupManager", null);
|
|
72
|
+
__decorate([
|
|
73
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create roles.' }),
|
|
74
|
+
__param(0, Ctx()),
|
|
75
|
+
__metadata("design:type", Function),
|
|
76
|
+
__metadata("design:paramtypes", [Context]),
|
|
77
|
+
__metadata("design:returntype", Promise)
|
|
78
|
+
], AccessResolver.prototype, "createRoles", null);
|
|
79
|
+
__decorate([
|
|
80
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create, edit, or add rules to one or more roles and should therefore see the role management UI.' }),
|
|
81
|
+
__param(0, Ctx()),
|
|
82
|
+
__metadata("design:type", Function),
|
|
83
|
+
__metadata("design:paramtypes", [Context]),
|
|
84
|
+
__metadata("design:returntype", Promise)
|
|
85
|
+
], AccessResolver.prototype, "viewRoleManager", null);
|
|
86
|
+
__decorate([
|
|
87
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create sites.' }),
|
|
88
|
+
__param(0, Ctx()),
|
|
89
|
+
__metadata("design:type", Function),
|
|
90
|
+
__metadata("design:paramtypes", [Context]),
|
|
91
|
+
__metadata("design:returntype", Promise)
|
|
92
|
+
], AccessResolver.prototype, "createSites", null);
|
|
93
|
+
__decorate([
|
|
94
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to edit pages in one or more sites and should therefore see the page management UI.' }),
|
|
95
|
+
__param(0, Ctx()),
|
|
96
|
+
__metadata("design:type", Function),
|
|
97
|
+
__metadata("design:paramtypes", [Context]),
|
|
98
|
+
__metadata("design:returntype", Promise)
|
|
99
|
+
], AccessResolver.prototype, "viewPageManager", null);
|
|
100
|
+
__decorate([
|
|
101
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to edit, launch, or create sites and should see the site management UI.' }),
|
|
102
|
+
__param(0, Ctx()),
|
|
103
|
+
__metadata("design:type", Function),
|
|
104
|
+
__metadata("design:paramtypes", [Context]),
|
|
105
|
+
__metadata("design:returntype", Promise)
|
|
106
|
+
], AccessResolver.prototype, "viewSiteManager", null);
|
|
107
|
+
__decorate([
|
|
108
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to edit assets in one or more sites and should therefore see the asset management UI.' }),
|
|
109
|
+
__param(0, Ctx()),
|
|
110
|
+
__metadata("design:type", Function),
|
|
111
|
+
__metadata("design:paramtypes", [Context]),
|
|
112
|
+
__metadata("design:returntype", Promise)
|
|
113
|
+
], AccessResolver.prototype, "viewAssetManager", null);
|
|
114
|
+
__decorate([
|
|
115
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to edit data of one or more types and should therefore see the data management UI.' }),
|
|
116
|
+
__param(0, Ctx()),
|
|
117
|
+
__metadata("design:type", Function),
|
|
118
|
+
__metadata("design:paramtypes", [Context]),
|
|
119
|
+
__metadata("design:returntype", Promise)
|
|
120
|
+
], AccessResolver.prototype, "viewDataManager", null);
|
|
121
|
+
__decorate([
|
|
122
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create global data entries of the specified type.' }),
|
|
123
|
+
__param(0, Ctx()),
|
|
124
|
+
__param(1, Arg('type')),
|
|
125
|
+
__metadata("design:type", Function),
|
|
126
|
+
__metadata("design:paramtypes", [Context, UrlSafeString]),
|
|
127
|
+
__metadata("design:returntype", Promise)
|
|
128
|
+
], AccessResolver.prototype, "createGlobalData", null);
|
|
129
|
+
AccessResolver = __decorate([
|
|
130
|
+
Resolver(of => Access)
|
|
131
|
+
], AccessResolver);
|
|
132
|
+
export { AccessResolver };
|
|
133
|
+
//# sourceMappingURL=access.resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.resolver.js","sourceRoot":"","sources":["../../src/access/access.resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Asset, AssetFilter, AssetResize, VersionedService, CreateAssetInput, AssetFolder } from '../internal.js';
|
|
2
|
+
import { DateTime } from 'luxon';
|
|
3
|
+
export declare function getAssets(filter?: AssetFilter): Promise<Asset[]>;
|
|
4
|
+
export declare function getResizes(assetIds: string[]): Promise<{
|
|
5
|
+
key: string;
|
|
6
|
+
value: AssetResize;
|
|
7
|
+
}[]>;
|
|
8
|
+
export declare function getLatestDownload(asset: Asset, resizeBinaryIds: number[]): Promise<DateTime>;
|
|
9
|
+
export declare function createAsset(versionedService: VersionedService, userId: string, args: CreateAssetInput): Promise<Asset>;
|
|
10
|
+
export declare function moveAsset(id: number, targetFolder: AssetFolder): Promise<number>;
|
|
11
|
+
export declare function deleteAsset(id: number, userInternalId: number): Promise<number>;
|
|
12
|
+
export declare function undeleteAsset(id: number): Promise<number>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import db from 'mysql2-async/db';
|
|
2
|
+
import { isNotNull, stringify } from 'txstate-utils';
|
|
3
|
+
import { Asset, AssetResize, AssetFolder } from '../internal.js';
|
|
4
|
+
import { DateTime } from 'luxon';
|
|
5
|
+
function processFilters(filter) {
|
|
6
|
+
const binds = [];
|
|
7
|
+
const where = [];
|
|
8
|
+
const joins = new Map();
|
|
9
|
+
if (typeof filter !== 'undefined') {
|
|
10
|
+
if (filter.internalIds?.length) {
|
|
11
|
+
where.push(`assets.id IN (${db.in(binds, filter.internalIds)})`);
|
|
12
|
+
}
|
|
13
|
+
if (filter.ids?.length) {
|
|
14
|
+
where.push(`assets.dataId IN (${db.in(binds, filter.ids)})`);
|
|
15
|
+
}
|
|
16
|
+
if (filter.folderIds?.length) {
|
|
17
|
+
where.push(`assetfolders.guid IN (${db.in(binds, filter.folderIds)})`);
|
|
18
|
+
if (!joins.has('assetfolders')) {
|
|
19
|
+
joins.set('assetfolders', 'INNER JOIN assetfolders ON assets.folderId = assetfolders.id');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (filter.folderInternalIds?.length) {
|
|
23
|
+
where.push(`assets.folderId IN (${db.in(binds, filter.folderInternalIds)})`);
|
|
24
|
+
}
|
|
25
|
+
if (filter.siteIds?.length) {
|
|
26
|
+
where.push(`assetfolders.siteId IN (${db.in(binds, filter.siteIds)})`);
|
|
27
|
+
if (!joins.has('assetfolders')) {
|
|
28
|
+
joins.set('assetfolders', 'INNER JOIN assetfolders ON assets.folderId = assetfolders.id');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (isNotNull(filter.referenced)) {
|
|
32
|
+
// TODO
|
|
33
|
+
}
|
|
34
|
+
if (isNotNull(filter.deleted)) {
|
|
35
|
+
if (filter.deleted) {
|
|
36
|
+
where.push('assets.deletedAt IS NOT NULL');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
where.push('assets.deletedAt IS NULL');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (filter.checksums?.length) {
|
|
43
|
+
where.push(`binaries.shasum IN (${db.in(binds, filter.checksums)})`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { binds, where, joins };
|
|
47
|
+
}
|
|
48
|
+
export async function getAssets(filter) {
|
|
49
|
+
const { binds, where, joins } = processFilters(filter);
|
|
50
|
+
const assets = await db.getall(`
|
|
51
|
+
SELECT assets.id, assets.dataId, assets.name, assets.folderId, assets.deletedAt, assets.deletedBy, binaries.bytes AS filesize, binaries.mime, binaries.shasum FROM assets
|
|
52
|
+
INNER JOIN binaries on assets.shasum = binaries.shasum
|
|
53
|
+
${joins.size ? Array.from(joins.values()).join('\n') : ''}
|
|
54
|
+
WHERE (${where.join(') AND (')})`, binds);
|
|
55
|
+
return assets.map(a => new Asset(a));
|
|
56
|
+
}
|
|
57
|
+
export async function getResizes(assetIds) {
|
|
58
|
+
const binds = [];
|
|
59
|
+
const resizes = await db.getall(`SELECT assets.id, resizes.* FROM resizes
|
|
60
|
+
INNER JOIN binaries ON resizes.originalBinaryId = binaries.id
|
|
61
|
+
INNER JOIN assets ON binaries.shasum = assets.shasum
|
|
62
|
+
WHERE assets.id IN (${db.in(binds, assetIds)})`, binds);
|
|
63
|
+
return resizes.map(row => ({ key: String(row.assetId), value: new AssetResize(row) }));
|
|
64
|
+
}
|
|
65
|
+
export async function getLatestDownload(asset, resizeBinaryIds) {
|
|
66
|
+
const binds = [];
|
|
67
|
+
const binaryId = await db.getval(`SELECT binaries.id FROM binaries
|
|
68
|
+
INNER JOIN assets on assets.shasum = binaries.shasum
|
|
69
|
+
WHERE assets.id = ?`, [asset.internalId]);
|
|
70
|
+
if (!binaryId)
|
|
71
|
+
throw new Error(`Could not find binary for asset ${String(asset.name)}`);
|
|
72
|
+
console.log(`SELECT binaryId, year, month, day, CONCAT(year,month,day) AS dateconcat
|
|
73
|
+
FROM downloads
|
|
74
|
+
WHERE binaryId in (${db.in(binds, [binaryId, ...resizeBinaryIds])})
|
|
75
|
+
ORDER BY dateconcat DESC
|
|
76
|
+
LIMIT 1`);
|
|
77
|
+
console.log(binds);
|
|
78
|
+
const latestDownload = await db.getrow(`SELECT binaryId, year, month, day, CONCAT(year,month,day) AS dateconcat
|
|
79
|
+
FROM downloads
|
|
80
|
+
WHERE binaryId in (${db.in(binds, [binaryId, ...resizeBinaryIds])})
|
|
81
|
+
ORDER BY dateconcat DESC
|
|
82
|
+
LIMIT 1`, binds);
|
|
83
|
+
return DateTime.fromObject({ year: latestDownload.year, month: latestDownload.month, day: latestDownload.day });
|
|
84
|
+
}
|
|
85
|
+
export async function createAsset(versionedService, userId, args) {
|
|
86
|
+
return await db.transaction(async (db) => {
|
|
87
|
+
// TODO: What else should go in the data for an asset? What indexes does it need?
|
|
88
|
+
const dataId = await versionedService.create('asset', { shasum: args.checksum }, [{ name: 'type', values: [args.mime] }], userId, db);
|
|
89
|
+
const folderInternalId = await db.getval('SELECT id FROM assetfolders WHERE guid = ?', [args.folderId]);
|
|
90
|
+
// TODO: What goes in the meta field?
|
|
91
|
+
await db.insert(`
|
|
92
|
+
INSERT IGNORE INTO binaries (shasum, mime, meta, bytes)
|
|
93
|
+
VALUES(?, ?, ?, ?)`, [args.checksum, args.mime, stringify({}), args.size]);
|
|
94
|
+
const newInternalId = await db.insert(`
|
|
95
|
+
INSERT INTO assets (name, folderId, dataId, shasum)
|
|
96
|
+
VALUES(?, ?, ?, ?)`, [args.name, folderInternalId, dataId, args.checksum]);
|
|
97
|
+
return new Asset(await db.getrow('SELECT * FROM assets WHERE id=?', [newInternalId]));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export async function moveAsset(id, targetFolder) {
|
|
101
|
+
return await db.transaction(async (db) => {
|
|
102
|
+
const folder = new AssetFolder(await db.getrow('SELECT * FROM assetfolders WHERE id = ?', [targetFolder.internalId]));
|
|
103
|
+
// Ensure the target folder has not moved.
|
|
104
|
+
// Someone else may have moved it somewhere the current user does not have permission to create assets
|
|
105
|
+
if (folder.path !== targetFolder.path)
|
|
106
|
+
throw new Error('Target folder has moved since the mutation began.');
|
|
107
|
+
return await db.update('UPDATE assets set folderId = ? WHERE id = ?', [targetFolder.internalId, id]);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export async function deleteAsset(id, userInternalId) {
|
|
111
|
+
return await db.update('UPDATE assets SET deletedAt = NOW(), deletedBy = ? WHERE id = ?', [userInternalId, id]);
|
|
112
|
+
}
|
|
113
|
+
export async function undeleteAsset(id) {
|
|
114
|
+
return await db.update('UPDATE assets SET deletedBy = null, deletedAt = null WHERE id = ?', [id]);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=asset.database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset.database.js","sourceRoot":"","sources":["../../src/asset/asset.database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { ValidatedResponse, ValidatedResponseArgs } from '@txstate-mws/graphql-server';
|
|
3
|
+
import { UrlSafeString } from '../internal.js';
|
|
4
|
+
export declare class BoxAttributes {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
constructor(row: any);
|
|
8
|
+
static hasBox(row: any): boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class Asset {
|
|
11
|
+
internalId: number;
|
|
12
|
+
id: string;
|
|
13
|
+
name: UrlSafeString;
|
|
14
|
+
size: number;
|
|
15
|
+
mime: string;
|
|
16
|
+
extension: string;
|
|
17
|
+
box?: BoxAttributes;
|
|
18
|
+
checksum: string;
|
|
19
|
+
deleted: boolean;
|
|
20
|
+
deletedAt?: DateTime;
|
|
21
|
+
lastRawDownload?: DateTime;
|
|
22
|
+
deletedBy?: number;
|
|
23
|
+
folderInternalId: number;
|
|
24
|
+
dataId: string;
|
|
25
|
+
constructor(row: any);
|
|
26
|
+
}
|
|
27
|
+
export declare class AssetFilter {
|
|
28
|
+
internalIds?: number[];
|
|
29
|
+
ids?: string[];
|
|
30
|
+
siteIds?: string[];
|
|
31
|
+
links?: AssetLinkInput[];
|
|
32
|
+
checksums?: string[];
|
|
33
|
+
folderIds?: string[];
|
|
34
|
+
folderInternalIds?: number[];
|
|
35
|
+
names?: string[];
|
|
36
|
+
paths?: string[];
|
|
37
|
+
beneath?: string[];
|
|
38
|
+
parentPaths?: string[];
|
|
39
|
+
referenced?: boolean;
|
|
40
|
+
deleted?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class CreateAssetInput {
|
|
43
|
+
name: string;
|
|
44
|
+
folderId: string;
|
|
45
|
+
checksum: string;
|
|
46
|
+
mime: string;
|
|
47
|
+
size: number;
|
|
48
|
+
}
|
|
49
|
+
export declare class UpdateAssetInput {
|
|
50
|
+
name: string;
|
|
51
|
+
checksum: string;
|
|
52
|
+
}
|
|
53
|
+
export declare class AssetResponse extends ValidatedResponse {
|
|
54
|
+
asset?: Asset;
|
|
55
|
+
constructor(config: ValidatedResponseArgs & {
|
|
56
|
+
asset?: Asset;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
export declare class AssetPermissions {
|
|
60
|
+
}
|
|
61
|
+
export declare enum AssetPermission {
|
|
62
|
+
UPDATE = "update",
|
|
63
|
+
MOVE = "move",
|
|
64
|
+
DELETE = "delete",
|
|
65
|
+
UNDELETE = "undelete"
|
|
66
|
+
}
|
|
67
|
+
export declare class AssetResize {
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
quality: number;
|
|
71
|
+
settings: any;
|
|
72
|
+
lastDownload: DateTime;
|
|
73
|
+
binaryId: number;
|
|
74
|
+
originalBinaryId: number;
|
|
75
|
+
constructor(row: any);
|
|
76
|
+
}
|
|
77
|
+
export declare class AssetLinkInput {
|
|
78
|
+
id: string;
|
|
79
|
+
path: string;
|
|
80
|
+
checksum: string;
|
|
81
|
+
}
|