@solidxai/core 0.1.6-beta.0 → 0.1.6-beta.10
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/controllers/dashboard-layout.controller.d.ts +47 -0
- package/dist/controllers/dashboard-layout.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-layout.controller.js +204 -0
- package/dist/controllers/dashboard-layout.controller.js.map +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts.map +1 -1
- package/dist/controllers/scheduled-job.controller.js +12 -0
- package/dist/controllers/scheduled-job.controller.js.map +1 -1
- package/dist/dtos/create-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/create-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-layout.dto.js +53 -0
- package/dist/dtos/create-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/create-dashboard-variable.dto.js +7 -1
- package/dist/dtos/create-dashboard-variable.dto.js.map +1 -1
- package/dist/dtos/update-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/update-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-layout.dto.js +53 -0
- package/dist/dtos/update-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/update-dashboard-variable.dto.js +7 -1
- package/dist/dtos/update-dashboard-variable.dto.js.map +1 -1
- package/dist/entities/action-metadata.entity.d.ts.map +1 -1
- package/dist/entities/action-metadata.entity.js.map +1 -1
- package/dist/entities/ai-interaction.entity.d.ts.map +1 -1
- package/dist/entities/ai-interaction.entity.js +5 -4
- package/dist/entities/ai-interaction.entity.js.map +1 -1
- package/dist/entities/chatter-message-details.entity.d.ts +1 -0
- package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message-details.entity.js +9 -4
- package/dist/entities/chatter-message-details.entity.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +4 -3
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/common.entity.js +1 -1
- package/dist/entities/common.entity.js.map +1 -1
- package/dist/entities/dashboard-layout.entity.d.ts +9 -0
- package/dist/entities/dashboard-layout.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-layout.entity.js +41 -0
- package/dist/entities/dashboard-layout.entity.js.map +1 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js +5 -4
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -1
- package/dist/entities/dashboard-question.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question.entity.js +5 -4
- package/dist/entities/dashboard-question.entity.js.map +1 -1
- package/dist/entities/dashboard-variable.entity.d.ts +1 -0
- package/dist/entities/dashboard-variable.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-variable.entity.js +10 -4
- package/dist/entities/dashboard-variable.entity.js.map +1 -1
- package/dist/entities/dashboard.entity.d.ts +2 -0
- package/dist/entities/dashboard.entity.d.ts.map +1 -1
- package/dist/entities/dashboard.entity.js +9 -3
- package/dist/entities/dashboard.entity.js.map +1 -1
- package/dist/entities/email-attachment.entity.d.ts.map +1 -1
- package/dist/entities/email-attachment.entity.js +2 -1
- package/dist/entities/email-attachment.entity.js.map +1 -1
- package/dist/entities/email-template.entity.js +1 -1
- package/dist/entities/email-template.entity.js.map +1 -1
- package/dist/entities/export-transaction.entity.d.ts.map +1 -1
- package/dist/entities/export-transaction.entity.js +2 -1
- package/dist/entities/export-transaction.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.js +2 -2
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.js +3 -2
- package/dist/entities/import-transaction-error-log.entity.js.map +1 -1
- package/dist/entities/import-transaction.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction.entity.js +2 -1
- package/dist/entities/import-transaction.entity.js.map +1 -1
- package/dist/entities/legacy-common.entity.d.ts.map +1 -1
- package/dist/entities/legacy-common.entity.js +1 -1
- package/dist/entities/legacy-common.entity.js.map +1 -1
- package/dist/entities/mq-message.entity.d.ts.map +1 -1
- package/dist/entities/mq-message.entity.js +4 -3
- package/dist/entities/mq-message.entity.js.map +1 -1
- package/dist/entities/saved-filters.entity.d.ts.map +1 -1
- package/dist/entities/saved-filters.entity.js +3 -2
- package/dist/entities/saved-filters.entity.js.map +1 -1
- package/dist/entities/security-rule.entity.d.ts.map +1 -1
- package/dist/entities/security-rule.entity.js +2 -1
- package/dist/entities/security-rule.entity.js.map +1 -1
- package/dist/entities/sms-template.entity.js +1 -1
- package/dist/entities/sms-template.entity.js.map +1 -1
- package/dist/entities/user-view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/user-view-metadata.entity.js +2 -1
- package/dist/entities/user-view-metadata.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +8 -9
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-registry.d.ts +3 -1
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +21 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +4 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/repository/dashboard-layout.repository.d.ts +12 -0
- package/dist/repository/dashboard-layout.repository.d.ts.map +1 -0
- package/dist/repository/dashboard-layout.repository.js +34 -0
- package/dist/repository/dashboard-layout.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.js +4 -4
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +445 -35
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +45 -21
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +26 -0
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +6 -5
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +9 -10
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
- package/dist/services/dashboard-layout.service.d.ts +20 -0
- package/dist/services/dashboard-layout.service.d.ts.map +1 -0
- package/dist/services/dashboard-layout.service.js +120 -0
- package/dist/services/dashboard-layout.service.js.map +1 -0
- package/dist/services/dashboard-question.service.d.ts +4 -0
- package/dist/services/dashboard-question.service.d.ts.map +1 -1
- package/dist/services/dashboard-question.service.js +22 -8
- package/dist/services/dashboard-question.service.js.map +1 -1
- package/dist/services/dashboard.service.d.ts +2 -0
- package/dist/services/dashboard.service.d.ts.map +1 -1
- package/dist/services/dashboard.service.js +4 -0
- package/dist/services/dashboard.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +3 -1
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +122 -8
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/interfaces.d.ts +1 -0
- package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
- package/dist/services/question-data-providers/interfaces.js +1 -0
- package/dist/services/question-data-providers/interfaces.js.map +1 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
- package/dist/services/queues/database-subscriber.service.d.ts +4 -2
- package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/database-subscriber.service.js +15 -2
- package/dist/services/queues/database-subscriber.service.js.map +1 -1
- package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
- package/dist/services/queues/publisher-factory.service.js +4 -6
- package/dist/services/queues/publisher-factory.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +8 -3
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +72 -5
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/scheduled-job.service.d.ts +6 -1
- package/dist/services/scheduled-job.service.d.ts.map +1 -1
- package/dist/services/scheduled-job.service.js +26 -2
- package/dist/services/scheduled-job.service.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts +2 -0
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.d.ts +6 -2
- package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.js +75 -17
- package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +9 -0
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- package/dist/services/solid-ts-morph.service.js +76 -0
- package/dist/services/solid-ts-morph.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +8 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +9 -1
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
- package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
- package/dist-tests/api/authenticate.spec.js +119 -0
- package/dist-tests/api/authenticate.spec.js.map +1 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
- package/dist-tests/api/ping.spec.js +21 -0
- package/dist-tests/api/ping.spec.js.map +1 -0
- package/dist-tests/helpers/auth.js +41 -0
- package/dist-tests/helpers/auth.js.map +1 -0
- package/dist-tests/helpers/env.js +11 -0
- package/dist-tests/helpers/env.js.map +1 -0
- package/package.json +1 -1
- package/sql/default/mariadb/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mariadb/proc_CleanupModuleMetadata.sql +56 -0
- package/sql/default/mysql/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mysql/proc_CleanupModuleMetadata.sql +56 -0
- package/src/controllers/dashboard-layout.controller.ts +106 -0
- package/src/controllers/scheduled-job.controller.ts +6 -0
- package/src/dtos/create-dashboard-layout.dto.ts +31 -0
- package/src/dtos/create-dashboard-variable.dto.ts +4 -0
- package/src/dtos/update-dashboard-layout.dto.ts +30 -0
- package/src/dtos/update-dashboard-variable.dto.ts +5 -1
- package/src/entities/action-metadata.entity.ts +3 -2
- package/src/entities/ai-interaction.entity.ts +5 -4
- package/src/entities/chatter-message-details.entity.ts +7 -3
- package/src/entities/chatter-message.entity.ts +4 -3
- package/src/entities/common.entity.ts +2 -2
- package/src/entities/dashboard-layout.entity.ts +18 -0
- package/src/entities/dashboard-question-sql-dataset-config.entity.ts +5 -4
- package/src/entities/dashboard-question.entity.ts +5 -4
- package/src/entities/dashboard-variable.entity.ts +9 -4
- package/src/entities/dashboard.entity.ts +7 -2
- package/src/entities/email-attachment.entity.ts +2 -1
- package/src/entities/email-template.entity.ts +1 -1
- package/src/entities/export-transaction.entity.ts +2 -1
- package/src/entities/field-metadata.entity.ts +2 -2
- package/src/entities/import-transaction-error-log.entity.ts +3 -2
- package/src/entities/import-transaction.entity.ts +2 -1
- package/src/entities/legacy-common.entity.ts +3 -4
- package/src/entities/mq-message.entity.ts +4 -3
- package/src/entities/saved-filters.entity.ts +3 -2
- package/src/entities/security-rule.entity.ts +2 -1
- package/src/entities/sms-template.entity.ts +1 -1
- package/src/entities/user-view-metadata.entity.ts +2 -1
- package/src/entities/view-metadata.entity.ts +3 -0
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +9 -9
- package/src/helpers/solid-registry.ts +3 -2
- package/src/helpers/typeorm-db-helper.ts +26 -0
- package/src/index.ts +1 -0
- package/src/interfaces.ts +7 -1
- package/src/repository/dashboard-layout.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +5 -5
- package/src/seeders/seed-data/solid-core-metadata.json +446 -36
- package/src/services/authentication.service.ts +47 -24
- package/src/services/chatter-message.service.ts +26 -0
- package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +6 -5
- package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +17 -22
- package/src/services/dashboard-layout.service.ts +111 -0
- package/src/services/dashboard-question.service.ts +23 -4
- package/src/services/dashboard.service.ts +7 -0
- package/src/services/model-metadata.service.ts +131 -50
- package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
- package/src/services/question-data-providers/interfaces.ts +0 -0
- package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
- package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
- package/src/services/queues/database-subscriber.service.ts +19 -2
- package/src/services/queues/publisher-factory.service.ts +8 -6
- package/src/services/queues/rabbitmq-subscriber.service.ts +115 -5
- package/src/services/scheduled-job.service.ts +31 -2
- package/src/services/scheduled-jobs/scheduler.interface.ts +4 -1
- package/src/services/scheduled-jobs/scheduler.service.ts +82 -20
- package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
- package/src/services/solid-ts-morph.service.ts +98 -0
- package/src/solid-core.module.ts +12 -0
- package/src/subscribers/computed-entity-field.subscriber.ts +9 -3
- package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
- package/.claude/settings.local.json +0 -15
- package/src/services/1.js +0 -6
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { Injectable, Logger } from '@nestjs/common';
|
|
1
|
+
import { BadRequestException, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { ModuleRef } from "@nestjs/core";
|
|
3
3
|
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
4
4
|
import { ScheduledJob } from 'src/entities/scheduled-job.entity';
|
|
5
|
+
import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
5
6
|
import { ScheduledJobRepository } from 'src/repository/scheduled-job.repository';
|
|
6
7
|
import { EntityManager } from 'typeorm';
|
|
7
8
|
import { CRUDService } from './crud.service';
|
|
9
|
+
import { SchedulerServiceImpl } from './scheduled-jobs/scheduler.service';
|
|
8
10
|
|
|
9
11
|
@Injectable()
|
|
10
12
|
export class ScheduledJobService extends CRUDService<ScheduledJob> {
|
|
@@ -16,9 +18,36 @@ export class ScheduledJobService extends CRUDService<ScheduledJob> {
|
|
|
16
18
|
// @InjectRepository(ScheduledJob)
|
|
17
19
|
// readonly repo: Repository<ScheduledJob>,
|
|
18
20
|
readonly repo: ScheduledJobRepository,
|
|
19
|
-
readonly moduleRef: ModuleRef
|
|
21
|
+
readonly moduleRef: ModuleRef,
|
|
22
|
+
private readonly solidRegistry: SolidRegistry,
|
|
23
|
+
private readonly schedulerService: SchedulerServiceImpl,
|
|
20
24
|
|
|
21
25
|
) {
|
|
22
26
|
super(entityManager, repo, 'scheduledJob', 'solid-core', moduleRef);
|
|
23
27
|
}
|
|
28
|
+
|
|
29
|
+
async triggerRun(id: number): Promise<ScheduledJob> {
|
|
30
|
+
const job = await this.repo.findOne({ where: { id } });
|
|
31
|
+
if (!job) {
|
|
32
|
+
throw new NotFoundException(`Scheduled job with id ${id} not found`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const handler = this.solidRegistry.getScheduledJobProviderInstance(job.job);
|
|
36
|
+
if (!handler) {
|
|
37
|
+
throw new BadRequestException(`Scheduled job handler not found: ${job.job}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.logger.log(`Manually triggering scheduled job id=${job.id}, job=${job.job}`);
|
|
41
|
+
|
|
42
|
+
await handler.execute(job);
|
|
43
|
+
|
|
44
|
+
const finishedAt = new Date();
|
|
45
|
+
job.lastRunAt = finishedAt;
|
|
46
|
+
job.nextRunAt = this.schedulerService.computeNextRunAt(job, finishedAt);
|
|
47
|
+
await this.repo.save(job);
|
|
48
|
+
|
|
49
|
+
this.logger.log(`Completed manual trigger for scheduled job id=${job.id}, nextRunAt=${job.nextRunAt?.toISOString?.()}`);
|
|
50
|
+
|
|
51
|
+
return job;
|
|
52
|
+
}
|
|
24
53
|
}
|
|
@@ -24,13 +24,23 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
24
24
|
async runScheduledJobs(): Promise<void> {
|
|
25
25
|
const solidSchedulerEnabled = process.env.SOLID_SCHEDULER_ENABLED || "true";
|
|
26
26
|
if (solidSchedulerEnabled.toLowerCase() !== "true") {
|
|
27
|
-
|
|
27
|
+
this.logger.debug('Solid scheduler is disabled via environment variable');
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
const solidCliRunning = process.env.SOLID_CLI_RUNNING || "false";
|
|
31
31
|
if (solidCliRunning === "true") {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
+
const jobsRegexToEnable = (process.env.SOLID_SCHEDULER_JOBS_REGEX_TO_ENABLE || '').trim();
|
|
35
|
+
let jobsRegex: RegExp | null = null;
|
|
36
|
+
if (jobsRegexToEnable && jobsRegexToEnable !== "all") {
|
|
37
|
+
try {
|
|
38
|
+
jobsRegex = new RegExp(jobsRegexToEnable);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
this.logger.error(`Invalid SOLID_SCHEDULER_JOBS_REGEX_TO_ENABLE regex "${jobsRegexToEnable}". Scheduler loop will skip this run.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
34
44
|
|
|
35
45
|
const now = new Date();
|
|
36
46
|
|
|
@@ -53,6 +63,12 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
53
63
|
|
|
54
64
|
for (const job of dueJobs) {
|
|
55
65
|
const jobKey = String(job.id ?? job.scheduleName ?? job.job);
|
|
66
|
+
const jobName = String(job.job ?? '');
|
|
67
|
+
|
|
68
|
+
if (jobsRegex && !jobsRegex.test(jobName)) {
|
|
69
|
+
this.logger.log(`[${now.getTime()}]: scheduler service skipping job ${jobName} because it does not match SOLID_SCHEDULER_JOBS_REGEX_TO_ENABLE=${jobsRegexToEnable}`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
56
72
|
|
|
57
73
|
if (this.runningJobs.has(jobKey)) {
|
|
58
74
|
this.logger.log(`[${now.getTime()}]: scheduler service skipping job ${job.job} because a run is already in progress`);
|
|
@@ -94,22 +110,21 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
94
110
|
}
|
|
95
111
|
|
|
96
112
|
private shouldRunNow(job: ScheduledJob, now: Date): boolean {
|
|
97
|
-
const today = now
|
|
98
|
-
|
|
113
|
+
const today = new Date(now);
|
|
114
|
+
today.setHours(0, 0, 0, 0);
|
|
115
|
+
const timeNow = this.toHHMM(now); // hh:mm
|
|
99
116
|
|
|
100
117
|
// 1. Check startDate / endDate
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
const startDate = this.toDateOnly(job.startDate as unknown as Date | string | null);
|
|
119
|
+
const endDate = this.toDateOnly(job.endDate as unknown as Date | string | null);
|
|
120
|
+
if (startDate && today < startDate) return false;
|
|
121
|
+
if (endDate && today > endDate) return false;
|
|
103
122
|
|
|
104
123
|
// 2. Check startTime / endTime
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (job.endTime) {
|
|
110
|
-
const jobEnd = job.endTime.toTimeString().slice(0, 5);
|
|
111
|
-
if (timeNow > jobEnd) return false;
|
|
112
|
-
}
|
|
124
|
+
const jobStart = this.toHHMM(job.startTime as unknown as Date | string | null);
|
|
125
|
+
const jobEnd = this.toHHMM(job.endTime as unknown as Date | string | null);
|
|
126
|
+
if (jobStart && timeNow < jobStart) return false;
|
|
127
|
+
if (jobEnd && timeNow > jobEnd) return false;
|
|
113
128
|
|
|
114
129
|
// 3. Check custom frequency
|
|
115
130
|
if (job.frequency.toLowerCase() === 'custom') {
|
|
@@ -121,8 +136,7 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
121
136
|
// 3. Check dayOfWeek (for weekly)
|
|
122
137
|
if (job.frequency.toLowerCase() === 'weekly' && job.dayOfWeek) {
|
|
123
138
|
const todayName = now.toLocaleString('en-US', { weekday: 'long' }); // e.g., "Monday"
|
|
124
|
-
|
|
125
|
-
const days = JSON.parse(job.dayOfWeek) as string[];
|
|
139
|
+
const days = this.parseDayOfWeek(job.dayOfWeek);
|
|
126
140
|
if (!days.includes(todayName)) return false;
|
|
127
141
|
}
|
|
128
142
|
|
|
@@ -135,7 +149,53 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
135
149
|
return true;
|
|
136
150
|
}
|
|
137
151
|
|
|
138
|
-
private
|
|
152
|
+
private parseDayOfWeek(dayOfWeek: string): string[] {
|
|
153
|
+
try {
|
|
154
|
+
const parsed = JSON.parse(dayOfWeek);
|
|
155
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
156
|
+
} catch (error) {
|
|
157
|
+
this.logger.warn(`Invalid dayOfWeek JSON '${dayOfWeek}'`, error as any);
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private toDateOnly(value: Date | string | null | undefined): Date | null {
|
|
163
|
+
if (!value) return null;
|
|
164
|
+
|
|
165
|
+
if (value instanceof Date) {
|
|
166
|
+
const d = new Date(value);
|
|
167
|
+
d.setHours(0, 0, 0, 0);
|
|
168
|
+
return d;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const parsed = new Date(value);
|
|
172
|
+
if (Number.isNaN(parsed.getTime())) return null;
|
|
173
|
+
|
|
174
|
+
parsed.setHours(0, 0, 0, 0);
|
|
175
|
+
return parsed;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private toHHMM(value: Date | string | null | undefined): string | null {
|
|
179
|
+
if (!value) return null;
|
|
180
|
+
|
|
181
|
+
if (value instanceof Date) {
|
|
182
|
+
return value.toTimeString().slice(0, 5);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (typeof value === 'string') {
|
|
186
|
+
const match = value.match(/^(\d{2}):(\d{2})/);
|
|
187
|
+
if (match) return `${match[1]}:${match[2]}`;
|
|
188
|
+
|
|
189
|
+
const parsed = new Date(value);
|
|
190
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
191
|
+
return parsed.toTimeString().slice(0, 5);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public computeNextRunForCustomCron(job: ScheduledJob, from: Date): Date {
|
|
139
199
|
const base = new Date(from);
|
|
140
200
|
|
|
141
201
|
if (!job.cronExpression) {
|
|
@@ -150,22 +210,24 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
150
210
|
tz: 'UTC'
|
|
151
211
|
});
|
|
152
212
|
const nextRun = interval.next().toDate();
|
|
213
|
+
const runAfterNext = interval.next().toDate();
|
|
153
214
|
|
|
154
|
-
// Validate minimum 1 minute
|
|
155
|
-
|
|
215
|
+
// Validate minimum 1 minute cadence between consecutive runs.
|
|
216
|
+
// Comparing nextRun to "from" is incorrect near minute boundaries.
|
|
217
|
+
if (runAfterNext.getTime() - nextRun.getTime() < 60000) {
|
|
156
218
|
throw new Error('Cron expression interval must be at least 1 minute');
|
|
157
219
|
}
|
|
158
220
|
|
|
159
221
|
this.logger.log(`Custom cron '${job.cronExpression}' next run: ${nextRun}`);
|
|
160
222
|
return nextRun;
|
|
161
223
|
} catch (error) {
|
|
162
|
-
this.logger.error(`Invalid cron expression for job ${job.scheduleName}: ${job.cronExpression}
|
|
224
|
+
this.logger.error(`Invalid cron expression for job ${job.scheduleName}: ${job.cronExpression}. Reason: ${(error as Error).message}`);
|
|
163
225
|
// Fallback to daily if cron parsing fails
|
|
164
226
|
return new Date(base.getTime() + 24 * 60 * 60 * 1000);
|
|
165
227
|
}
|
|
166
228
|
}
|
|
167
229
|
|
|
168
|
-
|
|
230
|
+
public computeNextRunAt(job: ScheduledJob, from: Date): Date {
|
|
169
231
|
const base = new Date(from);
|
|
170
232
|
|
|
171
233
|
switch (job.frequency.toLowerCase()) {
|
|
@@ -3,6 +3,7 @@ import { SelectionProvider } from "src/decorators/selection-provider.decorator";
|
|
|
3
3
|
import { SolidRegistry } from "src/helpers/solid-registry";
|
|
4
4
|
import { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext, ISelectionProviderValues } from "../../interfaces";
|
|
5
5
|
import { SQL_DYNAMIC_PROVIDER_NAME } from "../dashboard.service";
|
|
6
|
+
import { CHARTJS_SQL_DATA_PROVIDER_NAME, INBUILT_SQL_DATA_PROVIDERS, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME } from "../dashboard-question.service";
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
@SelectionProvider()
|
|
@@ -34,7 +35,9 @@ export class ListOfDashboardQuestionProvidersSelectionProvider implements ISelec
|
|
|
34
35
|
async values(query: string, ctxt: ISelectionProviderContext): Promise<readonly ISelectionProviderValues[]> {
|
|
35
36
|
const dashboardSelectionProviders = this.solidRegistry.getDashboardQuestionDataProviders()
|
|
36
37
|
//Exclude the SQL dynamic provider from the list, (since although it is a dashboard selection provider, it is not a valid option for the user to select)
|
|
37
|
-
return dashboardSelectionProviders
|
|
38
|
+
return dashboardSelectionProviders
|
|
39
|
+
.filter(provider => !INBUILT_SQL_DATA_PROVIDERS.includes(provider.name()))
|
|
40
|
+
.map(i => {
|
|
38
41
|
return { label: i.name, value: i.name };
|
|
39
42
|
});
|
|
40
43
|
}
|
|
@@ -324,6 +324,104 @@ export class SolidTsMorphService {
|
|
|
324
324
|
return { staged: true, overwritten: false, skipped: false };
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
|
|
328
|
+
//Removes all import declarations from a file whose module specifier matches the given predicate.
|
|
329
|
+
//Returns the set of identifier names that were imported by the removed declarations.
|
|
330
|
+
removeImports(
|
|
331
|
+
filePath: string,
|
|
332
|
+
filter: (moduleSpecifier: string) => boolean
|
|
333
|
+
): { removedIdentifiers: Set<string>; staged: boolean; skipped: boolean } {
|
|
334
|
+
const abs = this.resolveRepoPath(filePath);
|
|
335
|
+
if (!existsSync(abs)) {
|
|
336
|
+
this.logger.warn(`removeImport: file not found at ${filePath}, skipping.`);
|
|
337
|
+
return { removedIdentifiers: new Set(), staged: false, skipped: true };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const existing = this.project.getSourceFile(abs);
|
|
341
|
+
const sourceFile = existing
|
|
342
|
+
? existing
|
|
343
|
+
: this.project.createSourceFile(abs, readFileSync(abs, "utf8"), { overwrite: true });
|
|
344
|
+
|
|
345
|
+
const importsToRemove = sourceFile.getImportDeclarations().filter(decl => {
|
|
346
|
+
const spec = decl.getModuleSpecifierValue().replace(/\\/g, "/");
|
|
347
|
+
return filter(spec);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
if (importsToRemove.length === 0) {
|
|
351
|
+
return { removedIdentifiers: new Set(), staged: false, skipped: true };
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const removedIdentifiers = new Set<string>();
|
|
355
|
+
for (const decl of importsToRemove) {
|
|
356
|
+
for (const named of decl.getNamedImports()) {
|
|
357
|
+
removedIdentifiers.add(named.getAliasNode()?.getText() ?? named.getName());
|
|
358
|
+
}
|
|
359
|
+
const defaultImport = decl.getDefaultImport();
|
|
360
|
+
if (defaultImport) removedIdentifiers.add(defaultImport.getText());
|
|
361
|
+
decl.remove();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
this.dirtySourceFiles.add(abs);
|
|
365
|
+
this.logger.log(`Staged removal of ${importsToRemove.length} import(s) in: ${this.rel(abs)}`);
|
|
366
|
+
return { removedIdentifiers, staged: true, skipped: false };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
//Removes the given identifier names from all @Module decorator array properties
|
|
370
|
+
removeModuleMembers(
|
|
371
|
+
filePath: string,
|
|
372
|
+
names: Set<string> | string[]
|
|
373
|
+
): { staged: boolean; skipped: boolean } {
|
|
374
|
+
const abs = this.resolveRepoPath(filePath);
|
|
375
|
+
if (!existsSync(abs)) {
|
|
376
|
+
this.logger.warn(`removeImportMembers: file not found at ${filePath}, skipping.`);
|
|
377
|
+
return { staged: false, skipped: true };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const identifiers = names instanceof Set ? names : new Set(names);
|
|
381
|
+
if (identifiers.size === 0) return { staged: false, skipped: true };
|
|
382
|
+
|
|
383
|
+
const existing = this.project.getSourceFile(abs);
|
|
384
|
+
const sourceFile = existing
|
|
385
|
+
? existing
|
|
386
|
+
: this.project.createSourceFile(abs, readFileSync(abs, "utf8"), { overwrite: true });
|
|
387
|
+
|
|
388
|
+
const nestModuleClass = sourceFile.getClasses().find(cls =>
|
|
389
|
+
cls.getDecorators().some(dec => dec.getName() === "Module")
|
|
390
|
+
);
|
|
391
|
+
if (!nestModuleClass) {
|
|
392
|
+
this.logger.warn(`removeImportMembers: no @Module() class found in ${filePath}`);
|
|
393
|
+
return { staged: false, skipped: true };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const moduleDec = nestModuleClass.getDecorators().find(dec => dec.getName() === "Module");
|
|
397
|
+
const arg0 = moduleDec?.getCallExpression()?.getArguments()[0];
|
|
398
|
+
if (!arg0 || !Node.isObjectLiteralExpression(arg0)) return { staged: false, skipped: true };
|
|
399
|
+
|
|
400
|
+
const meta = arg0 as ObjectLiteralExpression;
|
|
401
|
+
for (const propName of ["imports", "providers", "controllers", "exports"] as const) {
|
|
402
|
+
const prop = meta.getProperty(propName);
|
|
403
|
+
if (!prop || !Node.isPropertyAssignment(prop)) continue;
|
|
404
|
+
const init = prop.getInitializer();
|
|
405
|
+
if (!init || !Node.isArrayLiteralExpression(init)) continue;
|
|
406
|
+
const arr = init as ArrayLiteralExpression;
|
|
407
|
+
const elements = arr.getElements();
|
|
408
|
+
for (let i = elements.length - 1; i >= 0; i--) {
|
|
409
|
+
const elemText = elements[i].getText().trim();
|
|
410
|
+
// Match direct identifiers (e.g. TestService) or call expressions that reference them (e.g. TypeOrmModule.forFeature([Test])).
|
|
411
|
+
const shouldRemove = identifiers.has(elemText) ||
|
|
412
|
+
[...identifiers].some(id => new RegExp(`\\b${id}\\b`).test(elemText));
|
|
413
|
+
if (shouldRemove) {
|
|
414
|
+
arr.removeElement(i);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
this.dirtySourceFiles.add(abs);
|
|
420
|
+
this.logger.log(`Staged removal of [${[...identifiers].join(", ")}] from @Module arrays in: ${this.rel(abs)}`);
|
|
421
|
+
return { staged: true, skipped: false };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
|
|
327
425
|
addImport(
|
|
328
426
|
filePath: string,
|
|
329
427
|
importLine: string
|
package/src/solid-core.module.ts
CHANGED
|
@@ -133,6 +133,8 @@ import { ChatterMessageController } from './controllers/chatter-message.controll
|
|
|
133
133
|
import { DashboardQuestionSqlDatasetConfigController } from './controllers/dashboard-question-sql-dataset-config.controller';
|
|
134
134
|
import { DashboardQuestionController } from './controllers/dashboard-question.controller';
|
|
135
135
|
import { DashboardVariableController } from './controllers/dashboard-variable.controller';
|
|
136
|
+
import { DashboardLayoutController } from './controllers/dashboard-layout.controller';
|
|
137
|
+
|
|
136
138
|
import { DashboardController } from './controllers/dashboard.controller';
|
|
137
139
|
import { ExportTemplateController } from './controllers/export-template.controller';
|
|
138
140
|
import { ExportTransactionController } from './controllers/export-transaction.controller';
|
|
@@ -156,6 +158,8 @@ import { ChatterMessage } from './entities/chatter-message.entity';
|
|
|
156
158
|
import { DashboardQuestionSqlDatasetConfig } from './entities/dashboard-question-sql-dataset-config.entity';
|
|
157
159
|
import { DashboardQuestion } from './entities/dashboard-question.entity';
|
|
158
160
|
import { DashboardVariable } from './entities/dashboard-variable.entity';
|
|
161
|
+
import { DashboardLayout } from './entities/dashboard-layout.entity';
|
|
162
|
+
|
|
159
163
|
import { Dashboard } from './entities/dashboard.entity';
|
|
160
164
|
import { ExportTemplate } from './entities/export-template.entity';
|
|
161
165
|
import { ExportTransaction } from './entities/export-transaction.entity';
|
|
@@ -221,6 +225,8 @@ import { DashboardQuestionSqlDatasetConfigRepository } from './repository/dashbo
|
|
|
221
225
|
import { DashboardQuestionRepository } from './repository/dashboard-question.repository';
|
|
222
226
|
import { DashboardVariableRepository } from './repository/dashboard-variable.repository';
|
|
223
227
|
import { DashboardRepository } from './repository/dashboard.repository';
|
|
228
|
+
import { DashboardLayoutRepository } from './repository/dashboard-layout.repository';
|
|
229
|
+
|
|
224
230
|
import { EmailTemplateRepository } from './repository/email-template.repository';
|
|
225
231
|
import { ExportTemplateRepository } from './repository/export-template.repository';
|
|
226
232
|
import { ExportTransactionRepository } from './repository/export-transaction.repository';
|
|
@@ -263,6 +269,8 @@ import { DashboardVariableSQLDynamicProvider } from './services/dashboard-select
|
|
|
263
269
|
import { DasbhoardVariableTestDynamicProvider } from './services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service';
|
|
264
270
|
import { DashboardVariableService } from './services/dashboard-variable.service';
|
|
265
271
|
import { DashboardService } from './services/dashboard.service';
|
|
272
|
+
import { DashboardLayoutService } from './services/dashboard-layout.service';
|
|
273
|
+
|
|
266
274
|
import { ExcelService } from './services/excel.service';
|
|
267
275
|
import { ExportTemplateService } from './services/export-template.service';
|
|
268
276
|
import { ExportTransactionService } from './services/export-transaction.service';
|
|
@@ -343,6 +351,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
343
351
|
DashboardQuestion,
|
|
344
352
|
DashboardQuestionSqlDatasetConfig,
|
|
345
353
|
DashboardVariable,
|
|
354
|
+
DashboardLayout,
|
|
346
355
|
EmailAttachment,
|
|
347
356
|
EmailTemplate,
|
|
348
357
|
ExportTemplate,
|
|
@@ -414,6 +423,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
414
423
|
DashboardQuestionController,
|
|
415
424
|
DashboardQuestionSqlDatasetConfigController,
|
|
416
425
|
DashboardVariableController,
|
|
426
|
+
DashboardLayoutController,
|
|
417
427
|
EmailTemplateController,
|
|
418
428
|
ExportTemplateController,
|
|
419
429
|
ExportTransactionController,
|
|
@@ -638,6 +648,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
638
648
|
UserActivityHistoryService,
|
|
639
649
|
DashboardService,
|
|
640
650
|
DashboardVariableService,
|
|
651
|
+
DashboardLayoutService,
|
|
641
652
|
DashboardQuestionService,
|
|
642
653
|
DashboardVariableSQLDynamicProvider,
|
|
643
654
|
DasbhoardVariableTestDynamicProvider,
|
|
@@ -682,6 +693,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
682
693
|
DashboardQuestionSqlDatasetConfigRepository,
|
|
683
694
|
DashboardQuestionRepository,
|
|
684
695
|
DashboardVariableRepository,
|
|
696
|
+
DashboardLayoutRepository,
|
|
685
697
|
EmailTemplateRepository,
|
|
686
698
|
ExportTemplateRepository,
|
|
687
699
|
ExportTransactionRepository,
|
|
@@ -78,9 +78,9 @@ export class ComputedEntityFieldSubscriber implements EntitySubscriberInterface
|
|
|
78
78
|
modelName
|
|
79
79
|
);
|
|
80
80
|
//TODO: We can add a feature i.e dependsOn, where we can check if the computed field depends on other computed fields and evaluate them first
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
for (const computedField of computedFieldsTobeEvaluated) {
|
|
82
|
+
await this.evaluateComputedField(this.attachContext(computedField, eventContext), entity, currentOperation);
|
|
83
|
+
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
private handleComputedFieldEvaluationJob(entity: any, currentOperation: ComputedFieldTriggerOperation, modelName: string, eventContext?: TypeOrmEventContext) {
|
|
@@ -189,6 +189,12 @@ export class ComputedEntityFieldSubscriber implements EntitySubscriberInterface
|
|
|
189
189
|
if ("updatedRelations" in event && event.updatedRelations) {
|
|
190
190
|
base.updatedRelations = event.updatedRelations.map((r: any) => r.propertyName);
|
|
191
191
|
}
|
|
192
|
+
if ("manager" in event && event.manager) {
|
|
193
|
+
base.manager = event.manager;
|
|
194
|
+
}
|
|
195
|
+
if ("queryRunner" in event && event.queryRunner) {
|
|
196
|
+
base.queryRunner = event.queryRunner;
|
|
197
|
+
}
|
|
192
198
|
if (event.entity) base.entity = event.entity;
|
|
193
199
|
if ("databaseEntity" in event && event.databaseEntity) {
|
|
194
200
|
base.databaseEntity = event.databaseEntity;
|
|
@@ -20,59 +20,67 @@ function dateToUtcComponentString(d: Date): string {
|
|
|
20
20
|
const ss = pad(d.getUTCSeconds());
|
|
21
21
|
const ms = pad(d.getUTCMilliseconds(), 3);
|
|
22
22
|
|
|
23
|
-
// A
|
|
23
|
+
// A "naive" timestamp string representing the DB wall-clock components
|
|
24
24
|
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}.${ms}`;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
function getWallClockConfig(): { tz: string; wallTimeMode: boolean } {
|
|
28
|
+
return {
|
|
29
|
+
tz: process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC",
|
|
30
|
+
wallTimeMode: (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns a dayjs instance positioned at the wall-clock time for the given Date.
|
|
36
|
+
* - Wall-clock mode ON: dayjs in the configured timezone (components = wall-clock components)
|
|
37
|
+
* - Wall-clock mode OFF: dayjs in UTC
|
|
38
|
+
* Counterpart to serializeDate — use this to format/display a date value correctly.
|
|
39
|
+
*/
|
|
40
|
+
export function parseDate(date: Date): dayjs.Dayjs {
|
|
41
|
+
const { tz, wallTimeMode } = getWallClockConfig();
|
|
42
|
+
if (!wallTimeMode) return dayjs.utc(date);
|
|
43
|
+
return dayjs(date).tz(tz);
|
|
44
|
+
}
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Converts a Date to a string for storage in plain text columns (e.g. audit values).
|
|
48
|
+
* - Wall-clock mode ON: "YYYY-MM-DD HH:mm:ss.SSS" in the configured timezone (no Z suffix)
|
|
49
|
+
* - Wall-clock mode OFF: ISO 8601 UTC string with Z suffix
|
|
50
|
+
* The presence/absence of the Z suffix lets consumers distinguish the two cases.
|
|
51
|
+
*/
|
|
52
|
+
export function serializeDate(date: Date): string {
|
|
53
|
+
const { wallTimeMode } = getWallClockConfig();
|
|
54
|
+
if (!wallTimeMode) return date.toISOString();
|
|
55
|
+
return parseDate(date).format("YYYY-MM-DD HH:mm:ss.SSS");
|
|
56
|
+
}
|
|
33
57
|
|
|
34
|
-
|
|
58
|
+
export const LocalDateTimeTransformer: ValueTransformer = {
|
|
59
|
+
// DB -> Entity
|
|
60
|
+
from(value: Date | string | null | undefined): Date | null | undefined {
|
|
61
|
+
// critical... super important to return undefined here
|
|
35
62
|
if (value === undefined) return undefined;
|
|
36
63
|
if (value === null) return null;
|
|
37
64
|
|
|
38
|
-
|
|
65
|
+
const { tz, wallTimeMode } = getWallClockConfig();
|
|
66
|
+
|
|
67
|
+
if (!wallTimeMode) {
|
|
39
68
|
return dayjs(value).toDate();
|
|
40
69
|
}
|
|
41
70
|
|
|
42
71
|
const naive = value instanceof Date ? dateToUtcComponentString(value) : String(value);
|
|
43
|
-
return dayjs.tz(naive,
|
|
72
|
+
return dayjs.tz(naive, tz).utc().toDate();
|
|
44
73
|
},
|
|
45
74
|
|
|
46
|
-
// Entity
|
|
75
|
+
// Entity -> DB
|
|
47
76
|
to(value: Date | null | undefined): Date | null | undefined {
|
|
48
|
-
|
|
49
|
-
const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC";
|
|
50
|
-
const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true";
|
|
51
|
-
|
|
52
|
-
// critical... super important to return undefined here
|
|
77
|
+
// critical... super important to return undefined here
|
|
53
78
|
if (value === undefined) return undefined;
|
|
54
79
|
if (value === null) return null;
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
return dayjs(value).toDate();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const wallTimeStr = dayjs(value).tz(SOLIDX_WALL_TIME_TZ).format("YYYY-MM-DD HH:mm:ss.SSS");
|
|
81
|
+
const wallTimeStr = serializeDate(value);
|
|
61
82
|
return dayjs.utc(wallTimeStr).toDate();
|
|
62
83
|
},
|
|
63
84
|
|
|
64
|
-
utc: {
|
|
65
|
-
from(value: Date | string | null | undefined): Date | null | undefined {
|
|
66
|
-
if (value === undefined) return undefined;
|
|
67
|
-
if (value === null) return null;
|
|
68
|
-
return dayjs(value).toDate();
|
|
69
|
-
},
|
|
70
|
-
to(value: Date | null | undefined): Date | null | undefined {
|
|
71
|
-
if (value === undefined) return undefined;
|
|
72
|
-
if (value === null) return null;
|
|
73
|
-
return dayjs(value).toDate();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
85
|
};
|
|
77
86
|
|
|
78
|
-
export const UtcDateTimeTransformer = LocalDateTimeTransformer.utc;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(node -e:*)",
|
|
5
|
-
"WebFetch(domain:docs.solidxai.com)",
|
|
6
|
-
"WebFetch(domain:github.com)",
|
|
7
|
-
"Read(//Users/oswald/projects/Solid_Starters/solidctl/**)",
|
|
8
|
-
"Read(//Users/oswald/projects/Solid_Starters/**)",
|
|
9
|
-
"Bash(find /Users/oswald/projects/Solid_Starters/solid-core-module -type d -name migration* -o -name *database*)"
|
|
10
|
-
],
|
|
11
|
-
"additionalDirectories": [
|
|
12
|
-
"/Users/oswald/projects/Solid_Starters/solidctl"
|
|
13
|
-
]
|
|
14
|
-
}
|
|
15
|
-
}
|
package/src/services/1.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
1. Do i need to create a storeStreams method for aws service too?
|
|
2
|
-
- Handle later
|
|
3
|
-
2. queues handling -> if queues is enabled by default, i.e triggerExport(exportTransactionEntity.id).
|
|
4
|
-
- startExport should either return the data or return the transaction id
|
|
5
|
-
3. How to handle scenarios wherein, nested related exist.(do i need to only get the userkey)
|
|
6
|
-
- show the userKey
|