nextjs-cms 0.8.9 → 0.9.0

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 (188) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +290 -290
  3. package/dist/api/index.d.ts +92 -9
  4. package/dist/api/index.d.ts.map +1 -1
  5. package/dist/api/lib/serverActions.d.ts +64 -9
  6. package/dist/api/lib/serverActions.d.ts.map +1 -1
  7. package/dist/api/lib/serverActions.js +463 -90
  8. package/dist/api/root.d.ts +184 -18
  9. package/dist/api/root.d.ts.map +1 -1
  10. package/dist/api/routers/accountSettings.d.ts +2 -2
  11. package/dist/api/routers/accountSettings.js +10 -10
  12. package/dist/api/routers/admins.js +11 -11
  13. package/dist/api/routers/auth.d.ts +1 -1
  14. package/dist/api/routers/config.d.ts +13 -0
  15. package/dist/api/routers/config.d.ts.map +1 -1
  16. package/dist/api/routers/config.js +4 -0
  17. package/dist/api/routers/cpanel.js +7 -7
  18. package/dist/api/routers/fields.d.ts +1 -0
  19. package/dist/api/routers/fields.d.ts.map +1 -1
  20. package/dist/api/routers/fields.js +39 -6
  21. package/dist/api/routers/gallery.js +1 -1
  22. package/dist/api/routers/hasItemsSection.d.ts +41 -2
  23. package/dist/api/routers/hasItemsSection.d.ts.map +1 -1
  24. package/dist/api/routers/hasItemsSection.js +43 -2
  25. package/dist/api/routers/logs.js +1 -1
  26. package/dist/api/routers/navigation.d.ts +3 -3
  27. package/dist/api/routers/simpleSection.d.ts +31 -1
  28. package/dist/api/routers/simpleSection.d.ts.map +1 -1
  29. package/dist/api/routers/simpleSection.js +44 -2
  30. package/dist/api/trpc.js +2 -2
  31. package/dist/auth/index.d.ts +1 -1
  32. package/dist/auth/index.d.ts.map +1 -1
  33. package/dist/auth/index.js +1 -1
  34. package/dist/auth/lib/actions.d.ts +3 -3
  35. package/dist/auth/lib/actions.d.ts.map +1 -1
  36. package/dist/auth/lib/actions.js +14 -14
  37. package/dist/auth/react.d.ts +2 -2
  38. package/dist/auth/react.d.ts.map +1 -1
  39. package/dist/auth/react.js +7 -7
  40. package/dist/cli/lib/db-config.js +10 -10
  41. package/dist/cli/lib/update-sections.d.ts.map +1 -1
  42. package/dist/cli/lib/update-sections.js +145 -9
  43. package/dist/cli/utils/schema-generator.d.ts +20 -0
  44. package/dist/cli/utils/schema-generator.d.ts.map +1 -1
  45. package/dist/cli/utils/schema-generator.js +40 -0
  46. package/dist/core/config/config-loader.d.ts +49 -5
  47. package/dist/core/config/config-loader.d.ts.map +1 -1
  48. package/dist/core/config/config-loader.js +100 -21
  49. package/dist/core/config/index.d.ts +2 -2
  50. package/dist/core/config/index.d.ts.map +1 -1
  51. package/dist/core/config/index.js +1 -1
  52. package/dist/core/db/table-checker/MysqlTable.js +8 -8
  53. package/dist/core/factories/FieldFactory.d.ts +5 -3
  54. package/dist/core/factories/FieldFactory.d.ts.map +1 -1
  55. package/dist/core/factories/FieldFactory.js +74 -16
  56. package/dist/core/factories/section-factory-with-esbuild.d.ts.map +1 -1
  57. package/dist/core/factories/section-factory-with-esbuild.js +15 -9
  58. package/dist/core/factories/section-factory-with-jiti.d.ts.map +1 -1
  59. package/dist/core/factories/section-factory-with-jiti.js +15 -9
  60. package/dist/core/fields/checkbox.d.ts +4 -1
  61. package/dist/core/fields/checkbox.d.ts.map +1 -1
  62. package/dist/core/fields/color.d.ts +4 -1
  63. package/dist/core/fields/color.d.ts.map +1 -1
  64. package/dist/core/fields/color.js +2 -2
  65. package/dist/core/fields/date.d.ts +4 -1
  66. package/dist/core/fields/date.d.ts.map +1 -1
  67. package/dist/core/fields/date.js +2 -2
  68. package/dist/core/fields/document.d.ts +4 -1
  69. package/dist/core/fields/document.d.ts.map +1 -1
  70. package/dist/core/fields/document.js +27 -18
  71. package/dist/core/fields/field-group.d.ts +3 -3
  72. package/dist/core/fields/field-group.d.ts.map +1 -1
  73. package/dist/core/fields/field.d.ts +11 -8
  74. package/dist/core/fields/field.d.ts.map +1 -1
  75. package/dist/core/fields/field.js +15 -11
  76. package/dist/core/fields/map.d.ts +4 -1
  77. package/dist/core/fields/map.d.ts.map +1 -1
  78. package/dist/core/fields/map.js +2 -2
  79. package/dist/core/fields/number.d.ts +26 -1
  80. package/dist/core/fields/number.d.ts.map +1 -1
  81. package/dist/core/fields/number.js +16 -7
  82. package/dist/core/fields/password.d.ts +4 -1
  83. package/dist/core/fields/password.d.ts.map +1 -1
  84. package/dist/core/fields/password.js +3 -3
  85. package/dist/core/fields/photo.d.ts +4 -1
  86. package/dist/core/fields/photo.d.ts.map +1 -1
  87. package/dist/core/fields/photo.js +17 -17
  88. package/dist/core/fields/richText.d.ts +17 -3
  89. package/dist/core/fields/richText.d.ts.map +1 -1
  90. package/dist/core/fields/richText.js +20 -8
  91. package/dist/core/fields/select.d.ts +10 -3
  92. package/dist/core/fields/select.d.ts.map +1 -1
  93. package/dist/core/fields/select.js +27 -34
  94. package/dist/core/fields/selectMultiple.d.ts +8 -4
  95. package/dist/core/fields/selectMultiple.d.ts.map +1 -1
  96. package/dist/core/fields/selectMultiple.js +32 -24
  97. package/dist/core/fields/slug.d.ts +16 -1
  98. package/dist/core/fields/slug.d.ts.map +1 -1
  99. package/dist/core/fields/slug.js +3 -3
  100. package/dist/core/fields/tags.d.ts +6 -3
  101. package/dist/core/fields/tags.d.ts.map +1 -1
  102. package/dist/core/fields/tags.js +26 -19
  103. package/dist/core/fields/text.d.ts +24 -1
  104. package/dist/core/fields/text.d.ts.map +1 -1
  105. package/dist/core/fields/text.js +12 -3
  106. package/dist/core/fields/textArea.d.ts +24 -1
  107. package/dist/core/fields/textArea.d.ts.map +1 -1
  108. package/dist/core/fields/textArea.js +9 -0
  109. package/dist/core/fields/video.d.ts +4 -1
  110. package/dist/core/fields/video.d.ts.map +1 -1
  111. package/dist/core/fields/video.js +14 -12
  112. package/dist/core/index.d.ts +1 -0
  113. package/dist/core/index.d.ts.map +1 -1
  114. package/dist/core/index.js +1 -0
  115. package/dist/core/localization/index.d.ts +3 -0
  116. package/dist/core/localization/index.d.ts.map +1 -0
  117. package/dist/core/localization/index.js +1 -0
  118. package/dist/core/localization/resolve-locale.d.ts +29 -0
  119. package/dist/core/localization/resolve-locale.d.ts.map +1 -0
  120. package/dist/core/localization/resolve-locale.js +43 -0
  121. package/dist/core/sections/category.d.ts +56 -44
  122. package/dist/core/sections/category.d.ts.map +1 -1
  123. package/dist/core/sections/category.js +3 -3
  124. package/dist/core/sections/hasItems.d.ts +80 -44
  125. package/dist/core/sections/hasItems.d.ts.map +1 -1
  126. package/dist/core/sections/section.d.ts +55 -28
  127. package/dist/core/sections/section.d.ts.map +1 -1
  128. package/dist/core/sections/section.js +22 -0
  129. package/dist/core/sections/simple.d.ts +8 -8
  130. package/dist/core/sections/simple.d.ts.map +1 -1
  131. package/dist/core/submit/ItemEditSubmit.d.ts +24 -16
  132. package/dist/core/submit/ItemEditSubmit.d.ts.map +1 -1
  133. package/dist/core/submit/ItemEditSubmit.js +62 -38
  134. package/dist/core/submit/LocaleSubmit.d.ts +97 -0
  135. package/dist/core/submit/LocaleSubmit.d.ts.map +1 -0
  136. package/dist/core/submit/LocaleSubmit.js +435 -0
  137. package/dist/core/submit/NewItemSubmit.d.ts +0 -8
  138. package/dist/core/submit/NewItemSubmit.d.ts.map +1 -1
  139. package/dist/core/submit/NewItemSubmit.js +6 -12
  140. package/dist/core/submit/index.d.ts +1 -0
  141. package/dist/core/submit/index.d.ts.map +1 -1
  142. package/dist/core/submit/index.js +1 -0
  143. package/dist/core/submit/submit.d.ts +35 -12
  144. package/dist/core/submit/submit.d.ts.map +1 -1
  145. package/dist/core/submit/submit.js +88 -69
  146. package/dist/db/schema.d.ts +17 -0
  147. package/dist/db/schema.d.ts.map +1 -1
  148. package/dist/db/schema.js +1 -0
  149. package/dist/logging/log.d.ts +1 -1
  150. package/dist/logging/log.d.ts.map +1 -1
  151. package/dist/plugins/index.d.ts +1 -1
  152. package/dist/plugins/index.d.ts.map +1 -1
  153. package/dist/plugins/loader.d.ts +3 -3
  154. package/dist/plugins/loader.d.ts.map +1 -1
  155. package/dist/translations/base/en.d.ts +24 -2
  156. package/dist/translations/base/en.d.ts.map +1 -1
  157. package/dist/translations/base/en.js +24 -2
  158. package/dist/translations/client.d.ts +292 -28
  159. package/dist/translations/client.d.ts.map +1 -1
  160. package/dist/translations/client.js +2 -2
  161. package/dist/translations/dict-store.d.ts +2 -2
  162. package/dist/translations/dict-store.d.ts.map +1 -1
  163. package/dist/translations/dict-store.js +9 -9
  164. package/dist/translations/index.d.ts +5 -5
  165. package/dist/translations/index.d.ts.map +1 -1
  166. package/dist/translations/index.js +6 -6
  167. package/dist/translations/language-cookie.d.ts +24 -0
  168. package/dist/translations/language-cookie.d.ts.map +1 -0
  169. package/dist/translations/language-cookie.js +44 -0
  170. package/dist/translations/language-utils.d.ts +42 -0
  171. package/dist/translations/language-utils.d.ts.map +1 -0
  172. package/dist/translations/language-utils.js +52 -0
  173. package/dist/translations/server.d.ts +293 -29
  174. package/dist/translations/server.d.ts.map +1 -1
  175. package/dist/translations/server.js +5 -5
  176. package/dist/validators/number.d.ts +1 -1
  177. package/dist/validators/number.d.ts.map +1 -1
  178. package/dist/validators/number.js +1 -1
  179. package/dist/validators/select-multiple.d.ts +2 -2
  180. package/dist/validators/select-multiple.d.ts.map +1 -1
  181. package/dist/validators/select-multiple.js +1 -1
  182. package/package.json +7 -3
  183. package/dist/translations/dictionaries/ar.d.ts +0 -433
  184. package/dist/translations/dictionaries/ar.d.ts.map +0 -1
  185. package/dist/translations/dictionaries/ar.js +0 -444
  186. package/dist/translations/dictionaries/en.d.ts +0 -433
  187. package/dist/translations/dictionaries/en.d.ts.map +0 -1
  188. package/dist/translations/dictionaries/en.js +0 -444
@@ -24,6 +24,7 @@ export declare const simpleSectionRouter: import("@trpc/server").TRPCBuiltRouter
24
24
  create: import("@trpc/server").TRPCQueryProcedure<{
25
25
  input: {
26
26
  sectionName: string;
27
+ locale?: string | undefined;
27
28
  };
28
29
  output: {
29
30
  error: {
@@ -31,6 +32,7 @@ export declare const simpleSectionRouter: import("@trpc/server").TRPCBuiltRouter
31
32
  };
32
33
  section?: undefined;
33
34
  inputGroups?: undefined;
35
+ localization?: undefined;
34
36
  } | {
35
37
  section: {
36
38
  name: string;
@@ -51,6 +53,7 @@ export declare const simpleSectionRouter: import("@trpc/server").TRPCBuiltRouter
51
53
  };
52
54
  } | undefined;
53
55
  variants: import("../../core/types/index.js").Variant[] | undefined;
56
+ configFile: string;
54
57
  };
55
58
  inputGroups: {
56
59
  groupId: number;
@@ -59,17 +62,44 @@ export declare const simpleSectionRouter: import("@trpc/server").TRPCBuiltRouter
59
62
  inputs: {
60
63
  type: import("../../core/types/index.js").FieldType;
61
64
  name: string;
62
- label: import("../../index.js").LocalizedString;
65
+ label: import("../../index.js").MultilingualString;
63
66
  required: boolean;
67
+ localized: boolean;
64
68
  conditionalFields: import("../../core/types/index.js").ConditionalField[];
65
69
  readonly: boolean;
66
70
  defaultValue: any;
67
71
  value: any;
68
72
  }[];
69
73
  }[] | undefined;
74
+ localization: {
75
+ defaultLocale: {
76
+ code: string;
77
+ label: any;
78
+ rtl?: boolean;
79
+ };
80
+ currentLocale: {
81
+ code: string;
82
+ label: any;
83
+ rtl?: boolean;
84
+ };
85
+ existingTranslations: string[];
86
+ locales: {
87
+ code: string;
88
+ label: any;
89
+ rtl?: boolean;
90
+ }[];
91
+ } | null;
70
92
  error?: undefined;
71
93
  };
72
94
  meta: object;
73
95
  }>;
96
+ deleteLocaleTranslation: import("@trpc/server").TRPCMutationProcedure<{
97
+ input: {
98
+ sectionName: string;
99
+ locale: string;
100
+ };
101
+ output: boolean;
102
+ meta: object;
103
+ }>;
74
104
  }>>;
75
105
  //# sourceMappingURL=simpleSection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"simpleSection.d.ts","sourceRoot":"","sources":["../../../src/api/routers/simpleSection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAU9B,CAAA"}
1
+ {"version":3,"file":"simpleSection.d.ts","sourceRoot":"","sources":["../../../src/api/routers/simpleSection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAOxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBA2D66Z,CAAC;;;;;uBAAsE,CAAC;;;;;;uBAA2G,CAAC;;;;;;;;;;;;;;;GAD/na,CAAA"}
@@ -1,12 +1,54 @@
1
1
  import { privateProcedure, router } from '../trpc.js';
2
2
  import * as z from 'zod';
3
- import { createSimpleSectionPage } from '../lib/serverActions.js';
3
+ import { createSimpleSectionPage, deleteLocaleTranslation } from '../lib/serverActions.js';
4
+ import { TRPCError } from '@trpc/server';
5
+ import { getCMSConfig } from '../../core/config/index.js';
6
+ import { resolveLocale } from '../../core/localization/index.js';
7
+ import getString from '../../translations/index.js';
4
8
  export const simpleSectionRouter = router({
5
9
  create: privateProcedure
6
10
  .input(z.object({
7
11
  sectionName: z.string(),
12
+ locale: z.string().optional(),
8
13
  }))
9
14
  .query(async ({ ctx, input }) => {
10
- return await createSimpleSectionPage(ctx.session, input.sectionName);
15
+ return await createSimpleSectionPage(ctx.session, input.sectionName, input.locale);
16
+ }),
17
+ deleteLocaleTranslation: privateProcedure
18
+ .input(z.object({
19
+ sectionName: z.string(),
20
+ locale: z.string(),
21
+ }))
22
+ .mutation(async ({ ctx, input }) => {
23
+ const cmsConfig = await getCMSConfig();
24
+ const localeResult = resolveLocale({
25
+ localization: cmsConfig.localization,
26
+ locale: input.locale,
27
+ });
28
+ if (!localeResult.resolvedLocale) {
29
+ if (localeResult.localizationEnabled === false) {
30
+ throw new TRPCError({
31
+ code: 'BAD_REQUEST',
32
+ message: getString('localizationNotEnabledForSection', ctx.session.user.language),
33
+ });
34
+ }
35
+ throw new TRPCError({
36
+ code: 'BAD_REQUEST',
37
+ message: getString('invalidLocale', ctx.session.user.language, {
38
+ locale: input.locale,
39
+ locales: localeResult.availableLocales.map((l) => l.code).join(', '),
40
+ }),
41
+ });
42
+ }
43
+ // Simple sections always have itemId = 1
44
+ const result = await deleteLocaleTranslation(ctx.session, input.sectionName, 1, localeResult.resolvedLocale.code);
45
+ if (result && typeof result === 'object' && 'error' in result) {
46
+ const message = result.error?.message ?? 'Failed to delete locale translation';
47
+ throw new TRPCError({
48
+ code: 'BAD_REQUEST',
49
+ message,
50
+ });
51
+ }
52
+ return result;
11
53
  }),
12
54
  });
package/dist/api/trpc.js CHANGED
@@ -85,13 +85,13 @@ const accessControlMiddleware = (sectionName, requiredRole) => isAuthedMiddlewar
85
85
  if (!allowed) {
86
86
  throw new TRPCError({
87
87
  code: 'NOT_FOUND',
88
- message: getString('sectionNotFound', ctx.session.user.locale),
88
+ message: getString('sectionNotFound', ctx.session.user.language),
89
89
  });
90
90
  }
91
91
  if (requiredRole && !allowed.operations.includes(requiredRole)) {
92
92
  throw new TRPCError({
93
93
  code: 'NOT_FOUND',
94
- message: getString('noAccessToThisOperation', ctx.session.user.locale),
94
+ message: getString('noAccessToThisOperation', ctx.session.user.language),
95
95
  });
96
96
  }
97
97
  return next();
@@ -4,7 +4,7 @@ export interface Session {
4
4
  export interface User {
5
5
  id: string;
6
6
  name: string;
7
- locale: string;
7
+ language: string;
8
8
  email?: string | null;
9
9
  image?: string | null;
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,IAAI,CAAA;CACb;AAED,MAAM,WAAW,IAAI;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAeD;;GAEG;AACH,iBAAe,gBAAgB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAczD;AAED;;GAEG;AACH,QAAA,MAAM,IAAI,yBAA0B,CAAA;AAEpC;;GAEG;AACH,eAAe,IAAI,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,IAAI,CAAA;CACb;AAED,MAAM,WAAW,IAAI;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAeD;;GAEG;AACH,iBAAe,gBAAgB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAczD;AAED;;GAEG;AACH,QAAA,MAAM,IAAI,yBAA0B,CAAA;AAEpC;;GAEG;AACH,eAAe,IAAI,CAAA"}
@@ -26,7 +26,7 @@ async function __auth__internal() {
26
26
  user: {
27
27
  id: jwt.id,
28
28
  name: jwt.sub,
29
- locale: jwt.locale,
29
+ language: jwt.language,
30
30
  },
31
31
  };
32
32
  }
@@ -19,17 +19,17 @@ export declare const authRefresh: (refreshToken?: {
19
19
  };
20
20
  code?: undefined;
21
21
  }>;
22
- export declare const login: ({ username, password, locale: localeParam, }: {
22
+ export declare const login: ({ username, password, language: languageParam, }: {
23
23
  username: string;
24
24
  password: string;
25
- locale?: string;
25
+ language?: string;
26
26
  }) => Promise<{
27
27
  status: number;
28
28
  session: {
29
29
  user: {
30
30
  id: string;
31
31
  name: string;
32
- locale: string;
32
+ language: string;
33
33
  };
34
34
  };
35
35
  user: {
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/auth/lib/actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAI1C,eAAO,MAAM,WAAW,GAAU,eAAe;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;EA4HjE,CAAA;AAED,eAAO,MAAM,KAAK,GAAU,8CAIzB;IACC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;;;;;;;;;;;;;;;;EAwHA,CAAA;AAED,eAAO,MAAM,aAAa,GAAU,UAAU,OAAO,GAAG,IAAI,qBA0B3D,CAAA"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/auth/lib/actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAI1C,eAAO,MAAM,WAAW,GAAU,eAAe;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;EA4HjE,CAAA;AAED,eAAO,MAAM,KAAK,GAAU,kDAIzB;IACC,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;;;;;;;;;;;;;;;;EAwHA,CAAA;AAED,eAAO,MAAM,aAAa,GAAU,UAAU,OAAO,GAAG,IAAI,qBA0B3D,CAAA"}
@@ -23,7 +23,7 @@ export const authRefresh = async (refreshToken) => {
23
23
  refreshToken: AccessTokensTable.refreshToken,
24
24
  expiration: AccessTokensTable.expiration,
25
25
  username: AdminsTable.user,
26
- locale: AdminsTable.language,
26
+ language: AdminsTable.language,
27
27
  coverphoto: AdminsTable.coverphoto,
28
28
  })
29
29
  .from(AccessTokensTable)
@@ -44,7 +44,7 @@ export const authRefresh = async (refreshToken) => {
44
44
  iss: 'nextjs-cms',
45
45
  aud: 'admin',
46
46
  sub: adminTokenResult.username,
47
- locale: adminTokenResult.locale,
47
+ language: adminTokenResult.language,
48
48
  });
49
49
  const newRefreshToken = encodeRefreshToken({
50
50
  id: adminTokenResult.adminId,
@@ -91,7 +91,7 @@ export const authRefresh = async (refreshToken) => {
91
91
  user: {
92
92
  id: adminTokenResult.adminId,
93
93
  name: adminTokenResult.username,
94
- locale: adminTokenResult.locale,
94
+ language: adminTokenResult.language,
95
95
  },
96
96
  };
97
97
  return {
@@ -101,7 +101,7 @@ export const authRefresh = async (refreshToken) => {
101
101
  user: {
102
102
  id: adminTokenResult.adminId,
103
103
  username: adminTokenResult.username,
104
- lang: adminTokenResult.locale,
104
+ lang: adminTokenResult.language,
105
105
  avatar: adminTokenResult.coverphoto,
106
106
  },
107
107
  };
@@ -114,7 +114,7 @@ export const authRefresh = async (refreshToken) => {
114
114
  };
115
115
  }
116
116
  };
117
- export const login = async ({ username, password, locale: localeParam, }) => {
117
+ export const login = async ({ username, password, language: languageParam, }) => {
118
118
  if (!username || !password) {
119
119
  throw new Error(getString('usernameAndPasswordRequired', 'en'));
120
120
  }
@@ -123,7 +123,7 @@ export const login = async ({ username, password, locale: localeParam, }) => {
123
123
  password: AdminsTable.pass,
124
124
  id: AdminsTable.id,
125
125
  username: AdminsTable.user,
126
- locale: AdminsTable.language,
126
+ language: AdminsTable.language,
127
127
  coverphoto: AdminsTable.coverphoto,
128
128
  })
129
129
  .from(AdminsTable)
@@ -137,17 +137,17 @@ export const login = async ({ username, password, locale: localeParam, }) => {
137
137
  if (!valid) {
138
138
  throw new Error(getString('invalidCredentials', 'en'));
139
139
  }
140
- let effectiveLocale = admin.locale;
141
- if (localeParam && localeParam !== admin.locale) {
140
+ let effectiveLanguage = admin.language;
141
+ if (languageParam && languageParam !== admin.language) {
142
142
  const config = await getCMSConfig();
143
143
  const supported = new Set(config.i18n.supportedLanguages);
144
- if (supported.has(localeParam)) {
144
+ if (supported.has(languageParam)) {
145
145
  await db
146
146
  .update(AdminsTable)
147
- .set({ language: localeParam })
147
+ .set({ language: languageParam })
148
148
  .where(eq(AdminsTable.id, admin.id))
149
149
  .execute();
150
- effectiveLocale = localeParam;
150
+ effectiveLanguage = languageParam;
151
151
  }
152
152
  }
153
153
  const accessToken = encodeJWT({
@@ -155,7 +155,7 @@ export const login = async ({ username, password, locale: localeParam, }) => {
155
155
  iss: 'nextjs-cms',
156
156
  aud: 'admin',
157
157
  sub: admin.username,
158
- locale: effectiveLocale,
158
+ language: effectiveLanguage,
159
159
  });
160
160
  const refreshToken = encodeRefreshToken({
161
161
  id: admin.id,
@@ -212,13 +212,13 @@ export const login = async ({ username, password, locale: localeParam, }) => {
212
212
  user: {
213
213
  id: admin.id,
214
214
  name: admin.username,
215
- locale: effectiveLocale,
215
+ language: effectiveLanguage,
216
216
  },
217
217
  },
218
218
  user: {
219
219
  id: admin.id,
220
220
  username: admin.username,
221
- lang: effectiveLocale,
221
+ lang: effectiveLanguage,
222
222
  avatar: admin.coverphoto,
223
223
  },
224
224
  accessToken,
@@ -56,10 +56,10 @@ export declare const __AUTH: AuthClientConfig;
56
56
  export declare function logout(options?: {
57
57
  deleteCookies?: boolean;
58
58
  }): Promise<void>;
59
- export declare function login({ username, password, locale, }: {
59
+ export declare function login({ username, password, language, }: {
60
60
  username: string;
61
61
  password: string;
62
- locale?: string;
62
+ language?: string;
63
63
  }): Promise<void>;
64
64
  export declare function refreshSession(session: Session): Promise<void>;
65
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/auth/react.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/auth/react.tsx"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { fetchData, now, useOnline } from './lib/client.js';
7
7
  import { useRouter } from 'next/navigation';
8
8
  import useAxiosPrivate from './hooks/useAxiosPrivate.js';
9
9
  import useRefreshToken from './hooks/useRefreshToken.js';
10
- import { setLoginPageLocaleCookie, clearLocaleChangedOnLogin } from '../translations/locale-cookie.js';
10
+ import { setLoginPageLanguageCookie, clearLanguageChangedOnLogin } from '../translations/language-cookie.js';
11
11
  export const __AUTH = {
12
12
  _lastSync: 0,
13
13
  _session: undefined,
@@ -40,10 +40,10 @@ export async function logout(options) {
40
40
  */
41
41
  await __AUTH._getSession({ event: 'logout' });
42
42
  }
43
- export async function login({ username, password, locale, }) {
43
+ export async function login({ username, password, language, }) {
44
44
  const body = { username, password };
45
- if (locale)
46
- body.locale = locale;
45
+ if (language)
46
+ body.language = language;
47
47
  const response = await fetch('/api/auth', {
48
48
  method: 'POST',
49
49
  headers: {
@@ -61,9 +61,9 @@ export async function login({ username, password, locale, }) {
61
61
  * Clear the locale changed flag and sync cookie with session locale.
62
62
  * This ensures the cookie matches the user's effective locale after login.
63
63
  */
64
- clearLocaleChangedOnLogin();
65
- if (data.session?.user?.locale) {
66
- setLoginPageLocaleCookie(data.session.user.locale);
64
+ clearLanguageChangedOnLogin();
65
+ if (data.session?.user?.language) {
66
+ setLoginPageLanguageCookie(data.session.user.language);
67
67
  }
68
68
  /**
69
69
  * Broadcast a message to all other tabs/windows to tell them the user has logged in.
@@ -140,16 +140,16 @@ export async function dbConfigSetup(options) {
140
140
  /**
141
141
  * Prepare new environment variables block
142
142
  */
143
- const newEnvBlock = `
144
-
145
- ####
146
- # generated by the init script
147
- ####
148
- DB_HOST=${dbHost}
149
- DB_PORT=${dbPort}
150
- DB_NAME=${dbName}
151
- DB_USER=${dbUser}
152
- DB_PASSWORD='${dbPassword}'
143
+ const newEnvBlock = `
144
+
145
+ ####
146
+ # generated by the init script
147
+ ####
148
+ DB_HOST=${dbHost}
149
+ DB_PORT=${dbPort}
150
+ DB_NAME=${dbName}
151
+ DB_USER=${dbUser}
152
+ DB_PASSWORD='${dbPassword}'
153
153
  `;
154
154
  /**
155
155
  * Append the new credentials to the .env file
@@ -1 +1 @@
1
- {"version":3,"file":"update-sections.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/update-sections.ts"],"names":[],"mappings":"AA0mCA,wBAAsB,cAAc,CAAC,SAAS,UAAQ,iBAoBrD"}
1
+ {"version":3,"file":"update-sections.d.ts","sourceRoot":"","sources":["../../../src/cli/lib/update-sections.ts"],"names":[],"mappings":"AAkxCA,wBAAsB,cAAc,CAAC,SAAS,UAAQ,iBAoBrD"}
@@ -5,13 +5,13 @@ import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { SectionFactory } from '../../core/factories/index.js';
7
7
  import { getCMSConfig } from '../../core/config/index.js';
8
- import { CheckboxField, ColorField, DateField, MapField, NumberField, PasswordField, RichTextField, SelectField, SelectMultipleField, TagsField, TextAreaField, TextField, textAreaField, textField, } from '../../core/fields/index.js';
8
+ import { CheckboxField, ColorField, DateField, MapField, NumberField, PasswordField, RichTextField, SelectField, SelectMultipleField, TagsField, TextAreaField, TextField, textAreaField, textField, numberField, } from '../../core/fields/index.js';
9
9
  import { is } from '../../core/helpers/index.js';
10
10
  import { FileField } from '../../core/fields/index.js';
11
11
  import chalk from 'chalk';
12
12
  import { intro, select, spinner, log } from '@clack/prompts';
13
13
  import { MysqlTableChecker } from '../../core/db/index.js';
14
- import { generateDrizzleSchema, resolveCaseStyleFns } from '../utils/schema-generator.js';
14
+ import { generateDrizzleSchema, generateLocalesTableSchema, resolveCaseStyleFns } from '../utils/schema-generator.js';
15
15
  import { addTableKeys } from '../utils/add-table-keys.js';
16
16
  function generateFieldSQL(input) {
17
17
  let fieldSQL = `\`${input.name}\` `;
@@ -446,6 +446,50 @@ async function updateTable(table, s) {
446
446
  }
447
447
  }
448
448
  }
449
+ /**
450
+ * Special handling: if this is a destinationDb table and 'locale' is being removed,
451
+ * it means a select/tags field was changed from localized: true to localized: false.
452
+ * Handle this with a detailed prompt and proper data cleanup.
453
+ */
454
+ if (table.sectionType === 'destinationDb' && fieldsToRemove.includes('locale')) {
455
+ fieldsToRemove = fieldsToRemove.filter((f) => f !== 'locale');
456
+ s.stop();
457
+ const cmsConfig = await getCMSConfig();
458
+ const defaultLocaleCode = cmsConfig.localization?.defaultLocale ?? 'en';
459
+ const shouldDelocalize = await select({
460
+ message: `The 'locale' column in junction table '${table.name}' is no longer needed (field is no longer localized). This will:\n` +
461
+ ` 1. Delete all non-default-locale rows (locale != '${defaultLocaleCode}')\n` +
462
+ ` 2. Drop the 'locale' column from the table\n` +
463
+ ` 3. Update the primary key to exclude 'locale'\n` +
464
+ `Proceed?`,
465
+ options: [
466
+ { value: 'no', label: 'No, keep the locale column' },
467
+ { value: 'yes', label: 'Yes, remove locale data and column' },
468
+ ],
469
+ initialValue: 'no',
470
+ });
471
+ if (shouldDelocalize === 'yes') {
472
+ try {
473
+ // Delete all non-default-locale rows
474
+ await db.execute(sql `DELETE FROM ${sql.raw(`\`${table.name}\``)} WHERE \`locale\` != ${defaultLocaleCode}`);
475
+ log.info(chalk.gray(` - Deleted non-default-locale rows from '${table.name}'`));
476
+ }
477
+ catch (error) {
478
+ console.error(chalk.red(` - Error deleting locale rows from '${table.name}':`, error));
479
+ }
480
+ alterTableSQLs.push({
481
+ field: 'locale',
482
+ table: table.name,
483
+ action: 'remove',
484
+ sql: `DROP COLUMN \`locale\``,
485
+ });
486
+ log.info(chalk.red(`Removing 'locale' column from '${table.name}'`));
487
+ }
488
+ else {
489
+ log.info(chalk.yellow(`- 'locale' column kept in '${table.name}'.`));
490
+ }
491
+ s.start();
492
+ }
449
493
  /**
450
494
  * Finally, check if there are fields to remove
451
495
  */
@@ -620,26 +664,44 @@ const main = async (s) => {
620
664
  required: true,
621
665
  order: 0,
622
666
  });
667
+ /**
668
+ * If the field is localized, add a locale column to the destination table
669
+ * so that junction table values can be scoped per locale
670
+ */
671
+ const isLocalized = field.localized && cmsConfig.localization?.enabled;
672
+ const localeFieldConfig = isLocalized
673
+ ? textField({
674
+ name: 'locale',
675
+ label: 'Locale',
676
+ required: false,
677
+ order: 0,
678
+ })
679
+ : undefined;
680
+ const tableFields = localeFieldConfig
681
+ ? [referenceIdFieldConfig.build(), selectIdFieldConfig.build(), localeFieldConfig.build()]
682
+ : [referenceIdFieldConfig.build(), selectIdFieldConfig.build()];
683
+ const primaryKeyFields = localeFieldConfig
684
+ ? [referenceIdFieldConfig, selectIdFieldConfig, localeFieldConfig]
685
+ : [referenceIdFieldConfig, selectIdFieldConfig];
623
686
  desiredTables.push({
624
687
  name: field.destinationDb.table,
625
- fields: [referenceIdFieldConfig.build(), selectIdFieldConfig.build()],
688
+ fields: tableFields,
626
689
  sectionName: s.name,
627
690
  sectionType: 'destinationDb',
628
691
  identifier: undefined,
629
- /**
630
- * We can use both the referenceIdField and the selectIdField as a composite primary key
631
- * since they are unique together for each row
632
- */
633
- primaryKey: [referenceIdFieldConfig, selectIdFieldConfig],
692
+ primaryKey: primaryKeyFields,
634
693
  });
635
694
  const destDbFields = [
636
695
  { name: field.destinationDb.itemIdentifier, type: 'text', required: true },
637
696
  { name: field.destinationDb.selectIdentifier, type: 'text', required: true },
697
+ ...(isLocalized ? [{ name: 'locale', type: 'text', required: false }] : []),
638
698
  ];
639
699
  const destDbSchema = generateDrizzleSchema({
640
700
  name: field.destinationDb.table,
641
701
  fields: destDbFields,
642
- compositePrimaryKey: destDbFields,
702
+ compositePrimaryKey: isLocalized
703
+ ? destDbFields
704
+ : destDbFields.filter((f) => f.name !== 'locale'),
643
705
  }, caseStyleFns);
644
706
  drizzleTableSchemas.push(destDbSchema.schema);
645
707
  destDbSchema.drizzleImports.forEach((type) => drizzleImports.add(type));
@@ -710,6 +772,64 @@ const main = async (s) => {
710
772
  drizzleTableSchemas.push(gallerySchema.schema);
711
773
  gallerySchema.drizzleImports.forEach((type) => drizzleImports.add(type));
712
774
  }
775
+ /**
776
+ * Check for localized fields — generate a _locales table if localization is enabled
777
+ */
778
+ if (cmsConfig.localization?.enabled && s.hasLocalizedFields) {
779
+ const localesTableName = s.localesTableName;
780
+ const parentIdFieldConfig = s.db.identifier.type === 'number'
781
+ ? numberField({
782
+ name: 'parent_id',
783
+ label: 'Parent ID',
784
+ required: true,
785
+ order: 0,
786
+ })
787
+ : textField({
788
+ name: 'parent_id',
789
+ label: 'Parent ID',
790
+ required: true,
791
+ maxLength: s.db.identifier.maxLength ?? 255,
792
+ order: 0,
793
+ });
794
+ const localeFieldConfig = textField({
795
+ name: 'locale',
796
+ label: 'Locale',
797
+ required: true,
798
+ maxLength: 10,
799
+ order: 0,
800
+ });
801
+ const idFieldConfig = numberField({
802
+ name: 'id',
803
+ label: 'ID',
804
+ required: true,
805
+ hasAutoIncrement: true,
806
+ order: 0,
807
+ });
808
+ const localizedFieldInstances = s.fields.filter((f) => f.localized);
809
+ desiredTables.push({
810
+ name: localesTableName,
811
+ fields: [
812
+ idFieldConfig.build(),
813
+ parentIdFieldConfig.build(),
814
+ localeFieldConfig.build(),
815
+ ...localizedFieldInstances,
816
+ ],
817
+ sectionName: s.name,
818
+ sectionType: 'locales',
819
+ identifier: idFieldConfig,
820
+ primaryKey: [idFieldConfig],
821
+ unique: [{ columns: [parentIdFieldConfig, localeFieldConfig] }],
822
+ });
823
+ const localizedFieldConfigs = s.fieldConfigs.filter((f) => 'localized' in f && f.localized === true);
824
+ const localesSchema = generateLocalesTableSchema({
825
+ parentTableName: s.db.table,
826
+ parentIdentifier: s.db.identifier,
827
+ localizedFields: localizedFieldConfigs,
828
+ caseStyleFns,
829
+ });
830
+ drizzleTableSchemas.push(localesSchema.schema);
831
+ localesSchema.drizzleImports.forEach((type) => drizzleImports.add(type));
832
+ }
713
833
  }
714
834
  /**
715
835
  * Write schema file if schema generation is enabled
@@ -827,6 +947,14 @@ const main = async (s) => {
827
947
  updatedBy: false,
828
948
  };
829
949
  }
950
+ if (table.sectionType === 'locales') {
951
+ options = {
952
+ createdAt: true,
953
+ updatedAt: true,
954
+ createdBy: false,
955
+ updatedBy: false,
956
+ };
957
+ }
830
958
  await createTable(table, options);
831
959
  break;
832
960
  }
@@ -891,6 +1019,14 @@ const main = async (s) => {
891
1019
  updatedBy: false,
892
1020
  };
893
1021
  }
1022
+ if (table.sectionType === 'locales') {
1023
+ options = {
1024
+ createdAt: true,
1025
+ updatedAt: true,
1026
+ createdBy: false,
1027
+ updatedBy: false,
1028
+ };
1029
+ }
894
1030
  await createTable(table, options);
895
1031
  /*} else {
896
1032
  console.log('Aborting...')
@@ -41,4 +41,24 @@ export declare function generateDrizzleSchema(table: {
41
41
  schema: string;
42
42
  drizzleImports: string[];
43
43
  };
44
+ /**
45
+ * Generates a Drizzle schema for a `_locales` table that stores per-locale
46
+ * translations of fields marked `localized: true`.
47
+ *
48
+ * The table has:
49
+ * - `id` – auto-increment primary key
50
+ * - `parent_id` – references the parent section's identifier
51
+ * - `locale` – locale code (e.g. "en", "ar")
52
+ * - one column per localized field
53
+ * - a unique constraint on `(parent_id, locale)`
54
+ */
55
+ export declare function generateLocalesTableSchema(params: {
56
+ parentTableName: string;
57
+ parentIdentifier: FieldConfig;
58
+ localizedFields: FieldConfig[];
59
+ caseStyleFns: CaseStyleFns;
60
+ }): {
61
+ schema: string;
62
+ drizzleImports: string[];
63
+ };
44
64
  //# sourceMappingURL=schema-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-generator.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/schema-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAoB7D,MAAM,WAAW,YAAY;IACzB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACzC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;CAC7C;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;IAChD,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;CACpD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CA8BtE;AAED,wBAAgB,qBAAqB,CACjC,KAAK,EAAE;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,WAAW,CAAA;IACxB,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxC,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxD,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC9D,EACD,YAAY,EAAE,YAAY,GAC3B;IACC,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;CAC3B,CAmLA"}
1
+ {"version":3,"file":"schema-generator.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/schema-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAoB7D,MAAM,WAAW,YAAY;IACzB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IACzC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;CAC7C;AAED,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;IAChD,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;CACpD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CA8BtE;AAED,wBAAgB,qBAAqB,CACjC,KAAK,EAAE;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,WAAW,CAAA;IACxB,mBAAmB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxC,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxD,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC9D,EACD,YAAY,EAAE,YAAY,GAC3B;IACC,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;CAC3B,CAmLA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE;IACJ,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,WAAW,CAAA;IAC7B,eAAe,EAAE,WAAW,EAAE,CAAA;IAC9B,YAAY,EAAE,YAAY,CAAA;CAC7B,GACF;IACC,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,EAAE,CAAA;CAC3B,CAoCA"}