@malevich-studio/strapi-sdk-typescript 1.0.1 → 1.0.3

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.
Files changed (38) hide show
  1. package/README.md +0 -0
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +4 -1
  4. package/dist/generate-strapi-types.d.ts +2 -2
  5. package/dist/generate-strapi-types.js +73 -170
  6. package/dist/generator/attributes/base-relation.d.ts +10 -0
  7. package/dist/generator/attributes/base-relation.js +56 -0
  8. package/dist/generator/attributes/base.d.ts +27 -0
  9. package/dist/generator/attributes/base.js +53 -0
  10. package/dist/generator/attributes/blocks.d.ts +12 -0
  11. package/dist/generator/attributes/blocks.js +29 -0
  12. package/dist/generator/attributes/boolean.d.ts +10 -0
  13. package/dist/generator/attributes/boolean.js +17 -0
  14. package/dist/generator/attributes/component.d.ts +20 -0
  15. package/dist/generator/attributes/component.js +36 -0
  16. package/dist/generator/attributes/date-time.d.ts +10 -0
  17. package/dist/generator/attributes/date-time.js +17 -0
  18. package/dist/generator/attributes/enumeration.d.ts +12 -0
  19. package/dist/generator/attributes/enumeration.js +17 -0
  20. package/dist/generator/attributes/index.d.ts +4 -0
  21. package/dist/generator/attributes/index.js +40 -0
  22. package/dist/generator/attributes/json.d.ts +11 -0
  23. package/dist/generator/attributes/json.js +20 -0
  24. package/dist/generator/attributes/media.d.ts +21 -0
  25. package/dist/generator/attributes/media.js +29 -0
  26. package/dist/generator/attributes/number.d.ts +12 -0
  27. package/dist/generator/attributes/number.js +17 -0
  28. package/dist/generator/attributes/relation.d.ts +48 -0
  29. package/dist/generator/attributes/relation.js +66 -0
  30. package/dist/generator/attributes/string.d.ts +13 -0
  31. package/dist/generator/attributes/string.js +17 -0
  32. package/dist/generator/utils/get-component-name.d.ts +5 -0
  33. package/dist/generator/utils/get-component-name.js +13 -0
  34. package/dist/generator/utils/get-content-type-name.d.ts +5 -0
  35. package/dist/generator/utils/get-content-type-name.js +18 -0
  36. package/dist/main.d.ts +5 -2
  37. package/dist/main.js +14 -2
  38. package/package.json +3 -2
package/README.md ADDED
File without changes
package/dist/cli.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ import 'dotenv/config';
package/dist/cli.js CHANGED
@@ -2,6 +2,9 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const generate_strapi_types_1 = require("./generate-strapi-types");
5
+ require("dotenv/config");
6
+ const main_1 = require("./main");
7
+ const strapi = new main_1.Strapi(process.env.STRAPI_URL, process.env.STRAPI_TOKEN);
5
8
  (async () => {
6
- await (0, generate_strapi_types_1.generateStrapiTypes)();
9
+ await (0, generate_strapi_types_1.generateStrapiTypes)(strapi);
7
10
  })();
@@ -1,5 +1,5 @@
1
- import 'dotenv/config';
1
+ import { Strapi } from "./main";
2
2
  /**
3
3
  * Main function to fetch Strapi (v5) data and generate the d.ts file
4
4
  */
5
- export declare function generateStrapiTypes(): Promise<void>;
5
+ export declare function generateStrapiTypes(strapi: Strapi): Promise<void>;
@@ -32,202 +32,88 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.generateStrapiTypes = generateStrapiTypes;
37
40
  const fs = __importStar(require("fs"));
38
41
  const path = __importStar(require("path"));
39
- require("dotenv/config");
40
- const main_1 = require("./main");
42
+ const get_component_name_1 = require("./generator/utils/get-component-name");
43
+ const attributes_1 = __importDefault(require("./generator/attributes"));
44
+ const get_content_type_name_1 = require("./generator/utils/get-content-type-name");
41
45
  var ContentTypeKind;
42
46
  (function (ContentTypeKind) {
43
47
  ContentTypeKind["CollectionType"] = "collectionType";
44
48
  ContentTypeKind["SingleType"] = "singleType";
45
49
  })(ContentTypeKind || (ContentTypeKind = {}));
46
- var AttributeType;
47
- (function (AttributeType) {
48
- AttributeType["BigInteger"] = "biginteger";
49
- AttributeType["Blocks"] = "blocks";
50
- AttributeType["Boolean"] = "boolean";
51
- AttributeType["Component"] = "component";
52
- AttributeType["DateTime"] = "datetime";
53
- AttributeType["Decimal"] = "decimal";
54
- AttributeType["Email"] = "email";
55
- AttributeType["Enumeration"] = "enumeration";
56
- AttributeType["Integer"] = "integer";
57
- AttributeType["Json"] = "json";
58
- AttributeType["Media"] = "media";
59
- AttributeType["Password"] = "password";
60
- AttributeType["Relation"] = "relation";
61
- AttributeType["String"] = "string";
62
- AttributeType["Text"] = "text";
63
- AttributeType["Float"] = "float";
64
- // RichText = 'richtext',
65
- })(AttributeType || (AttributeType = {}));
66
- var AttributeRelation;
67
- (function (AttributeRelation) {
68
- AttributeRelation["MorphToMany"] = "morphToMany";
69
- AttributeRelation["ManyToOne"] = "manyToOne";
70
- AttributeRelation["ManyToMany"] = "manyToMany";
71
- AttributeRelation["OneToMany"] = "oneToMany";
72
- AttributeRelation["OneToOne"] = "oneToOne";
73
- })(AttributeRelation || (AttributeRelation = {}));
74
- function getComponentType(attribute) {
75
- const componentTypeName = getComponentName(attribute.component);
76
- return attribute.repeatable ? `${componentTypeName}[]` : componentTypeName;
77
- }
78
- function getRelationType(attribute) {
79
- const ContentTypeName = getContentTypeName(attribute.target);
80
- switch (attribute.relation) {
81
- case AttributeRelation.ManyToMany:
82
- case AttributeRelation.OneToMany:
83
- case AttributeRelation.MorphToMany:
84
- return `${ContentTypeName}[]`;
85
- case AttributeRelation.ManyToOne:
86
- case AttributeRelation.OneToOne:
87
- default:
88
- return ContentTypeName;
89
- }
90
- }
91
- /**
92
- * Maps basic Strapi types to TypeScript types
93
- */
94
- function getAttributeType(attribute) {
95
- switch (attribute.type) {
96
- case AttributeType.String:
97
- case AttributeType.Text:
98
- case AttributeType.Password:
99
- case AttributeType.Email:
100
- return 'string';
101
- case AttributeType.Integer:
102
- case AttributeType.BigInteger:
103
- case AttributeType.Decimal:
104
- return 'number';
105
- case AttributeType.Boolean:
106
- return 'boolean';
107
- case AttributeType.Relation:
108
- return getRelationType(attribute);
109
- case AttributeType.Component:
110
- return getComponentType(attribute);
111
- case AttributeType.DateTime:
112
- return 'string'; // Usually, date/time fields come as strings from the API
113
- case AttributeType.Json:
114
- return 'object'; // Could be Record<string, unknown> if you want stricter typing
115
- case AttributeType.Media:
116
- // Media fields can be objects or arrays of objects representing files
117
- // You can type them more specifically if needed
118
- return 'any';
119
- case AttributeType.Enumeration:
120
- return `'${attribute.enum.join('\' | \'')}'`;
121
- default:
122
- // For unrecognized types, we check further below
123
- break;
124
- }
125
- }
126
- /**
127
- * Returns the TypeScript interface name from a component UID
128
- * e.g. "default.test-component" => "DefaultTestComponent"
129
- */
130
- function getComponentName(uid) {
131
- return uid
132
- .split(/[\.\-]/)
133
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
134
- .join('');
135
- }
136
- /**
137
- * Returns the TypeScript interface name from a content type UID
138
- * e.g. "api::article.article" => "Article"
139
- */
140
- function getContentTypeName(uid) {
141
- // Usually, UIDs look like "api::<api-name>.<model-name>"
142
- // We'll split at "::" and then take the part after the dot.
143
- const namePart = uid.split('::')[1] || uid;
144
- const modelName = namePart.split('.')[1] || namePart;
145
- // Convert to PascalCase
146
- return modelName
147
- .split('-')
148
- .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
149
- .join('');
150
- }
151
50
  function getContentTypeMethodName(uid) {
152
- const typeName = getContentTypeName(uid);
51
+ const typeName = (0, get_content_type_name_1.getContentTypeName)(uid);
153
52
  return typeName.charAt(0).toLowerCase() + typeName.slice(1);
154
53
  }
155
54
  /**
156
55
  * Generates a TS interface from a content type or component definition
157
56
  */
158
- function generateTypeCode(name, attributes) {
57
+ function generateResponseTypeCode(name, attributes) {
159
58
  const lines = [];
160
59
  lines.push(`export type ${name} = {`);
161
60
  for (const attributeName in attributes) {
162
61
  const attribute = attributes[attributeName];
163
- const typeName = getAttributeType(attribute);
164
62
  const isRequired = attribute.required ? '' : '?';
165
- lines.push(` ${attributeName}${isRequired}: ${typeName};`);
63
+ lines.push(` ${attributeName}${isRequired}: ${(0, attributes_1.default)(attributeName, attribute).getType()};`);
166
64
  }
167
65
  lines.push(`}`);
168
66
  return lines.join('\n');
169
67
  }
170
68
  function generateQueryTypeCode(name, attributes) {
171
69
  const fields = [];
172
- const sort = [];
70
+ const sortFields = [];
173
71
  const filters = [];
174
- const populate = [];
72
+ const populates = [];
175
73
  for (const attributeName in attributes) {
176
74
  const attribute = attributes[attributeName];
177
- fields.push(`'${attributeName}'`);
178
- if ([
179
- AttributeType.String,
180
- AttributeType.Text,
181
- AttributeType.Password,
182
- AttributeType.Email,
183
- AttributeType.Integer,
184
- AttributeType.BigInteger,
185
- AttributeType.Decimal,
186
- AttributeType.Float,
187
- AttributeType.Boolean,
188
- AttributeType.DateTime,
189
- AttributeType.Enumeration,
190
- ].includes(attribute.type)) {
191
- sort.push(`'${attributeName}'`);
192
- sort.push(`'${attributeName}:asc'`);
193
- sort.push(`'${attributeName}:desc'`);
194
- }
195
- const type = getAttributeType(attribute);
196
- switch (attribute.type) {
197
- case AttributeType.Relation:
198
- filters.push(` ${attributeName}?: ${getContentTypeName(attribute.target)}Filters;`);
199
- populate.push(` ${attributeName}?: ${getContentTypeName(attribute.target)}Query;`);
200
- break;
201
- case AttributeType.Component:
202
- populate.push(` ${attributeName}?: ${getComponentName(attribute.component)}Query;`);
203
- break;
204
- case AttributeType.Media:
205
- case AttributeType.Json:
206
- break;
207
- default:
208
- filters.push(` ${attributeName}?: FilterValue<${type}>;`);
209
- }
75
+ const attributeGenerator = (0, attributes_1.default)(attributeName, attribute);
76
+ fields.push(...attributeGenerator.getFields());
77
+ sortFields.push(...attributeGenerator.getSortFields());
78
+ filters.push(...attributeGenerator.getFilters());
79
+ populates.push(...attributeGenerator.getPopulates());
210
80
  }
211
81
  const lines = [];
212
82
  lines.push(`export type ${name}Filters = Filters<{`);
213
- lines.push(...filters);
83
+ lines.push(...filters.map(({ name, type }) => ` ${name}?: ${type};`));
214
84
  lines.push(`}>`);
215
85
  lines.push('');
216
86
  lines.push(`export type ${name}Populate = {`);
217
- lines.push(...populate);
87
+ lines.push(...populates.map(({ name, type }) => ` ${name}?: ${type};`));
218
88
  lines.push(`}`);
219
89
  lines.push('');
220
90
  lines.push(`export type ${name}Query = Query<`);
221
- lines.push(` ${fields.join(' | ')},`);
222
- lines.push(` ${sort.join(' | ')},`);
91
+ lines.push(` ${fields.map(field => `'${field}'`).join(' | ')},`);
92
+ lines.push(` ${sortFields.map(field => `'${field}'`).join(' | ')},`);
223
93
  lines.push(` ${name}Filters,`);
224
94
  lines.push(` ${name}Populate`);
225
95
  lines.push(`>`);
226
96
  return lines.join('\n');
227
97
  }
98
+ function generateInputTypeCode(name, attributes) {
99
+ const fields = [];
100
+ for (const attributeName in attributes) {
101
+ const attribute = attributes[attributeName];
102
+ const attributeGenerator = (0, attributes_1.default)(attributeName, attribute);
103
+ fields.push({
104
+ name: attributeName,
105
+ type: attributeGenerator.getInputType(),
106
+ });
107
+ }
108
+ const lines = [];
109
+ lines.push(`export type ${name}Input = {`);
110
+ lines.push(...fields.map(({ name, type }) => ` ${name}?: ${type};`));
111
+ lines.push(`}`);
112
+ return lines.join('\n');
113
+ }
228
114
  function generateMethodsCode(contentType) {
229
115
  const methods = [];
230
- const modelName = getContentTypeName(contentType.uid);
116
+ const modelName = (0, get_content_type_name_1.getContentTypeName)(contentType.uid);
231
117
  if (contentType.schema.kind === ContentTypeKind.CollectionType) {
232
118
  methods.push([
233
119
  ` public async ${getContentTypeMethodName(contentType.schema.pluralName)}(query?: ${modelName}Query, params?: RequestInit) {`,
@@ -240,62 +126,79 @@ function generateMethodsCode(contentType) {
240
126
  ` return await this.getDocument<${modelName}, ${modelName}Query>('${contentType.schema.singularName}', query, params);`,
241
127
  ' }',
242
128
  ].join('\n'));
129
+ methods.push([
130
+ ` public async create${(0, get_content_type_name_1.getContentTypeName)(contentType.schema.singularName)}(data: ${modelName}Input, params?: RequestInit) {`,
131
+ ` return await this.create<${modelName}, ${modelName}Input>('${contentType.schema.pluralName}', data, params);`,
132
+ ' }',
133
+ ].join('\n'));
134
+ methods.push([
135
+ ` public async update${(0, get_content_type_name_1.getContentTypeName)(contentType.schema.singularName)}(id: string, data: ${modelName}Input, params?: RequestInit) {`,
136
+ ` return await this.update<${modelName}, ${modelName}Input>('${contentType.schema.pluralName}', id, data, params);`,
137
+ ' }',
138
+ ].join('\n'));
139
+ methods.push([
140
+ ` public async delete${(0, get_content_type_name_1.getContentTypeName)(contentType.schema.singularName)}(id: string, params?: RequestInit) {`,
141
+ ` return await this.delete<${modelName}>('${contentType.schema.pluralName}', id, params);`,
142
+ ' }',
143
+ ].join('\n'));
243
144
  return methods;
244
145
  }
245
146
  /**
246
147
  * Main function to fetch Strapi (v5) data and generate the d.ts file
247
148
  */
248
- async function generateStrapiTypes() {
249
- const strapi = new main_1.Strapi(process.env.STRAPI_URL, process.env.STRAPI_TOKEN);
149
+ async function generateStrapiTypes(strapi) {
250
150
  const contentTypes = (await strapi.request('content-type-builder/content-types')).data;
251
151
  const components = (await strapi.request('content-type-builder/components')).data;
252
152
  const allInterfaces = [];
253
153
  const methods = [];
254
154
  for (const component of components) {
255
- console.log(component.schema.attributes);
256
- const componentName = getComponentName(component.uid);
155
+ const componentName = (0, get_component_name_1.getComponentName)(component.uid);
257
156
  const attributes = {
258
157
  id: {
259
- type: AttributeType.Integer,
158
+ type: 'integer',
260
159
  },
261
160
  ...component.schema.attributes,
262
161
  };
263
- const code = generateTypeCode(componentName, attributes);
162
+ allInterfaces.push(generateResponseTypeCode(componentName, attributes));
264
163
  allInterfaces.push(generateQueryTypeCode(componentName, attributes));
265
- allInterfaces.push(code);
164
+ allInterfaces.push(generateInputTypeCode(componentName, attributes));
266
165
  }
267
166
  for (const contentType of contentTypes) {
268
- // console.log(contentTypes);
269
- if (!(contentType.uid.startsWith('api::') || contentType.uid.startsWith('plugin::users-permissions'))) {
167
+ if (!['api::', 'plugin::upload', 'plugin::users-permissions'].filter(prefix => contentType.uid.startsWith(prefix)).length) {
270
168
  continue;
271
169
  }
272
170
  methods.push(...generateMethodsCode(contentType));
273
- const modelName = getContentTypeName(contentType.uid);
171
+ const modelName = (0, get_content_type_name_1.getContentTypeName)(contentType.uid);
274
172
  const attributes = {
275
173
  id: {
276
- type: AttributeType.Integer,
174
+ type: 'integer',
277
175
  },
278
176
  documentId: {
279
- type: AttributeType.String,
177
+ type: 'string',
280
178
  },
281
179
  createdAt: {
282
- type: AttributeType.DateTime,
180
+ type: 'datetime',
283
181
  },
284
182
  updatedAt: {
285
- type: AttributeType.DateTime,
183
+ type: 'datetime',
286
184
  },
287
185
  ...contentType.schema.attributes,
288
186
  };
289
- allInterfaces.push(generateTypeCode(modelName, attributes));
187
+ allInterfaces.push(generateResponseTypeCode(modelName, attributes));
290
188
  allInterfaces.push(generateQueryTypeCode(modelName, attributes));
189
+ allInterfaces.push(generateInputTypeCode(modelName, attributes));
291
190
  }
292
191
  const output = [
293
- 'import {Strapi as StrapiBase, Query, Filters, FilterValue} from "@malevich-studio/strapi-sdk-typescript";\n',
192
+ 'import {Strapi as StrapiBase, Query, Filters, FilterValue, RelationInput} from "@malevich-studio/strapi-sdk-typescript";',
193
+ 'import {BlocksContent} from "@strapi/blocks-react-renderer";',
194
+ '',
294
195
  'export default class Strapi extends StrapiBase {',
295
- ...methods,
196
+ methods.join('\n\n'),
296
197
  '}',
297
- ...allInterfaces,
298
- ].join('\n\n');
198
+ '',
199
+ allInterfaces.join('\n\n'),
200
+ '',
201
+ ].join('\n');
299
202
  const outPath = path.join(process.cwd(), 'strapi.ts');
300
203
  fs.writeFileSync(outPath, output, 'utf-8');
301
204
  console.log(`✅ "strapi.ts" has been successfully generated!`);
@@ -0,0 +1,10 @@
1
+ import Base, { AttributeMode, BaseAttribute } from "./base";
2
+ export default class BaseRelation extends Base {
3
+ protected readonly name: string;
4
+ protected readonly attribute: BaseAttribute;
5
+ constructor(name: string, attribute: BaseAttribute);
6
+ getType(): string;
7
+ getFields(): string[];
8
+ getSortFields(): string[];
9
+ getMode(): AttributeMode;
10
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const base_1 = __importStar(require("./base"));
37
+ class BaseRelation extends base_1.default {
38
+ constructor(name, attribute) {
39
+ super(name, attribute);
40
+ this.name = name;
41
+ this.attribute = attribute;
42
+ }
43
+ getType() {
44
+ return 'any';
45
+ }
46
+ getFields() {
47
+ return [];
48
+ }
49
+ getSortFields() {
50
+ return [];
51
+ }
52
+ getMode() {
53
+ return base_1.AttributeMode.Relation;
54
+ }
55
+ }
56
+ exports.default = BaseRelation;
@@ -0,0 +1,27 @@
1
+ export type BaseAttribute = {
2
+ configurable?: boolean;
3
+ required?: boolean;
4
+ private?: boolean;
5
+ };
6
+ export declare enum AttributeMode {
7
+ Field = "field",
8
+ Relation = "relation"
9
+ }
10
+ export type FieldType = {
11
+ name: string;
12
+ type: string;
13
+ };
14
+ export default class Base {
15
+ protected readonly name: string;
16
+ protected readonly attribute: BaseAttribute;
17
+ constructor(name: string, attribute: BaseAttribute);
18
+ getType(): string;
19
+ getInputType(): string;
20
+ getImports(): string[];
21
+ getPackages(): string[];
22
+ getFields(): string[];
23
+ getSortFields(): string[];
24
+ getPopulates(): FieldType[];
25
+ getFilters(): FieldType[];
26
+ getMode(): AttributeMode;
27
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AttributeMode = void 0;
4
+ var AttributeMode;
5
+ (function (AttributeMode) {
6
+ AttributeMode["Field"] = "field";
7
+ AttributeMode["Relation"] = "relation";
8
+ })(AttributeMode || (exports.AttributeMode = AttributeMode = {}));
9
+ class Base {
10
+ constructor(name, attribute) {
11
+ this.name = name;
12
+ this.attribute = attribute;
13
+ }
14
+ getType() {
15
+ return 'any';
16
+ }
17
+ getInputType() {
18
+ return this.getType();
19
+ }
20
+ getImports() {
21
+ return [];
22
+ }
23
+ getPackages() {
24
+ return [];
25
+ }
26
+ getFields() {
27
+ return [
28
+ this.name,
29
+ ];
30
+ }
31
+ getSortFields() {
32
+ return [
33
+ this.name,
34
+ `${this.name}:asc`,
35
+ `${this.name}:desc`,
36
+ ];
37
+ }
38
+ getPopulates() {
39
+ return [];
40
+ }
41
+ getFilters() {
42
+ return [
43
+ {
44
+ name: this.name,
45
+ type: `FilterValue<${this.getType()}>`,
46
+ },
47
+ ];
48
+ }
49
+ getMode() {
50
+ return AttributeMode.Field;
51
+ }
52
+ }
53
+ exports.default = Base;
@@ -0,0 +1,12 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type BlocksAttribute = BaseAttribute & {
3
+ type: 'blocks';
4
+ };
5
+ export default class Blocks extends Base {
6
+ protected readonly name: string;
7
+ protected readonly attribute: BlocksAttribute;
8
+ constructor(name: string, attribute: BlocksAttribute);
9
+ getType(): string;
10
+ getImports(): string[];
11
+ getPackages(): string[];
12
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class Blocks extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'BlocksContent';
15
+ }
16
+ getImports() {
17
+ return [
18
+ ...super.getImports(),
19
+ 'import {BlocksContent} from "@strapi/blocks-react-renderer";',
20
+ ];
21
+ }
22
+ getPackages() {
23
+ return [
24
+ ...super.getPackages(),
25
+ '@strapi/blocks-react-renderer',
26
+ ];
27
+ }
28
+ }
29
+ exports.default = Blocks;
@@ -0,0 +1,10 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type BooleanAttribute = BaseAttribute & {
3
+ type: 'boolean';
4
+ };
5
+ export default class Boolean extends Base {
6
+ protected readonly name: string;
7
+ protected readonly attribute: BooleanAttribute;
8
+ constructor(name: string, attribute: BooleanAttribute);
9
+ getType(): string;
10
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class Boolean extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'boolean';
15
+ }
16
+ }
17
+ exports.default = Boolean;
@@ -0,0 +1,20 @@
1
+ import { BaseAttribute, FieldType } from "./base";
2
+ import BaseRelation from "./base-relation";
3
+ export type ComponentAttribute = BaseAttribute & {
4
+ type: 'component';
5
+ repeatable: boolean;
6
+ component: string;
7
+ min?: number;
8
+ };
9
+ export default class Component extends BaseRelation {
10
+ protected readonly name: string;
11
+ protected readonly attribute: ComponentAttribute;
12
+ constructor(name: string, attribute: ComponentAttribute);
13
+ getType(): string;
14
+ getInputType(): string;
15
+ getPopulates(): {
16
+ name: string;
17
+ type: string;
18
+ }[];
19
+ getFilters(): FieldType[];
20
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const get_component_name_1 = require("../utils/get-component-name");
7
+ const base_relation_1 = __importDefault(require("./base-relation"));
8
+ class Component extends base_relation_1.default {
9
+ constructor(name, attribute) {
10
+ super(name, attribute);
11
+ this.name = name;
12
+ this.attribute = attribute;
13
+ }
14
+ getType() {
15
+ const componentName = (0, get_component_name_1.getComponentName)(this.attribute.component);
16
+ return this.attribute.repeatable ? `${componentName}[]` : componentName;
17
+ }
18
+ getInputType() {
19
+ return `${(0, get_component_name_1.getComponentName)(this.attribute.component)}Input`;
20
+ }
21
+ getPopulates() {
22
+ return [{
23
+ name: this.name,
24
+ type: `${(0, get_component_name_1.getComponentName)(this.attribute.component)}Query`,
25
+ }];
26
+ }
27
+ getFilters() {
28
+ return [
29
+ // {
30
+ // name: this.name,
31
+ // type: `${getComponentName(this.attribute.component)}Filters`,
32
+ // }
33
+ ];
34
+ }
35
+ }
36
+ exports.default = Component;
@@ -0,0 +1,10 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type DateTimeAttribute = BaseAttribute & {
3
+ type: 'datetime';
4
+ };
5
+ export default class DateTime extends Base {
6
+ protected readonly name: string;
7
+ protected readonly attribute: DateTimeAttribute;
8
+ constructor(name: string, attribute: DateTimeAttribute);
9
+ getType(): string;
10
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class DateTime extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'string';
15
+ }
16
+ }
17
+ exports.default = DateTime;
@@ -0,0 +1,12 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type EnumerationAttribute = BaseAttribute & {
3
+ type: 'enumeration';
4
+ enum: string[];
5
+ default: string;
6
+ };
7
+ export default class Enumeration extends Base {
8
+ protected readonly name: string;
9
+ protected readonly attribute: EnumerationAttribute;
10
+ constructor(name: string, attribute: EnumerationAttribute);
11
+ getType(): string;
12
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class Enumeration extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return `'${this.attribute.enum.join('\' | \'')}'`;
15
+ }
16
+ }
17
+ exports.default = Enumeration;
@@ -0,0 +1,4 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export default function getAttributeGenerator(name: string, attribute: BaseAttribute & {
3
+ type: string;
4
+ }): Base;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = getAttributeGenerator;
7
+ const string_1 = __importDefault(require("./string"));
8
+ const number_1 = __importDefault(require("./number"));
9
+ const media_1 = __importDefault(require("./media"));
10
+ const relation_1 = __importDefault(require("./relation"));
11
+ const enumeration_1 = __importDefault(require("./enumeration"));
12
+ const date_time_1 = __importDefault(require("./date-time"));
13
+ const component_1 = __importDefault(require("./component"));
14
+ const blocks_1 = __importDefault(require("./blocks"));
15
+ const json_1 = __importDefault(require("./json"));
16
+ const boolean_1 = __importDefault(require("./boolean"));
17
+ const types = {
18
+ 'string': string_1.default,
19
+ 'text': string_1.default,
20
+ 'password': string_1.default,
21
+ 'email': string_1.default,
22
+ 'integer': number_1.default,
23
+ 'biginteger': number_1.default,
24
+ 'decimal': number_1.default,
25
+ 'float': number_1.default,
26
+ 'boolean': boolean_1.default,
27
+ 'media': media_1.default,
28
+ 'relation': relation_1.default,
29
+ 'enumeration': enumeration_1.default,
30
+ 'datetime': date_time_1.default,
31
+ 'component': component_1.default,
32
+ 'blocks': blocks_1.default,
33
+ 'json': json_1.default,
34
+ };
35
+ function getAttributeGenerator(name, attribute) {
36
+ if (!types[attribute.type]) {
37
+ throw new Error(`Attribute type "${attribute.type}" is not defined`);
38
+ }
39
+ return new types[attribute.type](name, attribute);
40
+ }
@@ -0,0 +1,11 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type JsonAttribute = BaseAttribute & {
3
+ type: 'json';
4
+ };
5
+ export default class Json extends Base {
6
+ protected readonly name: string;
7
+ protected readonly attribute: JsonAttribute;
8
+ constructor(name: string, attribute: JsonAttribute);
9
+ getType(): string;
10
+ getFilters(): any[];
11
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class Json extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'object';
15
+ }
16
+ getFilters() {
17
+ return [];
18
+ }
19
+ }
20
+ exports.default = Json;
@@ -0,0 +1,21 @@
1
+ import { BaseAttribute } from "./base";
2
+ import BaseRelation from "./base-relation";
3
+ export type MediaAttribute = BaseAttribute & {
4
+ type: 'media';
5
+ multiple: boolean;
6
+ allowedTypes: string[];
7
+ };
8
+ export default class Media extends BaseRelation {
9
+ protected readonly name: string;
10
+ protected readonly attribute: MediaAttribute;
11
+ constructor(name: string, attribute: MediaAttribute);
12
+ getType(): "File[]" | "File";
13
+ getPopulates(): {
14
+ name: string;
15
+ type: string;
16
+ }[];
17
+ getFilters(): {
18
+ name: string;
19
+ type: string;
20
+ }[];
21
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_relation_1 = __importDefault(require("./base-relation"));
7
+ class Media extends base_relation_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return this.attribute.multiple ? 'File[]' : 'File';
15
+ }
16
+ getPopulates() {
17
+ return [{
18
+ name: this.name,
19
+ type: 'FileQuery',
20
+ }];
21
+ }
22
+ getFilters() {
23
+ return [{
24
+ name: this.name,
25
+ type: 'FileFilters',
26
+ }];
27
+ }
28
+ }
29
+ exports.default = Media;
@@ -0,0 +1,12 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type NumberAttribute = BaseAttribute & {
3
+ type: 'integer' | 'biginteger' | 'decimal';
4
+ min?: number;
5
+ max?: number;
6
+ };
7
+ export default class Number extends Base {
8
+ protected readonly name: string;
9
+ protected readonly attribute: NumberAttribute;
10
+ constructor(name: string, attribute: NumberAttribute);
11
+ getType(): string;
12
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class Number extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'number';
15
+ }
16
+ }
17
+ exports.default = Number;
@@ -0,0 +1,48 @@
1
+ import { BaseAttribute } from "./base";
2
+ import BaseRelation from "./base-relation";
3
+ export declare enum AttributeRelation {
4
+ MorphToMany = "morphToMany",
5
+ ManyToOne = "manyToOne",
6
+ ManyToMany = "manyToMany",
7
+ OneToMany = "oneToMany",
8
+ OneToOne = "oneToOne"
9
+ }
10
+ type RelationData = {
11
+ documentId: string;
12
+ before?: string;
13
+ after?: string;
14
+ start?: true;
15
+ end?: true;
16
+ locale?: string;
17
+ status?: 'published' | 'draft';
18
+ } | string;
19
+ export type RelationInput = {
20
+ connect?: RelationData[];
21
+ disconnect?: RelationData[];
22
+ set?: RelationData[];
23
+ } | RelationData[];
24
+ export type RelationAttribute = BaseAttribute & {
25
+ type: 'relation';
26
+ relation: AttributeRelation;
27
+ target: string;
28
+ targetAttribute?: string;
29
+ inversedBy: string;
30
+ mappedBy: string;
31
+ };
32
+ export default class Relation extends BaseRelation {
33
+ protected readonly name: string;
34
+ protected readonly attribute: RelationAttribute;
35
+ constructor(name: string, attribute: RelationAttribute);
36
+ getType(): string;
37
+ getInputType(): string;
38
+ getPopulates(): {
39
+ name: string;
40
+ type: string;
41
+ }[];
42
+ getFilters(): {
43
+ name: string;
44
+ type: string;
45
+ }[];
46
+ getImports(): string[];
47
+ }
48
+ export {};
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AttributeRelation = void 0;
7
+ const get_content_type_name_1 = require("../utils/get-content-type-name");
8
+ const base_relation_1 = __importDefault(require("./base-relation"));
9
+ var AttributeRelation;
10
+ (function (AttributeRelation) {
11
+ AttributeRelation["MorphToMany"] = "morphToMany";
12
+ AttributeRelation["ManyToOne"] = "manyToOne";
13
+ AttributeRelation["ManyToMany"] = "manyToMany";
14
+ AttributeRelation["OneToMany"] = "oneToMany";
15
+ AttributeRelation["OneToOne"] = "oneToOne";
16
+ })(AttributeRelation || (exports.AttributeRelation = AttributeRelation = {}));
17
+ class Relation extends base_relation_1.default {
18
+ constructor(name, attribute) {
19
+ super(name, attribute);
20
+ this.name = name;
21
+ this.attribute = attribute;
22
+ }
23
+ getType() {
24
+ if (this.attribute.relation === AttributeRelation.MorphToMany) {
25
+ return 'any';
26
+ }
27
+ const ContentTypeName = (0, get_content_type_name_1.getContentTypeName)(this.attribute.target);
28
+ switch (this.attribute.relation) {
29
+ case AttributeRelation.ManyToMany:
30
+ case AttributeRelation.OneToMany:
31
+ return `${ContentTypeName}[]`;
32
+ case AttributeRelation.ManyToOne:
33
+ case AttributeRelation.OneToOne:
34
+ default:
35
+ return ContentTypeName;
36
+ }
37
+ }
38
+ getInputType() {
39
+ return 'RelationInput';
40
+ }
41
+ getPopulates() {
42
+ if (this.attribute.relation === AttributeRelation.MorphToMany) {
43
+ return [];
44
+ }
45
+ return [{
46
+ name: this.name,
47
+ type: `${(0, get_content_type_name_1.getContentTypeName)(this.attribute.target)}Query`,
48
+ }];
49
+ }
50
+ getFilters() {
51
+ if (this.attribute.relation === AttributeRelation.MorphToMany) {
52
+ return [];
53
+ }
54
+ return [{
55
+ name: this.name,
56
+ type: `${(0, get_content_type_name_1.getContentTypeName)(this.attribute.target)}Filters`,
57
+ }];
58
+ }
59
+ getImports() {
60
+ return [
61
+ ...super.getImports(),
62
+ 'import {RelationInput} from "@strapi/blocks-react-renderer";',
63
+ ];
64
+ }
65
+ }
66
+ exports.default = Relation;
@@ -0,0 +1,13 @@
1
+ import Base, { BaseAttribute } from "./base";
2
+ export type StringAttribute = BaseAttribute & {
3
+ type: 'text' | 'string' | 'password' | 'email';
4
+ minLength?: number;
5
+ maxLength?: number;
6
+ searchable?: boolean;
7
+ };
8
+ export default class String extends Base {
9
+ protected readonly name: string;
10
+ protected readonly attribute: StringAttribute;
11
+ constructor(name: string, attribute: StringAttribute);
12
+ getType(): string;
13
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const base_1 = __importDefault(require("./base"));
7
+ class String extends base_1.default {
8
+ constructor(name, attribute) {
9
+ super(name, attribute);
10
+ this.name = name;
11
+ this.attribute = attribute;
12
+ }
13
+ getType() {
14
+ return 'string';
15
+ }
16
+ }
17
+ exports.default = String;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns the TypeScript interface name from a component UID
3
+ * e.g. "default.test-component" => "DefaultTestComponent"
4
+ */
5
+ export declare function getComponentName(uid: string): string;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getComponentName = getComponentName;
4
+ /**
5
+ * Returns the TypeScript interface name from a component UID
6
+ * e.g. "default.test-component" => "DefaultTestComponent"
7
+ */
8
+ function getComponentName(uid) {
9
+ return uid
10
+ .split(/[\.\-]/)
11
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
12
+ .join('');
13
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Returns the TypeScript interface name from a content type UID
3
+ * e.g. "api::article.article" => "Article"
4
+ */
5
+ export declare function getContentTypeName(uid: string): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getContentTypeName = getContentTypeName;
4
+ /**
5
+ * Returns the TypeScript interface name from a content type UID
6
+ * e.g. "api::article.article" => "Article"
7
+ */
8
+ function getContentTypeName(uid) {
9
+ // Usually, UIDs look like "api::<api-name>.<model-name>"
10
+ // We'll split at "::" and then take the part after the dot.
11
+ const namePart = uid.split('::')[1] || uid;
12
+ const modelName = namePart.split('.')[1] || namePart;
13
+ // Convert to PascalCase
14
+ return modelName
15
+ .split('-')
16
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
17
+ .join('');
18
+ }
package/dist/main.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { RelationInput } from "./generator/attributes/relation";
2
+ export type { RelationInput };
1
3
  type Response<T> = {
2
4
  data: T;
3
5
  meta: {
@@ -63,6 +65,7 @@ export declare class Strapi {
63
65
  request<T>(endpoint: string, data?: object, params?: RequestInit): Promise<Response<T>>;
64
66
  getDocuments<T, Q extends object>(endpoint: string, data?: Q, params?: RequestInit): Promise<Response<T[]>>;
65
67
  getDocument<T, Q extends object>(endpoint: string, data?: Q, params?: RequestInit): Promise<Response<T>>;
66
- create<T>(endpoint: string, data?: object, params?: RequestInit): Promise<Response<T>>;
68
+ create<T, Q extends object>(endpoint: string, data: Q, params?: RequestInit): Promise<Response<T>>;
69
+ update<T, Q extends object>(endpoint: string, id: string, data: Q, params?: RequestInit): Promise<Response<T>>;
70
+ delete<T>(endpoint: string, id: string, params?: RequestInit): Promise<Response<T>>;
67
71
  }
68
- export {};
package/dist/main.js CHANGED
@@ -20,7 +20,7 @@ class Strapi {
20
20
  'Content-Type': 'application/json',
21
21
  },
22
22
  cache: 'no-store',
23
- ...(params.method && params.method !== 'GET' ? {
23
+ ...(params.method && !['GET', 'DELETE'].includes(params.method) ? {
24
24
  body: JSON.stringify({
25
25
  data,
26
26
  })
@@ -45,11 +45,23 @@ class Strapi {
45
45
  ...params,
46
46
  });
47
47
  }
48
- async create(endpoint, data = {}, params = {}) {
48
+ async create(endpoint, data, params = {}) {
49
49
  return await this.request(endpoint, data, {
50
50
  method: 'POST',
51
51
  ...params,
52
52
  });
53
53
  }
54
+ async update(endpoint, id, data, params = {}) {
55
+ return await this.request(`${endpoint}/${id}`, data, {
56
+ method: 'PUT',
57
+ ...params,
58
+ });
59
+ }
60
+ async delete(endpoint, id, params = {}) {
61
+ return await this.request(`${endpoint}/${id}`, {}, {
62
+ method: 'DELETE',
63
+ ...params,
64
+ });
65
+ }
54
66
  }
55
67
  exports.Strapi = Strapi;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@malevich-studio/strapi-sdk-typescript",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/main.d.ts",
6
6
  "bin": {
7
7
  "generate-strapi-types": "dist/cli.js"
8
8
  },
9
9
  "files": [
10
- "dist"
10
+ "dist",
11
+ "README.md"
11
12
  ],
12
13
  "scripts": {
13
14
  "build": "tsc",