patreon-dl 1.0.0
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/README.md +422 -0
- package/bin/patreon-dl.js +5 -0
- package/dist/cli/CLIOptionValidator.d.ts +9 -0
- package/dist/cli/CLIOptionValidator.d.ts.map +1 -0
- package/dist/cli/CLIOptionValidator.js +85 -0
- package/dist/cli/CLIOptionValidator.js.map +1 -0
- package/dist/cli/CLIOptions.d.ts +20 -0
- package/dist/cli/CLIOptions.d.ts.map +1 -0
- package/dist/cli/CLIOptions.js +75 -0
- package/dist/cli/CLIOptions.js.map +1 -0
- package/dist/cli/CommandLineParser.d.ts +11 -0
- package/dist/cli/CommandLineParser.d.ts.map +1 -0
- package/dist/cli/CommandLineParser.js +212 -0
- package/dist/cli/CommandLineParser.js.map +1 -0
- package/dist/cli/ConfigFileParser.d.ts +9 -0
- package/dist/cli/ConfigFileParser.d.ts.map +1 -0
- package/dist/cli/ConfigFileParser.js +163 -0
- package/dist/cli/ConfigFileParser.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +162 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/downloaders/Bootstrap.d.ts +29 -0
- package/dist/downloaders/Bootstrap.d.ts.map +1 -0
- package/dist/downloaders/Bootstrap.js +51 -0
- package/dist/downloaders/Bootstrap.js.map +1 -0
- package/dist/downloaders/Downloader.d.ts +59 -0
- package/dist/downloaders/Downloader.d.ts.map +1 -0
- package/dist/downloaders/Downloader.js +357 -0
- package/dist/downloaders/Downloader.js.map +1 -0
- package/dist/downloaders/DownloaderEvent.d.ts +47 -0
- package/dist/downloaders/DownloaderEvent.d.ts.map +1 -0
- package/dist/downloaders/DownloaderEvent.js +6 -0
- package/dist/downloaders/DownloaderEvent.js.map +1 -0
- package/dist/downloaders/DownloaderOptions.d.ts +39 -0
- package/dist/downloaders/DownloaderOptions.d.ts.map +1 -0
- package/dist/downloaders/DownloaderOptions.js +69 -0
- package/dist/downloaders/DownloaderOptions.js.map +1 -0
- package/dist/downloaders/PostDownloader.d.ts +8 -0
- package/dist/downloaders/PostDownloader.d.ts.map +1 -0
- package/dist/downloaders/PostDownloader.js +428 -0
- package/dist/downloaders/PostDownloader.js.map +1 -0
- package/dist/downloaders/ProductDownloader.d.ts +8 -0
- package/dist/downloaders/ProductDownloader.d.ts.map +1 -0
- package/dist/downloaders/ProductDownloader.js +171 -0
- package/dist/downloaders/ProductDownloader.js.map +1 -0
- package/dist/downloaders/cache/StatusCache.d.ts +43 -0
- package/dist/downloaders/cache/StatusCache.d.ts.map +1 -0
- package/dist/downloaders/cache/StatusCache.js +206 -0
- package/dist/downloaders/cache/StatusCache.js.map +1 -0
- package/dist/downloaders/index.d.ts +7 -0
- package/dist/downloaders/index.d.ts.map +1 -0
- package/dist/downloaders/index.js +6 -0
- package/dist/downloaders/index.js.map +1 -0
- package/dist/downloaders/task/DownloadTask.d.ts +89 -0
- package/dist/downloaders/task/DownloadTask.d.ts.map +1 -0
- package/dist/downloaders/task/DownloadTask.js +240 -0
- package/dist/downloaders/task/DownloadTask.js.map +1 -0
- package/dist/downloaders/task/DownloadTaskBatch.d.ts +45 -0
- package/dist/downloaders/task/DownloadTaskBatch.d.ts.map +1 -0
- package/dist/downloaders/task/DownloadTaskBatch.js +195 -0
- package/dist/downloaders/task/DownloadTaskBatch.js.map +1 -0
- package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts +32 -0
- package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts.map +1 -0
- package/dist/downloaders/task/DownloadTaskBatchEvent.js +2 -0
- package/dist/downloaders/task/DownloadTaskBatchEvent.js.map +1 -0
- package/dist/downloaders/task/DownloadTaskFactory.d.ts +20 -0
- package/dist/downloaders/task/DownloadTaskFactory.d.ts.map +1 -0
- package/dist/downloaders/task/DownloadTaskFactory.js +177 -0
- package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -0
- package/dist/downloaders/task/FFmpegDownloadTask.d.ts +27 -0
- package/dist/downloaders/task/FFmpegDownloadTask.d.ts.map +1 -0
- package/dist/downloaders/task/FFmpegDownloadTask.js +206 -0
- package/dist/downloaders/task/FFmpegDownloadTask.js.map +1 -0
- package/dist/downloaders/task/FetcherDownloadTask.d.ts +21 -0
- package/dist/downloaders/task/FetcherDownloadTask.d.ts.map +1 -0
- package/dist/downloaders/task/FetcherDownloadTask.js +213 -0
- package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -0
- package/dist/downloaders/task/index.d.ts +4 -0
- package/dist/downloaders/task/index.d.ts.map +1 -0
- package/dist/downloaders/task/index.js +3 -0
- package/dist/downloaders/task/index.js.map +1 -0
- package/dist/downloaders/templates/CampaignInfo.d.ts +3 -0
- package/dist/downloaders/templates/CampaignInfo.d.ts.map +1 -0
- package/dist/downloaders/templates/CampaignInfo.js +58 -0
- package/dist/downloaders/templates/CampaignInfo.js.map +1 -0
- package/dist/downloaders/templates/PostInfo.d.ts +4 -0
- package/dist/downloaders/templates/PostInfo.d.ts.map +1 -0
- package/dist/downloaders/templates/PostInfo.js +45 -0
- package/dist/downloaders/templates/PostInfo.js.map +1 -0
- package/dist/downloaders/templates/ProductInfo.d.ts +3 -0
- package/dist/downloaders/templates/ProductInfo.d.ts.map +1 -0
- package/dist/downloaders/templates/ProductInfo.js +20 -0
- package/dist/downloaders/templates/ProductInfo.js.map +1 -0
- package/dist/entities/Attachment.d.ts +7 -0
- package/dist/entities/Attachment.d.ts.map +1 -0
- package/dist/entities/Attachment.js +2 -0
- package/dist/entities/Attachment.js.map +1 -0
- package/dist/entities/Campaign.d.ts +19 -0
- package/dist/entities/Campaign.d.ts.map +1 -0
- package/dist/entities/Campaign.js +2 -0
- package/dist/entities/Campaign.js.map +1 -0
- package/dist/entities/Downloadable.d.ts +6 -0
- package/dist/entities/Downloadable.d.ts.map +1 -0
- package/dist/entities/Downloadable.js +5 -0
- package/dist/entities/Downloadable.js.map +1 -0
- package/dist/entities/MediaItem.d.ts +95 -0
- package/dist/entities/MediaItem.d.ts.map +1 -0
- package/dist/entities/MediaItem.js +2 -0
- package/dist/entities/MediaItem.js.map +1 -0
- package/dist/entities/Post.d.ts +87 -0
- package/dist/entities/Post.d.ts.map +1 -0
- package/dist/entities/Post.js +2 -0
- package/dist/entities/Post.js.map +1 -0
- package/dist/entities/Product.d.ts +17 -0
- package/dist/entities/Product.d.ts.map +1 -0
- package/dist/entities/Product.js +2 -0
- package/dist/entities/Product.js.map +1 -0
- package/dist/entities/Reward.d.ts +14 -0
- package/dist/entities/Reward.d.ts.map +1 -0
- package/dist/entities/Reward.js +2 -0
- package/dist/entities/Reward.js.map +1 -0
- package/dist/entities/User.d.ts +15 -0
- package/dist/entities/User.d.ts.map +1 -0
- package/dist/entities/User.js +2 -0
- package/dist/entities/User.js.map +1 -0
- package/dist/entities/index.d.ts +9 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +6 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/PageParser.d.ts +6 -0
- package/dist/parsers/PageParser.d.ts.map +1 -0
- package/dist/parsers/PageParser.js +23 -0
- package/dist/parsers/PageParser.js.map +1 -0
- package/dist/parsers/Parser.d.ts +43 -0
- package/dist/parsers/Parser.d.ts.map +1 -0
- package/dist/parsers/Parser.js +439 -0
- package/dist/parsers/Parser.js.map +1 -0
- package/dist/parsers/PostParser.d.ts +7 -0
- package/dist/parsers/PostParser.d.ts.map +1 -0
- package/dist/parsers/PostParser.js +259 -0
- package/dist/parsers/PostParser.js.map +1 -0
- package/dist/parsers/ProductParser.d.ts +7 -0
- package/dist/parsers/ProductParser.d.ts.map +1 -0
- package/dist/parsers/ProductParser.js +70 -0
- package/dist/parsers/ProductParser.js.map +1 -0
- package/dist/utils/AttachmentFilenameResolver.d.ts +9 -0
- package/dist/utils/AttachmentFilenameResolver.d.ts.map +1 -0
- package/dist/utils/AttachmentFilenameResolver.js +73 -0
- package/dist/utils/AttachmentFilenameResolver.js.map +1 -0
- package/dist/utils/FSHelper.d.ts +57 -0
- package/dist/utils/FSHelper.d.ts.map +1 -0
- package/dist/utils/FSHelper.js +214 -0
- package/dist/utils/FSHelper.js.map +1 -0
- package/dist/utils/Fetcher.d.ts +45 -0
- package/dist/utils/Fetcher.d.ts.map +1 -0
- package/dist/utils/Fetcher.js +192 -0
- package/dist/utils/Fetcher.js.map +1 -0
- package/dist/utils/FetcherProgressMonitor.d.ts +18 -0
- package/dist/utils/FetcherProgressMonitor.d.ts.map +1 -0
- package/dist/utils/FetcherProgressMonitor.js +56 -0
- package/dist/utils/FetcherProgressMonitor.js.map +1 -0
- package/dist/utils/FilenameFormatHelper.d.ts +44 -0
- package/dist/utils/FilenameFormatHelper.d.ts.map +1 -0
- package/dist/utils/FilenameFormatHelper.js +98 -0
- package/dist/utils/FilenameFormatHelper.js.map +1 -0
- package/dist/utils/FllenameResolver.d.ts +20 -0
- package/dist/utils/FllenameResolver.d.ts.map +1 -0
- package/dist/utils/FllenameResolver.js +55 -0
- package/dist/utils/FllenameResolver.js.map +1 -0
- package/dist/utils/Formatter.d.ts +21 -0
- package/dist/utils/Formatter.d.ts.map +1 -0
- package/dist/utils/Formatter.js +112 -0
- package/dist/utils/Formatter.js.map +1 -0
- package/dist/utils/MediaFilenameResolver.d.ts +9 -0
- package/dist/utils/MediaFilenameResolver.d.ts.map +1 -0
- package/dist/utils/MediaFilenameResolver.js +90 -0
- package/dist/utils/MediaFilenameResolver.js.map +1 -0
- package/dist/utils/Misc.d.ts +14 -0
- package/dist/utils/Misc.d.ts.map +1 -0
- package/dist/utils/Misc.js +4 -0
- package/dist/utils/Misc.js.map +1 -0
- package/dist/utils/ObjectHelper.d.ts +4 -0
- package/dist/utils/ObjectHelper.d.ts.map +1 -0
- package/dist/utils/ObjectHelper.js +30 -0
- package/dist/utils/ObjectHelper.js.map +1 -0
- package/dist/utils/PackageInfo.d.ts +10 -0
- package/dist/utils/PackageInfo.d.ts.map +1 -0
- package/dist/utils/PackageInfo.js +33 -0
- package/dist/utils/PackageInfo.js.map +1 -0
- package/dist/utils/URLHelper.d.ts +40 -0
- package/dist/utils/URLHelper.d.ts.map +1 -0
- package/dist/utils/URLHelper.js +192 -0
- package/dist/utils/URLHelper.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logging/ChainLogger.d.ts +11 -0
- package/dist/utils/logging/ChainLogger.d.ts.map +1 -0
- package/dist/utils/logging/ChainLogger.js +50 -0
- package/dist/utils/logging/ChainLogger.js.map +1 -0
- package/dist/utils/logging/ConsoleLogger.d.ts +31 -0
- package/dist/utils/logging/ConsoleLogger.d.ts.map +1 -0
- package/dist/utils/logging/ConsoleLogger.js +126 -0
- package/dist/utils/logging/ConsoleLogger.js.map +1 -0
- package/dist/utils/logging/FileLogger.d.ts +26 -0
- package/dist/utils/logging/FileLogger.d.ts.map +1 -0
- package/dist/utils/logging/FileLogger.js +147 -0
- package/dist/utils/logging/FileLogger.js.map +1 -0
- package/dist/utils/logging/Logger.d.ts +12 -0
- package/dist/utils/logging/Logger.d.ts.map +1 -0
- package/dist/utils/logging/Logger.js +15 -0
- package/dist/utils/logging/Logger.js.map +1 -0
- package/dist/utils/logging/index.d.ts +7 -0
- package/dist/utils/logging/index.d.ts.map +1 -0
- package/dist/utils/logging/index.js +7 -0
- package/dist/utils/logging/index.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Campaign } from '../entities/Campaign.js';
|
|
2
|
+
import { MediaLike } from '../entities/MediaItem.js';
|
|
3
|
+
import { Product } from '../entities/Product.js';
|
|
4
|
+
import { FormatFieldRules } from './Formatter.js';
|
|
5
|
+
import { Attachment } from '../entities/Attachment.js';
|
|
6
|
+
import { Post } from '../entities/Post.js';
|
|
7
|
+
type CampaignDirNameFormatFieldName = 'creator.vanity' | 'creator.name' | 'creator.id' | 'campaign.name' | 'campaign.id';
|
|
8
|
+
export declare const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<CampaignDirNameFormatFieldName>;
|
|
9
|
+
type ContentDirNameFormatFieldName = 'content.id' | 'content.type' | 'content.slug' | 'content.name';
|
|
10
|
+
export declare const CONTENT_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<ContentDirNameFormatFieldName>;
|
|
11
|
+
type MediaFilenameFormatFieldName = 'media.id' | 'media.type' | 'media.filename' | 'media.variant';
|
|
12
|
+
export declare const MEDIA_FILENAME_VALIDATION_SCHEMA: FormatFieldRules<MediaFilenameFormatFieldName>;
|
|
13
|
+
export default class FilenameFormatHelper {
|
|
14
|
+
#private;
|
|
15
|
+
static getCampaignDirName(campaign: Campaign, format: string): string;
|
|
16
|
+
static getContentDirName(content: Product | Post, format: string): string;
|
|
17
|
+
static getMediaFilename(media: MediaLike & {
|
|
18
|
+
variant: string | null;
|
|
19
|
+
}, format: string): string;
|
|
20
|
+
static getAttachmentFilename(att: Attachment, format: string): string;
|
|
21
|
+
static validateCampaignDirNameFormat(format: string): {
|
|
22
|
+
validateOK: boolean;
|
|
23
|
+
regex?: undefined;
|
|
24
|
+
} | {
|
|
25
|
+
validateOK: boolean | null;
|
|
26
|
+
regex: RegExp;
|
|
27
|
+
};
|
|
28
|
+
static validateContentDirNameFormat(format: string): {
|
|
29
|
+
validateOK: boolean;
|
|
30
|
+
regex?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
validateOK: boolean | null;
|
|
33
|
+
regex: RegExp;
|
|
34
|
+
};
|
|
35
|
+
static validateMediaFilenameFormat(format: string): {
|
|
36
|
+
validateOK: boolean;
|
|
37
|
+
regex?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
validateOK: boolean | null;
|
|
40
|
+
regex: RegExp;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=FilenameFormatHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilenameFormatHelper.d.ts","sourceRoot":"","sources":["../../src/utils/FilenameFormatHelper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAkB,EAAmB,gBAAgB,EAAqB,MAAM,gBAAgB,CAAC;AAEjG,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C,KAAK,8BAA8B,GACjC,gBAAgB,GAChB,cAAc,GACd,YAAY,GACZ,eAAe,GACf,aAAa,CAAC;AAEhB,eAAO,MAAM,mCAAmC,EAAE,gBAAgB,CAAC,8BAA8B,CAMhG,CAAC;AAEF,KAAK,6BAA6B,GAChC,YAAY,GACZ,cAAc,GACd,cAAc,GACd,cAAc,CAAC;AAEjB,eAAO,MAAM,kCAAkC,EAAE,gBAAgB,CAAC,6BAA6B,CAK9F,CAAC;AAEF,KAAK,4BAA4B,GAC/B,UAAU,GACV,YAAY,GACZ,gBAAgB,GAChB,eAAe,CAAC;AAElB,eAAO,MAAM,gCAAgC,EAAE,gBAAgB,CAAC,4BAA4B,CAK3F,CAAC;AAMF,MAAM,CAAC,OAAO,OAAO,oBAAoB;;IAEvC,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAYrE,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAqBzE,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAW9F,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAsBrE,MAAM,CAAC,6BAA6B,CAAC,MAAM,EAAE,MAAM;;;;;;;IAInD,MAAM,CAAC,4BAA4B,CAAC,MAAM,EAAE,MAAM;;;;;;;IAIlD,MAAM,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM;;;;;;;CAGlD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _a, _FilenameFormatHelper_getFilename;
|
|
7
|
+
import sanitizeFilename from 'sanitize-filename';
|
|
8
|
+
import Formatter from './Formatter.js';
|
|
9
|
+
import URLHelper from './URLHelper.js';
|
|
10
|
+
export const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA = [
|
|
11
|
+
{ name: 'creator.vanity', atLeastOneOf: true },
|
|
12
|
+
{ name: 'creator.name', atLeastOneOf: true },
|
|
13
|
+
{ name: 'creator.id', atLeastOneOf: true },
|
|
14
|
+
{ name: 'campaign.name', atLeastOneOf: true },
|
|
15
|
+
{ name: 'campaign.id', atLeastOneOf: true }
|
|
16
|
+
];
|
|
17
|
+
export const CONTENT_DIR_NAME_VALIDATION_SCHEMA = [
|
|
18
|
+
{ name: 'content.id', atLeastOneOf: true },
|
|
19
|
+
{ name: 'content.type', atLeastOneOf: false },
|
|
20
|
+
{ name: 'content.slug', atLeastOneOf: true },
|
|
21
|
+
{ name: 'content.name', atLeastOneOf: false }
|
|
22
|
+
];
|
|
23
|
+
export const MEDIA_FILENAME_VALIDATION_SCHEMA = [
|
|
24
|
+
{ name: 'media.id', atLeastOneOf: true },
|
|
25
|
+
{ name: 'media.type', atLeastOneOf: false },
|
|
26
|
+
{ name: 'media.filename', atLeastOneOf: true },
|
|
27
|
+
{ name: 'media.variant', atLeastOneOf: false }
|
|
28
|
+
];
|
|
29
|
+
const CAMPAIGN_DIR_NAME_FALLBACK_FORMAT = 'campaign-{campaign.id}';
|
|
30
|
+
const CONTENT_DIR_NAME_FALLBACK_FORMAT = '{content.type}-{content.id}';
|
|
31
|
+
const MEDIA_FILENAME_FALLBACK_FORMAT = '{media.type}-{media.id}';
|
|
32
|
+
export default class FilenameFormatHelper {
|
|
33
|
+
static getCampaignDirName(campaign, format) {
|
|
34
|
+
const dict = {
|
|
35
|
+
'creator.vanity': campaign.creator?.vanity,
|
|
36
|
+
'creator.name': campaign.creator?.fullName,
|
|
37
|
+
'creator.id': campaign.creator?.id,
|
|
38
|
+
'campaign.name': campaign.name,
|
|
39
|
+
'campaign.id': campaign.id
|
|
40
|
+
};
|
|
41
|
+
return __classPrivateFieldGet(this, _a, "m", _FilenameFormatHelper_getFilename).call(this, format, dict, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA, CAMPAIGN_DIR_NAME_FALLBACK_FORMAT);
|
|
42
|
+
}
|
|
43
|
+
static getContentDirName(content, format) {
|
|
44
|
+
const dict = {
|
|
45
|
+
'content.id': content.id,
|
|
46
|
+
'content.type': content.type,
|
|
47
|
+
'content.slug': null,
|
|
48
|
+
'content.name': null
|
|
49
|
+
};
|
|
50
|
+
if (content.type === 'post') {
|
|
51
|
+
const urlAnalysis = content.url ? URLHelper.analyzeURL(content.url) : null;
|
|
52
|
+
dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'post' ? urlAnalysis.slug : null;
|
|
53
|
+
dict['content.name'] = content.title;
|
|
54
|
+
}
|
|
55
|
+
else if (content.type === 'product') {
|
|
56
|
+
const urlAnalysis = URLHelper.analyzeURL(content.url);
|
|
57
|
+
dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'product' ? urlAnalysis.slug : null;
|
|
58
|
+
dict['content.name'] = content.name;
|
|
59
|
+
}
|
|
60
|
+
return __classPrivateFieldGet(this, _a, "m", _FilenameFormatHelper_getFilename).call(this, format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);
|
|
61
|
+
}
|
|
62
|
+
static getMediaFilename(media, format) {
|
|
63
|
+
const dict = {
|
|
64
|
+
'media.id': media.id,
|
|
65
|
+
'media.type': media.type,
|
|
66
|
+
'media.filename': media.filename,
|
|
67
|
+
'media.variant': media.variant
|
|
68
|
+
};
|
|
69
|
+
return __classPrivateFieldGet(this, _a, "m", _FilenameFormatHelper_getFilename).call(this, format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT);
|
|
70
|
+
}
|
|
71
|
+
static getAttachmentFilename(att, format) {
|
|
72
|
+
const dict = {
|
|
73
|
+
'media.id': att.id,
|
|
74
|
+
'media.type': att.type,
|
|
75
|
+
'media.filename': att.name,
|
|
76
|
+
'media.variant': null
|
|
77
|
+
};
|
|
78
|
+
return __classPrivateFieldGet(this, _a, "m", _FilenameFormatHelper_getFilename).call(this, format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT);
|
|
79
|
+
}
|
|
80
|
+
static validateCampaignDirNameFormat(format) {
|
|
81
|
+
return Formatter.validate(format, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA);
|
|
82
|
+
}
|
|
83
|
+
static validateContentDirNameFormat(format) {
|
|
84
|
+
return Formatter.validate(format, CONTENT_DIR_NAME_VALIDATION_SCHEMA);
|
|
85
|
+
}
|
|
86
|
+
static validateMediaFilenameFormat(format) {
|
|
87
|
+
return Formatter.validate(format, MEDIA_FILENAME_VALIDATION_SCHEMA);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
_a = FilenameFormatHelper, _FilenameFormatHelper_getFilename = function _FilenameFormatHelper_getFilename(format, dict, rules, fallbackFormat) {
|
|
91
|
+
const { validateOK, result } = Formatter.format(format, dict, rules);
|
|
92
|
+
if (validateOK === false) {
|
|
93
|
+
const fallback = Formatter.format(fallbackFormat, dict).result;
|
|
94
|
+
return sanitizeFilename(fallback);
|
|
95
|
+
}
|
|
96
|
+
return sanitizeFilename(result);
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=FilenameFormatHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilenameFormatHelper.js","sourceRoot":"","sources":["../../src/utils/FilenameFormatHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import sanitizeFilename from 'sanitize-filename';\nimport { Campaign } from '../entities/Campaign.js';\nimport { MediaLike } from '../entities/MediaItem.js';\nimport { Product } from '../entities/Product.js';\nimport Formatter, { FormatFieldName, FormatFieldRules, FormatFieldValues } from './Formatter.js';\nimport URLHelper from './URLHelper.js';\nimport { Attachment } from '../entities/Attachment.js';\nimport { Post } from '../entities/Post.js';\n\ntype CampaignDirNameFormatFieldName =\n 'creator.vanity' |\n 'creator.name' |\n 'creator.id' |\n 'campaign.name' |\n 'campaign.id';\n\nexport const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<CampaignDirNameFormatFieldName> = [\n { name: 'creator.vanity', atLeastOneOf: true },\n { name: 'creator.name', atLeastOneOf: true },\n { name: 'creator.id', atLeastOneOf: true },\n { name: 'campaign.name', atLeastOneOf: true },\n { name: 'campaign.id', atLeastOneOf: true }\n];\n\ntype ContentDirNameFormatFieldName =\n 'content.id' |\n 'content.type' |\n 'content.slug' |\n 'content.name';\n\nexport const CONTENT_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<ContentDirNameFormatFieldName> = [\n { name: 'content.id', atLeastOneOf: true },\n { name: 'content.type', atLeastOneOf: false },\n { name: 'content.slug', atLeastOneOf: true },\n { name: 'content.name', atLeastOneOf: false }\n];\n\ntype MediaFilenameFormatFieldName =\n 'media.id' |\n 'media.type' |\n 'media.filename' |\n 'media.variant';\n\nexport const MEDIA_FILENAME_VALIDATION_SCHEMA: FormatFieldRules<MediaFilenameFormatFieldName> = [\n { name: 'media.id', atLeastOneOf: true },\n { name: 'media.type', atLeastOneOf: false },\n { name: 'media.filename', atLeastOneOf: true },\n { name: 'media.variant', atLeastOneOf: false }\n];\n\nconst CAMPAIGN_DIR_NAME_FALLBACK_FORMAT = 'campaign-{campaign.id}';\nconst CONTENT_DIR_NAME_FALLBACK_FORMAT = '{content.type}-{content.id}';\nconst MEDIA_FILENAME_FALLBACK_FORMAT = '{media.type}-{media.id}';\n\nexport default class FilenameFormatHelper {\n\n static getCampaignDirName(campaign: Campaign, format: string): string {\n const dict: FormatFieldValues<CampaignDirNameFormatFieldName> = {\n 'creator.vanity': campaign.creator?.vanity,\n 'creator.name': campaign.creator?.fullName,\n 'creator.id': campaign.creator?.id,\n 'campaign.name': campaign.name,\n 'campaign.id': campaign.id\n };\n\n return this.#getFilename(format, dict, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA, CAMPAIGN_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getContentDirName(content: Product | Post, format: string): string {\n const dict: FormatFieldValues<ContentDirNameFormatFieldName> = {\n 'content.id': content.id,\n 'content.type': content.type,\n 'content.slug': null,\n 'content.name': null\n };\n if (content.type === 'post') {\n const urlAnalysis = content.url ? URLHelper.analyzeURL(content.url) : null;\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'post' ? urlAnalysis.slug : null;\n dict['content.name'] = content.title;\n }\n else if (content.type === 'product') {\n const urlAnalysis = URLHelper.analyzeURL(content.url);\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'product' ? urlAnalysis.slug : null;\n dict['content.name'] = content.name;\n }\n\n return this.#getFilename(format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getMediaFilename(media: MediaLike & { variant: string | null }, format: string): string {\n const dict: FormatFieldValues<MediaFilenameFormatFieldName> = {\n 'media.id': media.id,\n 'media.type': media.type,\n 'media.filename': media.filename,\n 'media.variant': media.variant\n };\n\n return this.#getFilename(format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT);\n }\n\n static getAttachmentFilename(att: Attachment, format: string): string {\n const dict: FormatFieldValues<MediaFilenameFormatFieldName> = {\n 'media.id': att.id,\n 'media.type': att.type,\n 'media.filename': att.name,\n 'media.variant': null\n };\n\n return this.#getFilename(format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT);\n }\n\n static #getFilename<T extends FormatFieldName>(format: string, dict: FormatFieldValues<T>, rules: FormatFieldRules<T>, fallbackFormat: string) {\n const { validateOK, result } = Formatter.format(format, dict, rules);\n\n if (validateOK === false) {\n const fallback = Formatter.format(fallbackFormat, dict).result;\n return sanitizeFilename(fallback);\n }\n\n return sanitizeFilename(result);\n }\n\n static validateCampaignDirNameFormat(format: string) {\n return Formatter.validate(format, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateContentDirNameFormat(format: string) {\n return Formatter.validate(format, CONTENT_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateMediaFilenameFormat(format: string) {\n return Formatter.validate(format, MEDIA_FILENAME_VALIDATION_SCHEMA);\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Response } from 'node-fetch';
|
|
2
|
+
/**
|
|
3
|
+
* Used by `Fetcher.download()` to resolve the destination filename
|
|
4
|
+
* of the downloaded item. The resolver implementation depends on the
|
|
5
|
+
* type of target being downloaded. `resolve()` is called with the
|
|
6
|
+
* `Response` object fetched by `Fetcher`, since filename resolution could
|
|
7
|
+
* use data provided in the response headers.
|
|
8
|
+
*/
|
|
9
|
+
export default abstract class FilenameResolver<T> {
|
|
10
|
+
protected target: T;
|
|
11
|
+
protected srcURL: string;
|
|
12
|
+
constructor(target: T, srcURL: string);
|
|
13
|
+
abstract resolve(response: Response): string;
|
|
14
|
+
protected getFilenamePartsFromResponse(response: Response): {
|
|
15
|
+
name: string;
|
|
16
|
+
ext: string;
|
|
17
|
+
};
|
|
18
|
+
protected getExtensionByContentType(type: string): string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=FllenameResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FllenameResolver.d.ts","sourceRoot":"","sources":["../../src/utils/FllenameResolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,gBAAgB,CAAC,CAAC;IAE9C,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACpB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEb,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM;IAKrC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;IAE5C,SAAS,CAAC,4BAA4B,CAAC,QAAQ,EAAE,QAAQ;;;;IA6BzD,SAAS,CAAC,yBAAyB,CAAC,IAAI,EAAE,MAAM;CAWjD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import contentDisposition from 'content-disposition';
|
|
2
|
+
import mimeTypes from 'mime-types';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import URLHelper from './URLHelper.js';
|
|
5
|
+
/**
|
|
6
|
+
* Used by `Fetcher.download()` to resolve the destination filename
|
|
7
|
+
* of the downloaded item. The resolver implementation depends on the
|
|
8
|
+
* type of target being downloaded. `resolve()` is called with the
|
|
9
|
+
* `Response` object fetched by `Fetcher`, since filename resolution could
|
|
10
|
+
* use data provided in the response headers.
|
|
11
|
+
*/
|
|
12
|
+
export default class FilenameResolver {
|
|
13
|
+
constructor(target, srcURL) {
|
|
14
|
+
this.target = target;
|
|
15
|
+
this.srcURL = srcURL;
|
|
16
|
+
}
|
|
17
|
+
getFilenamePartsFromResponse(response) {
|
|
18
|
+
const parts = {
|
|
19
|
+
name: '',
|
|
20
|
+
ext: ''
|
|
21
|
+
};
|
|
22
|
+
const disposition = response.headers.get('content-disposition');
|
|
23
|
+
if (disposition) {
|
|
24
|
+
const parsedDisposition = contentDisposition.parse(disposition);
|
|
25
|
+
const filename = parsedDisposition.parameters['filename'] || null;
|
|
26
|
+
if (filename) {
|
|
27
|
+
const parsed = path.parse(filename);
|
|
28
|
+
parts.name = parsed.name;
|
|
29
|
+
parts.ext = parsed.ext;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Filename obtained from content-disposition could have wrong extension.
|
|
33
|
+
// Always use extension derived from headers content-type if available.
|
|
34
|
+
const contentType = response.headers.get('content-type') || null;
|
|
35
|
+
if (contentType) {
|
|
36
|
+
const extByContentType = this.getExtensionByContentType(contentType);
|
|
37
|
+
if (extByContentType) {
|
|
38
|
+
parts.ext = extByContentType;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return parts;
|
|
42
|
+
}
|
|
43
|
+
getExtensionByContentType(type) {
|
|
44
|
+
// Mime-types does not recognize 'application/x-mpegURL'
|
|
45
|
+
if (type === 'application/x-mpegURL' && URLHelper.getExtensionFromURL(this.srcURL) === '.m3u8') {
|
|
46
|
+
return '.m3u8';
|
|
47
|
+
}
|
|
48
|
+
let ext = mimeTypes.extension(type);
|
|
49
|
+
if (ext === 'jpeg') {
|
|
50
|
+
ext = 'jpg';
|
|
51
|
+
}
|
|
52
|
+
return ext ? `.${ext}` : '';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=FllenameResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FllenameResolver.js","sourceRoot":"","sources":["../../src/utils/FllenameResolver.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,qBAAqB,CAAC;AACrD,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAEvC;;;;;;GAMG;AAEH,MAAM,CAAC,OAAO,OAAgB,gBAAgB;IAK5C,YAAY,MAAS,EAAE,MAAc;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAIS,4BAA4B,CAAC,QAAkB;QACvD,MAAM,KAAK,GAAG;YACZ,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,EAAE;SACR,CAAC;QAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAChE,IAAI,WAAW,EAAE;YACf,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;YAClE,IAAI,QAAQ,EAAE;gBACZ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;gBACzB,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;aACxB;SACF;QACD,yEAAyE;QACzE,uEAAuE;QACvE,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC;QACjE,IAAI,WAAW,EAAE;YACf,MAAM,gBAAgB,GAAG,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC;YACrE,IAAI,gBAAgB,EAAE;gBACpB,KAAK,CAAC,GAAG,GAAG,gBAAgB,CAAC;aAC9B;SACF;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAES,yBAAyB,CAAC,IAAY;QAC9C,wDAAwD;QACxD,IAAI,IAAI,KAAK,uBAAuB,IAAI,SAAS,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,OAAO,EAAE;YAC9F,OAAO,OAAO,CAAC;SAChB;QACD,IAAI,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,GAAG,KAAK,MAAM,EAAE;YAClB,GAAG,GAAG,KAAK,CAAC;SACb;QACD,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,CAAC;CACF","sourcesContent":["import contentDisposition from 'content-disposition';\nimport mimeTypes from 'mime-types';\nimport { Response } from 'node-fetch';\nimport path from 'path';\nimport URLHelper from './URLHelper.js';\n\n/**\n * Used by `Fetcher.download()` to resolve the destination filename\n * of the downloaded item. The resolver implementation depends on the\n * type of target being downloaded. `resolve()` is called with the\n * `Response` object fetched by `Fetcher`, since filename resolution could\n * use data provided in the response headers.\n */\n\nexport default abstract class FilenameResolver<T> {\n\n protected target: T;\n protected srcURL: string;\n\n constructor(target: T, srcURL: string) {\n this.target = target;\n this.srcURL = srcURL;\n }\n\n abstract resolve(response: Response): string;\n\n protected getFilenamePartsFromResponse(response: Response) {\n const parts = {\n name: '',\n ext: ''\n };\n\n const disposition = response.headers.get('content-disposition');\n if (disposition) {\n const parsedDisposition = contentDisposition.parse(disposition);\n const filename = parsedDisposition.parameters['filename'] || null;\n if (filename) {\n const parsed = path.parse(filename);\n parts.name = parsed.name;\n parts.ext = parsed.ext;\n }\n }\n // Filename obtained from content-disposition could have wrong extension.\n // Always use extension derived from headers content-type if available.\n const contentType = response.headers.get('content-type') || null;\n if (contentType) {\n const extByContentType = this.getExtensionByContentType(contentType);\n if (extByContentType) {\n parts.ext = extByContentType;\n }\n }\n\n return parts;\n }\n\n protected getExtensionByContentType(type: string) {\n // Mime-types does not recognize 'application/x-mpegURL'\n if (type === 'application/x-mpegURL' && URLHelper.getExtensionFromURL(this.srcURL) === '.m3u8') {\n return '.m3u8';\n }\n let ext = mimeTypes.extension(type);\n if (ext === 'jpeg') {\n ext = 'jpg';\n }\n return ext ? `.${ext}` : '';\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type FormatFieldName = string;
|
|
2
|
+
export type FormatFieldRules<T extends FormatFieldName> = {
|
|
3
|
+
name: T;
|
|
4
|
+
atLeastOneOf: boolean;
|
|
5
|
+
}[];
|
|
6
|
+
export type FormatFieldValues<T extends FormatFieldName> = Record<T, any>;
|
|
7
|
+
export default class Formatter {
|
|
8
|
+
#private;
|
|
9
|
+
static format<T extends FormatFieldName>(format: string, dict: FormatFieldValues<T>, rules?: FormatFieldRules<T>): {
|
|
10
|
+
result: string;
|
|
11
|
+
validateOK: boolean | null;
|
|
12
|
+
};
|
|
13
|
+
static validate<T extends FormatFieldName>(format: string, schema: FormatFieldRules<T>): {
|
|
14
|
+
validateOK: boolean;
|
|
15
|
+
regex?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
validateOK: boolean | null;
|
|
18
|
+
regex: RegExp;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=Formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Formatter.d.ts","sourceRoot":"","sources":["../../src/utils/Formatter.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,eAAe,IAAI;IACxD,IAAI,EAAE,CAAC,CAAC;IACR,YAAY,EAAE,OAAO,CAAC;CACvB,EAAE,CAAC;AAEJ,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,eAAe,IAAI,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAE1E,MAAM,CAAC,OAAO,OAAO,SAAS;;IAE5B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;;;;IA2FhH,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;;;;;;;CAwBvF"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var _a, _Formatter_getFieldRegex;
|
|
7
|
+
import escapeStringRegexp from 'escape-string-regexp';
|
|
8
|
+
export default class Formatter {
|
|
9
|
+
static format(format, dict, rules) {
|
|
10
|
+
let result = '';
|
|
11
|
+
const fieldRegex = __classPrivateFieldGet(this, _a, "m", _Formatter_getFieldRegex).call(this, Object.keys(dict));
|
|
12
|
+
const emptyValuePlaceHolder = '//';
|
|
13
|
+
const emptyValAdjCondSepRegex = /\[[^[]*?]\?\s*?\/\/\s*?\[.*?\]\?|\[[^[]*?]\?\s*?\/\/|\/\/\s*?\[.*?]\?/g;
|
|
14
|
+
const condSepRegex = /\[(.*?)]\?/g;
|
|
15
|
+
const fields = Object.keys(dict);
|
|
16
|
+
const consumedFields = [];
|
|
17
|
+
const __findPositionOfFirstField = (s) => {
|
|
18
|
+
const match = fieldRegex.exec(s);
|
|
19
|
+
if (match) {
|
|
20
|
+
const foundField = s.substring(match.index + 1, match.index + match[0].length - 1);
|
|
21
|
+
const placeholder = s.substring(match.index, match.index + match[0].length);
|
|
22
|
+
if (fields.includes(foundField)) {
|
|
23
|
+
return {
|
|
24
|
+
field: foundField,
|
|
25
|
+
placeholder,
|
|
26
|
+
placeholderPosition: match.index
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
field: null,
|
|
32
|
+
placeholder: null,
|
|
33
|
+
placeholderPosition: -1
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
let { field, placeholder, placeholderPosition } = __findPositionOfFirstField(format);
|
|
37
|
+
while (field && placeholder && placeholderPosition >= 0) {
|
|
38
|
+
result += format.substring(0, placeholderPosition);
|
|
39
|
+
const fieldValue = dict[field];
|
|
40
|
+
if (fieldValue) {
|
|
41
|
+
result += fieldValue;
|
|
42
|
+
if (!consumedFields.includes(field)) {
|
|
43
|
+
consumedFields.push(field);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
result += emptyValuePlaceHolder;
|
|
48
|
+
}
|
|
49
|
+
format = format.substring(placeholderPosition + placeholder.length);
|
|
50
|
+
if (format.length === 0) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
({ field, placeholder, placeholderPosition } = __findPositionOfFirstField(format));
|
|
54
|
+
}
|
|
55
|
+
result += format;
|
|
56
|
+
// Handle conditional separators
|
|
57
|
+
// - Strip empty value placeholders + adjacent separators
|
|
58
|
+
result = result.replaceAll(emptyValAdjCondSepRegex, '');
|
|
59
|
+
// - Strip remaining empty value placeholders
|
|
60
|
+
result = result.replaceAll(emptyValuePlaceHolder, '');
|
|
61
|
+
// - Remove []? around conditional separators
|
|
62
|
+
result = result.replace(condSepRegex, '$1');
|
|
63
|
+
result = result.trim();
|
|
64
|
+
// Validate
|
|
65
|
+
let validateOK = null;
|
|
66
|
+
if (rules) {
|
|
67
|
+
const atLeastOneOfFields = rules.reduce((result, f) => {
|
|
68
|
+
if (f.atLeastOneOf) {
|
|
69
|
+
result.push(f.name);
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
72
|
+
}, []);
|
|
73
|
+
validateOK = false;
|
|
74
|
+
if (result) {
|
|
75
|
+
for (const field of consumedFields) {
|
|
76
|
+
if (atLeastOneOfFields.includes(field)) {
|
|
77
|
+
validateOK = true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
result,
|
|
85
|
+
validateOK
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
static validate(format, schema) {
|
|
89
|
+
const fieldNames = schema.reduce((result, s) => {
|
|
90
|
+
if (s.atLeastOneOf) {
|
|
91
|
+
result.push(s.name);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}, []);
|
|
95
|
+
if (fieldNames.length === 0) {
|
|
96
|
+
return {
|
|
97
|
+
validateOK: true
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const fieldRegex = __classPrivateFieldGet(this, _a, "m", _Formatter_getFieldRegex).call(this, fieldNames, 'g');
|
|
101
|
+
const match = fieldRegex.exec(format);
|
|
102
|
+
return {
|
|
103
|
+
validateOK: match && match.length > 0,
|
|
104
|
+
regex: fieldRegex
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
_a = Formatter, _Formatter_getFieldRegex = function _Formatter_getFieldRegex(fieldNames, flags) {
|
|
109
|
+
const pattern = fieldNames.map((k) => `{${escapeStringRegexp(k)}}`).join('|');
|
|
110
|
+
return new RegExp(pattern, flags);
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=Formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Formatter.js","sourceRoot":"","sources":["../../src/utils/Formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import escapeStringRegexp from 'escape-string-regexp';\n\nexport type FormatFieldName = string;\n\nexport type FormatFieldRules<T extends FormatFieldName> = {\n name: T;\n atLeastOneOf: boolean;\n}[];\n\nexport type FormatFieldValues<T extends FormatFieldName> = Record<T, any>;\n\nexport default class Formatter {\n\n static format<T extends FormatFieldName>(format: string, dict: FormatFieldValues<T>, rules?: FormatFieldRules<T>) {\n\n let result = '';\n\n const fieldRegex = this.#getFieldRegex(Object.keys(dict));\n const emptyValuePlaceHolder = '//';\n const emptyValAdjCondSepRegex = /\\[[^[]*?]\\?\\s*?\\/\\/\\s*?\\[.*?\\]\\?|\\[[^[]*?]\\?\\s*?\\/\\/|\\/\\/\\s*?\\[.*?]\\?/g;\n const condSepRegex = /\\[(.*?)]\\?/g;\n\n const fields = Object.keys(dict);\n const consumedFields: string[] = [];\n\n const __findPositionOfFirstField = (s: string) => {\n const match = fieldRegex.exec(s);\n if (match) {\n const foundField = s.substring(match.index + 1, match.index + match[0].length - 1);\n const placeholder = s.substring(match.index, match.index + match[0].length);\n if (fields.includes(foundField)) {\n return {\n field: foundField as T,\n placeholder,\n placeholderPosition: match.index\n };\n }\n }\n return {\n field: null,\n placeholder: null,\n placeholderPosition: -1\n };\n };\n\n let { field, placeholder, placeholderPosition } = __findPositionOfFirstField(format);\n while (field && placeholder && placeholderPosition >= 0) {\n result += format.substring(0, placeholderPosition);\n const fieldValue = dict[field];\n if (fieldValue) {\n result += fieldValue;\n if (!consumedFields.includes(field)) {\n consumedFields.push(field);\n }\n }\n else {\n result += emptyValuePlaceHolder;\n }\n format = format.substring(placeholderPosition + placeholder.length);\n\n if (format.length === 0) {\n break;\n }\n ({ field, placeholder, placeholderPosition } = __findPositionOfFirstField(format));\n }\n result += format;\n\n // Handle conditional separators\n // - Strip empty value placeholders + adjacent separators\n result = result.replaceAll(emptyValAdjCondSepRegex, '');\n // - Strip remaining empty value placeholders\n result = result.replaceAll(emptyValuePlaceHolder, '');\n // - Remove []? around conditional separators\n result = result.replace(condSepRegex, '$1');\n\n result = result.trim();\n\n // Validate\n let validateOK: boolean | null = null;\n if (rules) {\n const atLeastOneOfFields = rules.reduce<string[]>((result, f) => {\n if (f.atLeastOneOf) {\n result.push(f.name);\n }\n return result;\n }, []);\n\n validateOK = false;\n if (result) {\n for (const field of consumedFields) {\n if (atLeastOneOfFields.includes(field)) {\n validateOK = true;\n break;\n }\n }\n }\n }\n\n return {\n result,\n validateOK\n };\n }\n\n static validate<T extends FormatFieldName>(format: string, schema: FormatFieldRules<T>) {\n const fieldNames = schema.reduce<string[]>((result, s) => {\n if (s.atLeastOneOf) {\n result.push(s.name);\n }\n return result;\n }, []);\n if (fieldNames.length === 0) {\n return {\n validateOK: true\n };\n }\n const fieldRegex = this.#getFieldRegex(fieldNames, 'g');\n const match = fieldRegex.exec(format);\n return {\n validateOK: match && match.length > 0,\n regex: fieldRegex\n };\n }\n\n static #getFieldRegex(fieldNames: string[], flags?: string) {\n const pattern = fieldNames.map((k) => `{${escapeStringRegexp(k)}}`).join('|');\n return new RegExp(pattern, flags);\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MediaLike } from '../entities/MediaItem.js';
|
|
2
|
+
import { Response } from 'node-fetch';
|
|
3
|
+
import FilenameResolver from './FllenameResolver.js';
|
|
4
|
+
export default class MediaFilenameResolver<T extends MediaLike> extends FilenameResolver<T> {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(target: T, srcURL: string, format: string, variant: string | null, ensureVariant: boolean);
|
|
7
|
+
resolve(response: Response): string;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=MediaFilenameResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaFilenameResolver.d.ts","sourceRoot":"","sources":["../../src/utils/MediaFilenameResolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AAIrD,MAAM,CAAC,OAAO,OAAO,qBAAqB,CAAC,CAAC,SAAS,SAAS,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;;gBAK7E,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,aAAa,EAAE,OAAO;IAUrG,OAAO,CAAC,QAAQ,EAAE,QAAQ;CAmE3B"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _MediaFilenameResolver_format, _MediaFilenameResolver_variant;
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import FilenameResolver from './FllenameResolver.js';
|
|
15
|
+
import URLHelper from './URLHelper.js';
|
|
16
|
+
import FilenameFormatHelper from './FilenameFormatHelper.js';
|
|
17
|
+
export default class MediaFilenameResolver extends FilenameResolver {
|
|
18
|
+
constructor(target, srcURL, format, variant, ensureVariant) {
|
|
19
|
+
super(target, srcURL);
|
|
20
|
+
_MediaFilenameResolver_format.set(this, void 0);
|
|
21
|
+
_MediaFilenameResolver_variant.set(this, void 0);
|
|
22
|
+
__classPrivateFieldSet(this, _MediaFilenameResolver_format, format, "f");
|
|
23
|
+
__classPrivateFieldSet(this, _MediaFilenameResolver_variant, variant, "f");
|
|
24
|
+
if (ensureVariant && !__classPrivateFieldGet(this, _MediaFilenameResolver_format, "f").includes('{media.variant}')) {
|
|
25
|
+
__classPrivateFieldSet(this, _MediaFilenameResolver_format, `${format}[-]?{media.variant}`, "f");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
resolve(response) {
|
|
29
|
+
const mi = this.target;
|
|
30
|
+
const miFilenameParts = mi.filename ? path.parse(mi.filename) : null;
|
|
31
|
+
const resFilenameParts = this.getFilenamePartsFromResponse(response);
|
|
32
|
+
const filenameParts = {
|
|
33
|
+
name: '',
|
|
34
|
+
ext: ''
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Obtain `name` part from (in order of priority):
|
|
38
|
+
* 1. Media filename
|
|
39
|
+
* 2. Filename from response headers
|
|
40
|
+
* 3. If none of the above is available, fallback to using the media ID
|
|
41
|
+
*/
|
|
42
|
+
if (miFilenameParts?.name) {
|
|
43
|
+
filenameParts.name = miFilenameParts.name;
|
|
44
|
+
}
|
|
45
|
+
else if (resFilenameParts.name) {
|
|
46
|
+
filenameParts.name = resFilenameParts.name;
|
|
47
|
+
}
|
|
48
|
+
else if (!__classPrivateFieldGet(this, _MediaFilenameResolver_format, "f").includes('{media.id}')) {
|
|
49
|
+
filenameParts.name = mi.id;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Obtain `extension` from (in order of priority):
|
|
53
|
+
* 1. Response headers
|
|
54
|
+
* 2. Media filename
|
|
55
|
+
* 3. Media mimetype
|
|
56
|
+
* 4. Src URL
|
|
57
|
+
*/
|
|
58
|
+
if (resFilenameParts.ext) {
|
|
59
|
+
// Use media item filename if the same (preserves case)
|
|
60
|
+
if (miFilenameParts?.ext?.toLowerCase() === resFilenameParts.ext.toLowerCase() &&
|
|
61
|
+
filenameParts.name === miFilenameParts.name && __classPrivateFieldGet(this, _MediaFilenameResolver_format, "f").includes('{media.filename}')) {
|
|
62
|
+
filenameParts.ext = miFilenameParts.ext;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
filenameParts.ext = resFilenameParts.ext;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (miFilenameParts?.ext) {
|
|
69
|
+
filenameParts.ext = miFilenameParts.ext;
|
|
70
|
+
}
|
|
71
|
+
else if (mi.mimeType) {
|
|
72
|
+
filenameParts.ext = this.getExtensionByContentType(mi.mimeType);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
filenameParts.ext = URLHelper.getExtensionFromURL(this.srcURL);
|
|
76
|
+
}
|
|
77
|
+
const tmpMI = {
|
|
78
|
+
...mi,
|
|
79
|
+
filename: filenameParts.name,
|
|
80
|
+
variant: __classPrivateFieldGet(this, _MediaFilenameResolver_variant, "f")
|
|
81
|
+
};
|
|
82
|
+
let resolvedFilename = FilenameFormatHelper.getMediaFilename(tmpMI, __classPrivateFieldGet(this, _MediaFilenameResolver_format, "f"));
|
|
83
|
+
if (filenameParts.ext) {
|
|
84
|
+
resolvedFilename += filenameParts.ext;
|
|
85
|
+
}
|
|
86
|
+
return resolvedFilename;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
_MediaFilenameResolver_format = new WeakMap(), _MediaFilenameResolver_variant = new WeakMap();
|
|
90
|
+
//# sourceMappingURL=MediaFilenameResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaFilenameResolver.js","sourceRoot":"","sources":["../../src/utils/MediaFilenameResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { MediaLike } from '../entities/MediaItem.js';\nimport { Response } from 'node-fetch';\nimport FilenameResolver from './FllenameResolver.js';\nimport URLHelper from './URLHelper.js';\nimport FilenameFormatHelper from './FilenameFormatHelper.js';\n\nexport default class MediaFilenameResolver<T extends MediaLike> extends FilenameResolver<T> {\n\n #format: string;\n #variant: string | null;\n\n constructor(target: T, srcURL: string, format: string, variant: string | null, ensureVariant: boolean) {\n super(target, srcURL);\n this.#format = format;\n this.#variant = variant;\n\n if (ensureVariant && !this.#format.includes('{media.variant}')) {\n this.#format = `${format}[-]?{media.variant}`;\n }\n }\n\n resolve(response: Response) {\n const mi = this.target;\n const miFilenameParts = mi.filename ? path.parse(mi.filename) : null;\n const resFilenameParts = this.getFilenamePartsFromResponse(response);\n\n const filenameParts = {\n name: '',\n ext: ''\n };\n\n /**\n * Obtain `name` part from (in order of priority):\n * 1. Media filename\n * 2. Filename from response headers\n * 3. If none of the above is available, fallback to using the media ID\n */\n if (miFilenameParts?.name) {\n filenameParts.name = miFilenameParts.name;\n }\n else if (resFilenameParts.name) {\n filenameParts.name = resFilenameParts.name;\n }\n else if (!this.#format.includes('{media.id}')) {\n filenameParts.name = mi.id;\n }\n\n /**\n * Obtain `extension` from (in order of priority):\n * 1. Response headers\n * 2. Media filename\n * 3. Media mimetype\n * 4. Src URL\n */\n if (resFilenameParts.ext) {\n // Use media item filename if the same (preserves case)\n if (miFilenameParts?.ext?.toLowerCase() === resFilenameParts.ext.toLowerCase() &&\n filenameParts.name === miFilenameParts.name && this.#format.includes('{media.filename}')) {\n\n filenameParts.ext = miFilenameParts.ext;\n }\n else {\n filenameParts.ext = resFilenameParts.ext;\n }\n }\n else if (miFilenameParts?.ext) {\n filenameParts.ext = miFilenameParts.ext;\n }\n else if (mi.mimeType) {\n filenameParts.ext = this.getExtensionByContentType(mi.mimeType);\n }\n else {\n filenameParts.ext = URLHelper.getExtensionFromURL(this.srcURL);\n }\n\n const tmpMI = {\n ...mi,\n filename: filenameParts.name,\n variant: this.#variant\n };\n\n let resolvedFilename = FilenameFormatHelper.getMediaFilename(tmpMI, this.#format);\n if (filenameParts.ext) {\n resolvedFilename += filenameParts.ext;\n }\n\n return resolvedFilename;\n }\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DeepRequired<T> = {
|
|
2
|
+
[P in keyof T]-?: DeepRequired<T[P]>;
|
|
3
|
+
};
|
|
4
|
+
export type DeepPartial<T> = {
|
|
5
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
6
|
+
};
|
|
7
|
+
export type RecursivePropsTo<T, U> = T extends object ? {
|
|
8
|
+
[P in keyof T]: RecursivePropsTo<T[P], U>;
|
|
9
|
+
} : T extends undefined | null ? never : U;
|
|
10
|
+
export declare function pickDefined<T>(value1: T | undefined, value2: T): T;
|
|
11
|
+
export declare function pickDefined<T>(value1: T, value2: T | undefined): T;
|
|
12
|
+
export declare function pickDefined(value1: undefined, value2: undefined): undefined;
|
|
13
|
+
export declare function pickDefined<T>(value1?: T, value2?: T): T | undefined;
|
|
14
|
+
//# sourceMappingURL=Misc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Misc.d.ts","sourceRoot":"","sources":["../../src/utils/Misc.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;KAC3B,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACrC,CAAA;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACnC,CAAA;AAGD,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,IAC/B,CAAC,SAAS,MAAM,GAAG;KAAI,CAAC,IAAI,MAAM,CAAC,GAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CAAE,GAClE,CAAC,SAAS,SAAS,GAAG,IAAI,GAAG,KAAK,GAClC,CAAC,CAAA;AAGH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;AACpE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;AACpE,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;AAC7E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Misc.js","sourceRoot":"","sources":["../../src/utils/Misc.ts"],"names":[],"mappings":"AAoBA,MAAM,UAAU,WAAW,CAAI,MAAU,EAAE,MAAU;IACnD,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAChD,CAAC","sourcesContent":["// https://stackoverflow.com/questions/57835286/deep-recursive-requiredt-on-specific-properties\nexport type DeepRequired<T> = {\n [P in keyof T]-?: DeepRequired<T[P]>\n}\n\nexport type DeepPartial<T> = {\n [P in keyof T]?: DeepPartial<T[P]>\n}\n\n// Recursively sets properties of T to U\nexport type RecursivePropsTo<T, U> =\n T extends object ? { [ P in keyof T ]: RecursivePropsTo<T[P], U> } :\n T extends undefined | null ? never :\n U\n\n\nexport function pickDefined<T>(value1: T | undefined, value2: T): T;\nexport function pickDefined<T>(value1: T, value2: T | undefined): T;\nexport function pickDefined(value1: undefined, value2: undefined): undefined;\nexport function pickDefined<T>(value1?: T, value2?: T): T | undefined;\nexport function pickDefined<T>(value1?: T, value2?: T) {\n return value1 !== undefined ? value1 : value2;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectHelper.d.ts","sourceRoot":"","sources":["../../src/utils/ObjectHelper.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,YAAY;IAE/B,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,UAAQ;CAoB5D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export default class ObjectHelper {
|
|
2
|
+
static getProperty(obj, prop, required = false) {
|
|
3
|
+
const props = prop.split('.');
|
|
4
|
+
let v = obj;
|
|
5
|
+
while (props.length > 0) {
|
|
6
|
+
const p = props.shift();
|
|
7
|
+
if (v && typeof v === 'object') {
|
|
8
|
+
v = v[p];
|
|
9
|
+
if (v === undefined) {
|
|
10
|
+
if (required) {
|
|
11
|
+
throw new ObjectPropertyNotFoundError(prop);
|
|
12
|
+
}
|
|
13
|
+
return v;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else if (required) {
|
|
17
|
+
throw new ObjectPropertyNotFoundError(prop);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return v;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
class ObjectPropertyNotFoundError extends Error {
|
|
24
|
+
constructor(prop) {
|
|
25
|
+
super();
|
|
26
|
+
this.name = 'ObjectPropertyNotFoundError';
|
|
27
|
+
this.prop = prop;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=ObjectHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObjectHelper.js","sourceRoot":"","sources":["../../src/utils/ObjectHelper.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,YAAY;IAE/B,MAAM,CAAC,WAAW,CAAC,GAAQ,EAAE,IAAY,EAAE,QAAQ,GAAG,KAAK;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,GAAG,CAAC;QACZ,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;YACvB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAY,CAAC;YAClC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE;gBAC9B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACT,IAAI,CAAC,KAAK,SAAS,EAAE;oBACnB,IAAI,QAAQ,EAAE;wBACZ,MAAM,IAAI,2BAA2B,CAAC,IAAI,CAAC,CAAC;qBAC7C;oBACD,OAAO,CAAC,CAAC;iBACV;aACF;iBACI,IAAI,QAAQ,EAAE;gBACjB,MAAM,IAAI,2BAA2B,CAAC,IAAI,CAAC,CAAC;aAC7C;SACF;QACD,OAAO,CAAC,CAAC;IACX,CAAC;CACF;AAED,MAAM,2BAA4B,SAAQ,KAAK;IAI7C,YAAY,IAAY;QACtB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF","sourcesContent":["export default class ObjectHelper {\n\n static getProperty(obj: any, prop: string, required = false) {\n const props = prop.split('.');\n let v = obj;\n while (props.length > 0) {\n const p = props.shift() as string;\n if (v && typeof v === 'object') {\n v = v[p];\n if (v === undefined) {\n if (required) {\n throw new ObjectPropertyNotFoundError(prop);\n }\n return v;\n }\n }\n else if (required) {\n throw new ObjectPropertyNotFoundError(prop);\n }\n }\n return v;\n }\n}\n\nclass ObjectPropertyNotFoundError extends Error {\n\n prop: string;\n\n constructor(prop: string) {\n super();\n this.name = 'ObjectPropertyNotFoundError';\n this.prop = prop;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PackageInfo.d.ts","sourceRoot":"","sources":["../../src/utils/PackageInfo.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,wBAAgB,cAAc,gBA4B7B"}
|