@purpleproser/soundboard-downloader-cli 1.5.0 → 1.6.1
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/CHANGELOG.md +21 -0
- package/dist/api/api-config.js +31 -0
- package/dist/api/api-config.js.map +1 -0
- package/dist/api/my-instants.api.js +88 -28
- package/dist/api/my-instants.api.js.map +1 -1
- package/dist/api/my-instants.api.mock.js +136 -0
- package/dist/api/my-instants.api.mock.js.map +1 -0
- package/dist/api/validation-schemas.js +67 -0
- package/dist/api/validation-schemas.js.map +1 -0
- package/dist/common/types/query.type.js +3 -0
- package/dist/common/types/query.type.js.map +1 -0
- package/dist/main.js +286 -92
- package/dist/main.js.map +1 -1
- package/dist/service/my-instants.service.js +115 -25
- package/dist/service/my-instants.service.js.map +1 -1
- package/dist/utils/pagination-utils.js +82 -0
- package/dist/utils/pagination-utils.js.map +1 -0
- package/package.json +4 -3
- package/src/api/README.md +128 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
This changelog is automatically generated by [release-please](https://github.com/google-github-actions/release-please-action).
|
|
4
4
|
|
|
5
|
+
## [1.6.1](https://github.com/blacksagres/soundboard-downloader-cli/compare/v1.6.0...v1.6.1) (2026-03-07)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* run npm audit ([7dfe691](https://github.com/blacksagres/soundboard-downloader-cli/commit/7dfe69192dfe2aac1f407b3eb731fe15531334bb))
|
|
11
|
+
|
|
12
|
+
## [1.6.0](https://github.com/blacksagres/soundboard-downloader-cli/compare/v1.5.0...v1.6.0) (2026-03-01)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* data validation with valibot ([1357286](https://github.com/blacksagres/soundboard-downloader-cli/commit/1357286c9c22153fccc6571f1b7dd1f554bbb057))
|
|
18
|
+
* paginate search list to avoid blastinhg the myinstants page with requests ([439751c](https://github.com/blacksagres/soundboard-downloader-cli/commit/439751cb70d3586aae8d026db902932d41fc2a68))
|
|
19
|
+
* restore single selection for sounds to keep UI clean ([c21895d](https://github.com/blacksagres/soundboard-downloader-cli/commit/c21895dcf373d55b1b87659371c5550d21773355))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* use a mock api for integration tests ([9f410df](https://github.com/blacksagres/soundboard-downloader-cli/commit/9f410dfa796bafc11dc49177667388a84e638e41))
|
|
25
|
+
|
|
5
26
|
## [1.5.0](https://github.com/blacksagres/soundboard-downloader-cli/compare/v1.4.0...v1.5.0) (2026-02-26)
|
|
6
27
|
|
|
7
28
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API Configuration - allows switching between real and mock API
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isMockMode = exports.getApiMode = exports.setApiMode = void 0;
|
|
7
|
+
// Default to real API, but can be overridden for testing
|
|
8
|
+
let currentApiMode = 'real';
|
|
9
|
+
/**
|
|
10
|
+
* Set the API mode
|
|
11
|
+
* @param mode - 'real' for production, 'mock' for testing
|
|
12
|
+
*/
|
|
13
|
+
const setApiMode = (mode) => {
|
|
14
|
+
currentApiMode = mode;
|
|
15
|
+
};
|
|
16
|
+
exports.setApiMode = setApiMode;
|
|
17
|
+
/**
|
|
18
|
+
* Get the current API mode
|
|
19
|
+
*/
|
|
20
|
+
const getApiMode = () => {
|
|
21
|
+
return currentApiMode;
|
|
22
|
+
};
|
|
23
|
+
exports.getApiMode = getApiMode;
|
|
24
|
+
/**
|
|
25
|
+
* Check if we're using mock API
|
|
26
|
+
*/
|
|
27
|
+
const isMockMode = () => {
|
|
28
|
+
return currentApiMode === 'mock';
|
|
29
|
+
};
|
|
30
|
+
exports.isMockMode = isMockMode;
|
|
31
|
+
//# sourceMappingURL=api-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-config.js","sourceRoot":"","sources":["../../src/api/api-config.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAIH,yDAAyD;AACzD,IAAI,cAAc,GAAY,MAAM,CAAC;AAErC;;;GAGG;AACI,MAAM,UAAU,GAAG,CAAC,IAAa,EAAQ,EAAE;IAChD,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC,CAAC;AAFW,QAAA,UAAU,cAErB;AAEF;;GAEG;AACI,MAAM,UAAU,GAAG,GAAY,EAAE;IACtC,OAAO,cAAc,CAAC;AACxB,CAAC,CAAC;AAFW,QAAA,UAAU,cAErB;AAEF;;GAEG;AACI,MAAM,UAAU,GAAG,GAAY,EAAE;IACtC,OAAO,cAAc,KAAK,MAAM,CAAC;AACnC,CAAC,CAAC;AAFW,QAAA,UAAU,cAErB"}
|
|
@@ -1,46 +1,106 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Fetch the html from myinstants.com.
|
|
3
|
+
* Fetch the html from myinstants.com with server-side pagination support.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* 5. Download the sound (donwload folder from the user)
|
|
5
|
+
* This module provides functions to fetch sound nodes page by page,
|
|
6
|
+
* enabling efficient browsing of search results without loading everything at once.
|
|
7
|
+
*
|
|
8
|
+
* Can be switched to mock mode for testing via api-config.ts
|
|
10
9
|
*/
|
|
11
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getNodeDownloadPage = exports.
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
exports.getNodeDownloadPage = exports.getAllSoundNodes = exports.hasNextPage = exports.getSoundNodesPage = void 0;
|
|
12
|
+
const api_config_1 = require("./api-config");
|
|
13
|
+
const MockApi = require("./my-instants.api.mock");
|
|
14
|
+
/**
|
|
15
|
+
* Fetch a single page of sound nodes from myinstants.com
|
|
16
|
+
* @param searchString The search term
|
|
17
|
+
* @param page The page number to fetch (default: 1)
|
|
18
|
+
* @returns HTML content of the requested page
|
|
19
|
+
* @throws Error if the page cannot be fetched
|
|
20
|
+
*/
|
|
21
|
+
const getSoundNodesPage = async ({ searchString, page = 1 }) => {
|
|
22
|
+
// Use mock data if in mock mode
|
|
23
|
+
if ((0, api_config_1.isMockMode)()) {
|
|
24
|
+
return MockApi.getSoundNodesPage({ searchString, page });
|
|
25
|
+
}
|
|
16
26
|
const escapedSearchParam = encodeURIComponent(searchString);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
const url = `https://www.myinstants.com/en/search/?name=${escapedSearchParam}&page=${page}`;
|
|
28
|
+
const response = await fetch(url);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(`Failed to fetch page ${page} for search: ${searchString}`);
|
|
31
|
+
}
|
|
32
|
+
return response.text();
|
|
33
|
+
};
|
|
34
|
+
exports.getSoundNodesPage = getSoundNodesPage;
|
|
35
|
+
/**
|
|
36
|
+
* Check if next page exists using HEAD request for efficiency
|
|
37
|
+
* @param searchString The search term
|
|
38
|
+
* @param page The current page number (default: 1)
|
|
39
|
+
* @returns true if next page exists, false otherwise
|
|
40
|
+
*/
|
|
41
|
+
const hasNextPage = async ({ searchString, page = 1 }) => {
|
|
42
|
+
// Use mock data if in mock mode
|
|
43
|
+
if ((0, api_config_1.isMockMode)()) {
|
|
44
|
+
return MockApi.hasNextPage({ searchString, page });
|
|
45
|
+
}
|
|
46
|
+
const escapedSearchParam = encodeURIComponent(searchString);
|
|
47
|
+
const url = `https://www.myinstants.com/en/search/?name=${escapedSearchParam}&page=${page + 1}`;
|
|
48
|
+
try {
|
|
49
|
+
const response = await fetch(url, { method: 'HEAD' });
|
|
50
|
+
return response.ok;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
exports.hasNextPage = hasNextPage;
|
|
57
|
+
/**
|
|
58
|
+
* Fetch all pages (for --all flag)
|
|
59
|
+
* This maintains the original functionality but as an explicit option
|
|
60
|
+
* @param searchString The search term
|
|
61
|
+
* @returns Array of HTML content for all pages
|
|
62
|
+
*/
|
|
63
|
+
const getAllSoundNodes = async ({ searchString }) => {
|
|
64
|
+
// Use mock data if in mock mode
|
|
65
|
+
if ((0, api_config_1.isMockMode)()) {
|
|
66
|
+
return MockApi.getAllSoundNodes({ searchString });
|
|
67
|
+
}
|
|
68
|
+
const result = [];
|
|
69
|
+
let page = 1;
|
|
26
70
|
while (true) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const htmlResult = await response.text();
|
|
31
|
-
result.push(htmlResult);
|
|
71
|
+
try {
|
|
72
|
+
const html = await (0, exports.getSoundNodesPage)({ searchString, page });
|
|
73
|
+
result.push(html);
|
|
32
74
|
page++;
|
|
33
|
-
|
|
75
|
+
// Check if next page exists
|
|
76
|
+
const nextExists = await (0, exports.hasNextPage)({ searchString, page });
|
|
77
|
+
if (!nextExists)
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
// If we get an error fetching a page, assume we've reached the end
|
|
82
|
+
break;
|
|
34
83
|
}
|
|
35
|
-
break;
|
|
36
84
|
}
|
|
37
85
|
return result;
|
|
38
86
|
};
|
|
39
|
-
exports.
|
|
87
|
+
exports.getAllSoundNodes = getAllSoundNodes;
|
|
88
|
+
/**
|
|
89
|
+
* Fetch the download page for a specific sound node
|
|
90
|
+
* @param soundNodeDetailsURL The relative URL of the sound detail page
|
|
91
|
+
* @returns HTML content of the sound detail page
|
|
92
|
+
*/
|
|
40
93
|
const getNodeDownloadPage = async (soundNodeDetailsURL) => {
|
|
94
|
+
// Use mock data if in mock mode
|
|
95
|
+
if ((0, api_config_1.isMockMode)()) {
|
|
96
|
+
return MockApi.getNodeDownloadPage(soundNodeDetailsURL);
|
|
97
|
+
}
|
|
41
98
|
const root = `https://www.myinstants.com${soundNodeDetailsURL}`;
|
|
42
99
|
const response = await fetch(root);
|
|
43
|
-
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
throw new Error(`Failed to fetch sound detail page: ${soundNodeDetailsURL}`);
|
|
102
|
+
}
|
|
103
|
+
return response.text();
|
|
44
104
|
};
|
|
45
105
|
exports.getNodeDownloadPage = getNodeDownloadPage;
|
|
46
106
|
//# sourceMappingURL=my-instants.api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"my-instants.api.js","sourceRoot":"","sources":["../../src/api/my-instants.api.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"my-instants.api.js","sourceRoot":"","sources":["../../src/api/my-instants.api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mock API layer for testing purposes
|
|
4
|
+
* Returns predictable data without making actual HTTP requests
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getNodeDownloadPage = exports.getAllSoundNodes = exports.hasNextPage = exports.getSoundNodesPage = void 0;
|
|
8
|
+
// Mock data for testing
|
|
9
|
+
const mockSounds = [
|
|
10
|
+
{
|
|
11
|
+
label: "Wilhelm Scream",
|
|
12
|
+
detail_url: "/en/instant/wilhelm-scream/"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
label: "THX Deep Note",
|
|
16
|
+
detail_url: "/en/instant/thx-deep-note/"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: "Test Sound 1",
|
|
20
|
+
detail_url: "/en/instant/test-sound-1/"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
label: "Test Sound 2",
|
|
24
|
+
detail_url: "/en/instant/test-sound-2/"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
label: "Test Sound 3",
|
|
28
|
+
detail_url: "/en/instant/test-sound-3/"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
label: "Test Sound 4",
|
|
32
|
+
detail_url: "/en/instant/test-sound-4/"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: "Test Sound 5",
|
|
36
|
+
detail_url: "/en/instant/test-sound-5/"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: "Test Sound 6",
|
|
40
|
+
detail_url: "/en/instant/test-sound-6/"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Test Sound 7",
|
|
44
|
+
detail_url: "/en/instant/test-sound-7/"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
label: "Test Sound 8",
|
|
48
|
+
detail_url: "/en/instant/test-sound-8/"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: "Test Sound 9",
|
|
52
|
+
detail_url: "/en/instant/test-sound-9/"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "Test Sound 10",
|
|
56
|
+
detail_url: "/en/instant/test-sound-10/"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: "Test Sound 11",
|
|
60
|
+
detail_url: "/en/instant/test-sound-11/"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: "Test Sound 12",
|
|
64
|
+
detail_url: "/en/instant/test-sound-12/"
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
// Mock HTML templates
|
|
68
|
+
const mockSearchPage = (sounds, page) => `
|
|
69
|
+
<!DOCTYPE html>
|
|
70
|
+
<html>
|
|
71
|
+
<head><title>MyInstants - Search Results</title></head>
|
|
72
|
+
<body>
|
|
73
|
+
<div class="instant-list">
|
|
74
|
+
${sounds.map(sound => `
|
|
75
|
+
<div class="instant">
|
|
76
|
+
<a href="${sound.detail_url}" class="instant-link">${sound.label}</a>
|
|
77
|
+
</div>
|
|
78
|
+
`).join('')}
|
|
79
|
+
</div>
|
|
80
|
+
</body>
|
|
81
|
+
</html>
|
|
82
|
+
`;
|
|
83
|
+
const mockDetailPage = (downloadUrl) => `
|
|
84
|
+
<!DOCTYPE html>
|
|
85
|
+
<html>
|
|
86
|
+
<head><title>MyInstants - Sound Detail</title></head>
|
|
87
|
+
<body>
|
|
88
|
+
<a href="${downloadUrl}" download="sound.mp3">Download MP3</a>
|
|
89
|
+
</body>
|
|
90
|
+
</html>
|
|
91
|
+
`;
|
|
92
|
+
/**
|
|
93
|
+
* Mock implementation of getSoundNodesPage
|
|
94
|
+
*/
|
|
95
|
+
const getSoundNodesPage = async ({ searchString, page = 1 }) => {
|
|
96
|
+
// Return mock data for any search string
|
|
97
|
+
const pageSize = 6;
|
|
98
|
+
const startIndex = (page - 1) * pageSize;
|
|
99
|
+
const pageSounds = mockSounds.slice(startIndex, startIndex + pageSize);
|
|
100
|
+
return mockSearchPage(pageSounds, page);
|
|
101
|
+
};
|
|
102
|
+
exports.getSoundNodesPage = getSoundNodesPage;
|
|
103
|
+
/**
|
|
104
|
+
* Mock implementation of hasNextPage
|
|
105
|
+
*/
|
|
106
|
+
const hasNextPage = async ({ searchString, page = 1 }) => {
|
|
107
|
+
const pageSize = 6;
|
|
108
|
+
const startIndex = (page - 1) * pageSize;
|
|
109
|
+
return startIndex + pageSize < mockSounds.length;
|
|
110
|
+
};
|
|
111
|
+
exports.hasNextPage = hasNextPage;
|
|
112
|
+
/**
|
|
113
|
+
* Mock implementation of getAllSoundNodes
|
|
114
|
+
*/
|
|
115
|
+
const getAllSoundNodes = async ({ searchString }) => {
|
|
116
|
+
const pageSize = 6;
|
|
117
|
+
const pages = [];
|
|
118
|
+
for (let page = 1;; page++) {
|
|
119
|
+
const startIndex = (page - 1) * pageSize;
|
|
120
|
+
const pageSounds = mockSounds.slice(startIndex, startIndex + pageSize);
|
|
121
|
+
if (pageSounds.length === 0)
|
|
122
|
+
break;
|
|
123
|
+
pages.push(mockSearchPage(pageSounds, page));
|
|
124
|
+
}
|
|
125
|
+
return pages;
|
|
126
|
+
};
|
|
127
|
+
exports.getAllSoundNodes = getAllSoundNodes;
|
|
128
|
+
/**
|
|
129
|
+
* Mock implementation of getNodeDownloadPage
|
|
130
|
+
*/
|
|
131
|
+
const getNodeDownloadPage = async (soundNodeDetailsURL) => {
|
|
132
|
+
// Return a mock detail page with a valid download URL
|
|
133
|
+
return mockDetailPage("https://www.myinstants.com/media/sounds/test-sound.mp3");
|
|
134
|
+
};
|
|
135
|
+
exports.getNodeDownloadPage = getNodeDownloadPage;
|
|
136
|
+
//# sourceMappingURL=my-instants.api.mock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"my-instants.api.mock.js","sourceRoot":"","sources":["../../src/api/my-instants.api.mock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Valibot validation schemas for API responses
|
|
4
|
+
* Ensures both real and mock API responses match expected structure
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.validateSoundsArray = exports.safeValidateSound = exports.validateHtml = exports.validatePaginatedResults = exports.validateSound = void 0;
|
|
8
|
+
const valibot_1 = require("valibot");
|
|
9
|
+
// Schema for a single sound result
|
|
10
|
+
const SoundSchema = (0, valibot_1.object)({
|
|
11
|
+
label: (0, valibot_1.string)('Label must be a string'),
|
|
12
|
+
download_url: (0, valibot_1.string)('Download URL must be a string'),
|
|
13
|
+
});
|
|
14
|
+
// Schema for paginated results
|
|
15
|
+
const PaginatedResultsSchema = (0, valibot_1.object)({
|
|
16
|
+
results: (0, valibot_1.array)(SoundSchema, 'Results must be an array of sounds'),
|
|
17
|
+
hasNextPage: (0, valibot_1.boolean)('hasNextPage should be a boolean'),
|
|
18
|
+
hasPreviousPage: (0, valibot_1.boolean)('hasPreviousPage should be a boolean'),
|
|
19
|
+
currentPage: (0, valibot_1.number)('currentPage should be a number'),
|
|
20
|
+
});
|
|
21
|
+
// Schema for HTML response (used internally)
|
|
22
|
+
const HtmlSchema = (0, valibot_1.string)('HTML response must be a string');
|
|
23
|
+
/**
|
|
24
|
+
* Validate a single sound result
|
|
25
|
+
* @throws ValidationError if sound doesn't match schema
|
|
26
|
+
*/
|
|
27
|
+
const validateSound = (sound) => {
|
|
28
|
+
return (0, valibot_1.parse)(SoundSchema, sound);
|
|
29
|
+
};
|
|
30
|
+
exports.validateSound = validateSound;
|
|
31
|
+
/**
|
|
32
|
+
* Validate paginated results
|
|
33
|
+
* @throws ValidationError if results don't match schema
|
|
34
|
+
*/
|
|
35
|
+
const validatePaginatedResults = (results) => {
|
|
36
|
+
return (0, valibot_1.parse)(PaginatedResultsSchema, results);
|
|
37
|
+
};
|
|
38
|
+
exports.validatePaginatedResults = validatePaginatedResults;
|
|
39
|
+
/**
|
|
40
|
+
* Validate HTML response
|
|
41
|
+
* @throws ValidationError if HTML is not a string
|
|
42
|
+
*/
|
|
43
|
+
const validateHtml = (html) => {
|
|
44
|
+
return (0, valibot_1.parse)(HtmlSchema, html);
|
|
45
|
+
};
|
|
46
|
+
exports.validateHtml = validateHtml;
|
|
47
|
+
/**
|
|
48
|
+
* Safe validation that returns null instead of throwing
|
|
49
|
+
*/
|
|
50
|
+
const safeValidateSound = (sound) => {
|
|
51
|
+
try {
|
|
52
|
+
return (0, exports.validateSound)(sound);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('Validation failed:', error);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.safeValidateSound = safeValidateSound;
|
|
60
|
+
/**
|
|
61
|
+
* Validate an array of sounds
|
|
62
|
+
*/
|
|
63
|
+
const validateSoundsArray = (sounds) => {
|
|
64
|
+
return sounds.map(sound => (0, exports.validateSound)(sound));
|
|
65
|
+
};
|
|
66
|
+
exports.validateSoundsArray = validateSoundsArray;
|
|
67
|
+
//# sourceMappingURL=validation-schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-schemas.js","sourceRoot":"","sources":["../../src/api/validation-schemas.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,qCAA+F;AAE/F,mCAAmC;AACnC,MAAM,WAAW,GAAG,IAAA,gBAAM,EAAC;IACzB,KAAK,EAAE,IAAA,gBAAM,EAAC,wBAAwB,CAAC;IACvC,YAAY,EAAE,IAAA,gBAAM,EAAC,+BAA+B,CAAC;CACtD,CAAC,CAAC;AAIH,+BAA+B;AAC/B,MAAM,sBAAsB,GAAG,IAAA,gBAAM,EAAC;IACpC,OAAO,EAAE,IAAA,eAAK,EAAC,WAAW,EAAE,oCAAoC,CAAC;IACjE,WAAW,EAAE,IAAA,iBAAO,EAAC,iCAAiC,CAAC;IACvD,eAAe,EAAE,IAAA,iBAAO,EAAC,qCAAqC,CAAC;IAC/D,WAAW,EAAE,IAAA,gBAAM,EAAC,gCAAgC,CAAC;CACtD,CAAC,CAAC;AAIH,6CAA6C;AAC7C,MAAM,UAAU,GAAG,IAAA,gBAAM,EAAC,gCAAgC,CAAC,CAAC;AAG5D;;;GAGG;AACI,MAAM,aAAa,GAAG,CAAC,KAAc,EAAkB,EAAE;IAC9D,OAAO,IAAA,eAAK,EAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC,CAAC;AAFW,QAAA,aAAa,iBAExB;AAEF;;;GAGG;AACI,MAAM,wBAAwB,GAAG,CAAC,OAAgB,EAA6B,EAAE;IACtF,OAAO,IAAA,eAAK,EAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC,CAAC;AAFW,QAAA,wBAAwB,4BAEnC;AAEF;;;GAGG;AACI,MAAM,YAAY,GAAG,CAAC,IAAa,EAAiB,EAAE;IAC3D,OAAO,IAAA,eAAK,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB;AAEF;;GAEG;AACI,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAyB,EAAE;IACzE,IAAI,CAAC;QACH,OAAO,IAAA,qBAAa,EAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAPW,QAAA,iBAAiB,qBAO5B;AAEF;;GAEG;AACI,MAAM,mBAAmB,GAAG,CAAC,MAAiB,EAAoB,EAAE;IACzE,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAA,qBAAa,EAAC,KAAK,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC;AAFW,QAAA,mBAAmB,uBAE9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.type.js","sourceRoot":"","sources":["../../../src/common/types/query.type.ts"],"names":[],"mappings":""}
|