@apiverve/wordsearch 1.1.14 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +340 -343
- package/index.d.ts +46 -34
- package/index.js +209 -209
- package/package.json +7 -8
package/index.d.ts
CHANGED
|
@@ -1,51 +1,63 @@
|
|
|
1
|
-
declare module '@apiverve/wordsearch' {
|
|
2
|
-
export interface wordsearchOptions {
|
|
3
|
-
api_key: string;
|
|
4
|
-
secure?: boolean;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
declare module '@apiverve/wordsearch' {
|
|
2
|
+
export interface wordsearchOptions {
|
|
3
|
+
api_key: string;
|
|
4
|
+
secure?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Describes fields the current plan does not unlock. Locked fields arrive as null
|
|
9
|
+
* in `data`; `locked_fields` names them, using dot paths for nested fields.
|
|
10
|
+
* Absent when the plan unlocks everything.
|
|
11
|
+
*/
|
|
12
|
+
export interface PremiumInfo {
|
|
13
|
+
message: string;
|
|
14
|
+
upgrade_url: string;
|
|
15
|
+
locked_fields: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface wordsearchResponse {
|
|
19
|
+
status: string;
|
|
20
|
+
error: string | null;
|
|
21
|
+
data: WordSearchGeneratorData;
|
|
22
|
+
code?: number;
|
|
23
|
+
premium?: PremiumInfo;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
|
|
15
27
|
interface WordSearchGeneratorData {
|
|
16
|
-
grid: Array<string[]>;
|
|
28
|
+
grid: Array<(null | string)[]>;
|
|
17
29
|
words: Word[];
|
|
18
|
-
wordCount: number;
|
|
19
|
-
size: number;
|
|
20
|
-
difficulty: string;
|
|
21
|
-
html: string;
|
|
30
|
+
wordCount: number | null;
|
|
31
|
+
size: number | null;
|
|
32
|
+
difficulty: null | string;
|
|
33
|
+
html: null | string;
|
|
22
34
|
image: Image;
|
|
23
35
|
solutionImage: Image;
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
interface Image {
|
|
27
|
-
imageName: string;
|
|
28
|
-
format: string;
|
|
29
|
-
downloadURL: string;
|
|
30
|
-
expires: number;
|
|
39
|
+
imageName: null | string;
|
|
40
|
+
format: null | string;
|
|
41
|
+
downloadURL: null | string;
|
|
42
|
+
expires: number | null;
|
|
31
43
|
}
|
|
32
44
|
|
|
33
45
|
interface Word {
|
|
34
|
-
word: string;
|
|
46
|
+
word: null | string;
|
|
35
47
|
start: Start;
|
|
36
|
-
direction: string;
|
|
48
|
+
direction: null | string;
|
|
37
49
|
}
|
|
38
50
|
|
|
39
51
|
interface Start {
|
|
40
|
-
row: number;
|
|
41
|
-
col: number;
|
|
52
|
+
row: number | null;
|
|
53
|
+
col: number | null;
|
|
42
54
|
}
|
|
43
55
|
|
|
44
|
-
export default class wordsearchWrapper {
|
|
45
|
-
constructor(options: wordsearchOptions);
|
|
46
|
-
|
|
47
|
-
execute(callback: (error: any, data: wordsearchResponse | null) => void): Promise<wordsearchResponse>;
|
|
48
|
-
execute(query: Record<string, any>, callback: (error: any, data: wordsearchResponse | null) => void): Promise<wordsearchResponse>;
|
|
49
|
-
execute(query?: Record<string, any>): Promise<wordsearchResponse>;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
56
|
+
export default class wordsearchWrapper {
|
|
57
|
+
constructor(options: wordsearchOptions);
|
|
58
|
+
|
|
59
|
+
execute(callback: (error: any, data: wordsearchResponse | null) => void): Promise<wordsearchResponse>;
|
|
60
|
+
execute(query: Record<string, any>, callback: (error: any, data: wordsearchResponse | null) => void): Promise<wordsearchResponse>;
|
|
61
|
+
execute(query?: Record<string, any>): Promise<wordsearchResponse>;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/index.js
CHANGED
|
@@ -1,209 +1,209 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
|
-
|
|
3
|
-
class wordsearchWrapper {
|
|
4
|
-
|
|
5
|
-
constructor(options) {
|
|
6
|
-
if (!options || typeof options !== 'object') {
|
|
7
|
-
throw new Error('Options object must be provided. See documentation: https://docs.apiverve.com/ref/wordsearch');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const { api_key, secure = true } = options;
|
|
11
|
-
|
|
12
|
-
if (!api_key || typeof api_key !== 'string') {
|
|
13
|
-
throw new Error('API key must be provided as a non-empty string. Get your API key at: https://apiverve.com');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Validate API key format (GUID, prefixed keys like apv_xxx, or alphanumeric)
|
|
17
|
-
const apiKeyPattern = /^[a-zA-Z0-9_-]+$/;
|
|
18
|
-
if (!apiKeyPattern.test(api_key)) {
|
|
19
|
-
throw new Error('Invalid API key format. API key must be alphanumeric and may contain hyphens and underscores. Get your API key at: https://apiverve.com');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (typeof secure !== 'boolean') {
|
|
23
|
-
throw new Error('Secure parameter must be a boolean value.');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
this.APIKey = api_key;
|
|
27
|
-
this.IsSecure = secure;
|
|
28
|
-
|
|
29
|
-
// secure is deprecated, all requests must be made over HTTPS
|
|
30
|
-
this.baseURL = 'https://api.apiverve.com/v1/wordsearch';
|
|
31
|
-
|
|
32
|
-
// Validation rules for parameters (generated from schema)
|
|
33
|
-
this.validationRules = {"words":{"type":"array","required":true},"size":{"type":"integer","required":false,"min":10,"max":30,"default":15},"difficulty":{"type":"string","required":false,"default":"medium"}};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Validate query parameters against schema rules
|
|
38
|
-
* @param {Object} query - The query parameters to validate
|
|
39
|
-
* @throws {Error} - If validation fails
|
|
40
|
-
*/
|
|
41
|
-
validateParams(query) {
|
|
42
|
-
const errors = [];
|
|
43
|
-
|
|
44
|
-
for (const [paramName, rules] of Object.entries(this.validationRules)) {
|
|
45
|
-
const value = query[paramName];
|
|
46
|
-
|
|
47
|
-
// Check required
|
|
48
|
-
if (rules.required && (value === undefined || value === null || value === '')) {
|
|
49
|
-
errors.push(`Required parameter [${paramName}] is missing.`);
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Skip validation if value is not provided and not required
|
|
54
|
-
if (value === undefined || value === null) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Type validation
|
|
59
|
-
if (rules.type === 'integer' || rules.type === 'number') {
|
|
60
|
-
const numValue = Number(value);
|
|
61
|
-
if (isNaN(numValue)) {
|
|
62
|
-
errors.push(`Parameter [${paramName}] must be a valid ${rules.type}.`);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (rules.type === 'integer' && !Number.isInteger(numValue)) {
|
|
67
|
-
errors.push(`Parameter [${paramName}] must be an integer.`);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Min/max validation for numbers
|
|
72
|
-
if (rules.min !== undefined && numValue < rules.min) {
|
|
73
|
-
errors.push(`Parameter [${paramName}] must be at least ${rules.min}.`);
|
|
74
|
-
}
|
|
75
|
-
if (rules.max !== undefined && numValue > rules.max) {
|
|
76
|
-
errors.push(`Parameter [${paramName}] must be at most ${rules.max}.`);
|
|
77
|
-
}
|
|
78
|
-
} else if (rules.type === 'string') {
|
|
79
|
-
if (typeof value !== 'string') {
|
|
80
|
-
errors.push(`Parameter [${paramName}] must be a string.`);
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Length validation for strings
|
|
85
|
-
if (rules.minLength !== undefined && value.length < rules.minLength) {
|
|
86
|
-
errors.push(`Parameter [${paramName}] must be at least ${rules.minLength} characters.`);
|
|
87
|
-
}
|
|
88
|
-
if (rules.maxLength !== undefined && value.length > rules.maxLength) {
|
|
89
|
-
errors.push(`Parameter [${paramName}] must be at most ${rules.maxLength} characters.`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Format validation
|
|
93
|
-
if (rules.format) {
|
|
94
|
-
const formatPatterns = {
|
|
95
|
-
'email': /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
96
|
-
'url': /^https?:\/\/.+/i,
|
|
97
|
-
'ip': /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/,
|
|
98
|
-
'date': /^\d{4}-\d{2}-\d{2}$/,
|
|
99
|
-
'hexColor': /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
if (formatPatterns[rules.format] && !formatPatterns[rules.format].test(value)) {
|
|
103
|
-
errors.push(`Parameter [${paramName}] must be a valid ${rules.format}.`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
} else if (rules.type === 'boolean') {
|
|
107
|
-
if (typeof value !== 'boolean' && value !== 'true' && value !== 'false') {
|
|
108
|
-
errors.push(`Parameter [${paramName}] must be a boolean.`);
|
|
109
|
-
}
|
|
110
|
-
} else if (rules.type === 'array') {
|
|
111
|
-
if (!Array.isArray(value)) {
|
|
112
|
-
errors.push(`Parameter [${paramName}] must be an array.`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Enum validation
|
|
117
|
-
if (rules.enum && Array.isArray(rules.enum)) {
|
|
118
|
-
if (!rules.enum.includes(value)) {
|
|
119
|
-
errors.push(`Parameter [${paramName}] must be one of: ${rules.enum.join(', ')}.`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (errors.length > 0) {
|
|
125
|
-
throw new Error(`Validation failed: ${errors.join(' ')} See documentation: https://docs.apiverve.com/ref/wordsearch`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async execute(query, callback) {
|
|
130
|
-
// Handle different argument patterns
|
|
131
|
-
if(arguments.length === 0) {
|
|
132
|
-
// execute() - no args
|
|
133
|
-
query = {};
|
|
134
|
-
callback = null;
|
|
135
|
-
} else if(arguments.length === 1) {
|
|
136
|
-
if (typeof query === 'function') {
|
|
137
|
-
// execute(callback)
|
|
138
|
-
callback = query;
|
|
139
|
-
query = {};
|
|
140
|
-
} else {
|
|
141
|
-
// execute(query)
|
|
142
|
-
callback = null;
|
|
143
|
-
}
|
|
144
|
-
} else {
|
|
145
|
-
// execute(query, callback)
|
|
146
|
-
if (!query || typeof query !== 'object') {
|
|
147
|
-
throw new Error('Query parameters must be provided as an object.');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Validate parameters against schema rules
|
|
152
|
-
this.validateParams(query);
|
|
153
|
-
|
|
154
|
-
const method = 'POST';
|
|
155
|
-
const url = method === 'POST' ? this.baseURL : this.constructURL(query);
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
const response = await axios({
|
|
159
|
-
method,
|
|
160
|
-
url,
|
|
161
|
-
headers: {
|
|
162
|
-
'Content-Type': 'application/json',
|
|
163
|
-
'x-api-key': this.APIKey,
|
|
164
|
-
'auth-mode': 'npm-package'
|
|
165
|
-
},
|
|
166
|
-
data: method === 'POST' ? query : undefined
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
const data = response.data;
|
|
170
|
-
if (callback) callback(null, data);
|
|
171
|
-
return data;
|
|
172
|
-
} catch (error) {
|
|
173
|
-
let apiError;
|
|
174
|
-
|
|
175
|
-
if (error.response && error.response.data) {
|
|
176
|
-
apiError = error.response.data;
|
|
177
|
-
} else if (error.message) {
|
|
178
|
-
apiError = { error: error.message, status: 'error' };
|
|
179
|
-
} else {
|
|
180
|
-
apiError = { error: 'An unknown error occurred', status: 'error' };
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (callback) {
|
|
184
|
-
callback(apiError, null);
|
|
185
|
-
return; // Don't throw if callback is provided
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
throw apiError;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
constructURL(query) {
|
|
193
|
-
let url = this.baseURL;
|
|
194
|
-
|
|
195
|
-
if(query && typeof query === 'object')
|
|
196
|
-
{
|
|
197
|
-
if (Object.keys(query).length > 0) {
|
|
198
|
-
const queryString = Object.keys(query)
|
|
199
|
-
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
|
|
200
|
-
.join('&');
|
|
201
|
-
url += `?${queryString}`;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return url;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
module.exports = wordsearchWrapper;
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
class wordsearchWrapper {
|
|
4
|
+
|
|
5
|
+
constructor(options) {
|
|
6
|
+
if (!options || typeof options !== 'object') {
|
|
7
|
+
throw new Error('Options object must be provided. See documentation: https://docs.apiverve.com/ref/wordsearch');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { api_key, secure = true } = options;
|
|
11
|
+
|
|
12
|
+
if (!api_key || typeof api_key !== 'string') {
|
|
13
|
+
throw new Error('API key must be provided as a non-empty string. Get your API key at: https://apiverve.com');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Validate API key format (GUID, prefixed keys like apv_xxx, or alphanumeric)
|
|
17
|
+
const apiKeyPattern = /^[a-zA-Z0-9_-]+$/;
|
|
18
|
+
if (!apiKeyPattern.test(api_key)) {
|
|
19
|
+
throw new Error('Invalid API key format. API key must be alphanumeric and may contain hyphens and underscores. Get your API key at: https://apiverve.com');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof secure !== 'boolean') {
|
|
23
|
+
throw new Error('Secure parameter must be a boolean value.');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.APIKey = api_key;
|
|
27
|
+
this.IsSecure = secure;
|
|
28
|
+
|
|
29
|
+
// secure is deprecated, all requests must be made over HTTPS
|
|
30
|
+
this.baseURL = 'https://api.apiverve.com/v1/wordsearch';
|
|
31
|
+
|
|
32
|
+
// Validation rules for parameters (generated from schema)
|
|
33
|
+
this.validationRules = {"words":{"type":"array","required":true},"size":{"type":"integer","required":false,"min":10,"max":30,"default":15},"difficulty":{"type":"string","required":false,"default":"medium"},"image":{"type":"boolean","required":false,"default":false},"solutionImage":{"type":"boolean","required":false,"default":false}};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Validate query parameters against schema rules
|
|
38
|
+
* @param {Object} query - The query parameters to validate
|
|
39
|
+
* @throws {Error} - If validation fails
|
|
40
|
+
*/
|
|
41
|
+
validateParams(query) {
|
|
42
|
+
const errors = [];
|
|
43
|
+
|
|
44
|
+
for (const [paramName, rules] of Object.entries(this.validationRules)) {
|
|
45
|
+
const value = query[paramName];
|
|
46
|
+
|
|
47
|
+
// Check required
|
|
48
|
+
if (rules.required && (value === undefined || value === null || value === '')) {
|
|
49
|
+
errors.push(`Required parameter [${paramName}] is missing.`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Skip validation if value is not provided and not required
|
|
54
|
+
if (value === undefined || value === null) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Type validation
|
|
59
|
+
if (rules.type === 'integer' || rules.type === 'number') {
|
|
60
|
+
const numValue = Number(value);
|
|
61
|
+
if (isNaN(numValue)) {
|
|
62
|
+
errors.push(`Parameter [${paramName}] must be a valid ${rules.type}.`);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (rules.type === 'integer' && !Number.isInteger(numValue)) {
|
|
67
|
+
errors.push(`Parameter [${paramName}] must be an integer.`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Min/max validation for numbers
|
|
72
|
+
if (rules.min !== undefined && numValue < rules.min) {
|
|
73
|
+
errors.push(`Parameter [${paramName}] must be at least ${rules.min}.`);
|
|
74
|
+
}
|
|
75
|
+
if (rules.max !== undefined && numValue > rules.max) {
|
|
76
|
+
errors.push(`Parameter [${paramName}] must be at most ${rules.max}.`);
|
|
77
|
+
}
|
|
78
|
+
} else if (rules.type === 'string') {
|
|
79
|
+
if (typeof value !== 'string') {
|
|
80
|
+
errors.push(`Parameter [${paramName}] must be a string.`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Length validation for strings
|
|
85
|
+
if (rules.minLength !== undefined && value.length < rules.minLength) {
|
|
86
|
+
errors.push(`Parameter [${paramName}] must be at least ${rules.minLength} characters.`);
|
|
87
|
+
}
|
|
88
|
+
if (rules.maxLength !== undefined && value.length > rules.maxLength) {
|
|
89
|
+
errors.push(`Parameter [${paramName}] must be at most ${rules.maxLength} characters.`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Format validation
|
|
93
|
+
if (rules.format) {
|
|
94
|
+
const formatPatterns = {
|
|
95
|
+
'email': /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
96
|
+
'url': /^https?:\/\/.+/i,
|
|
97
|
+
'ip': /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/,
|
|
98
|
+
'date': /^\d{4}-\d{2}-\d{2}$/,
|
|
99
|
+
'hexColor': /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (formatPatterns[rules.format] && !formatPatterns[rules.format].test(value)) {
|
|
103
|
+
errors.push(`Parameter [${paramName}] must be a valid ${rules.format}.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
} else if (rules.type === 'boolean') {
|
|
107
|
+
if (typeof value !== 'boolean' && value !== 'true' && value !== 'false') {
|
|
108
|
+
errors.push(`Parameter [${paramName}] must be a boolean.`);
|
|
109
|
+
}
|
|
110
|
+
} else if (rules.type === 'array') {
|
|
111
|
+
if (!Array.isArray(value)) {
|
|
112
|
+
errors.push(`Parameter [${paramName}] must be an array.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Enum validation
|
|
117
|
+
if (rules.enum && Array.isArray(rules.enum)) {
|
|
118
|
+
if (!rules.enum.includes(value)) {
|
|
119
|
+
errors.push(`Parameter [${paramName}] must be one of: ${rules.enum.join(', ')}.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (errors.length > 0) {
|
|
125
|
+
throw new Error(`Validation failed: ${errors.join(' ')} See documentation: https://docs.apiverve.com/ref/wordsearch`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async execute(query, callback) {
|
|
130
|
+
// Handle different argument patterns
|
|
131
|
+
if(arguments.length === 0) {
|
|
132
|
+
// execute() - no args
|
|
133
|
+
query = {};
|
|
134
|
+
callback = null;
|
|
135
|
+
} else if(arguments.length === 1) {
|
|
136
|
+
if (typeof query === 'function') {
|
|
137
|
+
// execute(callback)
|
|
138
|
+
callback = query;
|
|
139
|
+
query = {};
|
|
140
|
+
} else {
|
|
141
|
+
// execute(query)
|
|
142
|
+
callback = null;
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
// execute(query, callback)
|
|
146
|
+
if (!query || typeof query !== 'object') {
|
|
147
|
+
throw new Error('Query parameters must be provided as an object.');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Validate parameters against schema rules
|
|
152
|
+
this.validateParams(query);
|
|
153
|
+
|
|
154
|
+
const method = 'POST';
|
|
155
|
+
const url = method === 'POST' ? this.baseURL : this.constructURL(query);
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const response = await axios({
|
|
159
|
+
method,
|
|
160
|
+
url,
|
|
161
|
+
headers: {
|
|
162
|
+
'Content-Type': 'application/json',
|
|
163
|
+
'x-api-key': this.APIKey,
|
|
164
|
+
'auth-mode': 'npm-package'
|
|
165
|
+
},
|
|
166
|
+
data: method === 'POST' ? query : undefined
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const data = response.data;
|
|
170
|
+
if (callback) callback(null, data);
|
|
171
|
+
return data;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
let apiError;
|
|
174
|
+
|
|
175
|
+
if (error.response && error.response.data) {
|
|
176
|
+
apiError = error.response.data;
|
|
177
|
+
} else if (error.message) {
|
|
178
|
+
apiError = { error: error.message, status: 'error' };
|
|
179
|
+
} else {
|
|
180
|
+
apiError = { error: 'An unknown error occurred', status: 'error' };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (callback) {
|
|
184
|
+
callback(apiError, null);
|
|
185
|
+
return; // Don't throw if callback is provided
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
throw apiError;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
constructURL(query) {
|
|
193
|
+
let url = this.baseURL;
|
|
194
|
+
|
|
195
|
+
if(query && typeof query === 'object')
|
|
196
|
+
{
|
|
197
|
+
if (Object.keys(query).length > 0) {
|
|
198
|
+
const queryString = Object.keys(query)
|
|
199
|
+
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
|
|
200
|
+
.join('&');
|
|
201
|
+
url += `?${queryString}`;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return url;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
module.exports = wordsearchWrapper;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apiverve/wordsearch",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Word Search Generator creates customizable word search puzzles with configurable grid size, word placement, and difficulty levels.",
|
|
3
|
+
"version": "1.2.2",
|
|
4
|
+
"description": "Word Search Generator is a word search API that creates customizable word search puzzles with configurable grid size, word placement, and difficulty levels.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"engines": {
|
|
9
|
-
"node": ">=
|
|
9
|
+
"node": ">=18.0.0"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"directory": "npm"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
|
-
""
|
|
26
|
+
"word search api", "wordsearch api", "word search generator api", "word search", "word search maker"
|
|
27
27
|
],
|
|
28
28
|
"author": {
|
|
29
29
|
"name": "APIVerve",
|
|
@@ -34,15 +34,14 @@
|
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/apiverve/wordsearch-api/issues"
|
|
36
36
|
},
|
|
37
|
-
"homepage": "https://apiverve.com/marketplace/wordsearch?utm_source=npm&utm_medium=homepage",
|
|
37
|
+
"homepage": "https://apiverve.com/marketplace/wordsearch?utm_source=npm&utm_medium=referral&utm_content=homepage",
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"mocha": "^11.0.1",
|
|
40
40
|
"chai": "^5.1.2",
|
|
41
41
|
"dotenv": "^16.4.7"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"axios": "1.13.2"
|
|
44
|
+
"axios": "1.13.2",
|
|
45
|
+
"form-data": "^4.0.1"
|
|
47
46
|
}
|
|
48
47
|
}
|