@carlonicora/nextjs-jsonapi 1.2.0 → 1.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.
- package/dist/{BlockNoteEditor-CNXQ3WL3.js → BlockNoteEditor-7WYPN34K.js} +17 -17
- package/dist/{BlockNoteEditor-CNXQ3WL3.js.map → BlockNoteEditor-7WYPN34K.js.map} +1 -1
- package/dist/{BlockNoteEditor-DC33K4IF.mjs → BlockNoteEditor-V625C23O.mjs} +7 -7
- package/dist/{JsonApiRequest-O7BGUMFO.mjs → JsonApiRequest-6UR7DIAR.mjs} +4 -2
- package/dist/JsonApiRequest-UJ7FGIVI.js +25 -0
- package/dist/JsonApiRequest-UJ7FGIVI.js.map +1 -0
- package/dist/{chunk-EZK3H6EJ.js → chunk-5IET37O4.js} +206 -206
- package/dist/{chunk-EZK3H6EJ.js.map → chunk-5IET37O4.js.map} +1 -1
- package/dist/{chunk-Y4XI3AZR.mjs → chunk-5QC7A6BL.mjs} +32 -20
- package/dist/chunk-5QC7A6BL.mjs.map +1 -0
- package/dist/{chunk-LJRD4SRV.js → chunk-DEYKTLA3.js} +6 -6
- package/dist/{chunk-LJRD4SRV.js.map → chunk-DEYKTLA3.js.map} +1 -1
- package/dist/{chunk-NPPQNSXN.mjs → chunk-FMBQZAIP.mjs} +3 -3
- package/dist/{chunk-MHVXFWZY.mjs → chunk-HTLEKZND.mjs} +3 -3
- package/dist/{chunk-74F6BBHH.mjs → chunk-IKBA4AHN.mjs} +2 -1
- package/dist/chunk-IKBA4AHN.mjs.map +1 -0
- package/dist/{chunk-JLN6UWII.mjs → chunk-JGFWIT2E.mjs} +2 -2
- package/dist/{chunk-KDFDGXCX.js → chunk-K2ANOT66.js} +576 -564
- package/dist/chunk-K2ANOT66.js.map +1 -0
- package/dist/{chunk-X53MF5ZN.mjs → chunk-P2F54I7Q.mjs} +2 -2
- package/dist/{chunk-5ZEADNNP.js → chunk-PMXG5WBC.js} +3 -2
- package/dist/chunk-PMXG5WBC.js.map +1 -0
- package/dist/{chunk-L6LH7WA4.js → chunk-PO5Q3H5I.js} +190 -190
- package/dist/{chunk-L6LH7WA4.js.map → chunk-PO5Q3H5I.js.map} +1 -1
- package/dist/{chunk-WZJDLITG.js → chunk-Q4FXESVT.js} +3 -3
- package/dist/{chunk-WZJDLITG.js.map → chunk-Q4FXESVT.js.map} +1 -1
- package/dist/client/index.js +7 -7
- package/dist/client/index.mjs +6 -6
- package/dist/components/index.js +7 -7
- package/dist/components/index.mjs +6 -6
- package/dist/contexts/index.js +7 -7
- package/dist/contexts/index.mjs +6 -6
- package/dist/core/index.js +2 -2
- package/dist/core/index.mjs +1 -1
- package/dist/features/index.js +4 -4
- package/dist/features/index.mjs +3 -3
- package/dist/hooks/index.js +7 -7
- package/dist/hooks/index.mjs +6 -6
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/scripts/generate-web-module/generator.d.ts +15 -0
- package/dist/scripts/generate-web-module/generator.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/generator.js +320 -0
- package/dist/scripts/generate-web-module/generator.js.map +1 -0
- package/dist/scripts/generate-web-module/index.d.ts +16 -0
- package/dist/scripts/generate-web-module/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/index.js +80 -0
- package/dist/scripts/generate-web-module/index.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/container.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/container.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/container.template.js +124 -0
- package/dist/scripts/generate-web-module/templates/components/container.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/content.template.d.ts +15 -0
- package/dist/scripts/generate-web-module/templates/components/content.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/content.template.js +39 -0
- package/dist/scripts/generate-web-module/templates/components/content.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/deleter.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/deleter.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/deleter.template.js +51 -0
- package/dist/scripts/generate-web-module/templates/components/deleter.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/details.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/details.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/details.template.js +109 -0
- package/dist/scripts/generate-web-module/templates/components/details.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/editor.template.js +459 -0
- package/dist/scripts/generate-web-module/templates/components/editor.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/index.d.ts +15 -0
- package/dist/scripts/generate-web-module/templates/components/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/index.js +29 -0
- package/dist/scripts/generate-web-module/templates/components/index.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/list-container.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/list-container.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/list-container.template.js +30 -0
- package/dist/scripts/generate-web-module/templates/components/list-container.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/list.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/list.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/list.template.js +84 -0
- package/dist/scripts/generate-web-module/templates/components/list.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/multi-selector.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/multi-selector.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/multi-selector.template.js +184 -0
- package/dist/scripts/generate-web-module/templates/components/multi-selector.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/components/selector.template.js +199 -0
- package/dist/scripts/generate-web-module/templates/components/selector.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/context.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/context.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/context.template.js +121 -0
- package/dist/scripts/generate-web-module/templates/context.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/fields.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/data/fields.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/fields.template.js +55 -0
- package/dist/scripts/generate-web-module/templates/data/fields.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/index.d.ts +10 -0
- package/dist/scripts/generate-web-module/templates/data/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/index.js +26 -0
- package/dist/scripts/generate-web-module/templates/data/index.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/interface.template.js +116 -0
- package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/model.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/data/model.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/model.template.js +274 -0
- package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/service.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/data/service.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/data/service.template.js +168 -0
- package/dist/scripts/generate-web-module/templates/data/service.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/index.d.ts +12 -0
- package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/index.js +37 -0
- package/dist/scripts/generate-web-module/templates/index.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/module.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/module.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/module.template.js +64 -0
- package/dist/scripts/generate-web-module/templates/module.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js +65 -0
- package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/index.d.ts +8 -0
- package/dist/scripts/generate-web-module/templates/pages/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/index.js +13 -0
- package/dist/scripts/generate-web-module/templates/pages/index.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.js +37 -0
- package/dist/scripts/generate-web-module/templates/pages/list-page.template.js.map +1 -0
- package/dist/scripts/generate-web-module/templates/table-hook.template.d.ts +14 -0
- package/dist/scripts/generate-web-module/templates/table-hook.template.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/templates/table-hook.template.js +174 -0
- package/dist/scripts/generate-web-module/templates/table-hook.template.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/field-mapper.d.ts +55 -0
- package/dist/scripts/generate-web-module/transformers/field-mapper.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/field-mapper.js +179 -0
- package/dist/scripts/generate-web-module/transformers/field-mapper.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/i18n-generator.d.ts +78 -0
- package/dist/scripts/generate-web-module/transformers/i18n-generator.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/i18n-generator.js +182 -0
- package/dist/scripts/generate-web-module/transformers/i18n-generator.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts +106 -0
- package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/import-resolver.js +193 -0
- package/dist/scripts/generate-web-module/transformers/import-resolver.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/index.d.ts +12 -0
- package/dist/scripts/generate-web-module/transformers/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/index.js +28 -0
- package/dist/scripts/generate-web-module/transformers/index.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/name-transformer.d.ts +60 -0
- package/dist/scripts/generate-web-module/transformers/name-transformer.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/name-transformer.js +115 -0
- package/dist/scripts/generate-web-module/transformers/name-transformer.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/parent-detector.d.ts +57 -0
- package/dist/scripts/generate-web-module/transformers/parent-detector.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/parent-detector.js +88 -0
- package/dist/scripts/generate-web-module/transformers/parent-detector.js.map +1 -0
- package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts +68 -0
- package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/transformers/relationship-resolver.js +219 -0
- package/dist/scripts/generate-web-module/transformers/relationship-resolver.js.map +1 -0
- package/dist/scripts/generate-web-module/types/field-mapping.types.d.ts +68 -0
- package/dist/scripts/generate-web-module/types/field-mapping.types.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/types/field-mapping.types.js +129 -0
- package/dist/scripts/generate-web-module/types/field-mapping.types.js.map +1 -0
- package/dist/scripts/generate-web-module/types/index.d.ts +9 -0
- package/dist/scripts/generate-web-module/types/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/types/index.js +25 -0
- package/dist/scripts/generate-web-module/types/index.js.map +1 -0
- package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts +40 -0
- package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/types/json-schema.interface.js +10 -0
- package/dist/scripts/generate-web-module/types/json-schema.interface.js.map +1 -0
- package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +128 -0
- package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/types/template-data.interface.js +9 -0
- package/dist/scripts/generate-web-module/types/template-data.interface.js.map +1 -0
- package/dist/scripts/generate-web-module/utils/bootstrapper-updater.d.ts +29 -0
- package/dist/scripts/generate-web-module/utils/bootstrapper-updater.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/utils/bootstrapper-updater.js +153 -0
- package/dist/scripts/generate-web-module/utils/bootstrapper-updater.js.map +1 -0
- package/dist/scripts/generate-web-module/utils/file-writer.d.ts +38 -0
- package/dist/scripts/generate-web-module/utils/file-writer.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/utils/file-writer.js +126 -0
- package/dist/scripts/generate-web-module/utils/file-writer.js.map +1 -0
- package/dist/scripts/generate-web-module/utils/i18n-updater.d.ts +28 -0
- package/dist/scripts/generate-web-module/utils/i18n-updater.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/utils/i18n-updater.js +122 -0
- package/dist/scripts/generate-web-module/utils/i18n-updater.js.map +1 -0
- package/dist/scripts/generate-web-module/utils/index.d.ts +9 -0
- package/dist/scripts/generate-web-module/utils/index.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/utils/index.js +20 -0
- package/dist/scripts/generate-web-module/utils/index.js.map +1 -0
- package/dist/scripts/generate-web-module/validators/json-schema-validator.d.ts +46 -0
- package/dist/scripts/generate-web-module/validators/json-schema-validator.d.ts.map +1 -0
- package/dist/scripts/generate-web-module/validators/json-schema-validator.js +265 -0
- package/dist/scripts/generate-web-module/validators/json-schema-validator.js.map +1 -0
- package/dist/shadcnui/index.js +4 -4
- package/dist/shadcnui/index.mjs +3 -3
- package/dist/utils/index.js +3 -3
- package/dist/utils/index.mjs +2 -2
- package/package.json +27 -21
- package/scripts/generate-web-module/generator.ts +363 -0
- package/scripts/generate-web-module/index.ts +49 -0
- package/scripts/generate-web-module/templates/components/container.template.ts +129 -0
- package/scripts/generate-web-module/templates/components/content.template.ts +40 -0
- package/scripts/generate-web-module/templates/components/deleter.template.ts +51 -0
- package/scripts/generate-web-module/templates/components/details.template.ts +115 -0
- package/scripts/generate-web-module/templates/components/editor.template.ts +495 -0
- package/scripts/generate-web-module/templates/components/index.ts +18 -0
- package/scripts/generate-web-module/templates/components/list-container.template.ts +30 -0
- package/scripts/generate-web-module/templates/components/list.template.ts +91 -0
- package/scripts/generate-web-module/templates/components/multi-selector.template.ts +184 -0
- package/scripts/generate-web-module/templates/components/selector.template.ts +199 -0
- package/scripts/generate-web-module/templates/context.template.ts +121 -0
- package/scripts/generate-web-module/templates/data/fields.template.ts +64 -0
- package/scripts/generate-web-module/templates/data/index.ts +10 -0
- package/scripts/generate-web-module/templates/data/interface.template.ts +136 -0
- package/scripts/generate-web-module/templates/data/model.template.ts +327 -0
- package/scripts/generate-web-module/templates/data/service.template.ts +185 -0
- package/scripts/generate-web-module/templates/index.ts +34 -0
- package/scripts/generate-web-module/templates/module.template.ts +69 -0
- package/scripts/generate-web-module/templates/pages/detail-page.template.ts +65 -0
- package/scripts/generate-web-module/templates/pages/index.ts +8 -0
- package/scripts/generate-web-module/templates/pages/list-page.template.ts +37 -0
- package/scripts/generate-web-module/templates/table-hook.template.ts +182 -0
- package/scripts/generate-web-module/transformers/field-mapper.ts +201 -0
- package/scripts/generate-web-module/transformers/i18n-generator.ts +199 -0
- package/scripts/generate-web-module/transformers/import-resolver.ts +250 -0
- package/scripts/generate-web-module/transformers/index.ts +12 -0
- package/scripts/generate-web-module/transformers/name-transformer.ts +115 -0
- package/scripts/generate-web-module/transformers/parent-detector.ts +87 -0
- package/scripts/generate-web-module/transformers/relationship-resolver.ts +221 -0
- package/scripts/generate-web-module/tsconfig.json +24 -0
- package/scripts/generate-web-module/types/field-mapping.types.ts +141 -0
- package/scripts/generate-web-module/types/index.ts +9 -0
- package/scripts/generate-web-module/types/json-schema.interface.ts +42 -0
- package/scripts/generate-web-module/types/template-data.interface.ts +164 -0
- package/scripts/generate-web-module/utils/bootstrapper-updater.ts +145 -0
- package/scripts/generate-web-module/utils/file-writer.ts +115 -0
- package/scripts/generate-web-module/utils/i18n-updater.ts +108 -0
- package/scripts/generate-web-module/utils/index.ts +9 -0
- package/scripts/generate-web-module/validators/json-schema-validator.ts +306 -0
- package/src/components/errors/ErrorDetails.tsx +2 -2
- package/src/features/auth/components/containers/AuthContainer.tsx +1 -1
- package/src/features/auth/components/details/LandingComponent.tsx +20 -1
- package/src/features/auth/components/forms/AcceptInvitation.tsx +1 -1
- package/src/features/auth/components/forms/ActivateAccount.tsx +1 -1
- package/src/features/auth/components/forms/ForgotPassword.tsx +1 -1
- package/src/features/auth/components/forms/Login.tsx +1 -1
- package/src/features/auth/components/forms/Register.tsx +1 -1
- package/src/features/auth/components/forms/ResetPassword.tsx +1 -1
- package/src/features/company/components/forms/CompanyLicense.tsx +1 -8
- package/src/unified/JsonApiRequest.ts +2 -2
- package/dist/JsonApiRequest-VARLNKAF.js +0 -23
- package/dist/JsonApiRequest-VARLNKAF.js.map +0 -1
- package/dist/chunk-5ZEADNNP.js.map +0 -1
- package/dist/chunk-74F6BBHH.mjs.map +0 -1
- package/dist/chunk-KDFDGXCX.js.map +0 -1
- package/dist/chunk-Y4XI3AZR.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-DC33K4IF.mjs.map → BlockNoteEditor-V625C23O.mjs.map} +0 -0
- /package/dist/{JsonApiRequest-O7BGUMFO.mjs.map → JsonApiRequest-6UR7DIAR.mjs.map} +0 -0
- /package/dist/{chunk-NPPQNSXN.mjs.map → chunk-FMBQZAIP.mjs.map} +0 -0
- /package/dist/{chunk-MHVXFWZY.mjs.map → chunk-HTLEKZND.mjs.map} +0 -0
- /package/dist/{chunk-JLN6UWII.mjs.map → chunk-JGFWIT2E.mjs.map} +0 -0
- /package/dist/{chunk-X53MF5ZN.mjs.map → chunk-P2F54I7Q.mjs.map} +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* i18n Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates internationalization keys and messages for a module.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { FrontendField, FrontendRelationship, I18nKeySet, NameTransforms } from "../types/template-data.interface";
|
|
8
|
+
import { toTitleCase, pluralize, toCamelCase, toKebabCase } from "./name-transformer";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate complete i18n key set for a module
|
|
12
|
+
*
|
|
13
|
+
* @param names - Name transforms
|
|
14
|
+
* @param fields - Array of frontend fields
|
|
15
|
+
* @param relationships - Array of frontend relationships
|
|
16
|
+
* @returns i18n key set
|
|
17
|
+
*/
|
|
18
|
+
export function generateI18nKeys(
|
|
19
|
+
names: NameTransforms,
|
|
20
|
+
fields: FrontendField[],
|
|
21
|
+
relationships: FrontendRelationship[]
|
|
22
|
+
): I18nKeySet {
|
|
23
|
+
const lowerModuleName = names.camelCase;
|
|
24
|
+
|
|
25
|
+
// Generate field keys
|
|
26
|
+
const fieldKeys: I18nKeySet["fields"] = {};
|
|
27
|
+
fields.forEach((field) => {
|
|
28
|
+
fieldKeys[field.name] = {
|
|
29
|
+
label: toTitleCase(field.name),
|
|
30
|
+
placeholder: `Enter ${toTitleCase(field.name).toLowerCase()}`,
|
|
31
|
+
error: `${toTitleCase(field.name)} is required`,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Generate relationship keys
|
|
36
|
+
const relationshipKeys: I18nKeySet["relationships"] = {};
|
|
37
|
+
relationships.forEach((rel) => {
|
|
38
|
+
const effectiveName = rel.variant || rel.name;
|
|
39
|
+
const effectiveKey = toCamelCase(effectiveName);
|
|
40
|
+
relationshipKeys[effectiveKey] = {
|
|
41
|
+
label: toTitleCase(effectiveName),
|
|
42
|
+
placeholder: `Select ${toTitleCase(effectiveName).toLowerCase()}`,
|
|
43
|
+
error: `${toTitleCase(effectiveName)} is required`,
|
|
44
|
+
list: pluralize(toTitleCase(rel.name)),
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Generate type keys
|
|
49
|
+
const singularTitle = names.titleCase;
|
|
50
|
+
const pluralTitle = names.pluralTitleCase;
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
moduleName: lowerModuleName,
|
|
54
|
+
fields: fieldKeys,
|
|
55
|
+
relationships: relationshipKeys,
|
|
56
|
+
type: {
|
|
57
|
+
singular: singularTitle,
|
|
58
|
+
plural: pluralTitle,
|
|
59
|
+
icuPlural: `{count, plural, =1 {${singularTitle}} other {${pluralTitle}}}`,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build the i18n message object to merge into en.json
|
|
66
|
+
*
|
|
67
|
+
* @param i18nKeys - i18n key set
|
|
68
|
+
* @returns Object structure for en.json
|
|
69
|
+
*/
|
|
70
|
+
export function buildI18nMessages(i18nKeys: I18nKeySet): Record<string, any> {
|
|
71
|
+
return {
|
|
72
|
+
features: {
|
|
73
|
+
[i18nKeys.moduleName]: {
|
|
74
|
+
fields: i18nKeys.fields,
|
|
75
|
+
relationships: i18nKeys.relationships,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
types: {
|
|
79
|
+
[i18nKeys.moduleName + "s"]: i18nKeys.type.icuPlural,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get the translation key path for a field label
|
|
86
|
+
*
|
|
87
|
+
* @param moduleName - Module name (lowercase)
|
|
88
|
+
* @param fieldName - Field name
|
|
89
|
+
* @returns Translation key path
|
|
90
|
+
*/
|
|
91
|
+
export function getFieldLabelKey(moduleName: string, fieldName: string): string {
|
|
92
|
+
return `features.${moduleName}.fields.${fieldName}.label`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get the translation key path for a field placeholder
|
|
97
|
+
*
|
|
98
|
+
* @param moduleName - Module name (lowercase)
|
|
99
|
+
* @param fieldName - Field name
|
|
100
|
+
* @returns Translation key path
|
|
101
|
+
*/
|
|
102
|
+
export function getFieldPlaceholderKey(moduleName: string, fieldName: string): string {
|
|
103
|
+
return `features.${moduleName}.fields.${fieldName}.placeholder`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the translation key path for a field error
|
|
108
|
+
*
|
|
109
|
+
* @param moduleName - Module name (lowercase)
|
|
110
|
+
* @param fieldName - Field name
|
|
111
|
+
* @returns Translation key path
|
|
112
|
+
*/
|
|
113
|
+
export function getFieldErrorKey(moduleName: string, fieldName: string): string {
|
|
114
|
+
return `features.${moduleName}.fields.${fieldName}.error`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get the translation key path for type pluralization
|
|
119
|
+
*
|
|
120
|
+
* @param pluralKebab - Plural kebab-case name
|
|
121
|
+
* @returns Translation key path
|
|
122
|
+
*/
|
|
123
|
+
export function getTypeKey(pluralKebab: string): string {
|
|
124
|
+
return `types.${pluralKebab}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate translation call for use in templates
|
|
129
|
+
*
|
|
130
|
+
* @param keyPath - Full translation key path
|
|
131
|
+
* @param params - Optional parameters for ICU messages
|
|
132
|
+
* @returns Translation function call as string
|
|
133
|
+
*/
|
|
134
|
+
export function generateTranslationCall(
|
|
135
|
+
keyPath: string,
|
|
136
|
+
params?: Record<string, any>
|
|
137
|
+
): string {
|
|
138
|
+
if (params) {
|
|
139
|
+
const paramStr = JSON.stringify(params);
|
|
140
|
+
return `t(\`${keyPath}\`, ${paramStr})`;
|
|
141
|
+
}
|
|
142
|
+
return `t(\`${keyPath}\`)`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Merge i18n messages into existing messages object
|
|
147
|
+
* This performs a deep merge, preserving existing keys
|
|
148
|
+
*
|
|
149
|
+
* @param existing - Existing messages object
|
|
150
|
+
* @param newMessages - New messages to merge
|
|
151
|
+
* @returns Merged messages object
|
|
152
|
+
*/
|
|
153
|
+
export function mergeI18nMessages(
|
|
154
|
+
existing: Record<string, any>,
|
|
155
|
+
newMessages: Record<string, any>
|
|
156
|
+
): Record<string, any> {
|
|
157
|
+
const result = { ...existing };
|
|
158
|
+
|
|
159
|
+
function deepMerge(target: Record<string, any>, source: Record<string, any>): void {
|
|
160
|
+
for (const key of Object.keys(source)) {
|
|
161
|
+
if (
|
|
162
|
+
source[key] &&
|
|
163
|
+
typeof source[key] === "object" &&
|
|
164
|
+
!Array.isArray(source[key])
|
|
165
|
+
) {
|
|
166
|
+
if (!target[key]) {
|
|
167
|
+
target[key] = {};
|
|
168
|
+
}
|
|
169
|
+
deepMerge(target[key], source[key]);
|
|
170
|
+
} else {
|
|
171
|
+
target[key] = source[key];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
deepMerge(result, newMessages);
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Sort object keys alphabetically (for consistent output)
|
|
182
|
+
*
|
|
183
|
+
* @param obj - Object to sort
|
|
184
|
+
* @returns New object with sorted keys
|
|
185
|
+
*/
|
|
186
|
+
export function sortObjectKeys(obj: Record<string, any>): Record<string, any> {
|
|
187
|
+
const sorted: Record<string, any> = {};
|
|
188
|
+
const keys = Object.keys(obj).sort();
|
|
189
|
+
|
|
190
|
+
for (const key of keys) {
|
|
191
|
+
if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
|
|
192
|
+
sorted[key] = sortObjectKeys(obj[key]);
|
|
193
|
+
} else {
|
|
194
|
+
sorted[key] = obj[key];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return sorted;
|
|
199
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import Resolver
|
|
3
|
+
*
|
|
4
|
+
* Builds import paths for selectors, models, and related modules.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { FrontendRelationship, ImportStatements, FrontendTemplateData } from "../types/template-data.interface";
|
|
8
|
+
import { AUTHOR_VARIANT } from "../types/field-mapping.types";
|
|
9
|
+
import { toKebabCase, pluralize } from "./name-transformer";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build all import statements needed for a module
|
|
13
|
+
*
|
|
14
|
+
* @param relationships - Array of frontend relationships
|
|
15
|
+
* @param extendsContent - Whether the module extends Content
|
|
16
|
+
* @returns Import statements grouped by category
|
|
17
|
+
*/
|
|
18
|
+
export function buildImportStatements(
|
|
19
|
+
relationships: FrontendRelationship[],
|
|
20
|
+
extendsContent: boolean
|
|
21
|
+
): ImportStatements {
|
|
22
|
+
return {
|
|
23
|
+
models: buildModelImports(relationships),
|
|
24
|
+
selectors: buildSelectorImports(relationships),
|
|
25
|
+
library: buildLibraryImports(extendsContent),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Build model/interface import statements
|
|
31
|
+
*
|
|
32
|
+
* @param relationships - Array of frontend relationships
|
|
33
|
+
* @returns Array of import statements for models
|
|
34
|
+
*/
|
|
35
|
+
export function buildModelImports(relationships: FrontendRelationship[]): string[] {
|
|
36
|
+
const imports: string[] = [];
|
|
37
|
+
|
|
38
|
+
relationships.forEach((rel) => {
|
|
39
|
+
// Import interface for relationships
|
|
40
|
+
imports.push(
|
|
41
|
+
`import { ${rel.interfaceName} } from "${rel.interfaceImportPath}";`
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return [...new Set(imports)]; // Deduplicate
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build selector component import statements
|
|
50
|
+
*
|
|
51
|
+
* @param relationships - Array of frontend relationships
|
|
52
|
+
* @returns Array of import statements for selectors
|
|
53
|
+
*/
|
|
54
|
+
export function buildSelectorImports(relationships: FrontendRelationship[]): string[] {
|
|
55
|
+
const imports: string[] = [];
|
|
56
|
+
|
|
57
|
+
relationships.forEach((rel) => {
|
|
58
|
+
// Skip author - handled specially or auto-set
|
|
59
|
+
if (rel.variant === AUTHOR_VARIANT) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const componentName = rel.single ? `${rel.name}Selector` : `${rel.name}MultiSelector`;
|
|
64
|
+
imports.push(
|
|
65
|
+
`import ${componentName} from "${rel.importPath}";`
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return [...new Set(imports)]; // Deduplicate
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build library import statements
|
|
74
|
+
*
|
|
75
|
+
* @param extendsContent - Whether the module extends Content
|
|
76
|
+
* @returns Array of import statements for library
|
|
77
|
+
*/
|
|
78
|
+
export function buildLibraryImports(extendsContent: boolean): string[] {
|
|
79
|
+
const imports: string[] = [];
|
|
80
|
+
|
|
81
|
+
// Core imports always needed
|
|
82
|
+
imports.push(
|
|
83
|
+
`import { AbstractApiData } from "@carlonicora/nextjs-jsonapi/core";`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Content import if extending
|
|
87
|
+
if (extendsContent) {
|
|
88
|
+
imports.push(
|
|
89
|
+
`import { Content, ContentInterface, ContentInput } from "@carlonicora/nextjs-jsonapi/core";`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return imports;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Build import path for a module's own files
|
|
98
|
+
*
|
|
99
|
+
* @param targetDir - Target directory
|
|
100
|
+
* @param moduleName - Module name (PascalCase)
|
|
101
|
+
* @param fileName - File name without extension
|
|
102
|
+
* @returns Import path
|
|
103
|
+
*/
|
|
104
|
+
export function buildModuleImportPath(
|
|
105
|
+
targetDir: string,
|
|
106
|
+
moduleName: string,
|
|
107
|
+
fileName: string
|
|
108
|
+
): string {
|
|
109
|
+
const kebab = toKebabCase(moduleName);
|
|
110
|
+
return `@/features/${targetDir}/${kebab}/data/${fileName}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Build import path for a related module's selector
|
|
115
|
+
*
|
|
116
|
+
* @param rel - Frontend relationship
|
|
117
|
+
* @returns Import path for selector
|
|
118
|
+
*/
|
|
119
|
+
export function buildSelectorImportPath(rel: FrontendRelationship): string {
|
|
120
|
+
const componentName = rel.single ? `${rel.name}Selector` : `${rel.name}MultiSelector`;
|
|
121
|
+
return `@/features/${rel.directory}/${rel.modelKebab}/components/forms/${componentName}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get the web base path for generated files
|
|
126
|
+
*
|
|
127
|
+
* @param targetDir - Target directory (features or foundations)
|
|
128
|
+
* @param moduleName - Module name (PascalCase)
|
|
129
|
+
* @returns Base path for generated files
|
|
130
|
+
*/
|
|
131
|
+
export function getWebBasePath(targetDir: string, moduleName: string): string {
|
|
132
|
+
const kebab = toKebabCase(moduleName);
|
|
133
|
+
return `apps/web/src/features/${targetDir}/${kebab}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get the page path for generated pages
|
|
138
|
+
*
|
|
139
|
+
* @param pluralKebab - Plural kebab-case name (e.g., "comments")
|
|
140
|
+
* @returns Base path for page files
|
|
141
|
+
*/
|
|
142
|
+
export function getPageBasePath(pluralKebab: string): string {
|
|
143
|
+
return `apps/web/src/app/[locale]/(main)/(features)/${pluralKebab}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* File paths interface
|
|
148
|
+
*/
|
|
149
|
+
export interface ModuleFilePaths {
|
|
150
|
+
interface: string;
|
|
151
|
+
model: string;
|
|
152
|
+
service: string;
|
|
153
|
+
fields: string;
|
|
154
|
+
editor: string;
|
|
155
|
+
deleter: string;
|
|
156
|
+
selector: string;
|
|
157
|
+
multiSelector: string;
|
|
158
|
+
list: string;
|
|
159
|
+
details: string;
|
|
160
|
+
content: string;
|
|
161
|
+
container: string;
|
|
162
|
+
listContainer: string;
|
|
163
|
+
context: string;
|
|
164
|
+
tableHook: string;
|
|
165
|
+
module: string;
|
|
166
|
+
listPage: string;
|
|
167
|
+
detailPage: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Build all file paths for a module from template data
|
|
172
|
+
*
|
|
173
|
+
* @param data - Frontend template data
|
|
174
|
+
* @param rootPath - Root path for the monorepo (optional, defaults to "")
|
|
175
|
+
* @returns Object with all file paths
|
|
176
|
+
*/
|
|
177
|
+
export function buildFilePaths(
|
|
178
|
+
data: FrontendTemplateData,
|
|
179
|
+
rootPath: string = ""
|
|
180
|
+
): ModuleFilePaths {
|
|
181
|
+
const { names, targetDir } = data;
|
|
182
|
+
const prefix = rootPath ? `${rootPath}/` : "";
|
|
183
|
+
const basePath = `${prefix}apps/web/src/features/${targetDir}/${names.kebabCase}`;
|
|
184
|
+
const pagePath = `${prefix}apps/web/src/app/[locale]/(main)/(features)/${names.pluralKebab}`;
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
// Data layer
|
|
188
|
+
interface: `${basePath}/data/${names.pascalCase}Interface.ts`,
|
|
189
|
+
model: `${basePath}/data/${names.pascalCase}.ts`,
|
|
190
|
+
service: `${basePath}/data/${names.pascalCase}Service.ts`,
|
|
191
|
+
fields: `${basePath}/data/${names.pascalCase}Fields.ts`,
|
|
192
|
+
|
|
193
|
+
// Components
|
|
194
|
+
editor: `${basePath}/components/forms/${names.pascalCase}Editor.tsx`,
|
|
195
|
+
deleter: `${basePath}/components/forms/${names.pascalCase}Deleter.tsx`,
|
|
196
|
+
selector: `${basePath}/components/forms/${names.pascalCase}Selector.tsx`,
|
|
197
|
+
multiSelector: `${basePath}/components/forms/${names.pascalCase}MultiSelector.tsx`,
|
|
198
|
+
list: `${basePath}/components/lists/${names.pascalCase}List.tsx`,
|
|
199
|
+
details: `${basePath}/components/details/${names.pascalCase}Details.tsx`,
|
|
200
|
+
content: `${basePath}/components/details/${names.pascalCase}Content.tsx`,
|
|
201
|
+
container: `${basePath}/components/containers/${names.pascalCase}Container.tsx`,
|
|
202
|
+
listContainer: `${basePath}/components/containers/${names.pascalCase}ListContainer.tsx`,
|
|
203
|
+
|
|
204
|
+
// Context & Hooks
|
|
205
|
+
context: `${basePath}/contexts/${names.pascalCase}Context.tsx`,
|
|
206
|
+
tableHook: `${basePath}/hooks/use${names.pascalCase}TableStructure.tsx`,
|
|
207
|
+
|
|
208
|
+
// Module
|
|
209
|
+
module: `${basePath}/${names.pascalCase}Module.ts`,
|
|
210
|
+
|
|
211
|
+
// Pages
|
|
212
|
+
listPage: `${pagePath}/page.tsx`,
|
|
213
|
+
detailPage: `${pagePath}/[id]/page.tsx`,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Build relative import path between two files
|
|
219
|
+
*
|
|
220
|
+
* @param fromPath - Source file path
|
|
221
|
+
* @param toPath - Target file path
|
|
222
|
+
* @returns Relative import path
|
|
223
|
+
*/
|
|
224
|
+
export function buildRelativeImport(fromPath: string, toPath: string): string {
|
|
225
|
+
// For files in same feature, use @ alias
|
|
226
|
+
if (toPath.startsWith("@/")) {
|
|
227
|
+
return toPath;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Calculate relative path
|
|
231
|
+
const fromParts = fromPath.split("/");
|
|
232
|
+
const toParts = toPath.split("/");
|
|
233
|
+
|
|
234
|
+
// Find common prefix
|
|
235
|
+
let commonLength = 0;
|
|
236
|
+
for (let i = 0; i < Math.min(fromParts.length, toParts.length); i++) {
|
|
237
|
+
if (fromParts[i] === toParts[i]) {
|
|
238
|
+
commonLength++;
|
|
239
|
+
} else {
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Build relative path
|
|
245
|
+
const upCount = fromParts.length - commonLength - 1; // -1 for the file itself
|
|
246
|
+
const relativeParts = toParts.slice(commonLength);
|
|
247
|
+
const prefix = upCount > 0 ? "../".repeat(upCount) : "./";
|
|
248
|
+
|
|
249
|
+
return prefix + relativeParts.join("/");
|
|
250
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transformers Index
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all transformer modules.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from "./name-transformer";
|
|
8
|
+
export * from "./parent-detector";
|
|
9
|
+
export * from "./field-mapper";
|
|
10
|
+
export * from "./relationship-resolver";
|
|
11
|
+
export * from "./import-resolver";
|
|
12
|
+
export * from "./i18n-generator";
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Name Transformer
|
|
3
|
+
*
|
|
4
|
+
* Transforms module names to various case conventions
|
|
5
|
+
* needed for code generation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NameTransforms } from "../types/template-data.interface";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Transform a module name to all necessary case conventions
|
|
12
|
+
*
|
|
13
|
+
* @param moduleName - PascalCase module name (e.g., "Comment")
|
|
14
|
+
* @param endpoint - Optional kebab-case plural endpoint (e.g., "comments"), derived from moduleName if not provided
|
|
15
|
+
* @returns All name transformations
|
|
16
|
+
*/
|
|
17
|
+
export function transformNames(moduleName: string, endpoint?: string): NameTransforms {
|
|
18
|
+
const pluralPascal = toPascalCase(pluralize(moduleName));
|
|
19
|
+
const pluralCamel = toCamelCase(pluralPascal);
|
|
20
|
+
const pluralKebab = endpoint || toKebabCase(pluralize(moduleName));
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
pascalCase: moduleName,
|
|
24
|
+
camelCase: toCamelCase(moduleName),
|
|
25
|
+
kebabCase: toKebabCase(moduleName),
|
|
26
|
+
pluralPascal,
|
|
27
|
+
pluralCamel,
|
|
28
|
+
pluralKebab,
|
|
29
|
+
titleCase: toTitleCase(moduleName),
|
|
30
|
+
pluralTitleCase: toTitleCase(pluralPascal),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Convert PascalCase to camelCase
|
|
36
|
+
*
|
|
37
|
+
* @param str - PascalCase string
|
|
38
|
+
* @returns camelCase string
|
|
39
|
+
*/
|
|
40
|
+
export function toCamelCase(str: string): string {
|
|
41
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Convert PascalCase to kebab-case
|
|
46
|
+
*
|
|
47
|
+
* @param str - PascalCase string
|
|
48
|
+
* @returns kebab-case string
|
|
49
|
+
*/
|
|
50
|
+
export function toKebabCase(str: string): string {
|
|
51
|
+
return str
|
|
52
|
+
.replace(/([A-Z])/g, "-$1")
|
|
53
|
+
.toLowerCase()
|
|
54
|
+
.replace(/^-/, "");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert string to PascalCase
|
|
59
|
+
*
|
|
60
|
+
* @param str - Any case string
|
|
61
|
+
* @returns PascalCase string
|
|
62
|
+
*/
|
|
63
|
+
export function toPascalCase(str: string): string {
|
|
64
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Convert PascalCase/camelCase to Title Case with spaces
|
|
69
|
+
* e.g., "firstName" -> "First Name", "UserProfile" -> "User Profile"
|
|
70
|
+
*
|
|
71
|
+
* @param str - PascalCase or camelCase string
|
|
72
|
+
* @returns Title Case string with spaces
|
|
73
|
+
*/
|
|
74
|
+
export function toTitleCase(str: string): string {
|
|
75
|
+
return str
|
|
76
|
+
.replace(/([A-Z])/g, " $1")
|
|
77
|
+
.replace(/^./, (char) => char.toUpperCase())
|
|
78
|
+
.trim();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Simple pluralization
|
|
83
|
+
* Note: This is a basic implementation. For production, consider using a library like 'pluralize'
|
|
84
|
+
*
|
|
85
|
+
* @param str - Singular form
|
|
86
|
+
* @returns Plural form
|
|
87
|
+
*/
|
|
88
|
+
export function pluralize(str: string): string {
|
|
89
|
+
if (str.endsWith("s")) {
|
|
90
|
+
return str + "es";
|
|
91
|
+
}
|
|
92
|
+
if (str.endsWith("y") && !["a", "e", "i", "o", "u"].includes(str[str.length - 2])) {
|
|
93
|
+
return str.slice(0, -1) + "ies";
|
|
94
|
+
}
|
|
95
|
+
return str + "s";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Simple singularization (reverse of pluralize)
|
|
100
|
+
*
|
|
101
|
+
* @param str - Plural form
|
|
102
|
+
* @returns Singular form
|
|
103
|
+
*/
|
|
104
|
+
export function singularize(str: string): string {
|
|
105
|
+
if (str.endsWith("ies")) {
|
|
106
|
+
return str.slice(0, -3) + "y";
|
|
107
|
+
}
|
|
108
|
+
if (str.endsWith("ses") || str.endsWith("xes") || str.endsWith("zes")) {
|
|
109
|
+
return str.slice(0, -2);
|
|
110
|
+
}
|
|
111
|
+
if (str.endsWith("s") && !str.endsWith("ss")) {
|
|
112
|
+
return str.slice(0, -1);
|
|
113
|
+
}
|
|
114
|
+
return str;
|
|
115
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parent Class Detector
|
|
3
|
+
*
|
|
4
|
+
* Determines whether a module should extend Content or AbstractApiData
|
|
5
|
+
* based on the presence of Content-specific fields.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { JsonFieldDefinition } from "../types/json-schema.interface";
|
|
9
|
+
import { CONTENT_INDICATOR_FIELDS } from "../types/field-mapping.types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check if a module should extend Content based on its fields
|
|
13
|
+
*
|
|
14
|
+
* @param fields - Array of field definitions from JSON schema
|
|
15
|
+
* @returns true if the module should extend Content
|
|
16
|
+
*/
|
|
17
|
+
export function detectExtendsContent(fields: JsonFieldDefinition[]): boolean {
|
|
18
|
+
const fieldNames = fields.map((f) => f.name);
|
|
19
|
+
return CONTENT_INDICATOR_FIELDS.some((indicator) => fieldNames.includes(indicator));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the parent class name based on detection result
|
|
24
|
+
*
|
|
25
|
+
* @param extendsContent - Whether the module extends Content
|
|
26
|
+
* @returns Parent class name
|
|
27
|
+
*/
|
|
28
|
+
export function getParentClassName(extendsContent: boolean): string {
|
|
29
|
+
return extendsContent ? "Content" : "AbstractApiData";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get the parent interface name based on detection result
|
|
34
|
+
*
|
|
35
|
+
* @param extendsContent - Whether the module extends Content
|
|
36
|
+
* @returns Parent interface name
|
|
37
|
+
*/
|
|
38
|
+
export function getParentInterfaceName(extendsContent: boolean): string {
|
|
39
|
+
return extendsContent ? "ContentInterface" : "BaseInterface";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the parent input type name based on detection result
|
|
44
|
+
*
|
|
45
|
+
* @param extendsContent - Whether the module extends Content
|
|
46
|
+
* @returns Parent input type or null if standalone
|
|
47
|
+
*/
|
|
48
|
+
export function getParentInputType(extendsContent: boolean): string | null {
|
|
49
|
+
return extendsContent ? "ContentInput" : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the import path for the parent class
|
|
54
|
+
*
|
|
55
|
+
* @param extendsContent - Whether the module extends Content
|
|
56
|
+
* @returns Import path for parent class
|
|
57
|
+
*/
|
|
58
|
+
export function getParentClassImport(extendsContent: boolean): string {
|
|
59
|
+
if (extendsContent) {
|
|
60
|
+
return '@carlonicora/nextjs-jsonapi/core';
|
|
61
|
+
}
|
|
62
|
+
return '@carlonicora/nextjs-jsonapi/core';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check if the module needs to call super.addContentInput() in createJsonApi
|
|
67
|
+
*
|
|
68
|
+
* @param extendsContent - Whether the module extends Content
|
|
69
|
+
* @returns true if super.addContentInput() should be called
|
|
70
|
+
*/
|
|
71
|
+
export function needsAddContentInput(extendsContent: boolean): boolean {
|
|
72
|
+
return extendsContent;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get fields that are inherited from Content and should not be declared
|
|
77
|
+
*
|
|
78
|
+
* @param extendsContent - Whether the module extends Content
|
|
79
|
+
* @returns Array of field names to exclude from generation
|
|
80
|
+
*/
|
|
81
|
+
export function getInheritedFields(extendsContent: boolean): string[] {
|
|
82
|
+
if (extendsContent) {
|
|
83
|
+
// These fields are already in Content, don't redeclare them
|
|
84
|
+
return ["name", "tldr", "abstract", "relevance"];
|
|
85
|
+
}
|
|
86
|
+
return [];
|
|
87
|
+
}
|