@flusys/nestjs-localization 7.1.0 → 8.0.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 (117) hide show
  1. package/config/index.d.ts +3 -3
  2. package/controllers/index.d.ts +3 -3
  3. package/controllers/language.controller.d.ts +4 -4
  4. package/controllers/translation-key.controller.d.ts +3 -3
  5. package/controllers/translation.controller.d.ts +4 -4
  6. package/docs/index.d.ts +1 -1
  7. package/docs/localization-swagger.config.d.ts +1 -1
  8. package/dtos/index.d.ts +3 -3
  9. package/dtos/translation.dto.d.ts +2 -2
  10. package/entities/index.d.ts +6 -6
  11. package/entities/language.entity.d.ts +1 -1
  12. package/entities/translation-key.entity.d.ts +1 -1
  13. package/entities/translation.entity.d.ts +2 -2
  14. package/fesm/349.js +1179 -0
  15. package/fesm/692.js +1205 -0
  16. package/fesm/config/index.js +101 -3
  17. package/fesm/controllers/index.js +15 -3
  18. package/fesm/docs/index.js +126 -1
  19. package/fesm/dtos/index.js +680 -3
  20. package/fesm/entities/index.js +405 -8
  21. package/fesm/index.js +257 -7
  22. package/fesm/interfaces/index.js +18 -4
  23. package/fesm/modules/index.js +152 -1
  24. package/fesm/runtime.js +85 -0
  25. package/fesm/services/index.js +15 -5
  26. package/index.d.ts +7 -7
  27. package/interfaces/index.d.ts +4 -4
  28. package/interfaces/language.interface.d.ts +1 -1
  29. package/interfaces/localization-module-options.interface.d.ts +3 -3
  30. package/interfaces/translation-key.interface.d.ts +1 -1
  31. package/interfaces/translation.interface.d.ts +3 -3
  32. package/modules/index.d.ts +1 -1
  33. package/modules/localization.module.d.ts +2 -2
  34. package/package.json +25 -34
  35. package/services/index.d.ts +5 -5
  36. package/services/language.service.d.ts +6 -6
  37. package/services/localization-config.service.d.ts +3 -3
  38. package/services/localization-datasource.provider.d.ts +3 -3
  39. package/services/translation-key.service.d.ts +6 -6
  40. package/services/translation.service.d.ts +5 -5
  41. package/cjs/config/event-actions.js +0 -33
  42. package/cjs/config/index.js +0 -20
  43. package/cjs/config/localization.constants.js +0 -11
  44. package/cjs/config/message-keys.js +0 -41
  45. package/cjs/controllers/index.js +0 -20
  46. package/cjs/controllers/language.controller.js +0 -188
  47. package/cjs/controllers/language.controller.spec.js +0 -154
  48. package/cjs/controllers/translation-key.controller.js +0 -135
  49. package/cjs/controllers/translation-key.controller.spec.js +0 -70
  50. package/cjs/controllers/translation.controller.js +0 -195
  51. package/cjs/controllers/translation.controller.spec.js +0 -169
  52. package/cjs/docs/index.js +0 -11
  53. package/cjs/docs/localization-swagger.config.js +0 -111
  54. package/cjs/docs/localization-swagger.config.spec.js +0 -30
  55. package/cjs/dtos/index.js +0 -20
  56. package/cjs/dtos/language.dto.js +0 -213
  57. package/cjs/dtos/translation-key.dto.js +0 -215
  58. package/cjs/dtos/translation.dto.js +0 -269
  59. package/cjs/entities/index.js +0 -42
  60. package/cjs/entities/index.spec.js +0 -18
  61. package/cjs/entities/language.entity.js +0 -126
  62. package/cjs/entities/translation-key.entity.js +0 -126
  63. package/cjs/entities/translation.entity.js +0 -120
  64. package/cjs/index.js +0 -24
  65. package/cjs/interfaces/index.js +0 -21
  66. package/cjs/interfaces/language.interface.js +0 -4
  67. package/cjs/interfaces/localization-module-options.interface.js +0 -4
  68. package/cjs/interfaces/translation-key.interface.js +0 -4
  69. package/cjs/interfaces/translation.interface.js +0 -4
  70. package/cjs/modules/index.js +0 -18
  71. package/cjs/modules/localization.module.js +0 -116
  72. package/cjs/modules/localization.module.spec.js +0 -132
  73. package/cjs/services/index.js +0 -22
  74. package/cjs/services/language.service.js +0 -181
  75. package/cjs/services/language.service.spec.js +0 -256
  76. package/cjs/services/localization-config.service.js +0 -66
  77. package/cjs/services/localization-config.service.spec.js +0 -80
  78. package/cjs/services/localization-datasource.provider.js +0 -79
  79. package/cjs/services/localization-datasource.provider.spec.js +0 -85
  80. package/cjs/services/translation-key.service.js +0 -179
  81. package/cjs/services/translation-key.service.spec.js +0 -303
  82. package/cjs/services/translation.service.js +0 -228
  83. package/cjs/services/translation.service.spec.js +0 -530
  84. package/fesm/config/event-actions.js +0 -12
  85. package/fesm/config/localization.constants.js +0 -1
  86. package/fesm/config/message-keys.js +0 -20
  87. package/fesm/controllers/language.controller.js +0 -178
  88. package/fesm/controllers/language.controller.spec.js +0 -150
  89. package/fesm/controllers/translation-key.controller.js +0 -125
  90. package/fesm/controllers/translation-key.controller.spec.js +0 -66
  91. package/fesm/controllers/translation.controller.js +0 -185
  92. package/fesm/controllers/translation.controller.spec.js +0 -165
  93. package/fesm/docs/localization-swagger.config.js +0 -101
  94. package/fesm/docs/localization-swagger.config.spec.js +0 -26
  95. package/fesm/dtos/language.dto.js +0 -192
  96. package/fesm/dtos/translation-key.dto.js +0 -194
  97. package/fesm/dtos/translation.dto.js +0 -239
  98. package/fesm/entities/index.spec.js +0 -14
  99. package/fesm/entities/language.entity.js +0 -116
  100. package/fesm/entities/translation-key.entity.js +0 -116
  101. package/fesm/entities/translation.entity.js +0 -110
  102. package/fesm/interfaces/language.interface.js +0 -1
  103. package/fesm/interfaces/localization-module-options.interface.js +0 -1
  104. package/fesm/interfaces/translation-key.interface.js +0 -1
  105. package/fesm/interfaces/translation.interface.js +0 -1
  106. package/fesm/modules/localization.module.js +0 -106
  107. package/fesm/modules/localization.module.spec.js +0 -128
  108. package/fesm/services/language.service.js +0 -171
  109. package/fesm/services/language.service.spec.js +0 -252
  110. package/fesm/services/localization-config.service.js +0 -56
  111. package/fesm/services/localization-config.service.spec.js +0 -76
  112. package/fesm/services/localization-datasource.provider.js +0 -69
  113. package/fesm/services/localization-datasource.provider.spec.js +0 -81
  114. package/fesm/services/translation-key.service.js +0 -169
  115. package/fesm/services/translation-key.service.spec.js +0 -299
  116. package/fesm/services/translation.service.js +0 -218
  117. package/fesm/services/translation.service.spec.js +0 -526
@@ -1,132 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- const _localizationmodule = require("./localization.module");
6
- const _localizationconstants = require("../config/localization.constants");
7
- const _controllers = require("../controllers");
8
- function _define_property(obj, key, value) {
9
- if (key in obj) {
10
- Object.defineProperty(obj, key, {
11
- value: value,
12
- enumerable: true,
13
- configurable: true,
14
- writable: true
15
- });
16
- } else {
17
- obj[key] = value;
18
- }
19
- return obj;
20
- }
21
- function providerTokens(providers) {
22
- return providers.map((p)=>typeof p === 'function' ? p : p.provide);
23
- }
24
- describe('LocalizationModule', ()=>{
25
- describe('forRoot', ()=>{
26
- it('should default to a non-global module with all controllers registered', ()=>{
27
- const dynamicModule = _localizationmodule.LocalizationModule.forRoot({});
28
- expect(dynamicModule.module).toBe(_localizationmodule.LocalizationModule);
29
- expect(dynamicModule.global).toBe(false);
30
- expect(dynamicModule.controllers).toEqual([
31
- _controllers.LanguageController,
32
- _controllers.TranslationKeyController,
33
- _controllers.TranslationController
34
- ]);
35
- });
36
- it('should respect global: true', ()=>{
37
- expect(_localizationmodule.LocalizationModule.forRoot({
38
- global: true
39
- }).global).toBe(true);
40
- });
41
- it('should register no controllers when includeController is false', ()=>{
42
- expect(_localizationmodule.LocalizationModule.forRoot({
43
- includeController: false
44
- }).controllers).toEqual([]);
45
- });
46
- it('should register a LOCALIZATION_MODULE_OPTIONS provider carrying the given options', ()=>{
47
- const options = {
48
- bootstrapAppConfig: {}
49
- };
50
- const dynamicModule = _localizationmodule.LocalizationModule.forRoot(options);
51
- const provider = dynamicModule.providers.find((p)=>p.provide === _localizationconstants.LOCALIZATION_MODULE_OPTIONS);
52
- expect(provider.useValue).toBe(options);
53
- });
54
- it('should always export the same fixed set of services', ()=>{
55
- expect(_localizationmodule.LocalizationModule.forRoot({}).exports).toHaveLength(5);
56
- });
57
- });
58
- describe('forRootAsync', ()=>{
59
- it('should forward external imports alongside CacheModule/UtilsModule', ()=>{
60
- let FakeImportedModule = class FakeImportedModule {
61
- };
62
- const dynamicModule = _localizationmodule.LocalizationModule.forRootAsync({
63
- imports: [
64
- FakeImportedModule
65
- ]
66
- });
67
- expect(dynamicModule.imports).toEqual(expect.arrayContaining([
68
- FakeImportedModule
69
- ]));
70
- });
71
- it('useFactory: builds a LOCALIZATION_MODULE_OPTIONS provider merging resolved config', async ()=>{
72
- const useFactory = jest.fn().mockResolvedValue({
73
- foo: 'bar'
74
- });
75
- const dynamicModule = _localizationmodule.LocalizationModule.forRootAsync({
76
- useFactory,
77
- inject: [
78
- 'SOME_TOKEN'
79
- ]
80
- });
81
- const provider = dynamicModule.providers.find((p)=>p.provide === _localizationconstants.LOCALIZATION_MODULE_OPTIONS);
82
- expect(provider.inject).toEqual([
83
- 'SOME_TOKEN'
84
- ]);
85
- const resolved = await provider.useFactory('injected');
86
- expect(useFactory).toHaveBeenCalledWith('injected');
87
- expect(resolved.config).toEqual({
88
- foo: 'bar'
89
- });
90
- });
91
- it('useClass: registers both the class provider and an options provider calling createLocalizationOptions()', async ()=>{
92
- let MyOptionsFactory = class MyOptionsFactory {
93
- constructor(){
94
- _define_property(this, "createLocalizationOptions", jest.fn().mockResolvedValue({
95
- foo: 'from-class'
96
- }));
97
- }
98
- };
99
- const dynamicModule = _localizationmodule.LocalizationModule.forRootAsync({
100
- useClass: MyOptionsFactory
101
- });
102
- const classProvider = dynamicModule.providers.find((p)=>p.provide === MyOptionsFactory);
103
- expect(classProvider.useClass).toBe(MyOptionsFactory);
104
- const optionsProvider = dynamicModule.providers.find((p)=>p.provide === _localizationconstants.LOCALIZATION_MODULE_OPTIONS);
105
- const instance = new MyOptionsFactory();
106
- const resolved = await optionsProvider.useFactory(instance);
107
- expect(instance.createLocalizationOptions).toHaveBeenCalled();
108
- expect(resolved.config).toEqual({
109
- foo: 'from-class'
110
- });
111
- });
112
- it('useExisting: registers a single options provider without a duplicate class registration', ()=>{
113
- let MyOptionsFactory = class MyOptionsFactory {
114
- constructor(){
115
- _define_property(this, "createLocalizationOptions", jest.fn());
116
- }
117
- };
118
- const dynamicModule = _localizationmodule.LocalizationModule.forRootAsync({
119
- useExisting: MyOptionsFactory
120
- });
121
- expect(dynamicModule.providers.filter((p)=>p.provide === MyOptionsFactory)).toHaveLength(0);
122
- const optionsProvider = dynamicModule.providers.find((p)=>p.provide === _localizationconstants.LOCALIZATION_MODULE_OPTIONS);
123
- expect(optionsProvider.inject).toEqual([
124
- MyOptionsFactory
125
- ]);
126
- });
127
- it('should register no LOCALIZATION_MODULE_OPTIONS provider when neither useFactory, useClass, nor useExisting is given', ()=>{
128
- const dynamicModule = _localizationmodule.LocalizationModule.forRootAsync({});
129
- expect(providerTokens(dynamicModule.providers)).not.toContain(_localizationconstants.LOCALIZATION_MODULE_OPTIONS);
130
- });
131
- });
132
- });
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- _export_star(require("./localization-config.service"), exports);
6
- _export_star(require("./localization-datasource.provider"), exports);
7
- _export_star(require("./language.service"), exports);
8
- _export_star(require("./translation-key.service"), exports);
9
- _export_star(require("./translation.service"), exports);
10
- function _export_star(from, to) {
11
- Object.keys(from).forEach(function(k) {
12
- if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
13
- Object.defineProperty(to, k, {
14
- enumerable: true,
15
- get: function() {
16
- return from[k];
17
- }
18
- });
19
- }
20
- });
21
- return from;
22
- }
@@ -1,181 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "LanguageService", {
6
- enumerable: true,
7
- get: function() {
8
- return LanguageService;
9
- }
10
- });
11
- const _classes = require("@flusys/nestjs-shared/classes");
12
- const _modules = require("@flusys/nestjs-shared/modules");
13
- const _common = require("@nestjs/common");
14
- const _typeorm = require("typeorm");
15
- const _config = require("../config");
16
- const _entities = require("../entities");
17
- const _localizationdatasourceprovider = require("./localization-datasource.provider");
18
- function _define_property(obj, key, value) {
19
- if (key in obj) {
20
- Object.defineProperty(obj, key, {
21
- value: value,
22
- enumerable: true,
23
- configurable: true,
24
- writable: true
25
- });
26
- } else {
27
- obj[key] = value;
28
- }
29
- return obj;
30
- }
31
- function _ts_decorate(decorators, target, key, desc) {
32
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
33
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
34
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
35
- return c > 3 && r && Object.defineProperty(target, key, r), r;
36
- }
37
- function _ts_metadata(k, v) {
38
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
39
- }
40
- function _ts_param(paramIndex, decorator) {
41
- return function(target, key) {
42
- decorator(target, key, paramIndex);
43
- };
44
- }
45
- let LanguageService = class LanguageService extends _classes.ApiService {
46
- async beforeUpdateOperation(dto, _user, _queryRunner) {
47
- const dtos = Array.isArray(dto) ? dto : [
48
- dto
49
- ];
50
- const ids = dtos.map((d)=>d.id);
51
- await this.ensureDataSourceRepository();
52
- const existingLanguages = await this.repository.find({
53
- where: {
54
- id: (0, _typeorm.In)(ids),
55
- deletedAt: (0, _typeorm.IsNull)()
56
- }
57
- });
58
- for (const d of dtos){
59
- const existing = existingLanguages.find((e)=>e.id === d.id);
60
- if (!existing) {
61
- continue;
62
- }
63
- const changesIdentity = d.code !== undefined && d.code !== existing.code || d.name !== undefined && d.name !== existing.name || d.nativeName !== undefined && d.nativeName !== (existing.nativeName ?? undefined) || d.direction !== undefined && d.direction !== existing.direction;
64
- if (existing.isReadonly && changesIdentity) {
65
- throw new _common.ForbiddenException({
66
- message: `Cannot modify code/name of readonly language "${existing.name}"`,
67
- messageKey: _config.LANGUAGE_MESSAGES.READONLY_UPDATE_FORBIDDEN,
68
- messageVariables: {
69
- name: existing.name
70
- }
71
- });
72
- }
73
- }
74
- }
75
- async beforeDeleteOperation(dto, _user, _queryRunner) {
76
- const ids = Array.isArray(dto.id) ? dto.id : [
77
- dto.id
78
- ];
79
- await this.ensureDataSourceRepository();
80
- const languages = await this.repository.find({
81
- where: {
82
- id: (0, _typeorm.In)(ids),
83
- deletedAt: (0, _typeorm.IsNull)()
84
- }
85
- });
86
- const readonlyLanguages = languages.filter((l)=>l.isReadonly);
87
- if (readonlyLanguages.length > 0) {
88
- const names = readonlyLanguages.map((l)=>l.name).join(', ');
89
- throw new _common.ForbiddenException({
90
- message: `Cannot delete readonly language(s): ${names}`,
91
- messageKey: _config.LANGUAGE_MESSAGES.READONLY_DELETE_FORBIDDEN,
92
- messageVariables: {
93
- names
94
- }
95
- });
96
- }
97
- const defaultLanguages = languages.filter((l)=>l.isDefault);
98
- if (defaultLanguages.length > 0) {
99
- const names = defaultLanguages.map((l)=>l.name).join(', ');
100
- throw new _common.ForbiddenException({
101
- message: `Cannot delete the default language(s): ${names}. Set another language as default first.`,
102
- messageKey: _config.LANGUAGE_MESSAGES.DEFAULT_DELETE_FORBIDDEN,
103
- messageVariables: {
104
- names
105
- }
106
- });
107
- }
108
- }
109
- async getDefaultLanguage() {
110
- await this.ensureDataSourceRepository();
111
- return this.repository.findOne({
112
- where: {
113
- isDefault: true,
114
- deletedAt: (0, _typeorm.IsNull)()
115
- }
116
- });
117
- }
118
- async getActiveLanguages() {
119
- await this.ensureDataSourceRepository();
120
- return this.repository.find({
121
- where: {
122
- isActive: true,
123
- deletedAt: (0, _typeorm.IsNull)()
124
- },
125
- order: {
126
- serial: 'ASC',
127
- name: 'ASC'
128
- }
129
- });
130
- }
131
- async setAsDefault(id) {
132
- await this.ensureDataSourceRepository();
133
- const previousDefaults = await this.repository.find({
134
- where: {
135
- isDefault: true
136
- }
137
- });
138
- await this.repository.update({
139
- isDefault: true
140
- }, {
141
- isDefault: false
142
- });
143
- await this.repository.update({
144
- id
145
- }, {
146
- isDefault: true
147
- });
148
- const language = await this.repository.findOne({
149
- where: {
150
- id
151
- }
152
- });
153
- await Promise.all([
154
- this.clearCacheForAll(),
155
- this.clearCacheForId([
156
- ...previousDefaults,
157
- {
158
- id
159
- }
160
- ])
161
- ]);
162
- return language;
163
- }
164
- constructor(cacheManager, utilsService, dataSourceProvider){
165
- super(_config.LOCALIZATION_EVENT_ENTITIES.LANGUAGE, cacheManager, utilsService, LanguageService.name, true, _config.LOCALIZATION_EVENT_MODULE, dataSourceProvider, _entities.Language), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService;
166
- }
167
- };
168
- LanguageService = _ts_decorate([
169
- (0, _common.Injectable)({
170
- scope: _common.Scope.REQUEST
171
- }),
172
- _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
173
- _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
174
- _ts_param(2, (0, _common.Inject)(_localizationdatasourceprovider.LocalizationDataSourceProvider)),
175
- _ts_metadata("design:type", Function),
176
- _ts_metadata("design:paramtypes", [
177
- typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
178
- typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
179
- typeof _localizationdatasourceprovider.LocalizationDataSourceProvider === "undefined" ? Object : _localizationdatasourceprovider.LocalizationDataSourceProvider
180
- ])
181
- ], LanguageService);
@@ -1,256 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- const _testing = require("@nestjs/testing");
6
- const _modules = require("@flusys/nestjs-shared/modules");
7
- const _repositorymock = require("@test-utils/mocks/repository.mock");
8
- const _languageservice = require("./language.service");
9
- const _localizationdatasourceprovider = require("./localization-datasource.provider");
10
- function buildLanguage(overrides = {}) {
11
- return {
12
- id: 'language-uuid-1',
13
- code: 'en',
14
- name: 'English',
15
- nativeName: 'English',
16
- direction: 'ltr',
17
- isActive: true,
18
- isDefault: false,
19
- serial: 1,
20
- isReadonly: false,
21
- createdAt: new Date(),
22
- updatedAt: new Date(),
23
- deletedAt: null,
24
- createdById: null,
25
- updatedById: null,
26
- deletedById: null,
27
- ...overrides
28
- };
29
- }
30
- describe('LanguageService', ()=>{
31
- let service;
32
- let mockRepo;
33
- const mockUtilsService = {
34
- clearCache: jest.fn(),
35
- getCacheKey: jest.fn().mockReturnValue('cache-key'),
36
- trackCacheKey: jest.fn()
37
- };
38
- // Call history is shared across tests in this file; reset it so each cache assertion is exact.
39
- beforeEach(()=>{
40
- mockUtilsService.clearCache.mockClear();
41
- });
42
- beforeEach(async ()=>{
43
- mockRepo = (0, _repositorymock.createMockRepository)();
44
- const mockDataSourceProvider = (0, _repositorymock.createMockDataSourceProvider)(mockRepo);
45
- const module = await _testing.Test.createTestingModule({
46
- providers: [
47
- _languageservice.LanguageService,
48
- {
49
- provide: 'CACHE_INSTANCE',
50
- useValue: {}
51
- },
52
- {
53
- provide: _modules.UtilsService,
54
- useValue: mockUtilsService
55
- },
56
- {
57
- provide: _localizationdatasourceprovider.LocalizationDataSourceProvider,
58
- useValue: mockDataSourceProvider
59
- }
60
- ]
61
- }).compile();
62
- service = await module.resolve(_languageservice.LanguageService);
63
- });
64
- describe('getDefaultLanguage', ()=>{
65
- it('returns the language flagged as default', async ()=>{
66
- const defaultLanguage = buildLanguage({
67
- id: 'default-lang',
68
- isDefault: true,
69
- code: 'en'
70
- });
71
- mockRepo.findOne.mockResolvedValue(defaultLanguage);
72
- const result = await service.getDefaultLanguage();
73
- expect(mockRepo.findOne).toHaveBeenCalledWith({
74
- where: {
75
- isDefault: true,
76
- deletedAt: expect.anything()
77
- }
78
- });
79
- expect(result).toEqual(defaultLanguage);
80
- });
81
- it('returns null when no language is marked default', async ()=>{
82
- mockRepo.findOne.mockResolvedValue(null);
83
- const result = await service.getDefaultLanguage();
84
- expect(result).toBeNull();
85
- });
86
- });
87
- describe('getActiveLanguages', ()=>{
88
- it('returns active, non-deleted languages ordered by serial then name', async ()=>{
89
- const languages = [
90
- buildLanguage({
91
- code: 'en',
92
- serial: 1
93
- }),
94
- buildLanguage({
95
- code: 'bn',
96
- serial: 2
97
- })
98
- ];
99
- mockRepo.find.mockResolvedValue(languages);
100
- const result = await service.getActiveLanguages();
101
- expect(mockRepo.find).toHaveBeenCalledWith({
102
- where: {
103
- isActive: true,
104
- deletedAt: expect.anything()
105
- },
106
- order: {
107
- serial: 'ASC',
108
- name: 'ASC'
109
- }
110
- });
111
- expect(result).toHaveLength(2);
112
- });
113
- it('returns an empty array when no languages are active', async ()=>{
114
- mockRepo.find.mockResolvedValue([]);
115
- const result = await service.getActiveLanguages();
116
- expect(result).toEqual([]);
117
- });
118
- });
119
- describe('setAsDefault', ()=>{
120
- beforeEach(()=>{
121
- mockRepo.find.mockResolvedValue([]);
122
- });
123
- it('unsets the previous default and sets the requested language as default', async ()=>{
124
- const newDefault = buildLanguage({
125
- id: 'lang-2',
126
- isDefault: true,
127
- code: 'bn'
128
- });
129
- mockRepo.findOne.mockResolvedValue(newDefault);
130
- const result = await service.setAsDefault('lang-2');
131
- expect(mockRepo.update).toHaveBeenNthCalledWith(1, {
132
- isDefault: true
133
- }, {
134
- isDefault: false
135
- });
136
- expect(mockRepo.update).toHaveBeenNthCalledWith(2, {
137
- id: 'lang-2'
138
- }, {
139
- isDefault: true
140
- });
141
- expect(mockRepo.findOne).toHaveBeenCalledWith({
142
- where: {
143
- id: 'lang-2'
144
- }
145
- });
146
- expect(result).toEqual(newDefault);
147
- });
148
- it('invalidates the language list cache and both the old and new default entries', async ()=>{
149
- const previousDefault = buildLanguage({
150
- id: 'lang-1',
151
- isDefault: true,
152
- code: 'en'
153
- });
154
- mockRepo.find.mockResolvedValue([
155
- previousDefault
156
- ]);
157
- mockRepo.findOne.mockResolvedValue(buildLanguage({
158
- id: 'lang-2',
159
- isDefault: true
160
- }));
161
- await service.setAsDefault('lang-2');
162
- expect(mockUtilsService.clearCache).toHaveBeenCalledWith('language', expect.anything());
163
- expect(mockUtilsService.clearCache).toHaveBeenCalledWith('language', expect.anything(), 'lang-1');
164
- expect(mockUtilsService.clearCache).toHaveBeenCalledWith('language', expect.anything(), 'lang-2');
165
- });
166
- it('returns null when the id does not correspond to any language after the update', async ()=>{
167
- mockRepo.findOne.mockResolvedValue(null);
168
- const result = await service.setAsDefault('non-existent-id');
169
- expect(result).toBeNull();
170
- });
171
- it('still unsets other defaults first even when the target id is unknown (no exception thrown)', async ()=>{
172
- mockRepo.findOne.mockResolvedValue(null);
173
- await service.setAsDefault('unknown-id');
174
- expect(mockRepo.update).toHaveBeenCalledWith({
175
- isDefault: true
176
- }, {
177
- isDefault: false
178
- });
179
- });
180
- });
181
- describe('beforeUpdateOperation', ()=>{
182
- it('rejects renaming the code of a readonly language', async ()=>{
183
- mockRepo.find.mockResolvedValue([
184
- buildLanguage({
185
- isReadonly: true,
186
- code: 'en'
187
- })
188
- ]);
189
- await expect(service.beforeUpdateOperation({
190
- id: 'language-uuid-1',
191
- code: 'fr'
192
- }, null, {})).rejects.toThrow('Cannot modify code/name of readonly language');
193
- });
194
- it('allows updating isActive on a readonly language when identity fields are unchanged', async ()=>{
195
- mockRepo.find.mockResolvedValue([
196
- buildLanguage({
197
- isReadonly: true,
198
- code: 'en',
199
- name: 'English'
200
- })
201
- ]);
202
- await expect(service.beforeUpdateOperation({
203
- id: 'language-uuid-1',
204
- code: 'en',
205
- name: 'English',
206
- isActive: false
207
- }, null, {})).resolves.toBeUndefined();
208
- });
209
- it('allows any field change on a non-readonly language', async ()=>{
210
- mockRepo.find.mockResolvedValue([
211
- buildLanguage({
212
- isReadonly: false,
213
- code: 'en'
214
- })
215
- ]);
216
- await expect(service.beforeUpdateOperation({
217
- id: 'language-uuid-1',
218
- code: 'fr'
219
- }, null, {})).resolves.toBeUndefined();
220
- });
221
- });
222
- describe('beforeDeleteOperation', ()=>{
223
- it('rejects deleting a readonly language', async ()=>{
224
- mockRepo.find.mockResolvedValue([
225
- buildLanguage({
226
- isReadonly: true
227
- })
228
- ]);
229
- await expect(service.beforeDeleteOperation({
230
- id: 'language-uuid-1'
231
- }, null, {})).rejects.toThrow('Cannot delete readonly language');
232
- });
233
- it('rejects deleting the default language', async ()=>{
234
- mockRepo.find.mockResolvedValue([
235
- buildLanguage({
236
- isReadonly: false,
237
- isDefault: true
238
- })
239
- ]);
240
- await expect(service.beforeDeleteOperation({
241
- id: 'language-uuid-1'
242
- }, null, {})).rejects.toThrow('Cannot delete the default language');
243
- });
244
- it('allows deleting a non-readonly, non-default language', async ()=>{
245
- mockRepo.find.mockResolvedValue([
246
- buildLanguage({
247
- isReadonly: false,
248
- isDefault: false
249
- })
250
- ]);
251
- await expect(service.beforeDeleteOperation({
252
- id: 'language-uuid-1'
253
- }, null, {})).resolves.toBeUndefined();
254
- });
255
- });
256
- });
@@ -1,66 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "LocalizationConfigService", {
6
- enumerable: true,
7
- get: function() {
8
- return LocalizationConfigService;
9
- }
10
- });
11
- const _common = require("@nestjs/common");
12
- const _localizationconstants = require("../config/localization.constants");
13
- const _interfaces = require("../interfaces");
14
- function _define_property(obj, key, value) {
15
- if (key in obj) {
16
- Object.defineProperty(obj, key, {
17
- value: value,
18
- enumerable: true,
19
- configurable: true,
20
- writable: true
21
- });
22
- } else {
23
- obj[key] = value;
24
- }
25
- return obj;
26
- }
27
- function _ts_decorate(decorators, target, key, desc) {
28
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
29
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
30
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
31
- return c > 3 && r && Object.defineProperty(target, key, r), r;
32
- }
33
- function _ts_metadata(k, v) {
34
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
35
- }
36
- function _ts_param(paramIndex, decorator) {
37
- return function(target, key) {
38
- decorator(target, key, paramIndex);
39
- };
40
- }
41
- let LocalizationConfigService = class LocalizationConfigService {
42
- isCompanyFeatureEnabled() {
43
- return false;
44
- }
45
- getDatabaseMode() {
46
- return this.options.bootstrapAppConfig?.databaseMode ?? 'single';
47
- }
48
- isMultiTenant() {
49
- return this.getDatabaseMode() === 'multi-tenant';
50
- }
51
- getOptions() {
52
- return this.options;
53
- }
54
- constructor(options){
55
- _define_property(this, "options", void 0);
56
- this.options = options;
57
- }
58
- };
59
- LocalizationConfigService = _ts_decorate([
60
- (0, _common.Injectable)(),
61
- _ts_param(0, (0, _common.Inject)(_localizationconstants.LOCALIZATION_MODULE_OPTIONS)),
62
- _ts_metadata("design:type", Function),
63
- _ts_metadata("design:paramtypes", [
64
- typeof _interfaces.LocalizationModuleOptions === "undefined" ? Object : _interfaces.LocalizationModuleOptions
65
- ])
66
- ], LocalizationConfigService);