@strapi/strapi 4.3.0-beta.1 → 4.3.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.
Files changed (43) hide show
  1. package/bin/strapi.js +19 -1
  2. package/lib/Strapi.js +4 -2
  3. package/lib/commands/opt-in-telemetry.js +100 -0
  4. package/lib/commands/ts/generate-types.js +26 -0
  5. package/lib/core/app-configuration/config-loader.js +3 -1
  6. package/lib/core/domain/content-type/validator.js +29 -8
  7. package/lib/global.d.ts +61 -0
  8. package/lib/index.d.ts +2 -25
  9. package/lib/services/cron.js +7 -3
  10. package/lib/services/webhook-runner.js +1 -1
  11. package/lib/types/core/attributes/base.d.ts +74 -0
  12. package/lib/types/core/attributes/biginteger.d.ts +22 -0
  13. package/lib/types/core/attributes/boolean.d.ts +20 -0
  14. package/lib/types/core/attributes/common.d.ts +42 -0
  15. package/lib/types/core/attributes/component.d.ts +41 -0
  16. package/lib/types/core/attributes/date-time.d.ts +22 -0
  17. package/lib/types/core/attributes/date.d.ts +22 -0
  18. package/lib/types/core/attributes/decimal.d.ts +22 -0
  19. package/lib/types/core/attributes/dynamic-zone.d.ts +29 -0
  20. package/lib/types/core/attributes/email.d.ts +24 -0
  21. package/lib/types/core/attributes/enumeration.d.ts +28 -0
  22. package/lib/types/core/attributes/float.d.ts +22 -0
  23. package/lib/types/core/attributes/index.d.ts +26 -0
  24. package/lib/types/core/attributes/integer.d.ts +22 -0
  25. package/lib/types/core/attributes/json.d.ts +14 -0
  26. package/lib/types/core/attributes/media.d.ts +36 -0
  27. package/lib/types/core/attributes/password.d.ts +22 -0
  28. package/lib/types/core/attributes/relation.d.ts +66 -0
  29. package/lib/types/core/attributes/richtext.d.ts +22 -0
  30. package/lib/types/core/attributes/string.d.ts +30 -0
  31. package/lib/types/core/attributes/text.d.ts +30 -0
  32. package/lib/types/core/attributes/time.d.ts +22 -0
  33. package/lib/types/core/attributes/timestamp.d.ts +22 -0
  34. package/lib/types/core/attributes/uid.d.ts +57 -0
  35. package/lib/types/core/attributes/utils.d.ts +99 -0
  36. package/lib/types/core/index.d.ts +3 -0
  37. package/lib/types/core/schemas/index.d.ts +126 -0
  38. package/lib/types/{strapi.d.ts → core/strapi/index.d.ts} +21 -0
  39. package/lib/{factories.d.ts → types/factories.d.ts} +19 -11
  40. package/lib/types/index.d.ts +4 -0
  41. package/lib/types/utils.d.ts +95 -1
  42. package/lib/utils/machine-id.js +2 -2
  43. package/package.json +22 -22
package/bin/strapi.js CHANGED
@@ -231,7 +231,25 @@ program
231
231
  // `$ strapi opt-out-telemetry`
232
232
  program
233
233
  .command('telemetry:disable')
234
- .description('Stop Strapi from sending anonymous telemetry and metadata')
234
+ .description('Disable anonymous telemetry and metadata sending to Strapi analytics')
235
235
  .action(getLocalScript('opt-out-telemetry'));
236
236
 
237
+ // `$ strapi opt-in-telemetry`
238
+ program
239
+ .command('telemetry:enable')
240
+ .description('Enable anonymous telemetry and metadata sending to Strapi analytics')
241
+ .action(getLocalScript('opt-in-telemetry'));
242
+
243
+ program
244
+ .command('ts:generate-types')
245
+ .description(`Generate TypeScript typings for your schemas`)
246
+ .option(
247
+ '-o, --out-dir <outDir>',
248
+ 'Specify a relative directory in which the schemas definitions will be generated'
249
+ )
250
+ .option('-f, --file <file>', 'Specify a filename to store the schemas definitions')
251
+ .option('--verbose', `Display more information about the types generation`, false)
252
+ .option('-s, --silent', `Run the generation silently, without any output`, false)
253
+ .action(getLocalScript('ts/generate-types'));
254
+
237
255
  program.parseAsync(process.argv);
package/lib/Strapi.js CHANGED
@@ -405,8 +405,10 @@ class Strapi {
405
405
  entityValidator: this.entityValidator,
406
406
  });
407
407
 
408
- const cronTasks = this.config.get('server.cron.tasks', {});
409
- this.cron.add(cronTasks);
408
+ if (strapi.config.get('server.cron.enabled', true)) {
409
+ const cronTasks = this.config.get('server.cron.tasks', {});
410
+ this.cron.add(cronTasks);
411
+ }
410
412
 
411
413
  this.telemetry.bootstrap();
412
414
 
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+
3
+ const { resolve } = require('path');
4
+ const fse = require('fs-extra');
5
+ const chalk = require('chalk');
6
+ const fetch = require('node-fetch');
7
+ const { v4: uuidv4 } = require('uuid');
8
+ const machineID = require('../utils/machine-id');
9
+
10
+ const readPackageJSON = async path => {
11
+ try {
12
+ const packageObj = await fse.readJson(path);
13
+ return packageObj;
14
+ } catch (err) {
15
+ console.error(`${chalk.red('Error')}: ${err.message}`);
16
+ }
17
+ };
18
+
19
+ const writePackageJSON = async (path, file, spacing) => {
20
+ try {
21
+ await fse.writeJson(path, file, { spaces: spacing });
22
+ return true;
23
+ } catch (err) {
24
+ console.error(`${chalk.red('Error')}: ${err.message}`);
25
+ console.log(
26
+ `${chalk.yellow(
27
+ 'Warning'
28
+ )}: There has been an error, please set "telemetryDisabled": false in the "strapi" object of your package.json manually.`
29
+ );
30
+ return false;
31
+ }
32
+ };
33
+
34
+ const generateNewPackageJSON = packageObj => {
35
+ if (!packageObj.strapi) {
36
+ return {
37
+ ...packageObj,
38
+ strapi: {
39
+ uuid: uuidv4(),
40
+ telemetryDisabled: false,
41
+ },
42
+ };
43
+ } else {
44
+ return {
45
+ ...packageObj,
46
+ strapi: {
47
+ ...packageObj.strapi,
48
+ uuid: packageObj.strapi.uuid ? packageObj.strapi.uuid : uuidv4(),
49
+ telemetryDisabled: false,
50
+ },
51
+ };
52
+ }
53
+ };
54
+
55
+ const sendEvent = async uuid => {
56
+ try {
57
+ await fetch('https://analytics.strapi.io/track', {
58
+ method: 'POST',
59
+ body: JSON.stringify({
60
+ event: 'didOptInTelemetry',
61
+ uuid,
62
+ deviceId: machineID(),
63
+ }),
64
+ headers: { 'Content-Type': 'application/json' },
65
+ });
66
+ } catch (e) {
67
+ //...
68
+ }
69
+ };
70
+
71
+ module.exports = async function optInTelemetry() {
72
+ const packageJSONPath = resolve(process.cwd(), 'package.json');
73
+ const exists = await fse.pathExists(packageJSONPath);
74
+
75
+ if (!exists) {
76
+ console.log(`${chalk.yellow('Warning')}: could not find package.json`);
77
+ process.exit(0);
78
+ }
79
+
80
+ const packageObj = await readPackageJSON(packageJSONPath);
81
+
82
+ if (packageObj.strapi && packageObj.strapi.uuid) {
83
+ if (packageObj.strapi.telemetryDisabled === false) {
84
+ console.log(`${chalk.yellow('Warning:')} telemetry is already enabled`);
85
+ process.exit(0);
86
+ }
87
+ }
88
+
89
+ const updatedPackageJSON = generateNewPackageJSON(packageObj);
90
+
91
+ const write = await writePackageJSON(packageJSONPath, updatedPackageJSON, 2);
92
+
93
+ if (!write) {
94
+ process.exit(0);
95
+ }
96
+
97
+ await sendEvent(updatedPackageJSON.strapi.uuid);
98
+ console.log(`${chalk.green('Successfully opted into and enabled Strapi telemetry')}`);
99
+ process.exit(0);
100
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const tsUtils = require('@strapi/typescript-utils');
4
+
5
+ const strapi = require('../../index');
6
+
7
+ module.exports = async function({ outDir, file, verbose, silent }) {
8
+ if (verbose && silent) {
9
+ console.error('You cannot enable verbose and silent flags at the same time, exiting...');
10
+ process.exit(1);
11
+ }
12
+
13
+ const appContext = await strapi.compile();
14
+ const app = await strapi(appContext).register();
15
+
16
+ await tsUtils.generators.generateSchemasDefinitions({
17
+ strapi: app,
18
+ outDir: outDir || appContext.appDir,
19
+ file,
20
+ dirs: appContext,
21
+ verbose,
22
+ silent,
23
+ });
24
+
25
+ app.destroy();
26
+ };
@@ -4,12 +4,14 @@ const path = require('path');
4
4
  const fs = require('fs');
5
5
  const loadFile = require('./load-config-file');
6
6
 
7
+ const VALID_EXTENSIONS = ['.js', '.json'];
8
+
7
9
  module.exports = dir => {
8
10
  if (!fs.existsSync(dir)) return {};
9
11
 
10
12
  return fs
11
13
  .readdirSync(dir, { withFileTypes: true })
12
- .filter(file => file.isFile())
14
+ .filter(file => file.isFile() && VALID_EXTENSIONS.includes(path.extname(file.name)))
13
15
  .reduce((acc, file) => {
14
16
  const key = path.basename(file.name, path.extname(file.name));
15
17
 
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const _ = require('lodash');
4
- const { yup, toRegressedEnumValue, startsWithANumber } = require('@strapi/utils');
4
+ const { yup, toRegressedEnumValue } = require('@strapi/utils');
5
5
 
6
6
  const LIFECYCLES = [
7
7
  'beforeCreate',
@@ -24,6 +24,20 @@ const LIFECYCLES = [
24
24
  'afterDeleteMany',
25
25
  ];
26
26
 
27
+ /**
28
+ * For enumerations the least common denomiator is GraphQL, where
29
+ * values needs to match the secure name regex:
30
+ * GraphQL Spec https://spec.graphql.org/June2018/#sec-Names
31
+ *
32
+ * Therefore we need to make sure our users only use values, which
33
+ * can be returned by GraphQL, by checking the regressed values
34
+ * agains the GraphQL regex.
35
+ *
36
+ * TODO V5: check if we can avoid this coupling by moving this logic
37
+ * into the GraphQL plugin.
38
+ */
39
+ const GRAPHQL_ENUM_REGEX = new RegExp('^[_A-Za-z][_0-9A-Za-z]*$');
40
+
27
41
  const lifecyclesShape = _.mapValues(_.keyBy(LIFECYCLES), () =>
28
42
  yup
29
43
  .mixed()
@@ -54,22 +68,29 @@ const contentTypeSchemaValidator = yup.object().shape({
54
68
  for (const attrName in attributes) {
55
69
  const attr = attributes[attrName];
56
70
  if (attr.type === 'enumeration') {
57
- // should not start by a number
58
- if (attr.enum.some(startsWithANumber)) {
59
- const message = `Enum values should not start with a number. Please modify your enumeration '${attrName}'.`;
71
+ const regressedValues = attr.enum.map(toRegressedEnumValue);
72
+
73
+ // should match the GraphQL regex
74
+ if (!regressedValues.every(value => GRAPHQL_ENUM_REGEX.test(value))) {
75
+ const message = `Invalid enumeration value. Values should have at least one alphabetical character preceeding the first occurence of a number. Update your enumeration '${attrName}'.`;
60
76
 
61
77
  return this.createError({ message });
62
78
  }
63
79
 
80
+ // should not contain empty values
81
+ if (regressedValues.some(value => value === '')) {
82
+ return this.createError({
83
+ message: `At least one value of the enumeration '${attrName}' appears to be empty. Only alphanumerical characters are taken into account.`,
84
+ });
85
+ }
86
+
64
87
  // should not collide
65
88
  const duplicates = _.uniq(
66
- attr.enum
67
- .map(toRegressedEnumValue)
68
- .filter((value, index, values) => values.indexOf(value) !== index)
89
+ regressedValues.filter((value, index, values) => values.indexOf(value) !== index)
69
90
  );
70
91
 
71
92
  if (duplicates.length) {
72
- const message = `Some enum values of the field '${attrName}' collide when normalized: ${duplicates.join(
93
+ const message = `Some enumeration values of the field '${attrName}' collide when normalized: ${duplicates.join(
73
94
  ', '
74
95
  )}. Please modify your enumeration.`;
75
96
 
@@ -0,0 +1,61 @@
1
+ import type { Strapi as StrapiInterface } from './types/core';
2
+ import type { CollectionTypeSchema, SingleTypeSchema, ComponentSchema, ContentTypeSchema } from './types/core/schemas';
3
+ import type { KeysBy } from './types/utils';
4
+
5
+ declare global {
6
+ namespace Strapi {
7
+ /**
8
+ * Map of UID / schemas used as a schemas database for other types.
9
+ * It must be extended by the user application or plugins.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * declare global {
14
+ * namespace Strapi {
15
+ * interface Schemas {
16
+ * 'xxx::xxx.uid: ContentTypeSchema | ComponentSchema;
17
+ * }
18
+ * }
19
+ * }
20
+ * ```
21
+ */
22
+ interface Schemas {}
23
+
24
+ /**
25
+ * Literal union type of every content type registered in Strapi.Schemas
26
+ */
27
+ type ContentTypeUIDs = KeysBy<Schemas, ContentTypeSchema>;
28
+
29
+ /**
30
+ * Literal union type of every collection type registered in Strapi.Schemas
31
+ */
32
+ type CollectionTypeUIDs = KeysBy<Schemas, CollectionTypeSchema>;
33
+
34
+ /**
35
+ * Literal union type of every single type registered in Strapi.Schemas
36
+ */
37
+ type SingleTypeUIDs = KeysBy<Schemas, SingleTypeSchema>;
38
+
39
+ /**
40
+ * Literal union type of every component registered in Strapi.Schemas
41
+ */
42
+ type ComponentUIDs = KeysBy<Schemas, ComponentSchema>;
43
+
44
+ /**
45
+ * Global shorthand to access the `StrapiInterface` type
46
+ */
47
+ type Strapi = StrapiInterface;
48
+ }
49
+
50
+ /**
51
+ * Strapi global variable definition
52
+ **/
53
+ export const strapi: StrapiInterface;
54
+
55
+ /**
56
+ * Adds the strapi global variable to the NodeJS Global interface
57
+ */
58
+ export interface Global {
59
+ strapi: StrapiInterface;
60
+ }
61
+ }
package/lib/index.d.ts CHANGED
@@ -1,28 +1,5 @@
1
- import { Database } from '@strapi/database';
2
- import { EntityService } from './services/entity-service';
1
+ import './global';
3
2
 
4
- import * as Core from './types/strapi';
5
- export * as factories from './factories';
6
-
7
- export type { Core };
8
-
9
- // Alias to resolve the Strapi global type easily
10
- export type Strapi = Core.Strapi;
11
-
12
- export interface StrapiInterface extends Core.Strapi {};
13
-
14
- declare global {
15
- interface AllTypes {}
16
- }
17
-
18
- declare global {
19
- export interface Global {
20
- strapi: StrapiInterface;
21
- }
22
-
23
- export type Strapi = StrapiInterface;
24
-
25
- const strapi: StrapiInterface;
26
- }
3
+ export * from './types';
27
4
 
28
5
  export default function(opts): Strapi;
@@ -5,6 +5,7 @@ const { isFunction } = require('lodash/fp');
5
5
 
6
6
  const createCronService = () => {
7
7
  let jobsSpecs = [];
8
+ let running = false;
8
9
 
9
10
  return {
10
11
  add(tasks = {}) {
@@ -29,18 +30,21 @@ const createCronService = () => {
29
30
 
30
31
  const job = new Job(null, fnWithStrapi);
31
32
  jobsSpecs.push({ job, options });
33
+
34
+ if (running) {
35
+ job.schedule(options);
36
+ }
32
37
  }
33
38
  return this;
34
39
  },
35
40
  start() {
36
- if (!strapi.config.get('server.cron.enabled')) {
37
- return;
38
- }
39
41
  jobsSpecs.forEach(({ job, options }) => job.schedule(options));
42
+ running = true;
40
43
  return this;
41
44
  },
42
45
  stop() {
43
46
  jobsSpecs.forEach(({ job }) => job.cancel());
47
+ running = false;
44
48
  return this;
45
49
  },
46
50
  destroy() {
@@ -29,7 +29,7 @@ class WebhookRunner {
29
29
 
30
30
  this.config = _.merge(defaultConfiguration, configuration);
31
31
 
32
- this.queue = new WorkerQueue({ logger, concurency: 5 });
32
+ this.queue = new WorkerQueue({ logger, concurrency: 5 });
33
33
  this.queue.subscribe(this.executeListener.bind(this));
34
34
  }
35
35
 
@@ -0,0 +1,74 @@
1
+ import { GetAttributeValue } from './utils';
2
+
3
+ /**
4
+ * List of all the Strapi attribute types
5
+ */
6
+ export type AttributeType =
7
+ | 'string'
8
+ | 'text'
9
+ | 'richtext'
10
+ | 'email'
11
+ | 'password'
12
+ | 'date'
13
+ | 'time'
14
+ | 'datetime'
15
+ | 'timestamp'
16
+ | 'integer'
17
+ | 'biginteger'
18
+ | 'float'
19
+ | 'decimal'
20
+ | 'uid'
21
+ | 'enumeration'
22
+ | 'boolean'
23
+ | 'json'
24
+ | 'media'
25
+ | 'relation'
26
+ | 'component'
27
+ | 'dynamiczone';
28
+
29
+ /**
30
+ * Most basic shape of a schema attribute
31
+ */
32
+ export interface Attribute<T extends AttributeType = AttributeType> {
33
+ /**
34
+ * Type of the attribute
35
+ */
36
+ type: T;
37
+
38
+ /**
39
+ * Options defined and used by the plugins
40
+ */
41
+ pluginOptions?: object;
42
+ }
43
+
44
+ // Common attributes Options
45
+
46
+ export interface RequiredOption {
47
+ required?: boolean;
48
+ }
49
+
50
+ export interface PrivateOption {
51
+ private?: boolean;
52
+ }
53
+
54
+ export interface UniqueOption {
55
+ unique?: boolean;
56
+ }
57
+
58
+ export interface DefaultOption<T> {
59
+ default?: T;
60
+ }
61
+
62
+ export interface ConfigurableOption {
63
+ configurable?: boolean;
64
+ }
65
+
66
+ export interface MinMaxOption<T = number> {
67
+ min?: T;
68
+ max?: T;
69
+ }
70
+
71
+ export interface MinMaxLengthOption {
72
+ minLength?: number;
73
+ maxLength?: number;
74
+ }
@@ -0,0 +1,22 @@
1
+ import {
2
+ Attribute,
3
+ ConfigurableOption,
4
+ DefaultOption,
5
+ MinMaxOption,
6
+ PrivateOption,
7
+ RequiredOption,
8
+ } from './base';
9
+
10
+ export type BigIntegerAttribute = Attribute<'biginteger'> &
11
+ // Options
12
+ ConfigurableOption &
13
+ DefaultOption<BigIntegerValue> &
14
+ MinMaxOption<string> &
15
+ PrivateOption &
16
+ RequiredOption;
17
+
18
+ export type BigIntegerValue = string;
19
+
20
+ export type GetBigIntegerAttributeValue<T extends Attribute> = T extends BigIntegerAttribute
21
+ ? BigIntegerValue
22
+ : never;
@@ -0,0 +1,20 @@
1
+ import {
2
+ Attribute,
3
+ ConfigurableOption,
4
+ DefaultOption,
5
+ PrivateOption,
6
+ RequiredOption,
7
+ } from './base';
8
+
9
+ export type BooleanAttribute = Attribute<'boolean'> &
10
+ // Options
11
+ ConfigurableOption &
12
+ DefaultOption<BooleanValue> &
13
+ PrivateOption &
14
+ RequiredOption;
15
+
16
+ export type BooleanValue = boolean;
17
+
18
+ export type GetBooleanAttributeValue<T extends Attribute> = T extends BooleanAttribute
19
+ ? BooleanValue
20
+ : never;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Strapi custom scalar types
3
+ */
4
+
5
+ import { MinMaxLengthOption, MinMaxOption } from './base';
6
+ import { StringAttribute } from './string';
7
+
8
+ export type JSON<T extends object = object> = T;
9
+
10
+ export type Media = any;
11
+
12
+ /**
13
+ * Setters for the attributes options
14
+ */
15
+
16
+ // required
17
+ export type RequiredAttribute = { required: true };
18
+ export type NonRequiredAttribute = { required: false };
19
+
20
+ // private
21
+ export type PrivateAttribute = { private: true };
22
+ export type NonPrivateAttribute = { private: false };
23
+
24
+ // unique
25
+ export type UniqueAttribute = { unique: true };
26
+ export type NonUniqueAttribute = { unique: false };
27
+
28
+ // configurable
29
+ export type ConfigurableAttribute = { configurable: true };
30
+ export type NonConfigurableAttribute = { configurable: false };
31
+
32
+ // min/max
33
+ export type SetMinMax<T extends MinMaxOption<U>, U = number> = T;
34
+
35
+ // minLength/maxLength
36
+ export type SetMinMaxLength<T extends MinMaxLengthOption> = T;
37
+
38
+ // pluginOptions
39
+ export type SetPluginOptions<T extends object = object> = { pluginOptions?: T };
40
+
41
+ // default
42
+ export type DefaultTo<T> = { default: T };
@@ -0,0 +1,41 @@
1
+ import { Attribute, ConfigurableOption, MinMaxOption, PrivateOption, RequiredOption } from './base';
2
+ import { GetAttributesValues } from './utils';
3
+
4
+ export interface ComponentAttributeProperties<
5
+ // Targeted component
6
+ T extends Strapi.ComponentUIDs,
7
+ // Repeatable
8
+ R extends boolean = false
9
+ > {
10
+ component: T;
11
+ repeatable?: R;
12
+ }
13
+
14
+ export type ComponentAttribute<
15
+ // Targeted component
16
+ T extends Strapi.ComponentUIDs,
17
+ // Repeatable
18
+ R extends boolean = false
19
+ > = Attribute<'component'> &
20
+ // Component Properties
21
+ ComponentAttributeProperties<T, R> &
22
+ // Options
23
+ ConfigurableOption &
24
+ MinMaxOption &
25
+ PrivateOption &
26
+ RequiredOption;
27
+
28
+ export type ComponentValue<T extends Strapi.ComponentUIDs, R extends boolean> = GetAttributesValues<
29
+ T
30
+ > extends infer V
31
+ ? R extends true
32
+ ? V[]
33
+ : V
34
+ : never;
35
+
36
+ export type GetComponentAttributeValue<T extends Attribute> = T extends ComponentAttribute<
37
+ infer U,
38
+ infer R
39
+ >
40
+ ? ComponentValue<U, R>
41
+ : never;
@@ -0,0 +1,22 @@
1
+ import {
2
+ Attribute,
3
+ ConfigurableOption,
4
+ DefaultOption,
5
+ PrivateOption,
6
+ RequiredOption,
7
+ UniqueOption,
8
+ } from './base';
9
+
10
+ export type DateTimeAttribute = Attribute<'datetime'> &
11
+ // Options
12
+ ConfigurableOption &
13
+ DefaultOption<DateTimeValue> &
14
+ PrivateOption &
15
+ RequiredOption &
16
+ UniqueOption;
17
+
18
+ export type DateTimeValue = string;
19
+
20
+ export type GetDateTimeAttributeValue<T extends Attribute> = T extends DateTimeAttribute
21
+ ? DateTimeValue
22
+ : never;
@@ -0,0 +1,22 @@
1
+ import {
2
+ Attribute,
3
+ ConfigurableOption,
4
+ DefaultOption,
5
+ PrivateOption,
6
+ RequiredOption,
7
+ UniqueOption,
8
+ } from './base';
9
+
10
+ export type DateAttribute = Attribute<'date'> &
11
+ // Options
12
+ ConfigurableOption &
13
+ DefaultOption<DateValue> &
14
+ PrivateOption &
15
+ RequiredOption &
16
+ UniqueOption;
17
+
18
+ export type DateValue = Date;
19
+
20
+ export type GetDateAttributeValue<T extends Attribute> = T extends DateAttribute
21
+ ? DateValue
22
+ : never;
@@ -0,0 +1,22 @@
1
+ import {
2
+ Attribute,
3
+ ConfigurableOption,
4
+ DefaultOption,
5
+ MinMaxOption,
6
+ PrivateOption,
7
+ RequiredOption,
8
+ } from './base';
9
+
10
+ export type DecimalAttribute = Attribute<'decimal'> &
11
+ // Options
12
+ ConfigurableOption &
13
+ DefaultOption<DecimalValue> &
14
+ MinMaxOption &
15
+ PrivateOption &
16
+ RequiredOption;
17
+
18
+ export type DecimalValue = number;
19
+
20
+ export type GetDecimalAttributeValue<T extends Attribute> = T extends DecimalAttribute
21
+ ? DecimalValue
22
+ : never;
@@ -0,0 +1,29 @@
1
+ import { SchemaUID, GetArrayValues } from '../../utils';
2
+ import { Attribute, ConfigurableOption, MinMaxOption, RequiredOption } from './base';
3
+ import { GetAttributesValues } from './utils';
4
+
5
+ export interface DynamicZoneAttributeProperties<T extends Strapi.ComponentUIDs[] = []> {
6
+ components: T;
7
+ }
8
+
9
+ export type DynamicZoneAttribute<T extends Strapi.ComponentUIDs[] = []> = Attribute<'dynamiczone'> &
10
+ // Properties
11
+ DynamicZoneAttributeProperties<T> &
12
+ // Options
13
+ ConfigurableOption &
14
+ MinMaxOption &
15
+ RequiredOption;
16
+
17
+ type DynamicZoneValue<T extends Strapi.ComponentUIDs[]> = Array<
18
+ GetArrayValues<T> extends infer P
19
+ ? P extends SchemaUID
20
+ ? GetAttributesValues<P> & { __component: P }
21
+ : never
22
+ : never
23
+ >;
24
+
25
+ export type GetDynamicZoneAttributeValue<T extends Attribute> = T extends DynamicZoneAttribute<
26
+ infer U
27
+ >
28
+ ? DynamicZoneValue<U>
29
+ : never;