@strapi/typescript-utils 0.0.0-experimental.6340da17068c3bed7fb006e7bcc554c71129e282 → 0.0.0-experimental.63624e21eb5b0713345a0cf2f68f1c40eab427bc

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 (225) hide show
  1. package/dist/compile.d.ts +5 -0
  2. package/dist/compile.d.ts.map +1 -0
  3. package/dist/compile.js +12 -0
  4. package/dist/compile.js.map +1 -0
  5. package/dist/compile.mjs +10 -0
  6. package/dist/compile.mjs.map +1 -0
  7. package/dist/compilers/basic.d.ts +11 -0
  8. package/dist/compilers/basic.d.ts.map +1 -0
  9. package/dist/compilers/basic.js +58 -0
  10. package/dist/compilers/basic.js.map +1 -0
  11. package/dist/compilers/basic.mjs +36 -0
  12. package/dist/compilers/basic.mjs.map +1 -0
  13. package/dist/compilers/index.d.ts +3 -0
  14. package/dist/compilers/index.d.ts.map +1 -0
  15. package/dist/compilers/index.js +8 -0
  16. package/dist/compilers/index.js.map +1 -0
  17. package/dist/compilers/index.mjs +3 -0
  18. package/dist/compilers/index.mjs.map +1 -0
  19. package/dist/generators/common/compare.d.ts +14 -0
  20. package/dist/generators/common/compare.d.ts.map +1 -0
  21. package/dist/generators/common/compare.js +25 -0
  22. package/dist/generators/common/compare.js.map +1 -0
  23. package/dist/generators/common/compare.mjs +22 -0
  24. package/dist/generators/common/compare.mjs.map +1 -0
  25. package/dist/generators/common/imports.d.ts +5 -0
  26. package/dist/generators/common/imports.d.ts.map +1 -0
  27. package/dist/generators/common/imports.js +42 -0
  28. package/dist/generators/common/imports.js.map +1 -0
  29. package/dist/generators/common/imports.mjs +19 -0
  30. package/dist/generators/common/imports.mjs.map +1 -0
  31. package/dist/generators/common/index.d.ts +4 -0
  32. package/dist/generators/common/index.d.ts.map +1 -0
  33. package/dist/generators/common/interface-names.d.ts +16 -0
  34. package/dist/generators/common/interface-names.d.ts.map +1 -0
  35. package/dist/generators/common/interface-names.js +54 -0
  36. package/dist/generators/common/interface-names.js.map +1 -0
  37. package/dist/generators/common/interface-names.mjs +52 -0
  38. package/dist/generators/common/interface-names.mjs.map +1 -0
  39. package/dist/generators/common/models/attributes.d.ts +38 -0
  40. package/dist/generators/common/models/attributes.d.ts.map +1 -0
  41. package/dist/generators/common/models/attributes.js +205 -0
  42. package/dist/generators/common/models/attributes.js.map +1 -0
  43. package/dist/generators/common/models/attributes.mjs +176 -0
  44. package/dist/generators/common/models/attributes.mjs.map +1 -0
  45. package/dist/generators/common/models/index.d.ts +7 -0
  46. package/dist/generators/common/models/index.d.ts.map +1 -0
  47. package/dist/generators/common/models/mappers.d.ts +9 -0
  48. package/dist/generators/common/models/mappers.d.ts.map +1 -0
  49. package/dist/generators/common/models/mappers.js +227 -0
  50. package/dist/generators/common/models/mappers.js.map +1 -0
  51. package/dist/generators/common/models/mappers.mjs +202 -0
  52. package/dist/generators/common/models/mappers.mjs.map +1 -0
  53. package/dist/generators/common/models/schema.d.ts +8 -0
  54. package/dist/generators/common/models/schema.d.ts.map +1 -0
  55. package/dist/generators/common/models/schema.js +78 -0
  56. package/dist/generators/common/models/schema.js.map +1 -0
  57. package/dist/generators/common/models/schema.mjs +56 -0
  58. package/dist/generators/common/models/schema.mjs.map +1 -0
  59. package/dist/generators/common/models/utils.d.ts +57 -0
  60. package/dist/generators/common/models/utils.d.ts.map +1 -0
  61. package/dist/generators/common/models/utils.js +110 -0
  62. package/dist/generators/common/models/utils.js.map +1 -0
  63. package/dist/generators/common/models/utils.mjs +82 -0
  64. package/dist/generators/common/models/utils.mjs.map +1 -0
  65. package/dist/generators/common/sources.d.ts +133 -0
  66. package/dist/generators/common/sources.d.ts.map +1 -0
  67. package/dist/generators/common/sources.js +354 -0
  68. package/dist/generators/common/sources.js.map +1 -0
  69. package/dist/generators/common/sources.mjs +318 -0
  70. package/dist/generators/common/sources.mjs.map +1 -0
  71. package/dist/generators/components/index.d.ts +9 -0
  72. package/dist/generators/components/index.d.ts.map +1 -0
  73. package/dist/generators/components/index.js +84 -0
  74. package/dist/generators/components/index.js.map +1 -0
  75. package/dist/generators/components/index.mjs +62 -0
  76. package/dist/generators/components/index.mjs.map +1 -0
  77. package/dist/generators/constants.d.ts +3 -0
  78. package/dist/generators/constants.d.ts.map +1 -0
  79. package/dist/generators/constants.js +8 -0
  80. package/dist/generators/constants.js.map +1 -0
  81. package/dist/generators/constants.mjs +5 -0
  82. package/dist/generators/constants.mjs.map +1 -0
  83. package/dist/generators/content-types/index.d.ts +9 -0
  84. package/dist/generators/content-types/index.d.ts.map +1 -0
  85. package/dist/generators/content-types/index.js +84 -0
  86. package/dist/generators/content-types/index.js.map +1 -0
  87. package/dist/generators/content-types/index.mjs +62 -0
  88. package/dist/generators/content-types/index.mjs.map +1 -0
  89. package/dist/generators/controllers/index.d.ts +35 -0
  90. package/dist/generators/controllers/index.d.ts.map +1 -0
  91. package/dist/generators/controllers/index.js +88 -0
  92. package/dist/generators/controllers/index.js.map +1 -0
  93. package/dist/generators/controllers/index.mjs +86 -0
  94. package/dist/generators/controllers/index.mjs.map +1 -0
  95. package/dist/generators/index.d.ts +31 -0
  96. package/dist/generators/index.d.ts.map +1 -0
  97. package/dist/generators/index.js +150 -0
  98. package/dist/generators/index.js.map +1 -0
  99. package/dist/generators/index.mjs +142 -0
  100. package/dist/generators/index.mjs.map +1 -0
  101. package/dist/generators/middlewares/index.d.ts +30 -0
  102. package/dist/generators/middlewares/index.d.ts.map +1 -0
  103. package/dist/generators/middlewares/index.js +163 -0
  104. package/dist/generators/middlewares/index.js.map +1 -0
  105. package/dist/generators/middlewares/index.mjs +141 -0
  106. package/dist/generators/middlewares/index.mjs.map +1 -0
  107. package/dist/generators/plugins/index.d.ts +9 -0
  108. package/dist/generators/plugins/index.d.ts.map +1 -0
  109. package/dist/generators/plugins/index.js +225 -0
  110. package/dist/generators/plugins/index.js.map +1 -0
  111. package/dist/generators/plugins/index.mjs +200 -0
  112. package/dist/generators/plugins/index.mjs.map +1 -0
  113. package/dist/generators/policies/index.d.ts +29 -0
  114. package/dist/generators/policies/index.d.ts.map +1 -0
  115. package/dist/generators/policies/index.js +135 -0
  116. package/dist/generators/policies/index.js.map +1 -0
  117. package/dist/generators/policies/index.mjs +113 -0
  118. package/dist/generators/policies/index.mjs.map +1 -0
  119. package/dist/generators/services/index.d.ts +35 -0
  120. package/dist/generators/services/index.d.ts.map +1 -0
  121. package/dist/generators/services/index.js +87 -0
  122. package/dist/generators/services/index.js.map +1 -0
  123. package/dist/generators/services/index.mjs +85 -0
  124. package/dist/generators/services/index.mjs.map +1 -0
  125. package/dist/generators/strict/index.d.ts +13 -0
  126. package/dist/generators/strict/index.d.ts.map +1 -0
  127. package/dist/generators/strict/index.js +24 -0
  128. package/dist/generators/strict/index.js.map +1 -0
  129. package/dist/generators/strict/index.mjs +22 -0
  130. package/dist/generators/strict/index.mjs.map +1 -0
  131. package/dist/generators/utils.d.ts +68 -0
  132. package/dist/generators/utils.d.ts.map +1 -0
  133. package/dist/generators/utils.js +201 -0
  134. package/dist/generators/utils.js.map +1 -0
  135. package/dist/generators/utils.mjs +166 -0
  136. package/dist/generators/utils.mjs.map +1 -0
  137. package/dist/index.d.ts +5 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +28 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/index.mjs +14 -0
  142. package/dist/index.mjs.map +1 -0
  143. package/dist/utils/format-host.d.ts +3 -0
  144. package/dist/utils/format-host.d.ts.map +1 -0
  145. package/dist/utils/format-host.js +33 -0
  146. package/dist/utils/format-host.js.map +1 -0
  147. package/dist/utils/format-host.mjs +11 -0
  148. package/dist/utils/format-host.mjs.map +1 -0
  149. package/dist/utils/get-config-path.d.ts +10 -0
  150. package/dist/utils/get-config-path.d.ts.map +1 -0
  151. package/dist/utils/get-config-path.js +43 -0
  152. package/dist/utils/get-config-path.js.map +1 -0
  153. package/dist/utils/get-config-path.mjs +18 -0
  154. package/dist/utils/get-config-path.mjs.map +1 -0
  155. package/dist/utils/index.d.ts +9 -0
  156. package/dist/utils/index.d.ts.map +1 -0
  157. package/dist/utils/is-using-typescript-sync.d.ts +5 -0
  158. package/dist/utils/is-using-typescript-sync.d.ts.map +1 -0
  159. package/dist/utils/is-using-typescript-sync.js +20 -0
  160. package/dist/utils/is-using-typescript-sync.js.map +1 -0
  161. package/dist/utils/is-using-typescript-sync.mjs +14 -0
  162. package/dist/utils/is-using-typescript-sync.mjs.map +1 -0
  163. package/dist/utils/is-using-typescript.d.ts +5 -0
  164. package/dist/utils/is-using-typescript.d.ts.map +1 -0
  165. package/dist/utils/is-using-typescript.js +20 -0
  166. package/dist/utils/is-using-typescript.js.map +1 -0
  167. package/dist/utils/is-using-typescript.mjs +14 -0
  168. package/dist/utils/is-using-typescript.mjs.map +1 -0
  169. package/dist/utils/report-diagnostics.d.ts +6 -0
  170. package/dist/utils/report-diagnostics.d.ts.map +1 -0
  171. package/dist/utils/report-diagnostics.js +37 -0
  172. package/dist/utils/report-diagnostics.js.map +1 -0
  173. package/dist/utils/report-diagnostics.mjs +15 -0
  174. package/dist/utils/report-diagnostics.mjs.map +1 -0
  175. package/dist/utils/resolve-config-options.d.ts +12 -0
  176. package/dist/utils/resolve-config-options.d.ts.map +1 -0
  177. package/dist/utils/resolve-config-options.js +39 -0
  178. package/dist/utils/resolve-config-options.js.map +1 -0
  179. package/dist/utils/resolve-config-options.mjs +17 -0
  180. package/dist/utils/resolve-config-options.mjs.map +1 -0
  181. package/dist/utils/resolve-outdir-sync.d.ts +5 -0
  182. package/dist/utils/resolve-outdir-sync.d.ts.map +1 -0
  183. package/dist/utils/resolve-outdir-sync.js +19 -0
  184. package/dist/utils/resolve-outdir-sync.js.map +1 -0
  185. package/dist/utils/resolve-outdir-sync.mjs +13 -0
  186. package/dist/utils/resolve-outdir-sync.mjs.map +1 -0
  187. package/dist/utils/resolve-outdir.d.ts +5 -0
  188. package/dist/utils/resolve-outdir.d.ts.map +1 -0
  189. package/dist/utils/resolve-outdir.js +19 -0
  190. package/dist/utils/resolve-outdir.js.map +1 -0
  191. package/dist/utils/resolve-outdir.mjs +13 -0
  192. package/dist/utils/resolve-outdir.mjs.map +1 -0
  193. package/package.json +27 -12
  194. package/.eslintrc.cjs +0 -16
  195. package/index.d.ts +0 -5
  196. package/jest.config.js +0 -6
  197. package/lib/__tests__/generators/schemas/attributes.test.js +0 -903
  198. package/lib/__tests__/generators/schemas/imports.test.js +0 -56
  199. package/lib/__tests__/generators/schemas/utils.test.js +0 -314
  200. package/lib/compile.js +0 -10
  201. package/lib/compilers/basic.js +0 -50
  202. package/lib/compilers/index.js +0 -7
  203. package/lib/generators/common/imports.js +0 -34
  204. package/lib/generators/common/index.js +0 -9
  205. package/lib/generators/common/models/attributes.js +0 -198
  206. package/lib/generators/common/models/index.js +0 -15
  207. package/lib/generators/common/models/mappers.js +0 -144
  208. package/lib/generators/common/models/schema.js +0 -93
  209. package/lib/generators/common/models/utils.js +0 -178
  210. package/lib/generators/components/index.js +0 -74
  211. package/lib/generators/constants.js +0 -6
  212. package/lib/generators/content-types/index.js +0 -74
  213. package/lib/generators/index.js +0 -122
  214. package/lib/generators/utils.js +0 -216
  215. package/lib/index.js +0 -13
  216. package/lib/utils/format-host.js +0 -15
  217. package/lib/utils/get-config-path.js +0 -29
  218. package/lib/utils/index.js +0 -21
  219. package/lib/utils/is-using-typescript-sync.js +0 -19
  220. package/lib/utils/is-using-typescript.js +0 -17
  221. package/lib/utils/report-diagnostics.js +0 -19
  222. package/lib/utils/resolve-config-options.js +0 -23
  223. package/lib/utils/resolve-outdir-sync.js +0 -18
  224. package/lib/utils/resolve-outdir.js +0 -18
  225. package/lint-staged.config.mjs +0 -1
@@ -0,0 +1,318 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import * as ts from 'typescript';
4
+ import { kebabCase } from 'lodash';
5
+ import { pathExists, format, emitDefinitions } from '../utils.mjs';
6
+ import { compareCodeUnits } from './compare.mjs';
7
+
8
+ /**
9
+ * Shared by the generators of application modules (services, controllers, policies, middlewares):
10
+ * they find the source files the loaders of @strapi/core register, derive the same uids, and write
11
+ * one global registry each. Each generator keeps what it reads from a module type and which registry
12
+ * it writes.
13
+ */ const { factory } = ts;
14
+ const GLOBAL_NAMESPACE = 'Strapi';
15
+ const REGISTRIES_NAMESPACE = 'Registries';
16
+ // Ordered by precedence when several files resolve to the same uid
17
+ const SOURCE_EXTENSIONS = [
18
+ '.ts',
19
+ '.js'
20
+ ];
21
+ /**
22
+ * Mirror of the API loader's name normalization (@strapi/core, loaders/apis.ts): names already in
23
+ * kebab-case are kept as is, anything else is kebab-cased. Both must agree for the generated uids
24
+ * to match the ones registered at runtime. Global policies and middlewares (loaders/policies.ts,
25
+ * loaders/middlewares.ts) are not normalized.
26
+ */ const isKebabCase = (value)=>/^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);
27
+ const normalizeName = (name)=>isKebabCase(name) ? name : kebabCase(name);
28
+ const isSourceFile = (fd)=>fd.isFile() && !fd.name.endsWith('.d.ts') && SOURCE_EXTENSIONS.includes(path.extname(fd.name));
29
+ const byExtensionPrecedence = (a, b)=>SOURCE_EXTENSIONS.indexOf(path.extname(a.name)) - SOURCE_EXTENSIONS.indexOf(path.extname(b.name));
30
+ const toImportSpecifier = (from, to)=>{
31
+ const specifier = path.relative(from, to).split(path.sep).join('/');
32
+ return specifier.startsWith('.') ? specifier : `./${specifier}`;
33
+ };
34
+ /**
35
+ * Add the source files of a directory to `sources`, under the uid returned by `toUID`
36
+ */ const collectDirectorySources = async (dir, toUID, sources, outDir, logger)=>{
37
+ if (await pathExists(dir) === false) {
38
+ return;
39
+ }
40
+ const sourceFDs = (await fs.promises.readdir(dir, {
41
+ withFileTypes: true
42
+ })).filter(isSourceFile).sort(byExtensionPrecedence);
43
+ for (const sourceFD of sourceFDs){
44
+ const basename = path.basename(sourceFD.name, path.extname(sourceFD.name));
45
+ const uid = toUID(basename);
46
+ const file = path.join(dir, sourceFD.name);
47
+ if (sources.has(uid)) {
48
+ logger.warn(`Several source files resolve to ${uid}, ignoring ${file}`);
49
+ continue;
50
+ }
51
+ sources.set(uid, {
52
+ uid,
53
+ file,
54
+ specifier: toImportSpecifier(outDir, path.join(dir, basename))
55
+ });
56
+ }
57
+ };
58
+ /**
59
+ * Collect the global source files of a kind when `dirs.global` is given (src/<kind>/<name>.{ts,js}
60
+ * → global::<name>), then the ones of every API (src/api/<api>/<kind>/<name>.{ts,js} →
61
+ * api::<api>.<name>). The first file to resolve to a uid wins.
62
+ */ const collectAppSources = async (kind, dirs, outDir, logger)=>{
63
+ const sources = new Map();
64
+ if (dirs.global !== undefined) {
65
+ await collectDirectorySources(dirs.global, (basename)=>`global::${basename}`, sources, outDir, logger);
66
+ }
67
+ if (await pathExists(dirs.api) === true) {
68
+ const apiFDs = (await fs.promises.readdir(dirs.api, {
69
+ withFileTypes: true
70
+ })).filter((fd)=>fd.isDirectory() && !fd.name.startsWith('.'));
71
+ for (const apiFD of apiFDs){
72
+ const apiName = normalizeName(apiFD.name);
73
+ await collectDirectorySources(path.join(dirs.api, apiFD.name, kind), (basename)=>`api::${apiName}.${normalizeName(basename)}`, sources, outDir, logger);
74
+ }
75
+ }
76
+ return Array.from(sources.values());
77
+ };
78
+ /**
79
+ * Keep the sources whose uid the running app registered, sorted by uid
80
+ */ const filterRegisteredSources = (sources, registered, logger)=>{
81
+ const registeredUIDs = new Set(Object.keys(registered));
82
+ return sources.filter((source)=>{
83
+ if (!registeredUIDs.has(source.uid)) {
84
+ logger.debug(`${source.uid} is not registered, ignoring ${source.file}`);
85
+ return false;
86
+ }
87
+ return true;
88
+ }).sort((a, b)=>compareCodeUnits(a.uid, b.uid));
89
+ };
90
+ /**
91
+ * Application tsconfigs do not enable `allowJs`, so the import of a JS source does not resolve and is
92
+ * an error type. Unlike `any`, conditional types cannot map it to `unknown`.
93
+ */ const isTypedSource = (source)=>path.extname(source.file) === '.ts';
94
+ const hasModifier = (statement, kind)=>ts.canHaveModifiers(statement) && (ts.getModifiers(statement) ?? []).some((modifier)=>modifier.kind === kind);
95
+ /**
96
+ * Whether a top-level statement is `export type <name>` or `export interface <name>`
97
+ */ const isExportedTypeDeclarationNamed = (statement, name)=>(ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)) && statement.name.text === name && hasModifier(statement, ts.SyntaxKind.ExportKeyword) === true && hasModifier(statement, ts.SyntaxKind.DefaultKeyword) === false;
98
+ /**
99
+ * Whether a type declaration can be referenced without type arguments, as the generated file does
100
+ */ const hasDefaultTypeArguments = (statement)=>(statement.typeParameters ?? []).every((parameter)=>parameter.default !== undefined);
101
+ /**
102
+ * Whether a top-level statement exports a type under `name`: `export type <name>`,
103
+ * `export interface <name>`, or an export specifier named `<name>` (`export { <name> }`,
104
+ * `export { type X as <name> }`, `export type { X as <name> } from './x'`).
105
+ *
106
+ * A generic declaration only counts when each of its type parameters has a default: the generated
107
+ * file references it without type arguments.
108
+ *
109
+ * A specifier may name a value rather than a type, or a generic without defaults: its reference in
110
+ * the generated file does not resolve, and `tsc` reports it there.
111
+ * TODO @Nico a specifier of a local declaration could be checked like the declaration itself
112
+ */ const exportsTypeNamed = (statement, name)=>{
113
+ if (ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)) {
114
+ return isExportedTypeDeclarationNamed(statement, name) === true && hasDefaultTypeArguments(statement) === true;
115
+ }
116
+ if (ts.isExportDeclaration(statement) && statement.exportClause !== undefined && ts.isNamedExports(statement.exportClause)) {
117
+ return statement.exportClause.elements.some((element)=>element.name.text === name);
118
+ }
119
+ return false;
120
+ };
121
+ /**
122
+ * The uids of the TypeScript sources whose module exports a type named `name`, such as a service's
123
+ * `ServiceContract`.
124
+ *
125
+ * Each source is parsed on its own, without a program: type generation runs on every `strapi develop`
126
+ * start, before the compilation, and a program would need the application's tsconfig and its whole
127
+ * dependency graph. Only top-level declarations and export specifiers are read (see
128
+ * `exportsTypeNamed`). `export *` is not followed, and a source that cannot be read is skipped with a
129
+ * warning: both keep the type the source registers without a contract, rather than stopping the
130
+ * generation.
131
+ *
132
+ * JS sources are skipped: their import does not resolve without `allowJs` (see `isTypedSource`).
133
+ */ const findTypeExports = async (sources, name, logger)=>{
134
+ // TODO @Nico A JS source could get a contract from a sibling `<name>.d.ts` that exports it: the
135
+ // extension-less import of the source resolves to that file without `allowJs`.
136
+ const typedSources = sources.filter(isTypedSource);
137
+ const verdicts = await Promise.all(typedSources.map(async (source)=>{
138
+ let content;
139
+ try {
140
+ content = await fs.promises.readFile(source.file, 'utf8');
141
+ } catch (error) {
142
+ logger.warn(`Could not read ${source.file} to find its ${name} export, typing ${source.uid} without it: ${error instanceof Error ? error.message : String(error)}`);
143
+ return false;
144
+ }
145
+ const sourceFile = ts.createSourceFile(source.file, content, ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
146
+ if (sourceFile.statements.some((statement)=>exportsTypeNamed(statement, name)) === true) {
147
+ return true;
148
+ }
149
+ if (sourceFile.statements.some((statement)=>isExportedTypeDeclarationNamed(statement, name) === true && hasDefaultTypeArguments(statement) === false) === true) {
150
+ logger.warn(`${source.file} exports ${name} with type parameters that have no default, typing ${source.uid} without it`);
151
+ }
152
+ if (sourceFile.statements.some((statement)=>ts.isExportDeclaration(statement) && statement.exportClause === undefined) === true) {
153
+ logger.debug(`${source.uid}: \`export *\` is not followed to find a ${name} export`);
154
+ }
155
+ return false;
156
+ }));
157
+ return new Set(typedSources.filter((_, index)=>verdicts[index] === true).map(({ uid })=>uid));
158
+ };
159
+ /**
160
+ * The type a service or controller source registers:
161
+ * - `<contract helper><import('<source>').<contract export>>` when the module exports the contract;
162
+ * - `<helper><typeof import('<source>')>` otherwise, which infers it from the default export;
163
+ * - `unknown` for a JS source, whose import is an error type without `allowJs` (see `isTypedSource`).
164
+ *
165
+ * The contract does not depend on the default export, so the factory can be checked against its own
166
+ * uid (`Core.ServiceFactory<uid>`). The inferred type does: the generators list those uids in a
167
+ * marker registry (see `isInferredSource`), which the factory types reject.
168
+ */ const instanceTypeOf = (helper, logger, contract)=>(source)=>{
169
+ if (isTypedSource(source) === false) {
170
+ logger.debug(`${source.uid} has no TypeScript source, registering it as unknown`);
171
+ return factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
172
+ }
173
+ if (contract !== undefined && contract.uids.has(source.uid) === true) {
174
+ logger.debug(`${source.uid} exports ${contract.exportName}, registering it`);
175
+ return factory.createTypeReferenceNode(contract.helper, [
176
+ importedType(source, contract.exportName)
177
+ ]);
178
+ }
179
+ return factory.createTypeReferenceNode(helper, [
180
+ typeofImport(source)
181
+ ]);
182
+ };
183
+ /**
184
+ * Whether a source registers the type its module provides (see `instanceTypeOf`): a TypeScript
185
+ * source whose module does not export the contract.
186
+ */ const isInferredSource = (contract)=>(source)=>isTypedSource(source) === true && contract.uids.has(source.uid) === false;
187
+ /**
188
+ * typeof import('<relative path to the source>')
189
+ */ const typeofImport = (source)=>factory.createImportTypeNode(factory.createLiteralTypeNode(factory.createStringLiteral(source.specifier, true)), undefined, undefined, undefined, true);
190
+ /**
191
+ * import('<relative path to the source>').<name>
192
+ */ const importedType = (source, name)=>factory.createImportTypeNode(factory.createLiteralTypeNode(factory.createStringLiteral(source.specifier, true)), undefined, factory.createIdentifier(name), undefined, false);
193
+ const withDocComment = (node, comment)=>ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);
194
+ /**
195
+ * type <name><TModule> = TModule extends { default: infer TExport }
196
+ * ? 0 extends 1 & TExport
197
+ * ? unknown
198
+ * : TExport extends (...args: any[]) => infer TInstance ? TInstance : TExport
199
+ * : unknown;
200
+ *
201
+ * Emitted in each file so that services.ts and controllers.ts stand alone, and only when a source
202
+ * registers its inferred type.
203
+ *
204
+ * Resolves the type registered for a service or a controller from the type of its module: the return
205
+ * type of the default export when it is a factory, the default export itself otherwise. A module
206
+ * without a default export registers nothing usable at runtime; with strict types enabled, an
207
+ * unregistered uid resolves to `unknown`, so the helper does the same rather than claiming a
208
+ * permissive contract for it. A module typed `any` and a default export typed `any` resolve to
209
+ * `unknown` too: `any` would match the factory branch and register `any`.
210
+ *
211
+ * An import that no longer resolves (the source moved after the generation) is an error type, which
212
+ * no conditional type maps to `unknown`. The generated file is a `.ts` file, so `tsc` reports the
213
+ * TS2307 there, `skipLibCheck` or not, until the next generation drops the entry.
214
+ */ const generateInstanceHelperDefinition = (name, comment)=>{
215
+ const unwrapFactory = factory.createConditionalTypeNode(factory.createTypeReferenceNode('TExport'), factory.createFunctionTypeNode(undefined, [
216
+ factory.createParameterDeclaration(undefined, factory.createToken(ts.SyntaxKind.DotDotDotToken), 'args', undefined, factory.createArrayTypeNode(factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)))
217
+ ], factory.createInferTypeNode(factory.createTypeParameterDeclaration(undefined, 'TInstance'))), factory.createTypeReferenceNode('TInstance'), factory.createTypeReferenceNode('TExport'));
218
+ // 0 extends 1 & TExport: only true when TExport is `any`
219
+ const guardAny = factory.createConditionalTypeNode(factory.createLiteralTypeNode(factory.createNumericLiteral(0)), factory.createIntersectionTypeNode([
220
+ factory.createLiteralTypeNode(factory.createNumericLiteral(1)),
221
+ factory.createTypeReferenceNode('TExport')
222
+ ]), factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), unwrapFactory);
223
+ const unwrapDefaultExport = factory.createConditionalTypeNode(factory.createTypeReferenceNode('TModule'), factory.createTypeLiteralNode([
224
+ factory.createPropertySignature(undefined, 'default', undefined, factory.createInferTypeNode(factory.createTypeParameterDeclaration(undefined, 'TExport')))
225
+ ]), guardAny, factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword));
226
+ return withDocComment(factory.createTypeAliasDeclaration(undefined, factory.createIdentifier(name), [
227
+ factory.createTypeParameterDeclaration(undefined, 'TModule')
228
+ ], unwrapDefaultExport), comment);
229
+ };
230
+ /**
231
+ * type <name><TContract> = 0 extends 1 & TContract ? unknown : TContract;
232
+ *
233
+ * Emitted only when at least one source exports a contract: an application without contracts does
234
+ * not get it.
235
+ *
236
+ * A contract typed `any` registers `unknown`, as for an unregistered uid, rather than turning every
237
+ * lookup of the uid into `any`.
238
+ *
239
+ * A contract reference that no longer resolves to a type (the export was renamed after the
240
+ * generation, or a specifier names a value) is an error type, which no conditional type can map to
241
+ * `unknown` (an alias instantiated with the error type stays the error type). The generated file is a
242
+ * `.ts` file, so `tsc` reports the TS2694/TS2749 there, `skipLibCheck` or not. The next generation,
243
+ * on every `strapi develop` start, registers the source without its contract again.
244
+ */ const generateContractHelperDefinition = (name, comment)=>withDocComment(factory.createTypeAliasDeclaration(undefined, factory.createIdentifier(name), [
245
+ factory.createTypeParameterDeclaration(undefined, 'TContract')
246
+ ], factory.createConditionalTypeNode(factory.createLiteralTypeNode(factory.createNumericLiteral(0)), factory.createIntersectionTypeNode([
247
+ factory.createLiteralTypeNode(factory.createNumericLiteral(1)),
248
+ factory.createTypeReferenceNode('TContract')
249
+ ]), factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword), factory.createTypeReferenceNode('TContract'))), comment);
250
+ /**
251
+ * declare global {
252
+ * namespace Strapi {
253
+ * namespace Registries {
254
+ * interface <registry> {
255
+ * '<uid>': <value>;
256
+ * }
257
+ * …
258
+ * }
259
+ * }
260
+ * }
261
+ *
262
+ * The registries are global interfaces, so this augmentation merges with the base declaration and
263
+ * with the application's own entries, whatever module resolution the application uses. Lookups and
264
+ * route configs only consult it once the program opts into strict types.
265
+ */ const generateRegistryExtensionDefinition = (registries)=>{
266
+ const interfaces = registries.map(({ registry, entries })=>factory.createInterfaceDeclaration(undefined, factory.createIdentifier(registry), undefined, undefined, entries.map(([uid, value])=>factory.createPropertySignature(undefined, factory.createStringLiteral(uid, true), undefined, value))));
267
+ const namespaceOf = (name, statements)=>factory.createModuleDeclaration(undefined, factory.createIdentifier(name), factory.createModuleBlock(statements), ts.NodeFlags.Namespace);
268
+ return factory.createModuleDeclaration([
269
+ factory.createModifier(ts.SyntaxKind.DeclareKeyword)
270
+ ], factory.createIdentifier('global'), factory.createModuleBlock([
271
+ namespaceOf(GLOBAL_NAMESPACE, [
272
+ namespaceOf(REGISTRIES_NAMESPACE, interfaces)
273
+ ])
274
+ ]), ts.NodeFlags.GlobalAugmentation);
275
+ };
276
+ /**
277
+ * export {};
278
+ *
279
+ * <helpers>
280
+ *
281
+ * declare global { … <registry> … <markers> … }
282
+ *
283
+ * The module marker turns the generated file into a module: the global augmentation is only allowed
284
+ * in one. The helpers come first so that the file stands alone. A marker without uids is not
285
+ * emitted, so that the output of an application without such uids does not change.
286
+ */ const emitRegistryDefinitions = async (registry, helpers, sources, toValue, markers = [])=>{
287
+ const allDefinitions = [
288
+ // Module marker
289
+ factory.createExportDeclaration(undefined, false, factory.createNamedExports([])),
290
+ // Add a newline after the marker
291
+ factory.createIdentifier('\n'),
292
+ // Helpers
293
+ ...helpers,
294
+ // Add a newline after the helpers
295
+ factory.createIdentifier('\n'),
296
+ // Global
297
+ generateRegistryExtensionDefinition([
298
+ {
299
+ registry,
300
+ entries: sources.map((source)=>[
301
+ source.uid,
302
+ toValue(source)
303
+ ])
304
+ },
305
+ ...markers.filter((marker)=>marker.uids.length > 0).map((marker)=>({
306
+ registry: marker.registry,
307
+ entries: marker.uids.map((uid)=>[
308
+ uid,
309
+ factory.createLiteralTypeNode(factory.createTrue())
310
+ ])
311
+ }))
312
+ ])
313
+ ];
314
+ return format(emitDefinitions(allDefinitions));
315
+ };
316
+
317
+ export { collectAppSources, emitRegistryDefinitions, filterRegisteredSources, findTypeExports, generateContractHelperDefinition, generateInstanceHelperDefinition, instanceTypeOf, isInferredSource, isTypedSource, typeofImport, withDocComment };
318
+ //# sourceMappingURL=sources.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.mjs","sources":["../../../src/generators/common/sources.ts"],"sourcesContent":["import path from 'node:path';\nimport fs, { type Dirent } from 'node:fs';\nimport * as ts from 'typescript';\nimport { kebabCase } from 'lodash';\n\nimport { emitDefinitions, format, pathExists } from '../utils';\nimport type { Logger } from '../utils';\nimport { compareCodeUnits } from './compare';\n\n/**\n * Shared by the generators of application modules (services, controllers, policies, middlewares):\n * they find the source files the loaders of @strapi/core register, derive the same uids, and write\n * one global registry each. Each generator keeps what it reads from a module type and which registry\n * it writes.\n */\n\nconst { factory } = ts;\n\nconst GLOBAL_NAMESPACE = 'Strapi';\nconst REGISTRIES_NAMESPACE = 'Registries';\n\n// Ordered by precedence when several files resolve to the same uid\nconst SOURCE_EXTENSIONS = ['.ts', '.js'];\n\nexport type AppModuleSource = {\n uid: string;\n file: string;\n // Extension-less path of the source file, relative to the generated directory\n specifier: string;\n};\n\n/**\n * Directory of each module kind in an API (src/api/<api>/<kind>), and in src/ for the kinds the\n * loaders also register globally (policies, middlewares)\n */\nexport type AppModuleKind = 'services' | 'controllers' | 'policies' | 'middlewares';\n\n/**\n * Mirror of the API loader's name normalization (@strapi/core, loaders/apis.ts): names already in\n * kebab-case are kept as is, anything else is kebab-cased. Both must agree for the generated uids\n * to match the ones registered at runtime. Global policies and middlewares (loaders/policies.ts,\n * loaders/middlewares.ts) are not normalized.\n */\nconst isKebabCase = (value: string) => /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/.test(value);\nconst normalizeName = (name: string) => (isKebabCase(name) ? name : kebabCase(name));\n\nconst isSourceFile = (fd: Dirent) =>\n fd.isFile() && !fd.name.endsWith('.d.ts') && SOURCE_EXTENSIONS.includes(path.extname(fd.name));\n\nconst byExtensionPrecedence = (a: Dirent, b: Dirent) =>\n SOURCE_EXTENSIONS.indexOf(path.extname(a.name)) - SOURCE_EXTENSIONS.indexOf(path.extname(b.name));\n\nconst toImportSpecifier = (from: string, to: string) => {\n const specifier = path.relative(from, to).split(path.sep).join('/');\n\n return specifier.startsWith('.') ? specifier : `./${specifier}`;\n};\n\n/**\n * Add the source files of a directory to `sources`, under the uid returned by `toUID`\n */\nconst collectDirectorySources = async (\n dir: string,\n toUID: (basename: string) => string,\n sources: Map<string, AppModuleSource>,\n outDir: string,\n logger: Logger\n) => {\n if ((await pathExists(dir)) === false) {\n return;\n }\n\n const sourceFDs = (await fs.promises.readdir(dir, { withFileTypes: true }))\n .filter(isSourceFile)\n .sort(byExtensionPrecedence);\n\n for (const sourceFD of sourceFDs) {\n const basename = path.basename(sourceFD.name, path.extname(sourceFD.name));\n const uid = toUID(basename);\n const file = path.join(dir, sourceFD.name);\n\n if (sources.has(uid)) {\n logger.warn(`Several source files resolve to ${uid}, ignoring ${file}`);\n continue;\n }\n\n sources.set(uid, {\n uid,\n file,\n specifier: toImportSpecifier(outDir, path.join(dir, basename)),\n });\n }\n};\n\n/**\n * Collect the global source files of a kind when `dirs.global` is given (src/<kind>/<name>.{ts,js}\n * → global::<name>), then the ones of every API (src/api/<api>/<kind>/<name>.{ts,js} →\n * api::<api>.<name>). The first file to resolve to a uid wins.\n */\nexport const collectAppSources = async (\n kind: AppModuleKind,\n dirs: { global?: string; api: string },\n outDir: string,\n logger: Logger\n): Promise<AppModuleSource[]> => {\n const sources = new Map<string, AppModuleSource>();\n\n if (dirs.global !== undefined) {\n await collectDirectorySources(\n dirs.global,\n (basename) => `global::${basename}`,\n sources,\n outDir,\n logger\n );\n }\n\n if ((await pathExists(dirs.api)) === true) {\n const apiFDs = (await fs.promises.readdir(dirs.api, { withFileTypes: true })).filter(\n (fd) => fd.isDirectory() && !fd.name.startsWith('.')\n );\n\n for (const apiFD of apiFDs) {\n const apiName = normalizeName(apiFD.name);\n\n await collectDirectorySources(\n path.join(dirs.api, apiFD.name, kind),\n (basename) => `api::${apiName}.${normalizeName(basename)}`,\n sources,\n outDir,\n logger\n );\n }\n }\n\n return Array.from(sources.values());\n};\n\n/**\n * Keep the sources whose uid the running app registered, sorted by uid\n */\nexport const filterRegisteredSources = (\n sources: AppModuleSource[],\n registered: Record<string, unknown>,\n logger: Logger\n) => {\n const registeredUIDs = new Set(Object.keys(registered));\n\n return sources\n .filter((source) => {\n if (!registeredUIDs.has(source.uid)) {\n logger.debug(`${source.uid} is not registered, ignoring ${source.file}`);\n return false;\n }\n\n return true;\n })\n .sort((a, b) => compareCodeUnits(a.uid, b.uid));\n};\n\n/**\n * Application tsconfigs do not enable `allowJs`, so the import of a JS source does not resolve and is\n * an error type. Unlike `any`, conditional types cannot map it to `unknown`.\n */\nexport const isTypedSource = (source: AppModuleSource) => path.extname(source.file) === '.ts';\n\nconst hasModifier = (statement: ts.Statement, kind: ts.ModifierSyntaxKind) =>\n ts.canHaveModifiers(statement) &&\n (ts.getModifiers(statement) ?? []).some((modifier) => modifier.kind === kind);\n\n/**\n * Whether a top-level statement is `export type <name>` or `export interface <name>`\n */\nconst isExportedTypeDeclarationNamed = (\n statement: ts.Statement,\n name: string\n): statement is ts.TypeAliasDeclaration | ts.InterfaceDeclaration =>\n (ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)) &&\n statement.name.text === name &&\n hasModifier(statement, ts.SyntaxKind.ExportKeyword) === true &&\n hasModifier(statement, ts.SyntaxKind.DefaultKeyword) === false;\n\n/**\n * Whether a type declaration can be referenced without type arguments, as the generated file does\n */\nconst hasDefaultTypeArguments = (statement: ts.TypeAliasDeclaration | ts.InterfaceDeclaration) =>\n (statement.typeParameters ?? []).every((parameter) => parameter.default !== undefined);\n\n/**\n * Whether a top-level statement exports a type under `name`: `export type <name>`,\n * `export interface <name>`, or an export specifier named `<name>` (`export { <name> }`,\n * `export { type X as <name> }`, `export type { X as <name> } from './x'`).\n *\n * A generic declaration only counts when each of its type parameters has a default: the generated\n * file references it without type arguments.\n *\n * A specifier may name a value rather than a type, or a generic without defaults: its reference in\n * the generated file does not resolve, and `tsc` reports it there.\n * TODO @Nico a specifier of a local declaration could be checked like the declaration itself\n */\nconst exportsTypeNamed = (statement: ts.Statement, name: string) => {\n if (ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)) {\n return (\n isExportedTypeDeclarationNamed(statement, name) === true &&\n hasDefaultTypeArguments(statement) === true\n );\n }\n\n if (\n ts.isExportDeclaration(statement) &&\n statement.exportClause !== undefined &&\n ts.isNamedExports(statement.exportClause)\n ) {\n return statement.exportClause.elements.some((element) => element.name.text === name);\n }\n\n return false;\n};\n\n/**\n * The uids of the TypeScript sources whose module exports a type named `name`, such as a service's\n * `ServiceContract`.\n *\n * Each source is parsed on its own, without a program: type generation runs on every `strapi develop`\n * start, before the compilation, and a program would need the application's tsconfig and its whole\n * dependency graph. Only top-level declarations and export specifiers are read (see\n * `exportsTypeNamed`). `export *` is not followed, and a source that cannot be read is skipped with a\n * warning: both keep the type the source registers without a contract, rather than stopping the\n * generation.\n *\n * JS sources are skipped: their import does not resolve without `allowJs` (see `isTypedSource`).\n */\nexport const findTypeExports = async (\n sources: AppModuleSource[],\n name: string,\n logger: Logger\n): Promise<Set<string>> => {\n // TODO @Nico A JS source could get a contract from a sibling `<name>.d.ts` that exports it: the\n // extension-less import of the source resolves to that file without `allowJs`.\n const typedSources = sources.filter(isTypedSource);\n\n const verdicts = await Promise.all(\n typedSources.map(async (source) => {\n let content: string;\n\n try {\n content = await fs.promises.readFile(source.file, 'utf8');\n } catch (error) {\n logger.warn(\n `Could not read ${source.file} to find its ${name} export, typing ${source.uid} without it: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n return false;\n }\n\n const sourceFile = ts.createSourceFile(\n source.file,\n content,\n ts.ScriptTarget.Latest,\n false,\n ts.ScriptKind.TS\n );\n\n if (sourceFile.statements.some((statement) => exportsTypeNamed(statement, name)) === true) {\n return true;\n }\n\n if (\n sourceFile.statements.some(\n (statement) =>\n isExportedTypeDeclarationNamed(statement, name) === true &&\n hasDefaultTypeArguments(statement) === false\n ) === true\n ) {\n logger.warn(\n `${source.file} exports ${name} with type parameters that have no default, typing ${source.uid} without it`\n );\n }\n\n if (\n sourceFile.statements.some(\n (statement) => ts.isExportDeclaration(statement) && statement.exportClause === undefined\n ) === true\n ) {\n logger.debug(`${source.uid}: \\`export *\\` is not followed to find a ${name} export`);\n }\n\n return false;\n })\n );\n\n return new Set(typedSources.filter((_, index) => verdicts[index] === true).map(({ uid }) => uid));\n};\n\n/**\n * A type export that replaces the inferred type of the sources that have it, such as a service's\n * `ServiceContract`.\n */\nexport type AppModuleContract = {\n // Name of the type export\n exportName: string;\n // Name of the generated helper that reads it (see `generateContractHelperDefinition`)\n helper: string;\n // Uids of the sources whose module exports it (see `findTypeExports`)\n uids: Set<string>;\n};\n\n/**\n * The type a service or controller source registers:\n * - `<contract helper><import('<source>').<contract export>>` when the module exports the contract;\n * - `<helper><typeof import('<source>')>` otherwise, which infers it from the default export;\n * - `unknown` for a JS source, whose import is an error type without `allowJs` (see `isTypedSource`).\n *\n * The contract does not depend on the default export, so the factory can be checked against its own\n * uid (`Core.ServiceFactory<uid>`). The inferred type does: the generators list those uids in a\n * marker registry (see `isInferredSource`), which the factory types reject.\n */\nexport const instanceTypeOf =\n (helper: string, logger: Logger, contract?: AppModuleContract) =>\n (source: AppModuleSource): ts.TypeNode => {\n if (isTypedSource(source) === false) {\n logger.debug(`${source.uid} has no TypeScript source, registering it as unknown`);\n return factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);\n }\n\n if (contract !== undefined && contract.uids.has(source.uid) === true) {\n logger.debug(`${source.uid} exports ${contract.exportName}, registering it`);\n return factory.createTypeReferenceNode(contract.helper, [\n importedType(source, contract.exportName),\n ]);\n }\n\n return factory.createTypeReferenceNode(helper, [typeofImport(source)]);\n };\n\n/**\n * Whether a source registers the type its module provides (see `instanceTypeOf`): a TypeScript\n * source whose module does not export the contract.\n */\nexport const isInferredSource = (contract: AppModuleContract) => (source: AppModuleSource) =>\n isTypedSource(source) === true && contract.uids.has(source.uid) === false;\n\n/**\n * typeof import('<relative path to the source>')\n */\nexport const typeofImport = (source: AppModuleSource) =>\n factory.createImportTypeNode(\n factory.createLiteralTypeNode(factory.createStringLiteral(source.specifier, true)),\n undefined,\n undefined,\n undefined,\n true\n );\n\n/**\n * import('<relative path to the source>').<name>\n */\nconst importedType = (source: AppModuleSource, name: string) =>\n factory.createImportTypeNode(\n factory.createLiteralTypeNode(factory.createStringLiteral(source.specifier, true)),\n undefined,\n factory.createIdentifier(name),\n undefined,\n false\n );\n\nexport const withDocComment = <TNode extends ts.Node>(node: TNode, comment: string) =>\n ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);\n\n/**\n * type <name><TModule> = TModule extends { default: infer TExport }\n * ? 0 extends 1 & TExport\n * ? unknown\n * : TExport extends (...args: any[]) => infer TInstance ? TInstance : TExport\n * : unknown;\n *\n * Emitted in each file so that services.ts and controllers.ts stand alone, and only when a source\n * registers its inferred type.\n *\n * Resolves the type registered for a service or a controller from the type of its module: the return\n * type of the default export when it is a factory, the default export itself otherwise. A module\n * without a default export registers nothing usable at runtime; with strict types enabled, an\n * unregistered uid resolves to `unknown`, so the helper does the same rather than claiming a\n * permissive contract for it. A module typed `any` and a default export typed `any` resolve to\n * `unknown` too: `any` would match the factory branch and register `any`.\n *\n * An import that no longer resolves (the source moved after the generation) is an error type, which\n * no conditional type maps to `unknown`. The generated file is a `.ts` file, so `tsc` reports the\n * TS2307 there, `skipLibCheck` or not, until the next generation drops the entry.\n */\nexport const generateInstanceHelperDefinition = (name: string, comment: string) => {\n const unwrapFactory = factory.createConditionalTypeNode(\n factory.createTypeReferenceNode('TExport'),\n factory.createFunctionTypeNode(\n undefined,\n [\n factory.createParameterDeclaration(\n undefined,\n factory.createToken(ts.SyntaxKind.DotDotDotToken),\n 'args',\n undefined,\n factory.createArrayTypeNode(factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))\n ),\n ],\n factory.createInferTypeNode(factory.createTypeParameterDeclaration(undefined, 'TInstance'))\n ),\n factory.createTypeReferenceNode('TInstance'),\n factory.createTypeReferenceNode('TExport')\n );\n\n // 0 extends 1 & TExport: only true when TExport is `any`\n const guardAny = factory.createConditionalTypeNode(\n factory.createLiteralTypeNode(factory.createNumericLiteral(0)),\n factory.createIntersectionTypeNode([\n factory.createLiteralTypeNode(factory.createNumericLiteral(1)),\n factory.createTypeReferenceNode('TExport'),\n ]),\n factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),\n unwrapFactory\n );\n\n const unwrapDefaultExport = factory.createConditionalTypeNode(\n factory.createTypeReferenceNode('TModule'),\n factory.createTypeLiteralNode([\n factory.createPropertySignature(\n undefined,\n 'default',\n undefined,\n factory.createInferTypeNode(factory.createTypeParameterDeclaration(undefined, 'TExport'))\n ),\n ]),\n guardAny,\n factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword)\n );\n\n return withDocComment(\n factory.createTypeAliasDeclaration(\n undefined,\n factory.createIdentifier(name),\n [factory.createTypeParameterDeclaration(undefined, 'TModule')],\n unwrapDefaultExport\n ),\n comment\n );\n};\n\n/**\n * type <name><TContract> = 0 extends 1 & TContract ? unknown : TContract;\n *\n * Emitted only when at least one source exports a contract: an application without contracts does\n * not get it.\n *\n * A contract typed `any` registers `unknown`, as for an unregistered uid, rather than turning every\n * lookup of the uid into `any`.\n *\n * A contract reference that no longer resolves to a type (the export was renamed after the\n * generation, or a specifier names a value) is an error type, which no conditional type can map to\n * `unknown` (an alias instantiated with the error type stays the error type). The generated file is a\n * `.ts` file, so `tsc` reports the TS2694/TS2749 there, `skipLibCheck` or not. The next generation,\n * on every `strapi develop` start, registers the source without its contract again.\n */\nexport const generateContractHelperDefinition = (name: string, comment: string) =>\n withDocComment(\n factory.createTypeAliasDeclaration(\n undefined,\n factory.createIdentifier(name),\n [factory.createTypeParameterDeclaration(undefined, 'TContract')],\n factory.createConditionalTypeNode(\n factory.createLiteralTypeNode(factory.createNumericLiteral(0)),\n factory.createIntersectionTypeNode([\n factory.createLiteralTypeNode(factory.createNumericLiteral(1)),\n factory.createTypeReferenceNode('TContract'),\n ]),\n factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),\n factory.createTypeReferenceNode('TContract')\n )\n ),\n comment\n );\n\n/**\n * A registry that lists uids without typing them, such as the uids registered with their inferred\n * type. Each uid maps to `true`, which nothing reads: the marker never depends on a source.\n */\nexport type AppModuleMarker = {\n registry: string;\n uids: string[];\n};\n\n/**\n * declare global {\n * namespace Strapi {\n * namespace Registries {\n * interface <registry> {\n * '<uid>': <value>;\n * }\n * …\n * }\n * }\n * }\n *\n * The registries are global interfaces, so this augmentation merges with the base declaration and\n * with the application's own entries, whatever module resolution the application uses. Lookups and\n * route configs only consult it once the program opts into strict types.\n */\nconst generateRegistryExtensionDefinition = (\n registries: { registry: string; entries: [uid: string, value: ts.TypeNode][] }[]\n) => {\n const interfaces = registries.map(({ registry, entries }) =>\n factory.createInterfaceDeclaration(\n undefined,\n factory.createIdentifier(registry),\n undefined,\n undefined,\n entries.map(([uid, value]) =>\n factory.createPropertySignature(\n undefined,\n factory.createStringLiteral(uid, true),\n undefined,\n value\n )\n )\n )\n );\n\n const namespaceOf = (name: string, statements: ts.Statement[]) =>\n factory.createModuleDeclaration(\n undefined,\n factory.createIdentifier(name),\n factory.createModuleBlock(statements),\n ts.NodeFlags.Namespace\n );\n\n return factory.createModuleDeclaration(\n [factory.createModifier(ts.SyntaxKind.DeclareKeyword)],\n factory.createIdentifier('global'),\n factory.createModuleBlock([\n namespaceOf(GLOBAL_NAMESPACE, [namespaceOf(REGISTRIES_NAMESPACE, interfaces)]),\n ]),\n ts.NodeFlags.GlobalAugmentation\n );\n};\n\n/**\n * export {};\n *\n * <helpers>\n *\n * declare global { … <registry> … <markers> … }\n *\n * The module marker turns the generated file into a module: the global augmentation is only allowed\n * in one. The helpers come first so that the file stands alone. A marker without uids is not\n * emitted, so that the output of an application without such uids does not change.\n */\nexport const emitRegistryDefinitions = async (\n registry: string,\n helpers: ts.Node[],\n sources: AppModuleSource[],\n toValue: (source: AppModuleSource) => ts.TypeNode,\n markers: AppModuleMarker[] = []\n) => {\n const allDefinitions = [\n // Module marker\n factory.createExportDeclaration(undefined, false, factory.createNamedExports([])),\n\n // Add a newline after the marker\n factory.createIdentifier('\\n'),\n\n // Helpers\n ...helpers,\n\n // Add a newline after the helpers\n factory.createIdentifier('\\n'),\n\n // Global\n generateRegistryExtensionDefinition([\n {\n registry,\n entries: sources.map((source): [string, ts.TypeNode] => [source.uid, toValue(source)]),\n },\n ...markers\n .filter((marker) => marker.uids.length > 0)\n .map((marker) => ({\n registry: marker.registry,\n entries: marker.uids.map((uid): [string, ts.TypeNode] => [\n uid,\n factory.createLiteralTypeNode(factory.createTrue()),\n ]),\n })),\n ]),\n ];\n\n return format(emitDefinitions(allDefinitions));\n};\n"],"names":["factory","ts","GLOBAL_NAMESPACE","REGISTRIES_NAMESPACE","SOURCE_EXTENSIONS","isKebabCase","value","test","normalizeName","name","kebabCase","isSourceFile","fd","isFile","endsWith","includes","path","extname","byExtensionPrecedence","a","b","indexOf","toImportSpecifier","from","to","specifier","relative","split","sep","join","startsWith","collectDirectorySources","dir","toUID","sources","outDir","logger","pathExists","sourceFDs","fs","promises","readdir","withFileTypes","filter","sort","sourceFD","basename","uid","file","has","warn","set","collectAppSources","kind","dirs","Map","global","undefined","api","apiFDs","isDirectory","apiFD","apiName","Array","values","filterRegisteredSources","registered","registeredUIDs","Set","Object","keys","source","debug","compareCodeUnits","isTypedSource","hasModifier","statement","canHaveModifiers","getModifiers","some","modifier","isExportedTypeDeclarationNamed","isTypeAliasDeclaration","isInterfaceDeclaration","text","SyntaxKind","ExportKeyword","DefaultKeyword","hasDefaultTypeArguments","typeParameters","every","parameter","default","exportsTypeNamed","isExportDeclaration","exportClause","isNamedExports","elements","element","findTypeExports","typedSources","verdicts","Promise","all","map","content","readFile","error","Error","message","String","sourceFile","createSourceFile","ScriptTarget","Latest","ScriptKind","TS","statements","_","index","instanceTypeOf","helper","contract","createKeywordTypeNode","UnknownKeyword","uids","exportName","createTypeReferenceNode","importedType","typeofImport","isInferredSource","createImportTypeNode","createLiteralTypeNode","createStringLiteral","createIdentifier","withDocComment","node","comment","addSyntheticLeadingComment","MultiLineCommentTrivia","generateInstanceHelperDefinition","unwrapFactory","createConditionalTypeNode","createFunctionTypeNode","createParameterDeclaration","createToken","DotDotDotToken","createArrayTypeNode","AnyKeyword","createInferTypeNode","createTypeParameterDeclaration","guardAny","createNumericLiteral","createIntersectionTypeNode","unwrapDefaultExport","createTypeLiteralNode","createPropertySignature","createTypeAliasDeclaration","generateContractHelperDefinition","generateRegistryExtensionDefinition","registries","interfaces","registry","entries","createInterfaceDeclaration","namespaceOf","createModuleDeclaration","createModuleBlock","NodeFlags","Namespace","createModifier","DeclareKeyword","GlobalAugmentation","emitRegistryDefinitions","helpers","toValue","markers","allDefinitions","createExportDeclaration","createNamedExports","marker","length","createTrue","format","emitDefinitions"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { GeneratorOptions } from '../utils';
2
+ /**
3
+ * Generate type definitions for Strapi Components
4
+ */
5
+ export declare const generateComponentsDefinitions: (options?: GeneratorOptions) => Promise<{
6
+ output: string;
7
+ stats: {};
8
+ }>;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/generators/components/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AASjD;;GAEG;AACH,eAAO,MAAM,6BAA6B,GACxC,UAAS,gBAAyC;;;EAyDnD,CAAC"}
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ var ts = require('typescript');
4
+ var _ = require('lodash');
5
+ var schema = require('../common/models/schema.js');
6
+ var imports = require('../common/imports.js');
7
+ var interfaceNames = require('../common/interface-names.js');
8
+ var utils = require('../utils.js');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
29
+
30
+ const { factory } = ts__namespace;
31
+ const NO_COMPONENT_PLACEHOLDER_COMMENT = `/*
32
+ * The app doesn't have any components yet.
33
+ */
34
+ `;
35
+ /**
36
+ * Generate type definitions for Strapi Components
37
+ */ const generateComponentsDefinitions = async (options = {})=>{
38
+ const { strapi, strict = false } = options;
39
+ const { components } = strapi;
40
+ const schemas = _.sortBy(Object.values(components ?? {}), 'uid');
41
+ const interfaceNames$1 = interfaceNames.resolveInterfaceNames(schemas.map(({ uid })=>uid), options.logger, {
42
+ strict
43
+ });
44
+ const componentsDefinitions = schemas.map((component)=>({
45
+ uid: component.uid,
46
+ definition: schema.generateSchemaDefinition(component, interfaceNames$1.get(component.uid), {
47
+ strict
48
+ })
49
+ }));
50
+ options.logger.debug(`Found ${componentsDefinitions.length} components.`);
51
+ if (componentsDefinitions.length === 0) {
52
+ return {
53
+ output: NO_COMPONENT_PLACEHOLDER_COMMENT,
54
+ stats: {}
55
+ };
56
+ }
57
+ const formattedSchemasDefinitions = componentsDefinitions.reduce((acc, def)=>{
58
+ acc.push(// Definition
59
+ def.definition, // Add a newline between each interface declaration
60
+ factory.createIdentifier('\n'));
61
+ return acc;
62
+ }, []);
63
+ const allDefinitions = [
64
+ // Imports
65
+ ...imports.generateImportDefinition(),
66
+ // Add a newline after the import statement
67
+ factory.createIdentifier('\n'),
68
+ // Schemas
69
+ ...formattedSchemasDefinitions,
70
+ // Global
71
+ utils.generateSharedExtensionDefinition('ComponentSchemas', componentsDefinitions, {
72
+ strict
73
+ })
74
+ ];
75
+ const output = utils.emitDefinitions(allDefinitions);
76
+ const formattedOutput = await utils.format(output);
77
+ return {
78
+ output: formattedOutput,
79
+ stats: {}
80
+ };
81
+ };
82
+
83
+ exports.generateComponentsDefinitions = generateComponentsDefinitions;
84
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/generators/components/index.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport { sortBy } from 'lodash';\n\nimport { models } from '../common';\nimport { resolveInterfaceNames } from '../common/interface-names';\nimport { emitDefinitions, format, generateSharedExtensionDefinition } from '../utils';\nimport type { GeneratorOptions } from '../utils';\n\nconst { factory } = ts;\n\nconst NO_COMPONENT_PLACEHOLDER_COMMENT = `/*\n * The app doesn't have any components yet.\n */\n`;\n\n/**\n * Generate type definitions for Strapi Components\n */\nexport const generateComponentsDefinitions = async (\n options: GeneratorOptions = {} as GeneratorOptions\n) => {\n const { strapi, strict = false } = options;\n\n const { components } = strapi;\n\n const schemas = sortBy(Object.values<models.utils.Schema>(components ?? {}), 'uid');\n const interfaceNames = resolveInterfaceNames(\n schemas.map(({ uid }) => uid),\n options.logger,\n { strict }\n );\n const componentsDefinitions = schemas.map((component) => ({\n uid: component.uid,\n definition: models.schema.generateSchemaDefinition(\n component,\n interfaceNames.get(component.uid),\n { strict }\n ),\n }));\n\n options.logger.debug(`Found ${componentsDefinitions.length} components.`);\n\n if (componentsDefinitions.length === 0) {\n return { output: NO_COMPONENT_PLACEHOLDER_COMMENT, stats: {} };\n }\n\n const formattedSchemasDefinitions = componentsDefinitions.reduce<any[]>((acc, def) => {\n acc.push(\n // Definition\n def.definition,\n\n // Add a newline between each interface declaration\n factory.createIdentifier('\\n')\n );\n\n return acc;\n }, []);\n\n const allDefinitions = [\n // Imports\n ...models.imports.generateImportDefinition(),\n\n // Add a newline after the import statement\n factory.createIdentifier('\\n'),\n\n // Schemas\n ...formattedSchemasDefinitions,\n\n // Global\n generateSharedExtensionDefinition('ComponentSchemas', componentsDefinitions, { strict }),\n ];\n\n const output = emitDefinitions(allDefinitions);\n const formattedOutput = await format(output);\n\n return { output: formattedOutput, stats: {} };\n};\n"],"names":["factory","ts","NO_COMPONENT_PLACEHOLDER_COMMENT","generateComponentsDefinitions","options","strapi","strict","components","schemas","sortBy","Object","values","interfaceNames","resolveInterfaceNames","map","uid","logger","componentsDefinitions","component","definition","models","get","debug","length","output","stats","formattedSchemasDefinitions","reduce","acc","def","push","createIdentifier","allDefinitions","generateSharedExtensionDefinition","emitDefinitions","formattedOutput","format"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,EAAEA,OAAO,EAAE,GAAGC,aAAAA;AAEpB,MAAMC,mCAAmC,CAAC;;;AAG1C,CAAC;AAED;;AAEC,IACM,MAAMC,6BAAAA,GAAgC,OAC3CC,OAAAA,GAA4B,EAAsB,GAAA;AAElD,IAAA,MAAM,EAAEC,MAAM,EAAEC,MAAAA,GAAS,KAAK,EAAE,GAAGF,OAAAA;IAEnC,MAAM,EAAEG,UAAU,EAAE,GAAGF,MAAAA;AAEvB,IAAA,MAAMG,UAAUC,QAAAA,CAAOC,MAAAA,CAAOC,MAAM,CAAsBJ,UAAAA,IAAc,EAAC,CAAA,EAAI,KAAA,CAAA;AAC7E,IAAA,MAAMK,gBAAAA,GAAiBC,oCAAAA,CACrBL,OAAAA,CAAQM,GAAG,CAAC,CAAC,EAAEC,GAAG,EAAE,GAAKA,GAAAA,CAAAA,EACzBX,OAAAA,CAAQY,MAAM,EACd;AAAEV,QAAAA;AAAO,KAAA,CAAA;AAEX,IAAA,MAAMW,wBAAwBT,OAAAA,CAAQM,GAAG,CAAC,CAACI,aAAe;AACxDH,YAAAA,GAAAA,EAAKG,UAAUH,GAAG;YAClBI,UAAAA,EAAYC,+BAAsC,CAChDF,SAAAA,EACAN,gBAAAA,CAAeS,GAAG,CAACH,SAAAA,CAAUH,GAAG,CAAA,EAChC;AAAET,gBAAAA;AAAO,aAAA;SAEb,CAAA,CAAA;IAEAF,OAAAA,CAAQY,MAAM,CAACM,KAAK,CAAC,CAAC,MAAM,EAAEL,qBAAAA,CAAsBM,MAAM,CAAC,YAAY,CAAC,CAAA;IAExE,IAAIN,qBAAAA,CAAsBM,MAAM,KAAK,CAAA,EAAG;QACtC,OAAO;YAAEC,MAAAA,EAAQtB,gCAAAA;AAAkCuB,YAAAA,KAAAA,EAAO;AAAG,SAAA;AAC/D,IAAA;AAEA,IAAA,MAAMC,2BAAAA,GAA8BT,qBAAAA,CAAsBU,MAAM,CAAQ,CAACC,GAAAA,EAAKC,GAAAA,GAAAA;QAC5ED,GAAAA,CAAIE,IAAI;QAEND,GAAAA,CAAIV,UAAU;AAGdnB,QAAAA,OAAAA,CAAQ+B,gBAAgB,CAAC,IAAA,CAAA,CAAA;QAG3B,OAAOH,GAAAA;AACT,IAAA,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAMI,cAAAA,GAAiB;;WAElBZ,gCAAuC,EAAA;;AAG1CpB,QAAAA,OAAAA,CAAQ+B,gBAAgB,CAAC,IAAA,CAAA;;AAGtBL,QAAAA,GAAAA,2BAAAA;;AAGHO,QAAAA,uCAAAA,CAAkC,oBAAoBhB,qBAAAA,EAAuB;AAAEX,YAAAA;AAAO,SAAA;AACvF,KAAA;AAED,IAAA,MAAMkB,SAASU,qBAAAA,CAAgBF,cAAAA,CAAAA;IAC/B,MAAMG,eAAAA,GAAkB,MAAMC,YAAAA,CAAOZ,MAAAA,CAAAA;IAErC,OAAO;QAAEA,MAAAA,EAAQW,eAAAA;AAAiBV,QAAAA,KAAAA,EAAO;AAAG,KAAA;AAC9C;;;;"}
@@ -0,0 +1,62 @@
1
+ import * as ts from 'typescript';
2
+ import { sortBy } from 'lodash';
3
+ import { generateSchemaDefinition } from '../common/models/schema.mjs';
4
+ import { generateImportDefinition } from '../common/imports.mjs';
5
+ import { resolveInterfaceNames } from '../common/interface-names.mjs';
6
+ import { generateSharedExtensionDefinition, emitDefinitions, format } from '../utils.mjs';
7
+
8
+ const { factory } = ts;
9
+ const NO_COMPONENT_PLACEHOLDER_COMMENT = `/*
10
+ * The app doesn't have any components yet.
11
+ */
12
+ `;
13
+ /**
14
+ * Generate type definitions for Strapi Components
15
+ */ const generateComponentsDefinitions = async (options = {})=>{
16
+ const { strapi, strict = false } = options;
17
+ const { components } = strapi;
18
+ const schemas = sortBy(Object.values(components ?? {}), 'uid');
19
+ const interfaceNames = resolveInterfaceNames(schemas.map(({ uid })=>uid), options.logger, {
20
+ strict
21
+ });
22
+ const componentsDefinitions = schemas.map((component)=>({
23
+ uid: component.uid,
24
+ definition: generateSchemaDefinition(component, interfaceNames.get(component.uid), {
25
+ strict
26
+ })
27
+ }));
28
+ options.logger.debug(`Found ${componentsDefinitions.length} components.`);
29
+ if (componentsDefinitions.length === 0) {
30
+ return {
31
+ output: NO_COMPONENT_PLACEHOLDER_COMMENT,
32
+ stats: {}
33
+ };
34
+ }
35
+ const formattedSchemasDefinitions = componentsDefinitions.reduce((acc, def)=>{
36
+ acc.push(// Definition
37
+ def.definition, // Add a newline between each interface declaration
38
+ factory.createIdentifier('\n'));
39
+ return acc;
40
+ }, []);
41
+ const allDefinitions = [
42
+ // Imports
43
+ ...generateImportDefinition(),
44
+ // Add a newline after the import statement
45
+ factory.createIdentifier('\n'),
46
+ // Schemas
47
+ ...formattedSchemasDefinitions,
48
+ // Global
49
+ generateSharedExtensionDefinition('ComponentSchemas', componentsDefinitions, {
50
+ strict
51
+ })
52
+ ];
53
+ const output = emitDefinitions(allDefinitions);
54
+ const formattedOutput = await format(output);
55
+ return {
56
+ output: formattedOutput,
57
+ stats: {}
58
+ };
59
+ };
60
+
61
+ export { generateComponentsDefinitions };
62
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/generators/components/index.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport { sortBy } from 'lodash';\n\nimport { models } from '../common';\nimport { resolveInterfaceNames } from '../common/interface-names';\nimport { emitDefinitions, format, generateSharedExtensionDefinition } from '../utils';\nimport type { GeneratorOptions } from '../utils';\n\nconst { factory } = ts;\n\nconst NO_COMPONENT_PLACEHOLDER_COMMENT = `/*\n * The app doesn't have any components yet.\n */\n`;\n\n/**\n * Generate type definitions for Strapi Components\n */\nexport const generateComponentsDefinitions = async (\n options: GeneratorOptions = {} as GeneratorOptions\n) => {\n const { strapi, strict = false } = options;\n\n const { components } = strapi;\n\n const schemas = sortBy(Object.values<models.utils.Schema>(components ?? {}), 'uid');\n const interfaceNames = resolveInterfaceNames(\n schemas.map(({ uid }) => uid),\n options.logger,\n { strict }\n );\n const componentsDefinitions = schemas.map((component) => ({\n uid: component.uid,\n definition: models.schema.generateSchemaDefinition(\n component,\n interfaceNames.get(component.uid),\n { strict }\n ),\n }));\n\n options.logger.debug(`Found ${componentsDefinitions.length} components.`);\n\n if (componentsDefinitions.length === 0) {\n return { output: NO_COMPONENT_PLACEHOLDER_COMMENT, stats: {} };\n }\n\n const formattedSchemasDefinitions = componentsDefinitions.reduce<any[]>((acc, def) => {\n acc.push(\n // Definition\n def.definition,\n\n // Add a newline between each interface declaration\n factory.createIdentifier('\\n')\n );\n\n return acc;\n }, []);\n\n const allDefinitions = [\n // Imports\n ...models.imports.generateImportDefinition(),\n\n // Add a newline after the import statement\n factory.createIdentifier('\\n'),\n\n // Schemas\n ...formattedSchemasDefinitions,\n\n // Global\n generateSharedExtensionDefinition('ComponentSchemas', componentsDefinitions, { strict }),\n ];\n\n const output = emitDefinitions(allDefinitions);\n const formattedOutput = await format(output);\n\n return { output: formattedOutput, stats: {} };\n};\n"],"names":["factory","ts","NO_COMPONENT_PLACEHOLDER_COMMENT","generateComponentsDefinitions","options","strapi","strict","components","schemas","sortBy","Object","values","interfaceNames","resolveInterfaceNames","map","uid","logger","componentsDefinitions","component","definition","models","get","debug","length","output","stats","formattedSchemasDefinitions","reduce","acc","def","push","createIdentifier","allDefinitions","generateSharedExtensionDefinition","emitDefinitions","formattedOutput","format"],"mappings":";;;;;;;AAQA,MAAM,EAAEA,OAAO,EAAE,GAAGC,EAAAA;AAEpB,MAAMC,mCAAmC,CAAC;;;AAG1C,CAAC;AAED;;AAEC,IACM,MAAMC,6BAAAA,GAAgC,OAC3CC,OAAAA,GAA4B,EAAsB,GAAA;AAElD,IAAA,MAAM,EAAEC,MAAM,EAAEC,MAAAA,GAAS,KAAK,EAAE,GAAGF,OAAAA;IAEnC,MAAM,EAAEG,UAAU,EAAE,GAAGF,MAAAA;AAEvB,IAAA,MAAMG,UAAUC,MAAAA,CAAOC,MAAAA,CAAOC,MAAM,CAAsBJ,UAAAA,IAAc,EAAC,CAAA,EAAI,KAAA,CAAA;AAC7E,IAAA,MAAMK,cAAAA,GAAiBC,qBAAAA,CACrBL,OAAAA,CAAQM,GAAG,CAAC,CAAC,EAAEC,GAAG,EAAE,GAAKA,GAAAA,CAAAA,EACzBX,OAAAA,CAAQY,MAAM,EACd;AAAEV,QAAAA;AAAO,KAAA,CAAA;AAEX,IAAA,MAAMW,wBAAwBT,OAAAA,CAAQM,GAAG,CAAC,CAACI,aAAe;AACxDH,YAAAA,GAAAA,EAAKG,UAAUH,GAAG;YAClBI,UAAAA,EAAYC,wBAAsC,CAChDF,SAAAA,EACAN,cAAAA,CAAeS,GAAG,CAACH,SAAAA,CAAUH,GAAG,CAAA,EAChC;AAAET,gBAAAA;AAAO,aAAA;SAEb,CAAA,CAAA;IAEAF,OAAAA,CAAQY,MAAM,CAACM,KAAK,CAAC,CAAC,MAAM,EAAEL,qBAAAA,CAAsBM,MAAM,CAAC,YAAY,CAAC,CAAA;IAExE,IAAIN,qBAAAA,CAAsBM,MAAM,KAAK,CAAA,EAAG;QACtC,OAAO;YAAEC,MAAAA,EAAQtB,gCAAAA;AAAkCuB,YAAAA,KAAAA,EAAO;AAAG,SAAA;AAC/D,IAAA;AAEA,IAAA,MAAMC,2BAAAA,GAA8BT,qBAAAA,CAAsBU,MAAM,CAAQ,CAACC,GAAAA,EAAKC,GAAAA,GAAAA;QAC5ED,GAAAA,CAAIE,IAAI;QAEND,GAAAA,CAAIV,UAAU;AAGdnB,QAAAA,OAAAA,CAAQ+B,gBAAgB,CAAC,IAAA,CAAA,CAAA;QAG3B,OAAOH,GAAAA;AACT,IAAA,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAMI,cAAAA,GAAiB;;WAElBZ,wBAAuC,EAAA;;AAG1CpB,QAAAA,OAAAA,CAAQ+B,gBAAgB,CAAC,IAAA,CAAA;;AAGtBL,QAAAA,GAAAA,2BAAAA;;AAGHO,QAAAA,iCAAAA,CAAkC,oBAAoBhB,qBAAAA,EAAuB;AAAEX,YAAAA;AAAO,SAAA;AACvF,KAAA;AAED,IAAA,MAAMkB,SAASU,eAAAA,CAAgBF,cAAAA,CAAAA;IAC/B,MAAMG,eAAAA,GAAkB,MAAMC,MAAAA,CAAOZ,MAAAA,CAAAA;IAErC,OAAO;QAAEA,MAAAA,EAAQW,eAAAA;AAAiBV,QAAAA,KAAAA,EAAO;AAAG,KAAA;AAC9C;;;;"}
@@ -0,0 +1,3 @@
1
+ export declare const TYPES_ROOT_DIR = "types";
2
+ export declare const GENERATED_OUT_DIR = "generated";
3
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/generators/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,UAAU,CAAC;AACtC,eAAO,MAAM,iBAAiB,cAAc,CAAC"}
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const TYPES_ROOT_DIR = 'types';
4
+ const GENERATED_OUT_DIR = 'generated';
5
+
6
+ exports.GENERATED_OUT_DIR = GENERATED_OUT_DIR;
7
+ exports.TYPES_ROOT_DIR = TYPES_ROOT_DIR;
8
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../../src/generators/constants.ts"],"sourcesContent":["export const TYPES_ROOT_DIR = 'types';\nexport const GENERATED_OUT_DIR = 'generated';\n"],"names":["TYPES_ROOT_DIR","GENERATED_OUT_DIR"],"mappings":";;AAAO,MAAMA,iBAAiB;AACvB,MAAMC,oBAAoB;;;;;"}
@@ -0,0 +1,5 @@
1
+ const TYPES_ROOT_DIR = 'types';
2
+ const GENERATED_OUT_DIR = 'generated';
3
+
4
+ export { GENERATED_OUT_DIR, TYPES_ROOT_DIR };
5
+ //# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.mjs","sources":["../../src/generators/constants.ts"],"sourcesContent":["export const TYPES_ROOT_DIR = 'types';\nexport const GENERATED_OUT_DIR = 'generated';\n"],"names":["TYPES_ROOT_DIR","GENERATED_OUT_DIR"],"mappings":"AAAO,MAAMA,iBAAiB;AACvB,MAAMC,oBAAoB;;;;"}
@@ -0,0 +1,9 @@
1
+ import type { GeneratorOptions } from '../utils';
2
+ /**
3
+ * Generate type definitions for Strapi Content-Types
4
+ */
5
+ export declare const generateContentTypesDefinitions: (options?: GeneratorOptions) => Promise<{
6
+ output: string;
7
+ stats: {};
8
+ }>;
9
+ //# sourceMappingURL=index.d.ts.map