@dosgato/api 0.0.8 → 0.0.10
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/access/access.resolver.d.ts +1 -0
- package/dist/access/access.resolver.js +11 -1
- package/dist/access/access.resolver.js.map +1 -1
- package/dist/asset/asset.database.d.ts +5 -3
- package/dist/asset/asset.database.js +31 -9
- package/dist/asset/asset.database.js.map +1 -1
- package/dist/asset/asset.model.d.ts +4 -0
- package/dist/asset/asset.model.js +25 -7
- package/dist/asset/asset.model.js.map +1 -1
- package/dist/asset/asset.routes.d.ts +2 -0
- package/dist/asset/asset.routes.js +73 -0
- package/dist/asset/asset.routes.js.map +1 -0
- package/dist/asset/asset.service.d.ts +3 -0
- package/dist/asset/asset.service.js +79 -6
- package/dist/asset/asset.service.js.map +1 -1
- package/dist/assetrule/assetrule.resolver.d.ts +2 -2
- package/dist/assetrule/assetrule.resolver.js +4 -3
- package/dist/assetrule/assetrule.resolver.js.map +1 -1
- package/dist/assetrule/assetrule.service.d.ts +2 -2
- package/dist/assetrule/assetrule.service.js +23 -10
- package/dist/assetrule/assetrule.service.js.map +1 -1
- package/dist/datarule/datarule.database.js +2 -1
- package/dist/datarule/datarule.database.js.map +1 -1
- package/dist/datarule/datarule.resolver.d.ts +3 -3
- package/dist/datarule/datarule.resolver.js +4 -3
- package/dist/datarule/datarule.resolver.js.map +1 -1
- package/dist/datarule/datarule.service.d.ts +3 -3
- package/dist/datarule/datarule.service.js +36 -27
- package/dist/datarule/datarule.service.js.map +1 -1
- package/dist/globalrule/globalrule.resolver.d.ts +3 -3
- package/dist/globalrule/globalrule.resolver.js +8 -6
- package/dist/globalrule/globalrule.resolver.js.map +1 -1
- package/dist/globalrule/globalrule.service.d.ts +3 -3
- package/dist/globalrule/globalrule.service.js +20 -24
- package/dist/globalrule/globalrule.service.js.map +1 -1
- package/dist/index.js +3 -22
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/page/page.service.js +1 -1
- package/dist/page/page.service.js.map +1 -1
- package/dist/pagerule/pagerule.database.js +1 -1
- package/dist/pagerule/pagerule.database.js.map +1 -1
- package/dist/pagerule/pagerule.resolver.d.ts +3 -3
- package/dist/pagerule/pagerule.resolver.js +8 -6
- package/dist/pagerule/pagerule.resolver.js.map +1 -1
- package/dist/pagerule/pagerule.service.d.ts +3 -3
- package/dist/pagerule/pagerule.service.js +50 -30
- package/dist/pagerule/pagerule.service.js.map +1 -1
- package/dist/pagetree/pagetree.service.js +14 -14
- package/dist/pagetree/pagetree.service.js.map +1 -1
- package/dist/role/role.database.d.ts +2 -1
- package/dist/role/role.database.js +7 -2
- package/dist/role/role.database.js.map +1 -1
- package/dist/role/role.resolver.d.ts +2 -2
- package/dist/role/role.resolver.js +14 -13
- package/dist/role/role.resolver.js.map +1 -1
- package/dist/role/role.service.d.ts +2 -2
- package/dist/role/role.service.js +38 -23
- package/dist/role/role.service.js.map +1 -1
- package/dist/scalars/urlsafestring.d.ts +1 -0
- package/dist/scalars/urlsafestring.js +2 -2
- package/dist/scalars/urlsafestring.js.map +1 -1
- package/dist/siterule/siterule.resolver.d.ts +3 -3
- package/dist/siterule/siterule.resolver.js +8 -6
- package/dist/siterule/siterule.resolver.js.map +1 -1
- package/dist/siterule/siterule.service.d.ts +3 -3
- package/dist/siterule/siterule.service.js +29 -29
- package/dist/siterule/siterule.service.js.map +1 -1
- package/dist/templaterule/templaterule.database.js +4 -2
- package/dist/templaterule/templaterule.database.js.map +1 -1
- package/dist/templaterule/templaterule.resolver.d.ts +3 -3
- package/dist/templaterule/templaterule.resolver.js +8 -6
- package/dist/templaterule/templaterule.resolver.js.map +1 -1
- package/dist/templaterule/templaterule.service.d.ts +3 -3
- package/dist/templaterule/templaterule.service.js +33 -30
- package/dist/templaterule/templaterule.service.js.map +1 -1
- package/dist/user/user.database.d.ts +1 -0
- package/dist/user/user.database.js +3 -0
- package/dist/user/user.database.js.map +1 -1
- package/dist/user/user.resolver.d.ts +1 -0
- package/dist/user/user.resolver.js +16 -0
- package/dist/user/user.resolver.js.map +1 -1
- package/dist/user/user.service.d.ts +1 -0
- package/dist/user/user.service.js +23 -2
- package/dist/user/user.service.js.map +1 -1
- package/dist/util/filehandler.d.ts +12 -7
- package/dist/util/filehandler.js +58 -14
- package/dist/util/filehandler.js.map +1 -1
- package/package.json +9 -6
|
@@ -2,6 +2,7 @@ import { Context } from '@txstate-mws/graphql-server';
|
|
|
2
2
|
import { UrlSafeString } from '../internal.js';
|
|
3
3
|
export declare class AccessResolver {
|
|
4
4
|
access(ctx: Context): Promise<{}>;
|
|
5
|
+
createUsers(ctx: Context): Promise<boolean>;
|
|
5
6
|
createGroups(ctx: Context): Promise<boolean>;
|
|
6
7
|
viewGroupManager(ctx: Context): Promise<boolean>;
|
|
7
8
|
createRoles(ctx: Context): Promise<boolean>;
|
|
@@ -12,11 +12,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
};
|
|
13
13
|
import { Context } from '@txstate-mws/graphql-server';
|
|
14
14
|
import { Arg, Ctx, FieldResolver, Query, Resolver } from 'type-graphql';
|
|
15
|
-
import { AssetService, DataService, GroupService, PageService, RoleService,
|
|
15
|
+
import { Access, AssetService, DataService, GroupService, PageService, RoleService, SiteService, TemplateService, UrlSafeString, UserService } from '../internal.js';
|
|
16
16
|
let AccessResolver = class AccessResolver {
|
|
17
17
|
async access(ctx) {
|
|
18
18
|
return {};
|
|
19
19
|
}
|
|
20
|
+
async createUsers(ctx) {
|
|
21
|
+
return await ctx.svc(UserService).mayCreate();
|
|
22
|
+
}
|
|
20
23
|
async createGroups(ctx) {
|
|
21
24
|
return await ctx.svc(GroupService).mayCreate();
|
|
22
25
|
}
|
|
@@ -61,6 +64,13 @@ __decorate([
|
|
|
61
64
|
__metadata("design:paramtypes", [Context]),
|
|
62
65
|
__metadata("design:returntype", Promise)
|
|
63
66
|
], AccessResolver.prototype, "access", null);
|
|
67
|
+
__decorate([
|
|
68
|
+
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create new users.' }),
|
|
69
|
+
__param(0, Ctx()),
|
|
70
|
+
__metadata("design:type", Function),
|
|
71
|
+
__metadata("design:paramtypes", [Context]),
|
|
72
|
+
__metadata("design:returntype", Promise)
|
|
73
|
+
], AccessResolver.prototype, "createUsers", null);
|
|
64
74
|
__decorate([
|
|
65
75
|
FieldResolver(returns => Boolean, { description: 'Currently authenticated user is able to create groups.' }),
|
|
66
76
|
__param(0, Ctx()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access.resolver.js","sourceRoot":"","sources":["../../src/access/access.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"access.resolver.js","sourceRoot":"","sources":["../../src/access/access.resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Asset, AssetFilter, AssetResize, VersionedService, CreateAssetInput, AssetFolder } from '../internal.js';
|
|
2
2
|
import { DateTime } from 'luxon';
|
|
3
3
|
export declare function getAssets(filter?: AssetFilter): Promise<Asset[]>;
|
|
4
|
-
export declare function getResizes(
|
|
5
|
-
key:
|
|
4
|
+
export declare function getResizes(assetInternalIds: number[]): Promise<{
|
|
5
|
+
key: any;
|
|
6
6
|
value: AssetResize;
|
|
7
7
|
}[]>;
|
|
8
|
+
export declare function getResizesById(resizeIds: string[]): Promise<AssetResize[]>;
|
|
8
9
|
export declare function getLatestDownload(asset: Asset, resizeBinaryIds: number[]): Promise<DateTime>;
|
|
9
|
-
export declare function createAsset(versionedService: VersionedService, userId: string, args: CreateAssetInput): Promise<
|
|
10
|
+
export declare function createAsset(versionedService: VersionedService, userId: string, args: CreateAssetInput): Promise<number>;
|
|
11
|
+
export declare function registerResize(asset: Asset, width: number, shasum: string, mime: string, quality: number, size: number): Promise<number>;
|
|
10
12
|
export declare function moveAsset(id: number, targetFolder: AssetFolder): Promise<number>;
|
|
11
13
|
export declare function deleteAsset(id: number, userInternalId: number): Promise<number>;
|
|
12
14
|
export declare function undeleteAsset(id: number): Promise<number>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import db from 'mysql2-async/db';
|
|
2
|
-
import { isNotNull, stringify } from 'txstate-utils';
|
|
2
|
+
import { isNotNull, pick, stringify } from 'txstate-utils';
|
|
3
3
|
import { Asset, AssetResize, AssetFolder } from '../internal.js';
|
|
4
4
|
import { DateTime } from 'luxon';
|
|
5
5
|
function processFilters(filter) {
|
|
@@ -48,21 +48,31 @@ function processFilters(filter) {
|
|
|
48
48
|
export async function getAssets(filter) {
|
|
49
49
|
const { binds, where, joins } = processFilters(filter);
|
|
50
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
|
|
51
|
+
SELECT assets.id, assets.dataId, assets.name, assets.folderId, assets.deletedAt, assets.deletedBy, binaries.bytes AS filesize, binaries.mime, binaries.shasum, binaries.meta FROM assets
|
|
52
52
|
INNER JOIN binaries on assets.shasum = binaries.shasum
|
|
53
53
|
${joins.size ? Array.from(joins.values()).join('\n') : ''}
|
|
54
54
|
WHERE (${where.join(') AND (')})`, binds);
|
|
55
55
|
return assets.map(a => new Asset(a));
|
|
56
56
|
}
|
|
57
|
-
export async function getResizes(
|
|
57
|
+
export async function getResizes(assetInternalIds) {
|
|
58
58
|
const binds = [];
|
|
59
|
+
const where = [];
|
|
60
|
+
where.push(`a.id IN (${db.in(binds, assetInternalIds)})`);
|
|
59
61
|
const resizes = await db.getall(`SELECT a.id as assetId, r.*, rb.shasum, rb.bytes, rb.mime
|
|
60
62
|
FROM resizes r
|
|
61
63
|
INNER JOIN binaries b ON r.originalBinaryId = b.id
|
|
62
64
|
INNER JOIN binaries rb ON r.binaryId = rb.id
|
|
63
|
-
INNER JOIN assets a ON b.shasum =
|
|
64
|
-
WHERE
|
|
65
|
-
|
|
65
|
+
INNER JOIN assets a ON b.shasum = a.shasum
|
|
66
|
+
WHERE (${where.join(') AND (')})
|
|
67
|
+
ORDER BY rb.bytes`, binds);
|
|
68
|
+
return resizes.map(row => ({ key: row.assetId, value: new AssetResize(row) }));
|
|
69
|
+
}
|
|
70
|
+
export async function getResizesById(resizeIds) {
|
|
71
|
+
const rows = await db.getall(`SELECT r.*, rb.shasum, rb.bytes, rb.mime
|
|
72
|
+
FROM resizes r
|
|
73
|
+
INNER JOIN binaries rb ON r.binaryId = rb.id
|
|
74
|
+
WHERE rb.shasum IN (${db.in([], resizeIds)})`, [resizeIds]);
|
|
75
|
+
return rows.map(r => new AssetResize(r));
|
|
66
76
|
}
|
|
67
77
|
export async function getLatestDownload(asset, resizeBinaryIds) {
|
|
68
78
|
const binds = [];
|
|
@@ -83,14 +93,26 @@ export async function createAsset(versionedService, userId, args) {
|
|
|
83
93
|
// TODO: What else should go in the data for an asset? What indexes does it need?
|
|
84
94
|
const dataId = await versionedService.create('asset', { shasum: args.checksum }, [{ name: 'type', values: [args.mime] }], userId, db);
|
|
85
95
|
const folderInternalId = await db.getval('SELECT id FROM assetfolders WHERE guid = ?', [args.folderId]);
|
|
86
|
-
// TODO: What goes in the meta field?
|
|
87
96
|
await db.insert(`
|
|
88
97
|
INSERT IGNORE INTO binaries (shasum, mime, meta, bytes)
|
|
89
|
-
VALUES(?, ?, ?, ?)`, [args.checksum, args.mime, stringify(
|
|
98
|
+
VALUES(?, ?, ?, ?)`, [args.checksum, args.mime, stringify(pick(args, 'width', 'height')), args.size]);
|
|
90
99
|
const newInternalId = await db.insert(`
|
|
91
100
|
INSERT INTO assets (name, folderId, dataId, shasum)
|
|
92
101
|
VALUES(?, ?, ?, ?)`, [args.name, folderInternalId, dataId, args.checksum]);
|
|
93
|
-
return
|
|
102
|
+
return newInternalId;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
export async function registerResize(asset, width, shasum, mime, quality, size) {
|
|
106
|
+
const height = asset.box.height * width / asset.box.width;
|
|
107
|
+
return await db.transaction(async (db) => {
|
|
108
|
+
const binaryId = await db.insert(`
|
|
109
|
+
INSERT IGNORE INTO binaries (shasum, mime, meta, bytes) VALUES (?, ?, ?, ?)
|
|
110
|
+
`, [shasum, mime, stringify({ width, height }), size]);
|
|
111
|
+
const origBinaryId = await db.getval('SELECT id FROM binaries WHERE shasum=?', [asset.checksum]);
|
|
112
|
+
await db.insert(`
|
|
113
|
+
INSERT INTO resizes (binaryId, originalBinaryId, width, height, quality, othersettings) VALUES (?, ?, ?, ?, ?, ?)
|
|
114
|
+
`, [binaryId, origBinaryId, width, height, quality, stringify({})]);
|
|
115
|
+
return binaryId;
|
|
94
116
|
});
|
|
95
117
|
}
|
|
96
118
|
export async function moveAsset(id, targetFolder) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.database.js","sourceRoot":"","sources":["../../src/asset/asset.database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"asset.database.js","sourceRoot":"","sources":["../../src/asset/asset.database.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ export declare class Asset {
|
|
|
11
11
|
internalId: number;
|
|
12
12
|
id: string;
|
|
13
13
|
name: UrlSafeString;
|
|
14
|
+
filename: string;
|
|
14
15
|
size: number;
|
|
15
16
|
mime: string;
|
|
16
17
|
extension: string;
|
|
@@ -45,6 +46,8 @@ export declare class CreateAssetInput {
|
|
|
45
46
|
checksum: string;
|
|
46
47
|
mime: string;
|
|
47
48
|
size: number;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
48
51
|
}
|
|
49
52
|
export declare class UpdateAssetInput {
|
|
50
53
|
name: string;
|
|
@@ -66,6 +69,7 @@ export declare enum AssetPermission {
|
|
|
66
69
|
}
|
|
67
70
|
export declare class AssetResize {
|
|
68
71
|
id: string;
|
|
72
|
+
checksum: string;
|
|
69
73
|
mime: string;
|
|
70
74
|
extension: string;
|
|
71
75
|
width: number;
|
|
@@ -8,7 +8,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
10
|
import { DateTime } from 'luxon';
|
|
11
|
-
import { isNotNull } from 'txstate-utils';
|
|
11
|
+
import { isNotBlank, isNotNull } from 'txstate-utils';
|
|
12
12
|
import { Field, ID, InputType, Int, ObjectType, registerEnumType } from 'type-graphql';
|
|
13
13
|
import { ValidatedResponse } from '@txstate-mws/graphql-server';
|
|
14
14
|
import { extension } from 'mime-types';
|
|
@@ -23,11 +23,11 @@ const resizeMimeToExt = {
|
|
|
23
23
|
};
|
|
24
24
|
let BoxAttributes = class BoxAttributes {
|
|
25
25
|
constructor(row) {
|
|
26
|
-
this.width = row.width;
|
|
27
|
-
this.height = row.height;
|
|
26
|
+
this.width = row.meta.width;
|
|
27
|
+
this.height = row.meta.height;
|
|
28
28
|
}
|
|
29
29
|
static hasBox(row) {
|
|
30
|
-
return !!row.width;
|
|
30
|
+
return !!row.meta?.width;
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
__decorate([
|
|
@@ -51,6 +51,7 @@ let Asset = class Asset {
|
|
|
51
51
|
this.size = row.filesize;
|
|
52
52
|
this.mime = row.mime; // should be detected upon upload
|
|
53
53
|
this.extension = extension(this.mime) || ''; // TODO: extension can return false if mime is blank, not a string, or unrecognized. What should the extension be in that case?
|
|
54
|
+
this.filename = [this.name, this.extension].filter(isNotBlank).join('.');
|
|
54
55
|
this.box = BoxAttributes.hasBox(row) ? new BoxAttributes(row) : undefined;
|
|
55
56
|
this.folderInternalId = row.folderId;
|
|
56
57
|
this.dataId = row.dataId;
|
|
@@ -66,9 +67,13 @@ __decorate([
|
|
|
66
67
|
__metadata("design:type", String)
|
|
67
68
|
], Asset.prototype, "id", void 0);
|
|
68
69
|
__decorate([
|
|
69
|
-
Field({ description: '
|
|
70
|
+
Field({ description: 'Name of the asset, not including extension. May be different than the filename of the original upload.' }),
|
|
70
71
|
__metadata("design:type", UrlSafeString)
|
|
71
72
|
], Asset.prototype, "name", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
Field({ description: 'Filename that will be used when downloading the asset. Includes the extension.' }),
|
|
75
|
+
__metadata("design:type", String)
|
|
76
|
+
], Asset.prototype, "filename", void 0);
|
|
72
77
|
__decorate([
|
|
73
78
|
Field(type => Int, { description: 'Filesize in bytes.' }),
|
|
74
79
|
__metadata("design:type", Number)
|
|
@@ -82,7 +87,7 @@ __decorate([
|
|
|
82
87
|
__metadata("design:type", String)
|
|
83
88
|
], Asset.prototype, "extension", void 0);
|
|
84
89
|
__decorate([
|
|
85
|
-
Field(),
|
|
90
|
+
Field({ nullable: true }),
|
|
86
91
|
__metadata("design:type", BoxAttributes)
|
|
87
92
|
], Asset.prototype, "box", void 0);
|
|
88
93
|
__decorate([
|
|
@@ -172,6 +177,14 @@ __decorate([
|
|
|
172
177
|
Field(type => Int),
|
|
173
178
|
__metadata("design:type", Number)
|
|
174
179
|
], CreateAssetInput.prototype, "size", void 0);
|
|
180
|
+
__decorate([
|
|
181
|
+
Field(type => Int, { nullable: true, description: 'Must provide if asset is an image.' }),
|
|
182
|
+
__metadata("design:type", Number)
|
|
183
|
+
], CreateAssetInput.prototype, "width", void 0);
|
|
184
|
+
__decorate([
|
|
185
|
+
Field(type => Int, { nullable: true, description: 'Must provide if asset is an image.' }),
|
|
186
|
+
__metadata("design:type", Number)
|
|
187
|
+
], CreateAssetInput.prototype, "height", void 0);
|
|
175
188
|
CreateAssetInput = __decorate([
|
|
176
189
|
InputType()
|
|
177
190
|
], CreateAssetInput);
|
|
@@ -226,6 +239,7 @@ let AssetResize = class AssetResize {
|
|
|
226
239
|
constructor(row) {
|
|
227
240
|
this.id = row.shasum;
|
|
228
241
|
this.size = row.bytes;
|
|
242
|
+
this.checksum = row.shasum;
|
|
229
243
|
this.mime = row.mime;
|
|
230
244
|
this.extension = resizeMimeToExt[this.mime] ?? 'jpg';
|
|
231
245
|
this.width = row.width;
|
|
@@ -238,9 +252,13 @@ let AssetResize = class AssetResize {
|
|
|
238
252
|
}
|
|
239
253
|
};
|
|
240
254
|
__decorate([
|
|
241
|
-
Field(type => ID, { description: '
|
|
255
|
+
Field(type => ID, { description: 'Used for retrieval/display.' }),
|
|
242
256
|
__metadata("design:type", String)
|
|
243
257
|
], AssetResize.prototype, "id", void 0);
|
|
258
|
+
__decorate([
|
|
259
|
+
Field(),
|
|
260
|
+
__metadata("design:type", String)
|
|
261
|
+
], AssetResize.prototype, "checksum", void 0);
|
|
244
262
|
__decorate([
|
|
245
263
|
Field({ description: 'The mime type of this particular resized version. For instance, we may have resizes for each of the popular image formats like JPEG, AVIF, and WEBP.' }),
|
|
246
264
|
__metadata("design:type", String)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.model.js","sourceRoot":"","sources":["../../src/asset/asset.model.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"asset.model.js","sourceRoot":"","sources":["../../src/asset/asset.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import multipart from '@fastify/multipart';
|
|
2
|
+
import { AuthError, Context } from '@txstate-mws/graphql-server';
|
|
3
|
+
import { HttpError } from 'fastify-txstate';
|
|
4
|
+
import { createReadStream } from 'fs';
|
|
5
|
+
import { mkdir } from 'fs/promises';
|
|
6
|
+
import { DateTime } from 'luxon';
|
|
7
|
+
import { omit } from 'txstate-utils';
|
|
8
|
+
import { AssetService, AssetServiceInternal, handleUpload, FileSystemHandler, UserServiceInternal, VersionedService } from '../internal.js';
|
|
9
|
+
async function getEnabledUser(ctx) {
|
|
10
|
+
await ctx.waitForAuth();
|
|
11
|
+
if (!ctx.auth?.sub)
|
|
12
|
+
throw new AuthError();
|
|
13
|
+
const user = await ctx.svc(UserServiceInternal).findById(ctx.auth.sub);
|
|
14
|
+
if (!user || user.disabled)
|
|
15
|
+
throw new AuthError();
|
|
16
|
+
return user;
|
|
17
|
+
}
|
|
18
|
+
export async function createAssetRoutes(app) {
|
|
19
|
+
await mkdir('/files/tmp', { recursive: true });
|
|
20
|
+
await app.register(multipart);
|
|
21
|
+
app.post('/assets', async (req, res) => {
|
|
22
|
+
const ctx = new Context(req);
|
|
23
|
+
await getEnabledUser(ctx); // throws if not authorized
|
|
24
|
+
const { files, data } = await handleUpload(req);
|
|
25
|
+
const assetService = ctx.svc(AssetService);
|
|
26
|
+
for (const file of files) {
|
|
27
|
+
await assetService.create({ folderId: data.folderId, checksum: file.shasum, ...omit(file, 'shasum') });
|
|
28
|
+
}
|
|
29
|
+
return files;
|
|
30
|
+
});
|
|
31
|
+
app.get('/resize/:resizeid/:filename', async (req, res) => {
|
|
32
|
+
const ctx = new Context(req);
|
|
33
|
+
const resize = await ctx.svc(AssetService).getResize(req.params.resizeid);
|
|
34
|
+
if (!resize)
|
|
35
|
+
throw new HttpError(404);
|
|
36
|
+
const etag = req.headers['if-none-match'];
|
|
37
|
+
const resizeEtag = `"${resize.checksum}"`;
|
|
38
|
+
if (etag && resizeEtag === etag)
|
|
39
|
+
return await res.status(304).send();
|
|
40
|
+
const filepath = FileSystemHandler.getFileLocation(resize.checksum);
|
|
41
|
+
void res.header('Content-Type', resize.mime);
|
|
42
|
+
void res.header('Content-Disposition', 'inline');
|
|
43
|
+
void res.header('Content-Length', resize.size);
|
|
44
|
+
void res.header('ETag', resizeEtag);
|
|
45
|
+
void res.header('Cache-Control', `public, max-age=${String(60 * 60 * 24 * 30)}`);
|
|
46
|
+
return await res.status(200).send(createReadStream(filepath));
|
|
47
|
+
});
|
|
48
|
+
app.get('/assets/:id/:filename', async (req, res) => {
|
|
49
|
+
const ctx = new Context(req);
|
|
50
|
+
const asset = await ctx.svc(AssetServiceInternal).findById(req.params.id);
|
|
51
|
+
if (!asset)
|
|
52
|
+
throw new HttpError(404);
|
|
53
|
+
const etag = req.headers['if-none-match'];
|
|
54
|
+
const assetEtag = `"${asset.checksum}"`;
|
|
55
|
+
if (etag && assetEtag === etag)
|
|
56
|
+
return await res.status(304).send();
|
|
57
|
+
const data = await ctx.svc(VersionedService).get(asset.dataId);
|
|
58
|
+
const modifiedAt = DateTime.fromJSDate(data.modified);
|
|
59
|
+
const ifsince = req.headers['if-modified-since'] ? DateTime.fromHTTP(req.headers['if-modified-since']) : undefined;
|
|
60
|
+
if (ifsince?.isValid && modifiedAt <= ifsince)
|
|
61
|
+
return await res.status(304).send();
|
|
62
|
+
const filepath = FileSystemHandler.getFileLocation(asset?.checksum);
|
|
63
|
+
const filename = req.params.filename;
|
|
64
|
+
void res.header('Last-Modified', modifiedAt.toHTTP());
|
|
65
|
+
void res.header('ETag', assetEtag);
|
|
66
|
+
void res.header('Cache-Control', 'no-cache');
|
|
67
|
+
void res.header('Content-Type', asset.mime);
|
|
68
|
+
void res.header('Content-Disposition', 'attachment;filename=' + filename);
|
|
69
|
+
void res.header('Content-Length', asset.size);
|
|
70
|
+
return await res.status(200).send(createReadStream(filepath));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=asset.routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset.routes.js","sourceRoot":"","sources":["../../src/asset/asset.routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { Asset, AssetFilter, AssetFolder, DosGatoService, CreateAssetInput, Asse
|
|
|
3
3
|
export declare class AssetServiceInternal extends BaseService {
|
|
4
4
|
find(filter: AssetFilter): Promise<Asset[]>;
|
|
5
5
|
findById(id: string): Promise<Asset | undefined>;
|
|
6
|
+
findByInternalId(id: number): Promise<Asset | undefined>;
|
|
6
7
|
findByIds(ids: string[]): Promise<Asset[]>;
|
|
7
8
|
findByFolder(folder: AssetFolder, filter?: AssetFilter): Promise<Asset[]>;
|
|
8
9
|
findByFolders(folders: AssetFolder[], filter?: AssetFilter): Promise<Asset[]>;
|
|
@@ -20,12 +21,14 @@ export declare class AssetService extends DosGatoService<Asset> {
|
|
|
20
21
|
getSite(asset: Asset): Promise<import("../internal.js").Site | undefined>;
|
|
21
22
|
getPath(asset: Asset): Promise<string>;
|
|
22
23
|
getResizes(asset: Asset): Promise<import("./asset.model.js").AssetResize[]>;
|
|
24
|
+
getResize(resizeId: string): Promise<import("./asset.model.js").AssetResize | undefined>;
|
|
23
25
|
getThumbnail(asset: Asset): Promise<import("./asset.model.js").AssetResize | undefined>;
|
|
24
26
|
getLatestDownload(asset: Asset): Promise<import("luxon").DateTime>;
|
|
25
27
|
create(args: CreateAssetInput): Promise<AssetResponse>;
|
|
26
28
|
move(dataId: string, folderId: string): Promise<AssetResponse>;
|
|
27
29
|
delete(dataId: string): Promise<AssetResponse>;
|
|
28
30
|
undelete(dataId: string): Promise<AssetResponse>;
|
|
31
|
+
createResizes(asset: Asset): Promise<void>;
|
|
29
32
|
mayViewManagerUI(): Promise<boolean>;
|
|
30
33
|
mayView(asset: Asset): Promise<boolean>;
|
|
31
34
|
mayViewForEdit(asset: Asset): Promise<boolean>;
|
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
import { BaseService } from '@txstate-mws/graphql-server';
|
|
2
2
|
import { ManyJoinedLoader, OneToManyLoader, PrimaryKeyLoader } from 'dataloader-factory';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import sharp from 'sharp';
|
|
6
|
+
import { pipeline } from 'node:stream/promises';
|
|
7
|
+
import { intersect, isNotNull, keyby, roundTo, sortby } from 'txstate-utils';
|
|
8
|
+
import { getAssets, AssetFolderService, appendPath, getResizes, SiteService, DosGatoService, getLatestDownload, AssetFolderServiceInternal, createAsset, VersionedService, AssetResponse, FileSystemHandler, deleteAsset, undeleteAsset, moveAsset, popPath, basename, registerResize, getResizesById } from '../internal.js';
|
|
9
|
+
import { mkdir } from 'node:fs/promises';
|
|
10
|
+
import { dirname } from 'node:path';
|
|
11
|
+
import { lookup } from 'mime-types';
|
|
5
12
|
const thumbnailMimes = new Set(['image/jpg', 'image/jpeg', 'image/gif', 'image/png']);
|
|
6
13
|
const assetsByIdLoader = new PrimaryKeyLoader({
|
|
7
14
|
fetch: async (dataIds) => await getAssets({ ids: dataIds })
|
|
8
15
|
});
|
|
16
|
+
const assetsByInternalIdLoader = new PrimaryKeyLoader({
|
|
17
|
+
fetch: async (internalIds) => await getAssets({ internalIds }),
|
|
18
|
+
extractId: asset => asset.internalId,
|
|
19
|
+
idLoader: assetsByIdLoader
|
|
20
|
+
});
|
|
21
|
+
assetsByIdLoader.addIdLoader(assetsByInternalIdLoader);
|
|
9
22
|
const assetsByFolderInternalIdLoader = new OneToManyLoader({
|
|
10
23
|
fetch: async (folderInternalIds, filter) => await getAssets({ ...filter, folderInternalIds }),
|
|
11
24
|
keysFromFilter: (filter) => filter?.folderInternalIds ?? [],
|
|
12
25
|
extractKey: asset => asset.folderInternalId,
|
|
13
|
-
idLoader: assetsByIdLoader
|
|
26
|
+
idLoader: [assetsByIdLoader, assetsByInternalIdLoader]
|
|
14
27
|
});
|
|
15
28
|
const resizesByAssetIdLoader = new ManyJoinedLoader({
|
|
16
|
-
fetch: async (
|
|
29
|
+
fetch: async (assetInternalIds) => await getResizes(assetInternalIds)
|
|
30
|
+
});
|
|
31
|
+
const resizeLoader = new PrimaryKeyLoader({
|
|
32
|
+
fetch: async (ids) => await getResizesById(ids)
|
|
17
33
|
});
|
|
18
34
|
export class AssetServiceInternal extends BaseService {
|
|
19
35
|
async find(filter) {
|
|
@@ -25,6 +41,9 @@ export class AssetServiceInternal extends BaseService {
|
|
|
25
41
|
async findById(id) {
|
|
26
42
|
return await this.loaders.get(assetsByIdLoader).load(id);
|
|
27
43
|
}
|
|
44
|
+
async findByInternalId(id) {
|
|
45
|
+
return await this.loaders.get(assetsByInternalIdLoader).load(id);
|
|
46
|
+
}
|
|
28
47
|
async findByIds(ids) {
|
|
29
48
|
return await this.loaders.loadMany(assetsByIdLoader, ids);
|
|
30
49
|
}
|
|
@@ -117,7 +136,10 @@ export class AssetService extends DosGatoService {
|
|
|
117
136
|
return await this.raw.getPath(asset);
|
|
118
137
|
}
|
|
119
138
|
async getResizes(asset) {
|
|
120
|
-
return await this.loaders.get(resizesByAssetIdLoader).load(asset.
|
|
139
|
+
return await this.loaders.get(resizesByAssetIdLoader).load(asset.internalId);
|
|
140
|
+
}
|
|
141
|
+
async getResize(resizeId) {
|
|
142
|
+
return await this.loaders.get(resizeLoader).load(resizeId);
|
|
121
143
|
}
|
|
122
144
|
async getThumbnail(asset) {
|
|
123
145
|
const resizes = sortby(await this.getResizes(asset), 'size');
|
|
@@ -136,8 +158,10 @@ export class AssetService extends DosGatoService {
|
|
|
136
158
|
try {
|
|
137
159
|
await FileSystemHandler.moveToPermLocation(args.checksum);
|
|
138
160
|
const versionedService = this.svc(VersionedService);
|
|
139
|
-
const
|
|
161
|
+
const assetId = await createAsset(versionedService, this.auth.sub, args);
|
|
140
162
|
this.loaders.clear();
|
|
163
|
+
const asset = (await this.raw.findByInternalId(assetId));
|
|
164
|
+
this.createResizes(asset).catch(console.error);
|
|
141
165
|
return new AssetResponse({ asset, success: true });
|
|
142
166
|
}
|
|
143
167
|
catch (err) {
|
|
@@ -205,6 +229,55 @@ export class AssetService extends DosGatoService {
|
|
|
205
229
|
throw new Error('Could not restore asset folder');
|
|
206
230
|
}
|
|
207
231
|
}
|
|
232
|
+
async createResizes(asset) {
|
|
233
|
+
if (!asset.box)
|
|
234
|
+
return;
|
|
235
|
+
const filepath = FileSystemHandler.getFileLocation(asset.checksum);
|
|
236
|
+
const info = await sharp(filepath).metadata();
|
|
237
|
+
console.log(info);
|
|
238
|
+
const colors = await new Promise((resolve, reject) => {
|
|
239
|
+
const colorSet = new Set();
|
|
240
|
+
sharp(filepath)
|
|
241
|
+
.raw()
|
|
242
|
+
.on('data', (b) => {
|
|
243
|
+
for (let offset = 0; offset < b.length && colorSet.size < 10000; offset += info.channels) {
|
|
244
|
+
const colorString = Array.from({ length: info.channels }, (_, i) => b[offset + i]).join(',');
|
|
245
|
+
if (colorString === '212,222,214')
|
|
246
|
+
console.log(colorString);
|
|
247
|
+
colorSet.add(colorString);
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
.on('error', () => reject(new Error('there was a problem counting colors in image ' + asset.filename)))
|
|
251
|
+
.on('end', () => resolve(colorSet.size));
|
|
252
|
+
});
|
|
253
|
+
console.log(colors);
|
|
254
|
+
const outputformat = colors >= 10000
|
|
255
|
+
? 'jpg'
|
|
256
|
+
: (info.pages ?? 0) > 0 && info.format !== 'heif'
|
|
257
|
+
? 'gif'
|
|
258
|
+
: 'png';
|
|
259
|
+
const img = sharp(filepath, { animated: outputformat === 'gif' }).rotate();
|
|
260
|
+
const resizePromises = [];
|
|
261
|
+
for (let w = asset.box.width; w > 100; w = roundTo(w / 2)) {
|
|
262
|
+
const id = nanoid();
|
|
263
|
+
resizePromises.push((async () => {
|
|
264
|
+
const resized = img.clone().resize(w);
|
|
265
|
+
const formatted = outputformat === 'jpg'
|
|
266
|
+
? resized.jpeg({ quality: 60 })
|
|
267
|
+
: outputformat === 'png'
|
|
268
|
+
? resized.png({ palette: colors <= 256, compressionLevel: 9, progressive: true })
|
|
269
|
+
: resized.gif({ effort: 10, reoptimize: true, loop: info.loop ?? 0 });
|
|
270
|
+
const hash = crypto.createHash('sha1', { encoding: 'hex' });
|
|
271
|
+
await pipeline(formatted.clone(), hash);
|
|
272
|
+
const shasum = hash.read();
|
|
273
|
+
const filepath = FileSystemHandler.getFileLocation(shasum);
|
|
274
|
+
await mkdir(dirname(filepath), { recursive: true });
|
|
275
|
+
const outputinfo = await formatted.toFile(FileSystemHandler.getFileLocation(shasum));
|
|
276
|
+
await registerResize(asset, w, shasum, lookup(outputformat), outputformat === 'jpg' ? 60 : 0, outputinfo.size);
|
|
277
|
+
})());
|
|
278
|
+
}
|
|
279
|
+
await Promise.all(resizePromises);
|
|
280
|
+
}
|
|
208
281
|
async mayViewManagerUI() {
|
|
209
282
|
return (await this.currentAssetRules()).some(r => r.grants.viewForEdit);
|
|
210
283
|
}
|