feat: before split
This commit is contained in:
parent
9e0eff7e5a
commit
d8a6215155
|
|
@ -13,6 +13,8 @@ import { VideoModule } from '@gitroom/nestjs-libraries/videos/video.module';
|
|||
import { SentryModule } from '@sentry/nestjs/setup';
|
||||
import { FILTER } from '@gitroom/nestjs-libraries/sentry/sentry.exception';
|
||||
import { ChatModule } from '@gitroom/nestjs-libraries/chat/chat.module';
|
||||
import { getTemporalModule } from '@gitroom/nestjs-libraries/temporal/temporal.module';
|
||||
import { TemporalRegisterMissingSearchAttributesModule } from '@gitroom/nestjs-libraries/temporal/temporal.register';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
|
|
@ -26,6 +28,8 @@ import { ChatModule } from '@gitroom/nestjs-libraries/chat/chat.module';
|
|||
ThirdPartyModule,
|
||||
VideoModule,
|
||||
ChatModule,
|
||||
getTemporalModule(false),
|
||||
TemporalRegisterMissingSearchAttributesModule,
|
||||
ThrottlerModule.forRoot([
|
||||
{
|
||||
ttl: 3600000,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
dist/
|
||||
node_modules/
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"tsx": false,
|
||||
"decorators": true,
|
||||
"dynamicImport": true
|
||||
},
|
||||
"target": "es2020",
|
||||
"baseUrl": "/Users/nevodavid/Projects/gitroom",
|
||||
"paths": {
|
||||
"@gitroom/backend/*": ["apps/backend/src/*"],
|
||||
"@gitroom/cron/*": ["apps/cron/src/*"],
|
||||
"@gitroom/frontend/*": ["apps/frontend/src/*"],
|
||||
"@gitroom/helpers/*": ["libraries/helpers/src/*"],
|
||||
"@gitroom/nestjs-libraries/*": ["libraries/nestjs-libraries/src/*"],
|
||||
"@gitroom/react/*": ["libraries/react-shared-libraries/src/*"],
|
||||
"@gitroom/plugins/*": ["libraries/plugins/src/*"],
|
||||
"@gitroom/workers/*": ["apps/workers/src/*"],
|
||||
"@gitroom/extension/*": ["apps/extension/src/*"]
|
||||
},
|
||||
"keepClassNames": true,
|
||||
"transform": {
|
||||
"legacyDecorator": true,
|
||||
"decoratorMetadata": true
|
||||
},
|
||||
"loose": true
|
||||
},
|
||||
"module": {
|
||||
"type": "commonjs",
|
||||
"strict": false,
|
||||
"strictMode": true,
|
||||
"lazy": false,
|
||||
"noInterop": false
|
||||
},
|
||||
"sourceMaps": true,
|
||||
"minify": false
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"monorepo": false,
|
||||
"sourceRoot": "src",
|
||||
"entryFile": "../../dist/orchestrator/apps/orchestrator/src/main",
|
||||
"language": "ts",
|
||||
"generateOptions": {
|
||||
"spec": false
|
||||
},
|
||||
"compilerOptions": {
|
||||
"manualRestart": true,
|
||||
"tsConfigPath": "./tsconfig.build.json",
|
||||
"webpack": false,
|
||||
"deleteOutDir": true,
|
||||
"assets": [],
|
||||
"watchAssets": false,
|
||||
"plugins": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "postiz-orchestrator",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"dev": "dotenv -e ../../.env -- nest start --watch --entryFile=./apps/orchestrator/src/main",
|
||||
"build": "cross-env NODE_ENV=production nest build",
|
||||
"start": "dotenv -e ../../.env -- node --experimental-require-module ./dist/apps/orchestrator/src/main.js",
|
||||
"pm2": "pm2 start pnpm --name orchestrator -- start"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Activity, ActivityMethod } from 'nestjs-temporal-core';
|
||||
import { PostsService } from '@gitroom/nestjs-libraries/database/prisma/posts/posts.service';
|
||||
import {
|
||||
NotificationService,
|
||||
NotificationType,
|
||||
} from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service';
|
||||
import { Integration, Post, State } from '@prisma/client';
|
||||
import { stripHtmlValidation } from '@gitroom/helpers/utils/strip.html.validation';
|
||||
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
|
||||
import { AuthTokenDetails } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
|
||||
import { RefreshIntegrationService } from '@gitroom/nestjs-libraries/integrations/refresh.integration.service';
|
||||
import { timer } from '@gitroom/helpers/utils/timer';
|
||||
import { IntegrationService } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.service';
|
||||
import { WebhooksService } from '@gitroom/nestjs-libraries/database/prisma/webhooks/webhooks.service';
|
||||
|
||||
@Injectable()
|
||||
@Activity()
|
||||
export class PostActivity {
|
||||
constructor(
|
||||
private _postService: PostsService,
|
||||
private _notificationService: NotificationService,
|
||||
private _integrationManager: IntegrationManager,
|
||||
private _integrationService: IntegrationService,
|
||||
private _refreshIntegrationService: RefreshIntegrationService,
|
||||
private _webhookService: WebhooksService
|
||||
) {}
|
||||
|
||||
@ActivityMethod()
|
||||
async updatePost(id: string, postId: string, releaseURL: string) {
|
||||
return this._postService.updatePost(id, postId, releaseURL);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async getPostsList(orgId: string, postId: string) {
|
||||
return this._postService.getPostsRecursively(postId, true, orgId);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async isCommentable(integration: Integration) {
|
||||
const getIntegration = this._integrationManager.getSocialIntegration(
|
||||
integration.providerIdentifier
|
||||
);
|
||||
|
||||
return !!getIntegration.comment;
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async postComment(
|
||||
postId: string,
|
||||
lastPostId: string | undefined,
|
||||
integration: Integration,
|
||||
posts: Post[]
|
||||
) {
|
||||
const getIntegration = this._integrationManager.getSocialIntegration(
|
||||
integration.providerIdentifier
|
||||
);
|
||||
|
||||
const newPosts = await this._postService.updateTags(
|
||||
integration.organizationId,
|
||||
posts
|
||||
);
|
||||
|
||||
return getIntegration.comment(
|
||||
integration.internalId,
|
||||
postId,
|
||||
lastPostId,
|
||||
integration.token,
|
||||
await Promise.all(
|
||||
(newPosts || []).map(async (p) => ({
|
||||
id: p.id,
|
||||
message: stripHtmlValidation(
|
||||
getIntegration.editor,
|
||||
p.content,
|
||||
true,
|
||||
false,
|
||||
!/<\/?[a-z][\s\S]*>/i.test(p.content),
|
||||
getIntegration.mentionFormat
|
||||
),
|
||||
settings: JSON.parse(p.settings || '{}'),
|
||||
media: await this._postService.updateMedia(
|
||||
p.id,
|
||||
JSON.parse(p.image || '[]'),
|
||||
getIntegration?.convertToJPEG || false
|
||||
),
|
||||
}))
|
||||
),
|
||||
integration
|
||||
);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async postSocial(integration: Integration, posts: Post[]) {
|
||||
const getIntegration = this._integrationManager.getSocialIntegration(
|
||||
integration.providerIdentifier
|
||||
);
|
||||
|
||||
const newPosts = await this._postService.updateTags(
|
||||
integration.organizationId,
|
||||
posts
|
||||
);
|
||||
|
||||
return getIntegration.post(
|
||||
integration.internalId,
|
||||
integration.token,
|
||||
await Promise.all(
|
||||
(newPosts || []).map(async (p) => ({
|
||||
id: p.id,
|
||||
message: stripHtmlValidation(
|
||||
getIntegration.editor,
|
||||
p.content,
|
||||
true,
|
||||
false,
|
||||
!/<\/?[a-z][\s\S]*>/i.test(p.content),
|
||||
getIntegration.mentionFormat
|
||||
),
|
||||
settings: JSON.parse(p.settings || '{}'),
|
||||
media: await this._postService.updateMedia(
|
||||
p.id,
|
||||
JSON.parse(p.image || '[]'),
|
||||
getIntegration?.convertToJPEG || false
|
||||
),
|
||||
}))
|
||||
),
|
||||
integration
|
||||
);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async inAppNotification(
|
||||
orgId: string,
|
||||
subject: string,
|
||||
message: string,
|
||||
sendEmail = false,
|
||||
digest = false,
|
||||
type: NotificationType = 'success'
|
||||
) {
|
||||
return this._notificationService.inAppNotification(
|
||||
orgId,
|
||||
subject,
|
||||
message,
|
||||
sendEmail,
|
||||
digest,
|
||||
type
|
||||
);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async globalPlugs(integration: Integration) {
|
||||
return this._postService.checkPlugs(
|
||||
integration.organizationId,
|
||||
integration.providerIdentifier,
|
||||
integration.id
|
||||
);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async changeState(id: string, state: State, err?: any, body?: any) {
|
||||
return this._postService.changeState(id, state, err, body);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async internalPlugs(integration: Integration, settings: any) {
|
||||
return this._postService.checkInternalPlug(
|
||||
integration,
|
||||
integration.organizationId,
|
||||
integration.id,
|
||||
settings
|
||||
);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async sendWebhooks(postId: string, orgId: string, integrationId: string) {
|
||||
const webhooks = (await this._webhookService.getWebhooks(orgId)).filter(
|
||||
(f) => {
|
||||
return (
|
||||
f.integrations.length === 0 ||
|
||||
f.integrations.some((i) => i.integration.id === integrationId)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const post = await this._postService.getPostByForWebhookId(postId);
|
||||
return Promise.all(
|
||||
webhooks.map(async (webhook) => {
|
||||
try {
|
||||
await fetch(webhook.url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(post),
|
||||
});
|
||||
} catch (e) {
|
||||
/**empty**/
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
@ActivityMethod()
|
||||
async processPlug(data: {
|
||||
plugId: string;
|
||||
postId: string;
|
||||
delay: number;
|
||||
totalRuns: number;
|
||||
currentRun: number;
|
||||
}) {
|
||||
return this._integrationService.processPlugs(data);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async processInternalPlug(data: {
|
||||
post: string;
|
||||
originalIntegration: string;
|
||||
integration: string;
|
||||
plugName: string;
|
||||
orgId: string;
|
||||
delay: number;
|
||||
information: any;
|
||||
}) {
|
||||
return this._integrationService.processInternalPlug(data);
|
||||
}
|
||||
|
||||
@ActivityMethod()
|
||||
async refreshToken(
|
||||
integration: Integration
|
||||
): Promise<false | AuthTokenDetails> {
|
||||
const getIntegration = this._integrationManager.getSocialIntegration(
|
||||
integration.providerIdentifier
|
||||
);
|
||||
|
||||
try {
|
||||
const refresh = await this._refreshIntegrationService.refresh(
|
||||
integration
|
||||
);
|
||||
if (!refresh) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getIntegration.refreshWait) {
|
||||
await timer(10000);
|
||||
}
|
||||
|
||||
return refresh;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { PostActivity } from '@gitroom/orchestrator/activities/post.activity';
|
||||
import { getTemporalModule } from '@gitroom/nestjs-libraries/temporal/temporal.module';
|
||||
import { DatabaseModule } from '@gitroom/nestjs-libraries/database/prisma/database.module';
|
||||
import { BullMqModule } from '@gitroom/nestjs-libraries/bull-mq-transport-new/bull.mq.module';
|
||||
|
||||
const activities = [
|
||||
PostActivity,
|
||||
];
|
||||
@Module({
|
||||
imports: [
|
||||
BullMqModule,
|
||||
DatabaseModule,
|
||||
getTemporalModule(true, require.resolve('./workflows'), activities),
|
||||
],
|
||||
controllers: [],
|
||||
providers: [...activities],
|
||||
get exports() {
|
||||
return [...this.providers, ...this.imports];
|
||||
},
|
||||
})
|
||||
export class AppModule {}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import 'source-map-support/register';
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
dayjs.extend(utc);
|
||||
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from '@gitroom/orchestrator/app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
// some comment again
|
||||
const app = await NestFactory.createApplicationContext(AppModule);
|
||||
app.enableShutdownHooks();
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from './post.workflow';
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
import { PostActivity } from '@gitroom/orchestrator/activities/post.activity';
|
||||
import {
|
||||
ActivityFailure,
|
||||
ApplicationFailure,
|
||||
startChild,
|
||||
proxyActivities,
|
||||
sleep,
|
||||
} from '@temporalio/workflow';
|
||||
import dayjs from 'dayjs';
|
||||
import { Integration } from '@prisma/client';
|
||||
import { capitalize, sortBy } from 'lodash';
|
||||
import { PostResponse } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
|
||||
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
|
||||
import { TypedSearchAttributes } from '@temporalio/common';
|
||||
import { postId as postIdSearchParam } from '@gitroom/nestjs-libraries/temporal/temporal.search.attribute';
|
||||
|
||||
const {
|
||||
getPostsList,
|
||||
inAppNotification,
|
||||
postSocial,
|
||||
postComment,
|
||||
refreshToken,
|
||||
internalPlugs,
|
||||
changeState,
|
||||
globalPlugs,
|
||||
updatePost,
|
||||
processInternalPlug,
|
||||
processPlug,
|
||||
sendWebhooks,
|
||||
isCommentable,
|
||||
} = proxyActivities<PostActivity>({
|
||||
startToCloseTimeout: '10 minute',
|
||||
retry: {
|
||||
maximumAttempts: 3,
|
||||
backoffCoefficient: 1,
|
||||
initialInterval: '2 minutes',
|
||||
},
|
||||
});
|
||||
|
||||
export async function postWorkflow({
|
||||
postId,
|
||||
organizationId,
|
||||
postNow = false,
|
||||
}: {
|
||||
postId: string;
|
||||
organizationId: string;
|
||||
postNow?: boolean;
|
||||
}) {
|
||||
const startTime = new Date();
|
||||
// get all the posts and comments to post
|
||||
const postsList = await getPostsList(organizationId, postId);
|
||||
const [post] = postsList;
|
||||
|
||||
// in case doesn't exists for some reason, fail it
|
||||
if (!post) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a repeatable post, we should ignore this
|
||||
if (!postNow) {
|
||||
await sleep(dayjs(post.publishDate).diff(dayjs(), 'millisecond'));
|
||||
}
|
||||
|
||||
// if refresh is needed from last time, let's inform the user
|
||||
if (post.integration?.refreshNeeded) {
|
||||
await inAppNotification(
|
||||
post.organizationId,
|
||||
`We couldn't post to ${post.integration?.providerIdentifier} for ${post?.integration?.name}`,
|
||||
`We couldn't post to ${post.integration?.providerIdentifier} for ${post?.integration?.name} because you need to reconnect it. Please enable it and try again.`,
|
||||
true,
|
||||
false,
|
||||
'info'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's disabled, inform the user
|
||||
if (post.integration?.disabled) {
|
||||
await inAppNotification(
|
||||
post.organizationId,
|
||||
`We couldn't post to ${post.integration?.providerIdentifier} for ${post?.integration?.name}`,
|
||||
`We couldn't post to ${post.integration?.providerIdentifier} for ${post?.integration?.name} because it's disabled. Please enable it and try again.`,
|
||||
true,
|
||||
false,
|
||||
'info'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we need to post comment for this social?
|
||||
const toComment =
|
||||
postsList.length === 1 ? false : await isCommentable(post.integration);
|
||||
|
||||
// list of all the saved results
|
||||
const postsResults: PostResponse[] = [];
|
||||
|
||||
// iterate over the posts
|
||||
for (let i = 0; i < postsList.length; i++) {
|
||||
// this is a small trick to repeat an action in case of token refresh
|
||||
while (true) {
|
||||
try {
|
||||
// first post the main post
|
||||
if (i === 0) {
|
||||
postsResults.push(
|
||||
...(await postSocial(post.integration as Integration, [
|
||||
postsList[i],
|
||||
]))
|
||||
);
|
||||
|
||||
// then post the comments if any
|
||||
} else {
|
||||
if (!toComment) {
|
||||
break;
|
||||
}
|
||||
postsResults.push(
|
||||
...(await postComment(
|
||||
postsResults[0].postId,
|
||||
postsResults.length === 1 ? undefined : postsResults[i - 1].id,
|
||||
post.integration,
|
||||
[postsList[i]]
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
// mark post as successful
|
||||
await updatePost(
|
||||
postsList[i].id,
|
||||
postsResults[i].postId,
|
||||
postsResults[i].releaseURL
|
||||
);
|
||||
|
||||
// break the current while to move to the next post
|
||||
break;
|
||||
} catch (err) {
|
||||
// if token refresh is needed, do it and repeat
|
||||
if (
|
||||
err instanceof ActivityFailure &&
|
||||
err.cause instanceof ApplicationFailure &&
|
||||
err.cause.type === 'refresh_token'
|
||||
) {
|
||||
const refresh = await refreshToken(post.integration);
|
||||
if (!refresh) {
|
||||
return false;
|
||||
}
|
||||
|
||||
post.integration.token = refresh.accessToken;
|
||||
continue;
|
||||
}
|
||||
|
||||
// for other errors, change state and inform the user if needed
|
||||
await changeState(postsList[0].id, 'ERROR', err, postsList);
|
||||
|
||||
// specific case for bad body errors
|
||||
if (
|
||||
err instanceof ActivityFailure &&
|
||||
err.cause instanceof ApplicationFailure &&
|
||||
err.cause.type === 'bad_body'
|
||||
) {
|
||||
await inAppNotification(
|
||||
post.organizationId,
|
||||
`Error posting on ${post.integration?.providerIdentifier} for ${post?.integration?.name}`,
|
||||
`An error occurred while posting on ${
|
||||
post.integration?.providerIdentifier
|
||||
}${err?.message ? `: ${err?.message}` : ``}`,
|
||||
true,
|
||||
false,
|
||||
'fail'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send notification on a sucessful post
|
||||
await inAppNotification(
|
||||
post.integration.organizationId,
|
||||
`Your post has been published on ${capitalize(
|
||||
post.integration.providerIdentifier
|
||||
)}`,
|
||||
`Your post has been published on ${capitalize(
|
||||
post.integration.providerIdentifier
|
||||
)} at ${postsResults[0].releaseURL}`,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
// send webhooks for the post
|
||||
await sendWebhooks(
|
||||
postsResults[0].postId,
|
||||
post.organizationId,
|
||||
post.integration.id
|
||||
);
|
||||
|
||||
// load internal plugs like repost by other users
|
||||
const internalPlugsList = await internalPlugs(
|
||||
post.integration,
|
||||
JSON.parse(post.settings)
|
||||
);
|
||||
|
||||
// load global plugs, like repost a post if it gets to a certain number of likes
|
||||
const globalPlugsList = (await globalPlugs(post.integration)).reduce(
|
||||
(all, current) => {
|
||||
for (let i = 1; i <= current.totalRuns; i++) {
|
||||
all.push({
|
||||
...current,
|
||||
delay: current.delay * i,
|
||||
});
|
||||
}
|
||||
|
||||
return all;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Check if the post is repeatable
|
||||
const repeatPost = !post.intervalInDays
|
||||
? []
|
||||
: [
|
||||
{
|
||||
type: 'repeat-post',
|
||||
delay:
|
||||
post.intervalInDays * 24 * 60 * 60 * 1000 -
|
||||
(new Date().getTime() - startTime.getTime()),
|
||||
},
|
||||
];
|
||||
|
||||
// Sort all the actions by delay, so we can process them in order
|
||||
const list = sortBy(
|
||||
[...internalPlugsList, ...globalPlugsList, ...repeatPost],
|
||||
'delay'
|
||||
);
|
||||
|
||||
// process all the plugs in order, we are using while because in some cases we need to remove items from the list
|
||||
while (list.length > 0) {
|
||||
// get the next to process
|
||||
const todo = list.shift();
|
||||
|
||||
// wait for the delay
|
||||
await sleep(todo.delay);
|
||||
|
||||
// process internal plug
|
||||
if (todo.type === 'internal-plug') {
|
||||
while (true) {
|
||||
try {
|
||||
await processInternalPlug({ ...todo, post: postsResults[0].postId });
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof ActivityFailure &&
|
||||
err.cause instanceof ApplicationFailure &&
|
||||
err.cause.type === 'refresh_token'
|
||||
) {
|
||||
const refresh = await refreshToken(post.integration);
|
||||
if (!refresh) {
|
||||
return false;
|
||||
}
|
||||
|
||||
post.integration.token = refresh.accessToken;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// process global plug
|
||||
if (todo.type === 'global') {
|
||||
while (true) {
|
||||
try {
|
||||
const process = await processPlug({
|
||||
...todo,
|
||||
postId: postsResults[0].postId,
|
||||
});
|
||||
if (process) {
|
||||
const toDelete = list
|
||||
.reduce((all, current, index) => {
|
||||
if (current.plugId === todo.plugId) {
|
||||
all.push(index);
|
||||
}
|
||||
|
||||
return all;
|
||||
}, [])
|
||||
.reverse();
|
||||
|
||||
for (const index of toDelete) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof ActivityFailure &&
|
||||
err.cause instanceof ApplicationFailure &&
|
||||
err.cause.type === 'refresh_token'
|
||||
) {
|
||||
const refresh = await refreshToken(post.integration);
|
||||
if (!refresh) {
|
||||
return false;
|
||||
}
|
||||
|
||||
post.integration.token = refresh.accessToken;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// process repeat post in a new workflow, this is important so the other plugs can keep running
|
||||
if (todo.type === 'repeat-post') {
|
||||
await startChild(postWorkflow, {
|
||||
parentClosePolicy: 'ABANDON',
|
||||
args: [
|
||||
{
|
||||
postId,
|
||||
organizationId,
|
||||
postNow: true,
|
||||
},
|
||||
],
|
||||
workflowId: `post_${post.id}_${makeId(10)}`,
|
||||
typedSearchAttributes: new TypedSearchAttributes([
|
||||
{
|
||||
key: postIdSearchParam,
|
||||
value: postId,
|
||||
},
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"],
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "es2017",
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import { Controller } from '@nestjs/common';
|
||||
import { EventPattern, Transport } from '@nestjs/microservices';
|
||||
import { IntegrationService } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.service';
|
||||
|
||||
@Controller()
|
||||
export class PlugsController {
|
||||
constructor(private _integrationService: IntegrationService) {}
|
||||
|
||||
@EventPattern('plugs', Transport.REDIS)
|
||||
async plug(data: {
|
||||
plugId: string;
|
||||
postId: string;
|
||||
delay: number;
|
||||
totalRuns: number;
|
||||
currentRun: number;
|
||||
}) {
|
||||
try {
|
||||
return await this._integrationService.processPlugs(data);
|
||||
} catch (err) {
|
||||
console.log(
|
||||
"Unhandled error, let's avoid crashing the plug worker",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventPattern('internal-plugs', Transport.REDIS)
|
||||
async internalPlug(data: {
|
||||
post: string;
|
||||
originalIntegration: string;
|
||||
integration: string;
|
||||
plugName: string;
|
||||
orgId: string;
|
||||
delay: number;
|
||||
information: any;
|
||||
}) {
|
||||
try {
|
||||
return await this._integrationService.processInternalPlug(data);
|
||||
} catch (err) {
|
||||
console.log(
|
||||
"Unhandled error, let's avoid crashing the internal plugs worker",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,28 +12,6 @@ export class PostsController {
|
|||
private _autopostsService: AutopostService
|
||||
) {}
|
||||
|
||||
@EventPattern('post', Transport.REDIS)
|
||||
async post(data: { id: string }) {
|
||||
console.log('processing', data);
|
||||
try {
|
||||
return await this._postsService.post(data.id);
|
||||
} catch (err) {
|
||||
console.log("Unhandled error, let's avoid crashing the post worker", err);
|
||||
}
|
||||
}
|
||||
|
||||
@EventPattern('submit', Transport.REDIS)
|
||||
async payout(data: { id: string; releaseURL: string }) {
|
||||
try {
|
||||
return await this._postsService.payout(data.id, data.releaseURL);
|
||||
} catch (err) {
|
||||
console.log(
|
||||
"Unhandled error, let's avoid crashing the submit worker",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventPattern('sendDigestEmail', Transport.REDIS)
|
||||
async sendDigestEmail(data: { subject: string; org: string; since: string }) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service';
|
||||
import Bottleneck from 'bottleneck';
|
||||
import { timer } from '@gitroom/helpers/utils/timer';
|
||||
import { BadBody } from '@gitroom/nestjs-libraries/integrations/social.abstract';
|
||||
|
||||
const connection = new Bottleneck.IORedisConnection({
|
||||
|
|
@ -35,11 +34,12 @@ export const concurrency = async <T>(
|
|||
async () => {
|
||||
try {
|
||||
return await func();
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw new BadBody(
|
||||
identifier,
|
||||
JSON.stringify({}),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
import { forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
forwardRef,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { IntegrationRepository } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.repository';
|
||||
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
|
||||
import {
|
||||
|
|
@ -442,40 +448,15 @@ export class IntegrationService {
|
|||
getIntegration.providerIdentifier
|
||||
);
|
||||
|
||||
if (
|
||||
dayjs(getIntegration?.tokenExpiration).isBefore(dayjs()) ||
|
||||
forceRefresh
|
||||
) {
|
||||
const data = await this._refreshIntegrationService.refresh(
|
||||
getIntegration
|
||||
);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
const { accessToken } = data;
|
||||
// @ts-ignore
|
||||
await getSocialIntegration?.[getAllInternalPlugs.methodName]?.(
|
||||
getIntegration,
|
||||
originalIntegration,
|
||||
data.post,
|
||||
data.information
|
||||
);
|
||||
|
||||
getIntegration.token = accessToken;
|
||||
|
||||
if (getSocialIntegration.refreshWait) {
|
||||
await timer(10000);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// @ts-ignore
|
||||
await getSocialIntegration?.[getAllInternalPlugs.methodName]?.(
|
||||
getIntegration,
|
||||
originalIntegration,
|
||||
data.post,
|
||||
data.information
|
||||
);
|
||||
} catch (err) {
|
||||
if (err instanceof RefreshToken) {
|
||||
return this.processInternalPlug(data, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
async processPlugs(data: {
|
||||
|
|
@ -487,19 +468,13 @@ export class IntegrationService {
|
|||
}) {
|
||||
const getPlugById = await this._integrationRepository.getPlug(data.plugId);
|
||||
if (!getPlugById) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const integration = this._integrationManager.getSocialIntegration(
|
||||
getPlugById.integration.providerIdentifier
|
||||
);
|
||||
|
||||
const findPlug = this._integrationManager
|
||||
.getAllPlugs()
|
||||
.find(
|
||||
(p) => p.identifier === getPlugById.integration.providerIdentifier
|
||||
)!;
|
||||
|
||||
// @ts-ignore
|
||||
const process = await integration[getPlugById.plugFunction](
|
||||
getPlugById.integration,
|
||||
|
|
@ -511,26 +486,14 @@ export class IntegrationService {
|
|||
);
|
||||
|
||||
if (process) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (data.totalRuns === data.currentRun) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
this._workerServiceProducer.emit('plugs', {
|
||||
id: 'plug_' + data.postId + '_' + findPlug.identifier,
|
||||
options: {
|
||||
delay: data.delay,
|
||||
},
|
||||
payload: {
|
||||
plugId: data.plugId,
|
||||
postId: data.postId,
|
||||
delay: data.delay,
|
||||
totalRuns: data.totalRuns,
|
||||
currentRun: data.currentRun + 1,
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
async createOrUpdatePlug(
|
||||
|
|
|
|||
|
|
@ -694,6 +694,32 @@ export class PostsRepository {
|
|||
});
|
||||
}
|
||||
|
||||
async getPostByForWebhookId(postId: string) {
|
||||
return this._post.model.post.findMany({
|
||||
where: {
|
||||
id: postId,
|
||||
deletedAt: null,
|
||||
parentPostId: null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
content: true,
|
||||
publishDate: true,
|
||||
releaseURL: true,
|
||||
state: true,
|
||||
integration: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
providerIdentifier: true,
|
||||
picture: true,
|
||||
type: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getPostsSince(orgId: string, since: string) {
|
||||
return this._post.model.post.findMany({
|
||||
where: {
|
||||
|
|
|
|||
|
|
@ -8,38 +8,29 @@ import { PostsRepository } from '@gitroom/nestjs-libraries/database/prisma/posts
|
|||
import { CreatePostDto } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto';
|
||||
import dayjs from 'dayjs';
|
||||
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
|
||||
import { Integration, Post, Media, From } from '@prisma/client';
|
||||
import { Integration, Post, Media, From, State } from '@prisma/client';
|
||||
import { GetPostsDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.dto';
|
||||
import { NotificationService } from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service';
|
||||
import { capitalize, shuffle, uniq } from 'lodash';
|
||||
import { shuffle } from 'lodash';
|
||||
import { MessagesService } from '@gitroom/nestjs-libraries/database/prisma/marketplace/messages.service';
|
||||
import { StripeService } from '@gitroom/nestjs-libraries/services/stripe.service';
|
||||
import { CreateGeneratedPostsDto } from '@gitroom/nestjs-libraries/dtos/generator/create.generated.posts.dto';
|
||||
import { IntegrationService } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.service';
|
||||
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
|
||||
import {
|
||||
BadBody,
|
||||
RefreshToken,
|
||||
} from '@gitroom/nestjs-libraries/integrations/social.abstract';
|
||||
import { BullMqClient } from '@gitroom/nestjs-libraries/bull-mq-transport-new/client';
|
||||
import { timer } from '@gitroom/helpers/utils/timer';
|
||||
import { AuthTokenDetails } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import { MediaService } from '@gitroom/nestjs-libraries/database/prisma/media/media.service';
|
||||
import { ShortLinkService } from '@gitroom/nestjs-libraries/short-linking/short.link.service';
|
||||
import { WebhooksService } from '@gitroom/nestjs-libraries/database/prisma/webhooks/webhooks.service';
|
||||
import { CreateTagDto } from '@gitroom/nestjs-libraries/dtos/posts/create.tag.dto';
|
||||
import axios from 'axios';
|
||||
import sharp from 'sharp';
|
||||
import { UploadFactory } from '@gitroom/nestjs-libraries/upload/upload.factory';
|
||||
import { Readable } from 'stream';
|
||||
import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { validate } from 'class-validator';
|
||||
import { stripHtmlValidation } from '@gitroom/helpers/utils/strip.html.validation';
|
||||
dayjs.extend(utc);
|
||||
import * as Sentry from '@sentry/nestjs';
|
||||
import { RefreshIntegrationService } from '@gitroom/nestjs-libraries/integrations/refresh.integration.service';
|
||||
import { TemporalService } from 'nestjs-temporal-core';
|
||||
import { TypedSearchAttributes } from '@temporalio/common';
|
||||
import { postId as postIdSearchParam } from '@gitroom/nestjs-libraries/temporal/temporal.search.attribute';
|
||||
|
||||
type PostWithConditionals = Post & {
|
||||
integration?: Integration;
|
||||
|
|
@ -51,7 +42,6 @@ export class PostsService {
|
|||
private storage = UploadFactory.createStorage();
|
||||
constructor(
|
||||
private _postRepository: PostsRepository,
|
||||
private _workerServiceProducer: BullMqClient,
|
||||
private _integrationManager: IntegrationManager,
|
||||
private _notificationService: NotificationService,
|
||||
private _messagesService: MessagesService,
|
||||
|
|
@ -59,9 +49,8 @@ export class PostsService {
|
|||
private _integrationService: IntegrationService,
|
||||
private _mediaService: MediaService,
|
||||
private _shortLinkService: ShortLinkService,
|
||||
private _webhookService: WebhooksService,
|
||||
private openaiService: OpenaiService,
|
||||
private _refreshIntegrationService: RefreshIntegrationService
|
||||
private _temporalService: TemporalService
|
||||
) {}
|
||||
|
||||
checkPending15minutesBack() {
|
||||
|
|
@ -71,6 +60,10 @@ export class PostsService {
|
|||
return this._postRepository.searchForMissingThreeHoursPosts();
|
||||
}
|
||||
|
||||
updatePost(id: string, postId: string, releaseURL: string) {
|
||||
return this._postRepository.updatePost(id, postId, releaseURL);
|
||||
}
|
||||
|
||||
async getStatistics(orgId: string, id: string) {
|
||||
const getPost = await this.getPostsRecursively(id, true, orgId, true);
|
||||
const content = getPost.map((p) => p.content);
|
||||
|
|
@ -292,102 +285,7 @@ export class PostsService {
|
|||
return this._postRepository.getOldPosts(orgId, date);
|
||||
}
|
||||
|
||||
async post(id: string) {
|
||||
const allPosts = await this.getPostsRecursively(id, true);
|
||||
const [firstPost, ...morePosts] = allPosts;
|
||||
if (!firstPost) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPost.integration?.refreshNeeded) {
|
||||
await this._notificationService.inAppNotification(
|
||||
firstPost.organizationId,
|
||||
`We couldn't post to ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name}`,
|
||||
`We couldn't post to ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name} because you need to reconnect it. Please enable it and try again.`,
|
||||
true,
|
||||
false,
|
||||
'info'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstPost.integration?.disabled) {
|
||||
await this._notificationService.inAppNotification(
|
||||
firstPost.organizationId,
|
||||
`We couldn't post to ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name}`,
|
||||
`We couldn't post to ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name} because it's disabled. Please enable it and try again.`,
|
||||
true,
|
||||
false,
|
||||
'info'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const finalPost = await this.postSocial(firstPost.integration!, [
|
||||
firstPost,
|
||||
...morePosts,
|
||||
]);
|
||||
|
||||
if (firstPost?.intervalInDays) {
|
||||
this._workerServiceProducer.emit('post', {
|
||||
id,
|
||||
options: {
|
||||
delay: firstPost.intervalInDays * 86400000,
|
||||
},
|
||||
payload: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!finalPost?.postId || !finalPost?.releaseURL) {
|
||||
await this._postRepository.changeState(firstPost.id, 'ERROR');
|
||||
await this._notificationService.inAppNotification(
|
||||
firstPost.organizationId,
|
||||
`Error posting on ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name}`,
|
||||
`An error occurred while posting on ${firstPost.integration?.providerIdentifier}`,
|
||||
true,
|
||||
false,
|
||||
'fail'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (err: any) {
|
||||
await this._postRepository.changeState(
|
||||
firstPost.id,
|
||||
'ERROR',
|
||||
err,
|
||||
allPosts
|
||||
);
|
||||
if (err instanceof BadBody) {
|
||||
await this._notificationService.inAppNotification(
|
||||
firstPost.organizationId,
|
||||
`Error posting on ${firstPost.integration?.providerIdentifier} for ${firstPost?.integration?.name}`,
|
||||
`An error occurred while posting on ${
|
||||
firstPost.integration?.providerIdentifier
|
||||
}${err?.message ? `: ${err?.message}` : ``}`,
|
||||
true,
|
||||
false,
|
||||
'fail'
|
||||
);
|
||||
|
||||
console.error(
|
||||
'[Error] posting on',
|
||||
firstPost.integration?.providerIdentifier,
|
||||
err.identifier,
|
||||
err.json,
|
||||
err.body,
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private async updateTags(orgId: string, post: Post[]): Promise<Post[]> {
|
||||
public async updateTags(orgId: string, post: Post[]): Promise<Post[]> {
|
||||
const plainText = JSON.stringify(post);
|
||||
const extract = Array.from(
|
||||
plainText.match(/\(post:[a-zA-Z0-9-_]+\)/g) || []
|
||||
|
|
@ -411,127 +309,7 @@ export class PostsService {
|
|||
return this.updateTags(orgId, JSON.parse(newPlainText) as Post[]);
|
||||
}
|
||||
|
||||
private async postSocial(
|
||||
integration: Integration,
|
||||
posts: Post[],
|
||||
forceRefresh = false
|
||||
): Promise<Partial<{ postId: string; releaseURL: string }> | undefined> {
|
||||
const getIntegration = this._integrationManager.getSocialIntegration(
|
||||
integration.providerIdentifier
|
||||
);
|
||||
|
||||
if (!getIntegration) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (dayjs(integration?.tokenExpiration).isBefore(dayjs()) || forceRefresh) {
|
||||
const data = await this._refreshIntegrationService.refresh(integration);
|
||||
|
||||
if (!data) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
integration.token = data.accessToken;
|
||||
|
||||
if (getIntegration.refreshWait) {
|
||||
await timer(10000);
|
||||
}
|
||||
}
|
||||
|
||||
const newPosts = await this.updateTags(integration.organizationId, posts);
|
||||
|
||||
try {
|
||||
const publishedPosts = await getIntegration.post(
|
||||
integration.internalId,
|
||||
integration.token,
|
||||
await Promise.all(
|
||||
(newPosts || []).map(async (p) => ({
|
||||
id: p.id,
|
||||
message: stripHtmlValidation(
|
||||
getIntegration.editor,
|
||||
p.content,
|
||||
true,
|
||||
false,
|
||||
!/<\/?[a-z][\s\S]*>/i.test(p.content),
|
||||
getIntegration.mentionFormat
|
||||
),
|
||||
settings: JSON.parse(p.settings || '{}'),
|
||||
media: await this.updateMedia(
|
||||
p.id,
|
||||
JSON.parse(p.image || '[]'),
|
||||
getIntegration?.convertToJPEG || false
|
||||
),
|
||||
}))
|
||||
),
|
||||
integration
|
||||
);
|
||||
|
||||
for (const post of publishedPosts) {
|
||||
try {
|
||||
await this._postRepository.updatePost(
|
||||
post.id,
|
||||
post.postId,
|
||||
post.releaseURL
|
||||
);
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
try {
|
||||
await this._notificationService.inAppNotification(
|
||||
integration.organizationId,
|
||||
`Your post has been published on ${capitalize(
|
||||
integration.providerIdentifier
|
||||
)}`,
|
||||
`Your post has been published on ${capitalize(
|
||||
integration.providerIdentifier
|
||||
)} at ${publishedPosts[0].releaseURL}`,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
await this._webhookService.digestWebhooks(
|
||||
integration.organizationId,
|
||||
dayjs(newPosts[0].publishDate).format('YYYY-MM-DDTHH:mm:00')
|
||||
);
|
||||
|
||||
await this.checkPlugs(
|
||||
integration.organizationId,
|
||||
getIntegration.identifier,
|
||||
integration.id,
|
||||
publishedPosts[0].postId
|
||||
);
|
||||
|
||||
await this.checkInternalPlug(
|
||||
integration,
|
||||
integration.organizationId,
|
||||
publishedPosts[0].postId,
|
||||
JSON.parse(newPosts[0].settings || '{}')
|
||||
);
|
||||
} catch (err) {}
|
||||
|
||||
return {
|
||||
postId: publishedPosts[0].postId,
|
||||
releaseURL: publishedPosts[0].releaseURL,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof RefreshToken) {
|
||||
return this.postSocial(integration, posts, true);
|
||||
}
|
||||
|
||||
if (err instanceof BadBody) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
throw new BadBody(
|
||||
integration.providerIdentifier,
|
||||
JSON.stringify(err),
|
||||
{} as any,
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async checkInternalPlug(
|
||||
public async checkInternalPlug(
|
||||
integration: Integration,
|
||||
orgId: string,
|
||||
id: string,
|
||||
|
|
@ -542,7 +320,7 @@ export class PostsService {
|
|||
});
|
||||
|
||||
if (plugs.length === 0) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
const parsePlugs = plugs.reduce((all, [key, value]) => {
|
||||
|
|
@ -559,32 +337,24 @@ export class PostsService {
|
|||
active: boolean;
|
||||
}[] = Object.values(parsePlugs);
|
||||
|
||||
for (const trigger of list || []) {
|
||||
for (const int of trigger?.integrations || []) {
|
||||
this._workerServiceProducer.emit('internal-plugs', {
|
||||
id: 'plug_' + id + '_' + trigger.name + '_' + int.id,
|
||||
options: {
|
||||
delay: +trigger.delay,
|
||||
},
|
||||
payload: {
|
||||
post: id,
|
||||
originalIntegration: integration.id,
|
||||
integration: int.id,
|
||||
plugName: trigger.name,
|
||||
orgId: orgId,
|
||||
delay: +trigger.delay,
|
||||
information: trigger,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return (list || []).flatMap((trigger) => {
|
||||
return (trigger?.integrations || []).flatMap((int) => ({
|
||||
type: 'internal-plug',
|
||||
post: id,
|
||||
originalIntegration: integration.id,
|
||||
integration: int.id,
|
||||
plugName: trigger.name,
|
||||
orgId: orgId,
|
||||
delay: +trigger.delay,
|
||||
information: trigger,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private async checkPlugs(
|
||||
public async checkPlugs(
|
||||
orgId: string,
|
||||
providerName: string,
|
||||
integrationId: string,
|
||||
postId: string
|
||||
integrationId: string
|
||||
) {
|
||||
const loadAllPlugs = this._integrationManager.getAllPlugs();
|
||||
const getPlugs = await this._integrationService.getPlugs(
|
||||
|
|
@ -594,35 +364,51 @@ export class PostsService {
|
|||
|
||||
const currentPlug = loadAllPlugs.find((p) => p.identifier === providerName);
|
||||
|
||||
for (const plug of getPlugs) {
|
||||
const runPlug = currentPlug?.plugs?.find(
|
||||
(p: any) => p.methodName === plug.plugFunction
|
||||
)!;
|
||||
if (!runPlug) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this._workerServiceProducer.emit('plugs', {
|
||||
id: 'plug_' + postId + '_' + runPlug.identifier,
|
||||
options: {
|
||||
delay: runPlug.runEveryMilliseconds,
|
||||
},
|
||||
payload: {
|
||||
return getPlugs
|
||||
.filter((plug) => {
|
||||
return currentPlug?.plugs?.some(
|
||||
(p: any) => p.methodName === plug.plugFunction
|
||||
);
|
||||
})
|
||||
.map((plug) => {
|
||||
const runPlug = currentPlug?.plugs?.find(
|
||||
(p: any) => p.methodName === plug.plugFunction
|
||||
)!;
|
||||
return {
|
||||
type: 'global',
|
||||
plugId: plug.id,
|
||||
postId,
|
||||
delay: runPlug.runEveryMilliseconds,
|
||||
totalRuns: runPlug.totalRuns,
|
||||
currentRun: 1,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async deletePost(orgId: string, group: string) {
|
||||
const post = await this._postRepository.deletePost(orgId, group);
|
||||
|
||||
if (post?.id) {
|
||||
await this._workerServiceProducer.delete('post', post.id);
|
||||
return { id: post.id };
|
||||
try {
|
||||
const workflows = this._temporalService.client
|
||||
.getRawClient()
|
||||
?.workflow.list({
|
||||
query: `WorkflowType="postWorkflow" AND postId="${post.id}" AND ExecutionStatus="Running"`,
|
||||
});
|
||||
|
||||
for await (const executionInfo of workflows) {
|
||||
try {
|
||||
const workflow =
|
||||
await this._temporalService.client.getWorkflowHandle(
|
||||
executionInfo.workflowId
|
||||
);
|
||||
if (
|
||||
workflow &&
|
||||
(await workflow.describe()).status.name !== 'TERMINATED'
|
||||
) {
|
||||
await workflow.terminate();
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
return { error: true };
|
||||
|
|
@ -632,6 +418,9 @@ export class PostsService {
|
|||
return this._postRepository.countPostsFromDay(orgId, date);
|
||||
}
|
||||
|
||||
getPostByForWebhookId(id: string) {
|
||||
return this._postRepository.getPostByForWebhookId(id);
|
||||
}
|
||||
async createPost(orgId: string, body: CreatePostDto): Promise<any[]> {
|
||||
const postList = [];
|
||||
for (const post of body.posts) {
|
||||
|
|
@ -661,32 +450,42 @@ export class PostsService {
|
|||
return [] as any[];
|
||||
}
|
||||
|
||||
await this._workerServiceProducer.delete(
|
||||
'post',
|
||||
previousPost ? previousPost : posts?.[0]?.id
|
||||
);
|
||||
try {
|
||||
const workflows = this._temporalService.client
|
||||
.getRawClient()
|
||||
?.workflow.list({
|
||||
query: `WorkflowType="postWorkflow" AND postId="${posts[0].id}" AND ExecutionStatus="Running"`,
|
||||
});
|
||||
|
||||
if (
|
||||
body.type === 'now' ||
|
||||
(body.type === 'schedule' && dayjs(body.date).isAfter(dayjs()))
|
||||
) {
|
||||
this._workerServiceProducer.emit('post', {
|
||||
id: posts[0].id,
|
||||
options: {
|
||||
delay:
|
||||
body.type === 'now'
|
||||
? 0
|
||||
: dayjs(posts[0].publishDate).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
payload: {
|
||||
id: posts[0].id,
|
||||
delay:
|
||||
body.type === 'now'
|
||||
? 0
|
||||
: dayjs(posts[0].publishDate).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
for await (const executionInfo of workflows) {
|
||||
try {
|
||||
const workflow =
|
||||
await this._temporalService.client.getWorkflowHandle(
|
||||
executionInfo.workflowId
|
||||
);
|
||||
if (
|
||||
workflow &&
|
||||
(await workflow.describe()).status.name !== 'TERMINATED'
|
||||
) {
|
||||
await workflow.terminate();
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
await this._temporalService.client
|
||||
.getRawClient()
|
||||
?.workflow.start('postWorkflow', {
|
||||
workflowId: `post_${posts[0].id}`,
|
||||
taskQueue: 'main',
|
||||
args: [{ postId: posts[0].id, organizationId: orgId }],
|
||||
typedSearchAttributes: new TypedSearchAttributes([
|
||||
{
|
||||
key: postIdSearchParam,
|
||||
value: posts[0].id,
|
||||
},
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
Sentry.metrics.count('post_created', 1);
|
||||
postList.push({
|
||||
|
|
@ -702,24 +501,51 @@ export class PostsService {
|
|||
return this.openaiService.separatePosts(content, len);
|
||||
}
|
||||
|
||||
async changeState(id: string, state: State, err?: any, body?: any) {
|
||||
return this._postRepository.changeState(id, state, err, body);
|
||||
}
|
||||
|
||||
async changeDate(orgId: string, id: string, date: string) {
|
||||
const getPostById = await this._postRepository.getPostById(id, orgId);
|
||||
const newDate = await this._postRepository.changeDate(orgId, id, date);
|
||||
|
||||
await this._workerServiceProducer.delete('post', id);
|
||||
if (getPostById?.state !== 'DRAFT') {
|
||||
this._workerServiceProducer.emit('post', {
|
||||
id: id,
|
||||
options: {
|
||||
delay: dayjs(date).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
payload: {
|
||||
id: id,
|
||||
delay: dayjs(date).diff(dayjs(), 'millisecond'),
|
||||
},
|
||||
try {
|
||||
const workflows = this._temporalService.client
|
||||
.getRawClient()
|
||||
?.workflow.list({
|
||||
query: `WorkflowType="postWorkflow" AND postId="${getPostById.id}" AND ExecutionStatus="Running"`,
|
||||
});
|
||||
|
||||
for await (const executionInfo of workflows) {
|
||||
try {
|
||||
const workflow = await this._temporalService.client.getWorkflowHandle(
|
||||
executionInfo.workflowId
|
||||
);
|
||||
if (
|
||||
workflow &&
|
||||
(await workflow.describe()).status.name !== 'TERMINATED'
|
||||
) {
|
||||
await workflow.terminate();
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
} catch (err) {}
|
||||
|
||||
await this._temporalService.client
|
||||
.getRawClient()
|
||||
?.workflow.start('postWorkflow', {
|
||||
workflowId: `post_${getPostById.id}`,
|
||||
taskQueue: 'main',
|
||||
args: [{ postId: getPostById.id, organizationId: orgId }],
|
||||
typedSearchAttributes: new TypedSearchAttributes([
|
||||
{
|
||||
key: postIdSearchParam,
|
||||
value: getPostById.id,
|
||||
},
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
return this._postRepository.changeDate(orgId, id, date);
|
||||
return newDate;
|
||||
}
|
||||
|
||||
async payout(id: string, url: string) {
|
||||
|
|
|
|||
|
|
@ -1,22 +1,30 @@
|
|||
import { timer } from '@gitroom/helpers/utils/timer';
|
||||
import { concurrency } from '@gitroom/helpers/utils/concurrency.service';
|
||||
import { Integration } from '@prisma/client';
|
||||
import { ApplicationFailure } from '@temporalio/activity';
|
||||
|
||||
export class RefreshToken {
|
||||
constructor(
|
||||
public identifier: string,
|
||||
public json: string,
|
||||
public body: BodyInit,
|
||||
public message = ''
|
||||
) {}
|
||||
export class RefreshToken extends ApplicationFailure {
|
||||
constructor(identifier: string, json: string, body: BodyInit, message = '') {
|
||||
super(message, 'refresh_token', true, [
|
||||
{
|
||||
identifier,
|
||||
json,
|
||||
body,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
export class BadBody {
|
||||
constructor(
|
||||
public identifier: string,
|
||||
public json: string,
|
||||
public body: BodyInit,
|
||||
public message = ''
|
||||
) {}
|
||||
|
||||
export class BadBody extends ApplicationFailure {
|
||||
constructor(identifier: string, json: string, body: BodyInit, message = '') {
|
||||
super(message, 'bad_body', true, [
|
||||
{
|
||||
identifier,
|
||||
json,
|
||||
body,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
export class NotEnoughScopes {
|
||||
|
|
@ -58,7 +66,6 @@ export abstract class SocialAbstract {
|
|||
try {
|
||||
return await func();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
const handle = this.handleErrors(JSON.stringify(err));
|
||||
return { err: true, ...(handle || {}) };
|
||||
}
|
||||
|
|
@ -109,34 +116,36 @@ export abstract class SocialAbstract {
|
|||
json.includes('Rate limit')
|
||||
) {
|
||||
await timer(5000);
|
||||
return this.fetch(url, options, identifier, totalRetries + 1, ignoreConcurrency);
|
||||
return this.fetch(
|
||||
url,
|
||||
options,
|
||||
identifier,
|
||||
totalRetries + 1,
|
||||
ignoreConcurrency
|
||||
);
|
||||
}
|
||||
|
||||
const handleError = this.handleErrors(json || '{}');
|
||||
|
||||
if (handleError?.type === 'retry') {
|
||||
await timer(5000);
|
||||
return this.fetch(url, options, identifier, totalRetries + 1, ignoreConcurrency);
|
||||
return this.fetch(
|
||||
url,
|
||||
options,
|
||||
identifier,
|
||||
totalRetries + 1,
|
||||
ignoreConcurrency
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
request.status === 401 &&
|
||||
(handleError?.type === 'refresh-token' || !handleError)
|
||||
) {
|
||||
throw new RefreshToken(
|
||||
identifier,
|
||||
json,
|
||||
options.body!,
|
||||
handleError?.value
|
||||
);
|
||||
throw new RefreshToken(identifier, json, options.body!, handleError?.value);
|
||||
}
|
||||
|
||||
throw new BadBody(
|
||||
identifier,
|
||||
json,
|
||||
options.body!,
|
||||
handleError?.value || ''
|
||||
);
|
||||
throw new BadBody(identifier, json, options.body!, handleError?.value || '');
|
||||
}
|
||||
|
||||
checkScopes(required: string[], got: string | string[]) {
|
||||
|
|
|
|||
|
|
@ -554,6 +554,17 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
isPdf
|
||||
);
|
||||
|
||||
console.log({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'LinkedIn-Version': '202501',
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify(postPayload),
|
||||
});
|
||||
|
||||
const response = await this.fetch('https://api.linkedin.com/rest/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
@ -723,7 +734,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202504',
|
||||
'LinkedIn-Version': '202511',
|
||||
Authorization: `Bearer ${integration.token}`,
|
||||
},
|
||||
});
|
||||
|
|
@ -739,7 +750,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
headers: {
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
'LinkedIn-Version': '202504',
|
||||
'LinkedIn-Version': '202511',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,15 @@ export interface ISocialMediaIntegration {
|
|||
postDetails: PostDetails[],
|
||||
integration: Integration
|
||||
): Promise<PostResponse[]>; // Schedules a new post
|
||||
|
||||
comment?(
|
||||
id: string,
|
||||
postId: string,
|
||||
lastCommentId: string | undefined,
|
||||
accessToken: string,
|
||||
postDetails: PostDetails[],
|
||||
integration: Integration
|
||||
): Promise<PostResponse[]>; // Schedules a new post
|
||||
}
|
||||
|
||||
export type PostResponse = {
|
||||
|
|
@ -143,8 +152,14 @@ export interface SocialProvider
|
|||
url: string
|
||||
) => Promise<{ client_id: string; client_secret: string }>;
|
||||
mention?: (
|
||||
token: string, data: { query: string }, id: string, integration: Integration
|
||||
) => Promise<{ id: string; label: string; image: string, doNotCache?: boolean }[] | {none: true}>;
|
||||
token: string,
|
||||
data: { query: string },
|
||||
id: string,
|
||||
integration: Integration
|
||||
) => Promise<
|
||||
| { id: string; label: string; image: string; doNotCache?: boolean }[]
|
||||
| { none: true }
|
||||
>;
|
||||
mentionFormat?(idOrHandle: string, name: string): string;
|
||||
fetchPageInformation?(
|
||||
accessToken: string,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settin
|
|||
import { timer } from '@gitroom/helpers/utils/timer';
|
||||
import { Integration } from '@prisma/client';
|
||||
import { Rules } from '@gitroom/nestjs-libraries/chat/rules.description.decorator';
|
||||
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
|
||||
|
||||
@Rules(
|
||||
'TikTok can have one video or one picture or multiple pictures, it cannot be without an attachment'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import { TemporalModule } from 'nestjs-temporal-core';
|
||||
|
||||
export const getTemporalModule = (
|
||||
isWorkers: boolean,
|
||||
path?: string,
|
||||
activityClasses?: any[],
|
||||
) => {
|
||||
return TemporalModule.register({
|
||||
isGlobal: true,
|
||||
connection: {
|
||||
address: process.env.TEMPORAL_ADDRESS || 'localhost:7233',
|
||||
namespace: process.env.TEMPORAL_NAMESPACE || 'default',
|
||||
},
|
||||
taskQueue: 'main',
|
||||
...(isWorkers
|
||||
? {
|
||||
worker: {
|
||||
workflowsPath: path!,
|
||||
activityClasses: activityClasses!,
|
||||
autoStart: true,
|
||||
workerOptions: {
|
||||
maxConcurrentActivityTaskExecutions: 24,
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import {
|
||||
Global,
|
||||
Injectable,
|
||||
Module,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { TemporalService } from 'nestjs-temporal-core';
|
||||
import { Connection } from '@temporalio/client';
|
||||
|
||||
@Injectable()
|
||||
export class TemporalRegister implements OnModuleInit {
|
||||
constructor(private _client: TemporalService) {}
|
||||
|
||||
async onModuleInit(): Promise<void> {
|
||||
const connection = this._client?.client?.getRawClient()
|
||||
?.connection as Connection;
|
||||
|
||||
const { customAttributes } =
|
||||
await connection.operatorService.listSearchAttributes({
|
||||
namespace: process.env.TEMPORAL_NAMESPACE || 'default',
|
||||
});
|
||||
|
||||
const neededAttribute = ['organizationId', 'postId'];
|
||||
const missingAttributes = neededAttribute.filter(
|
||||
(attr) => !customAttributes[attr],
|
||||
);
|
||||
|
||||
if (missingAttributes.length > 0) {
|
||||
await connection.operatorService.addSearchAttributes({
|
||||
namespace: process.env.TEMPORAL_NAMESPACE || 'default',
|
||||
searchAttributes: missingAttributes.reduce((all, current) => {
|
||||
// @ts-ignore
|
||||
all[current] = 1;
|
||||
return all;
|
||||
}, {}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [],
|
||||
providers: [TemporalRegister],
|
||||
get exports() {
|
||||
return this.providers;
|
||||
},
|
||||
})
|
||||
export class TemporalRegisterMissingSearchAttributesModule {}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import {
|
||||
defineSearchAttributeKey,
|
||||
SearchAttributeType,
|
||||
} from '@temporalio/common';
|
||||
|
||||
export const organizationId = defineSearchAttributeKey(
|
||||
'organizationId',
|
||||
SearchAttributeType.TEXT
|
||||
);
|
||||
|
||||
export const postId = defineSearchAttributeKey(
|
||||
'postId',
|
||||
SearchAttributeType.TEXT
|
||||
);
|
||||
10
package.json
10
package.json
|
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"scripts": {
|
||||
"dev": "pnpm run --filter ./apps/extension --filter ./apps/cron --filter ./apps/workers --filter ./apps/backend --filter ./apps/frontend --parallel dev",
|
||||
"dev": "pnpm run --filter ./apps/extension --filter ./apps/cron --filter ./apps/orchestrator --filter ./apps/backend --filter ./apps/frontend --parallel dev",
|
||||
"pm2": "pnpm run pm2-run",
|
||||
"publish-sdk": "pnpm run --filter ./apps/sdk publish",
|
||||
"pm2-run": "pm2 delete all || true && pnpm run prisma-db-push && pnpm run --parallel pm2 && pm2 logs",
|
||||
|
|
@ -20,11 +20,13 @@
|
|||
"build:backend": "rm -rf apps/backend/dist && pnpm --filter ./apps/backend run build",
|
||||
"build:frontend": "rm -rf apps/frontend/dist && pnpm --filter ./apps/frontend run build",
|
||||
"build:workers": "rm -rf apps/workers/dist && pnpm --filter ./apps/workers run build",
|
||||
"build:orchestrator": "rm -rf apps/orchestrator/dist && pnpm --filter ./apps/orchestrator run build",
|
||||
"build:cron": "rm -rf apps/cron/dist && pnpm --filter ./apps/cron run build",
|
||||
"build:extension": "rm -rf apps/extension/dist && pnpm --filter ./apps/extension run build",
|
||||
"dev:backend": "rm -rf apps/backend/dist && pnpm --filter ./apps/backend run dev",
|
||||
"dev:frontend": "rm -rf apps/frontend/dist && pnpm --filter ./apps/frontend run dev",
|
||||
"dev:workers": "rm -rf apps/workers/dist && pnpm --filter ./apps/workers run dev",
|
||||
"dev:orchestrator": "rm -rf apps/orchestrator/dist && pnpm --filter ./apps/orchestrator run dev",
|
||||
"dev:cron": "rm -rf apps/cron/dist && pnpm --filter ./apps/cron run dev",
|
||||
"start:prod:backend": "pnpm --filter ./apps/backend run start",
|
||||
"start:prod:frontend": "pnpm --filter ./apps/frontend run start",
|
||||
|
|
@ -92,6 +94,11 @@
|
|||
"@swc/helpers": "0.5.13",
|
||||
"@sweetalert2/theme-dark": "^5.0.16",
|
||||
"@tailwindcss/postcss": "^4.1.7",
|
||||
"@temporalio/activity": "^1.14.0",
|
||||
"@temporalio/client": "^1.14.0",
|
||||
"@temporalio/common": "^1.14.0",
|
||||
"@temporalio/worker": "^1.14.0",
|
||||
"@temporalio/workflow": "^1.14.0",
|
||||
"@tiptap/extension-bold": "^3.0.6",
|
||||
"@tiptap/extension-document": "^3.0.6",
|
||||
"@tiptap/extension-heading": "^3.0.7",
|
||||
|
|
@ -181,6 +188,7 @@
|
|||
"music-metadata": "^7.14.0",
|
||||
"nestjs-command": "^3.1.4",
|
||||
"nestjs-real-ip": "^3.0.1",
|
||||
"nestjs-temporal-core": "^3.2.0",
|
||||
"next": "14.2.35",
|
||||
"next-plausible": "^3.12.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
|
|
|
|||
424
pnpm-lock.yaml
424
pnpm-lock.yaml
|
|
@ -156,6 +156,21 @@ importers:
|
|||
'@tailwindcss/postcss':
|
||||
specifier: ^4.1.7
|
||||
version: 4.1.18
|
||||
'@temporalio/activity':
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
'@temporalio/client':
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
'@temporalio/common':
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
'@temporalio/worker':
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0(@swc/helpers@0.5.13)(esbuild@0.25.12)
|
||||
'@temporalio/workflow':
|
||||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
'@tiptap/extension-bold':
|
||||
specifier: ^3.0.6
|
||||
version: 3.14.0(@tiptap/core@3.14.0(@tiptap/pm@3.14.0))
|
||||
|
|
@ -423,6 +438,9 @@ importers:
|
|||
nestjs-real-ip:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))
|
||||
nestjs-temporal-core:
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@10.4.20)(@temporalio/client@1.14.0)(@temporalio/common@1.14.0)(@temporalio/worker@1.14.0(@swc/helpers@0.5.13)(esbuild@0.25.12))(@temporalio/workflow@1.14.0)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
next:
|
||||
specifier: 14.2.35
|
||||
version: 14.2.35(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.1)
|
||||
|
|
@ -792,6 +810,8 @@ importers:
|
|||
|
||||
apps/frontend: {}
|
||||
|
||||
apps/orchestrator: {}
|
||||
|
||||
apps/sdk:
|
||||
dependencies:
|
||||
node-fetch:
|
||||
|
|
@ -2787,6 +2807,42 @@ packages:
|
|||
'@jsdevtools/ono@7.1.3':
|
||||
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
|
||||
|
||||
'@jsonjoy.com/base64@1.1.2':
|
||||
resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@jsonjoy.com/buffers@1.2.1':
|
||||
resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@jsonjoy.com/codegen@1.0.0':
|
||||
resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@jsonjoy.com/json-pack@1.21.0':
|
||||
resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@jsonjoy.com/json-pointer@1.0.2':
|
||||
resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@jsonjoy.com/util@1.9.0':
|
||||
resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
'@juggle/resize-observer@3.4.0':
|
||||
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
||||
|
||||
|
|
@ -6954,6 +7010,38 @@ packages:
|
|||
'@tanstack/virtual-core@3.13.13':
|
||||
resolution: {integrity: sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA==}
|
||||
|
||||
'@temporalio/activity@1.14.0':
|
||||
resolution: {integrity: sha512-ayGqfjqW8R1nhow54Y3A5ezoVwFr4SbB8VHaQA3seDFOB+6TyOVSlulYqGgFMxl/FXBkRa/VEswEDqS/xQq7aQ==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/client@1.14.0':
|
||||
resolution: {integrity: sha512-kjzJ+7M2kHj32cTTSQT5WOjEIOxY0TNV5g6Sw9PzWmKWdtIZig+d7qUIA3VjDe/TieNozxjR2wNAX5sKzYFANA==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/common@1.14.0':
|
||||
resolution: {integrity: sha512-jVmurBdFHdqw/wIehzVJikS8MhavL630p88TJ64P5PH0nP8S5V8R5vhkmHZ7n0sMRO+A0QFyWYyvnccu6MQZvw==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/core-bridge@1.14.0':
|
||||
resolution: {integrity: sha512-62WRbESKVtCx1FafbikQB90EwKNF+mEAaOJKifUIU4lQnk9wlZPRfrf6pwyqr+Uqi7uZhD2YqHXWUNVYbmQU7w==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/nexus@1.14.0':
|
||||
resolution: {integrity: sha512-0tgf+EBuz5vgYUukaYUzVHKr27XNQejXXO1i0x8+4sjR5zN6euNKraHfRzrDWRSm3nTZ6199rCTbR+CPrqaC/g==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/proto@1.14.0':
|
||||
resolution: {integrity: sha512-duYVjt3x6SkuFzJr+5NlklEgookPqW065qdcvogmdfVjrgiwz4W/07AN3+fL4ufmqt1//0SyF6nyqv9RNADYNA==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/worker@1.14.0':
|
||||
resolution: {integrity: sha512-wo5rgPSt83aT1hLYmh/0X4yOx/6uRbIvBa9LXqGo7s9s1GJkUyJpAahRt8aMoLm4qPsiZtu1gtU5KcASOmgqtg==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@temporalio/workflow@1.14.0':
|
||||
resolution: {integrity: sha512-hxUqCZTkdSwgy5nc/O1DIpYH0Z77cM57RfJvhK4ELmkkb1jh/Q4dshDannH1qQ1zYT0IKRBHSW7m1aMy1+dgDA==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
'@testing-library/dom@10.4.1':
|
||||
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
|
||||
engines: {node: '>=18'}
|
||||
|
|
@ -8306,6 +8394,12 @@ packages:
|
|||
peerDependencies:
|
||||
acorn: ^8
|
||||
|
||||
acorn-import-phases@1.0.4:
|
||||
resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
peerDependencies:
|
||||
acorn: ^8.14.0
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
|
|
@ -8932,6 +9026,10 @@ packages:
|
|||
capital-case@1.0.4:
|
||||
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
||||
|
||||
cargo-cp-artifact@0.1.9:
|
||||
resolution: {integrity: sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==}
|
||||
hasBin: true
|
||||
|
||||
caseless@0.12.0:
|
||||
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
|
||||
|
||||
|
|
@ -9965,6 +10063,9 @@ packages:
|
|||
es-module-lexer@1.7.0:
|
||||
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
|
||||
|
||||
es-module-lexer@2.0.0:
|
||||
resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -10776,6 +10877,12 @@ packages:
|
|||
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
glob-to-regex.js@1.2.0:
|
||||
resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
glob-to-regexp@0.4.1:
|
||||
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||
|
||||
|
|
@ -11029,6 +11136,10 @@ packages:
|
|||
header-case@2.0.4:
|
||||
resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==}
|
||||
|
||||
heap-js@2.7.1:
|
||||
resolution: {integrity: sha512-EQfezRg0NCZGNlhlDR3Evrw1FVL2G3LhU7EgPoxufQKruNBSYA8MiRPHeWbU+36o+Fhel0wMwM+sLEiBAlNLJA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
help-me@5.0.0:
|
||||
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
|
||||
|
||||
|
|
@ -11194,6 +11305,10 @@ packages:
|
|||
humanize-ms@1.2.1:
|
||||
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
|
||||
|
||||
hyperdyperid@1.2.0:
|
||||
resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
|
||||
engines: {node: '>=10.18'}
|
||||
|
||||
i18n-iso-countries@7.14.0:
|
||||
resolution: {integrity: sha512-nXHJZYtNrfsi1UQbyRqm3Gou431elgLjKl//CYlnBGt5aTWdRPH1PiS2T/p/n8Q8LnqYqzQJik3Q7mkwvLokeg==}
|
||||
engines: {node: '>= 12'}
|
||||
|
|
@ -11623,6 +11738,10 @@ packages:
|
|||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
isexe@3.1.1:
|
||||
resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
iso-3166-1@2.1.1:
|
||||
resolution: {integrity: sha512-RZxXf8cw5Y8LyHZIwIRvKw8sWTIHh2/txBT+ehO0QroesVfnz3JNFFX4i/OC/Yuv2bDIVYrHna5PMvjtpefq5w==}
|
||||
|
||||
|
|
@ -12611,6 +12730,9 @@ packages:
|
|||
resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
memfs@4.51.1:
|
||||
resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==}
|
||||
|
||||
memoize-one@5.2.1:
|
||||
resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
|
||||
|
||||
|
|
@ -13007,6 +13129,10 @@ packages:
|
|||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
ms@3.0.0-canary.1:
|
||||
resolution: {integrity: sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==}
|
||||
engines: {node: '>=12.13'}
|
||||
|
||||
msgpackr-extract@3.0.3:
|
||||
resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==}
|
||||
hasBin: true
|
||||
|
|
@ -13095,6 +13221,19 @@ packages:
|
|||
peerDependencies:
|
||||
'@nestjs/common': '>=8'
|
||||
|
||||
nestjs-temporal-core@3.2.0:
|
||||
resolution: {integrity: sha512-EIf1PZKBj9YR2ln8eDqBliGqo9IpWmetPbSbsO+X00s1qwewWNGGw7VX2Fq4Bw8/WPkbWeHgUHXwphkuOIIyaQ==}
|
||||
engines: {node: '>=16.0.0', npm: '>=8.0.0'}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
'@nestjs/core': ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
'@temporalio/client': ^1.12.0 || ^1.13.0
|
||||
'@temporalio/common': ^1.12.0 || ^1.13.0
|
||||
'@temporalio/worker': ^1.12.0 || ^1.13.0
|
||||
'@temporalio/workflow': ^1.12.0 || ^1.13.0
|
||||
reflect-metadata: ^0.2.2
|
||||
rxjs: ^7.8.0
|
||||
|
||||
netmask@2.0.2:
|
||||
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
|
@ -13124,6 +13263,10 @@ packages:
|
|||
sass:
|
||||
optional: true
|
||||
|
||||
nexus-rpc@0.0.1:
|
||||
resolution: {integrity: sha512-hAWn8Hh2eewpB5McXR5EW81R3pR/ziuGhKCF3wFyUVCklanPqrIgMNr7jKCbzXeNVad0nUDfWpFRqh2u+zxQtw==}
|
||||
engines: {node: '>= 18.0.0'}
|
||||
|
||||
nice-grpc-client-middleware-retry@3.1.13:
|
||||
resolution: {integrity: sha512-Q9I/wm5lYkDTveKFirrTHBkBY137yavXZ4xQDXTPIycUp7aLXD8xPTHFhqtAFWUw05aS91uffZZRgdv3HS0y/g==}
|
||||
|
||||
|
|
@ -14068,6 +14211,10 @@ packages:
|
|||
proto-list@1.2.4:
|
||||
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
|
||||
|
||||
proto3-json-serializer@2.0.2:
|
||||
resolution: {integrity: sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
protobufjs@7.5.4:
|
||||
resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
|
@ -15187,6 +15334,12 @@ packages:
|
|||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map-loader@4.0.2:
|
||||
resolution: {integrity: sha512-oYwAqCuL0OZhBoSgmdrLa7mv9MjommVMiQIWgcztf+eS4+8BfcUee6nenFnDhKOhzAVnk5gpZdfnz1iiBv+5sg==}
|
||||
engines: {node: '>= 14.15.0'}
|
||||
peerDependencies:
|
||||
webpack: ^5.72.1
|
||||
|
||||
source-map-support@0.5.13:
|
||||
resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
|
||||
|
||||
|
|
@ -15504,6 +15657,12 @@ packages:
|
|||
swagger-ui-dist@5.17.14:
|
||||
resolution: {integrity: sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==}
|
||||
|
||||
swc-loader@0.2.6:
|
||||
resolution: {integrity: sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==}
|
||||
peerDependencies:
|
||||
'@swc/core': ^1.2.147
|
||||
webpack: '>=2'
|
||||
|
||||
sweetalert2@11.4.8:
|
||||
resolution: {integrity: sha512-BDS/+E8RwaekGSxCPUbPnsRAyQ439gtXkTF/s98vY2l9DaVEOMjGj1FaQSorfGREKsbbxGSP7UXboibL5vgTMA==}
|
||||
|
||||
|
|
@ -15597,6 +15756,12 @@ packages:
|
|||
thenify@3.3.1:
|
||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||
|
||||
thingies@2.5.0:
|
||||
resolution: {integrity: sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==}
|
||||
engines: {node: '>=10.18'}
|
||||
peerDependencies:
|
||||
tslib: ^2
|
||||
|
||||
thread-stream@0.15.2:
|
||||
resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==}
|
||||
|
||||
|
|
@ -15745,6 +15910,12 @@ packages:
|
|||
resolution: {integrity: sha512-FvhKs0EBiQufK29irGLM/4aMIrfU5S/TiHB3h+DcO2hjRnVVM2WC278UQJCrNO4L/REE8IKWx/mQzQW2MrrLsg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
tree-dump@1.1.0:
|
||||
resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==}
|
||||
engines: {node: '>=10.0'}
|
||||
peerDependencies:
|
||||
tslib: '2'
|
||||
|
||||
tree-kill@1.2.2:
|
||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||
hasBin: true
|
||||
|
|
@ -16071,6 +16242,9 @@ packages:
|
|||
unified@11.0.5:
|
||||
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
||||
|
||||
unionfs@4.6.0:
|
||||
resolution: {integrity: sha512-fJAy3gTHjFi5S3TP5EGdjs/OUMFFvI/ady3T8qVuZfkv8Qi8prV/Q8BuFEgODJslhZTT2z2qdD2lGdee9qjEnA==}
|
||||
|
||||
unist-util-filter@5.0.1:
|
||||
resolution: {integrity: sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw==}
|
||||
|
||||
|
|
@ -16560,6 +16734,16 @@ packages:
|
|||
webpack-virtual-modules@0.5.0:
|
||||
resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==}
|
||||
|
||||
webpack@5.104.1:
|
||||
resolution: {integrity: sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
webpack-cli: '*'
|
||||
peerDependenciesMeta:
|
||||
webpack-cli:
|
||||
optional: true
|
||||
|
||||
webpack@5.87.0:
|
||||
resolution: {integrity: sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
|
@ -16632,6 +16816,11 @@ packages:
|
|||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
which@4.0.0:
|
||||
resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
|
||||
engines: {node: ^16.13.0 || >=18.0.0}
|
||||
hasBin: true
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -19954,6 +20143,42 @@ snapshots:
|
|||
|
||||
'@jsdevtools/ono@7.1.3': {}
|
||||
|
||||
'@jsonjoy.com/base64@1.1.2(tslib@2.8.1)':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)':
|
||||
dependencies:
|
||||
'@jsonjoy.com/base64': 1.1.2(tslib@2.8.1)
|
||||
'@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1)
|
||||
'@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1)
|
||||
'@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1)
|
||||
'@jsonjoy.com/util': 1.9.0(tslib@2.8.1)
|
||||
hyperdyperid: 1.2.0
|
||||
thingies: 2.5.0(tslib@2.8.1)
|
||||
tree-dump: 1.1.0(tslib@2.8.1)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)':
|
||||
dependencies:
|
||||
'@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1)
|
||||
'@jsonjoy.com/util': 1.9.0(tslib@2.8.1)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@jsonjoy.com/util@1.9.0(tslib@2.8.1)':
|
||||
dependencies:
|
||||
'@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1)
|
||||
'@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@juggle/resize-observer@3.4.0': {}
|
||||
|
||||
'@keystonehq/alias-sampling@0.1.2': {}
|
||||
|
|
@ -25035,6 +25260,86 @@ snapshots:
|
|||
|
||||
'@tanstack/virtual-core@3.13.13': {}
|
||||
|
||||
'@temporalio/activity@1.14.0':
|
||||
dependencies:
|
||||
'@temporalio/client': 1.14.0
|
||||
'@temporalio/common': 1.14.0
|
||||
abort-controller: 3.0.0
|
||||
|
||||
'@temporalio/client@1.14.0':
|
||||
dependencies:
|
||||
'@grpc/grpc-js': 1.14.3
|
||||
'@temporalio/common': 1.14.0
|
||||
'@temporalio/proto': 1.14.0
|
||||
abort-controller: 3.0.0
|
||||
long: 5.3.2
|
||||
uuid: 11.1.0
|
||||
|
||||
'@temporalio/common@1.14.0':
|
||||
dependencies:
|
||||
'@temporalio/proto': 1.14.0
|
||||
long: 5.3.2
|
||||
ms: 3.0.0-canary.1
|
||||
nexus-rpc: 0.0.1
|
||||
proto3-json-serializer: 2.0.2
|
||||
|
||||
'@temporalio/core-bridge@1.14.0':
|
||||
dependencies:
|
||||
'@grpc/grpc-js': 1.14.3
|
||||
'@temporalio/common': 1.14.0
|
||||
arg: 5.0.2
|
||||
cargo-cp-artifact: 0.1.9
|
||||
which: 4.0.0
|
||||
|
||||
'@temporalio/nexus@1.14.0':
|
||||
dependencies:
|
||||
'@temporalio/client': 1.14.0
|
||||
'@temporalio/common': 1.14.0
|
||||
'@temporalio/proto': 1.14.0
|
||||
long: 5.3.2
|
||||
nexus-rpc: 0.0.1
|
||||
|
||||
'@temporalio/proto@1.14.0':
|
||||
dependencies:
|
||||
long: 5.3.2
|
||||
protobufjs: 7.5.4
|
||||
|
||||
'@temporalio/worker@1.14.0(@swc/helpers@0.5.13)(esbuild@0.25.12)':
|
||||
dependencies:
|
||||
'@grpc/grpc-js': 1.14.3
|
||||
'@swc/core': 1.5.7(@swc/helpers@0.5.13)
|
||||
'@temporalio/activity': 1.14.0
|
||||
'@temporalio/client': 1.14.0
|
||||
'@temporalio/common': 1.14.0
|
||||
'@temporalio/core-bridge': 1.14.0
|
||||
'@temporalio/nexus': 1.14.0
|
||||
'@temporalio/proto': 1.14.0
|
||||
'@temporalio/workflow': 1.14.0
|
||||
abort-controller: 3.0.0
|
||||
heap-js: 2.7.1
|
||||
memfs: 4.51.1
|
||||
nexus-rpc: 0.0.1
|
||||
proto3-json-serializer: 2.0.2
|
||||
protobufjs: 7.5.4
|
||||
rxjs: 7.8.2
|
||||
source-map: 0.7.6
|
||||
source-map-loader: 4.0.2(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12))
|
||||
supports-color: 8.1.1
|
||||
swc-loader: 0.2.6(@swc/core@1.5.7(@swc/helpers@0.5.13))(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12))
|
||||
unionfs: 4.6.0
|
||||
webpack: 5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)
|
||||
transitivePeerDependencies:
|
||||
- '@swc/helpers'
|
||||
- esbuild
|
||||
- uglify-js
|
||||
- webpack-cli
|
||||
|
||||
'@temporalio/workflow@1.14.0':
|
||||
dependencies:
|
||||
'@temporalio/common': 1.14.0
|
||||
'@temporalio/proto': 1.14.0
|
||||
nexus-rpc: 0.0.1
|
||||
|
||||
'@testing-library/dom@10.4.1':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.27.1
|
||||
|
|
@ -27145,6 +27450,10 @@ snapshots:
|
|||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn-import-phases@1.0.4(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||
dependencies:
|
||||
acorn: 8.15.0
|
||||
|
|
@ -27905,6 +28214,8 @@ snapshots:
|
|||
tslib: 2.8.1
|
||||
upper-case-first: 2.0.2
|
||||
|
||||
cargo-cp-artifact@0.1.9: {}
|
||||
|
||||
caseless@0.12.0: {}
|
||||
|
||||
cbor-sync@1.0.4: {}
|
||||
|
|
@ -29028,6 +29339,8 @@ snapshots:
|
|||
|
||||
es-module-lexer@1.7.0: {}
|
||||
|
||||
es-module-lexer@2.0.0: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
|
@ -30208,6 +30521,10 @@ snapshots:
|
|||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
||||
glob-to-regex.js@1.2.0(tslib@2.8.1):
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
glob-to-regexp@0.4.1: {}
|
||||
|
||||
glob@10.5.0:
|
||||
|
|
@ -30646,6 +30963,8 @@ snapshots:
|
|||
capital-case: 1.0.4
|
||||
tslib: 2.8.1
|
||||
|
||||
heap-js@2.7.1: {}
|
||||
|
||||
help-me@5.0.0: {}
|
||||
|
||||
hermes-compiler@0.14.0: {}
|
||||
|
|
@ -30803,6 +31122,8 @@ snapshots:
|
|||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
hyperdyperid@1.2.0: {}
|
||||
|
||||
i18n-iso-countries@7.14.0:
|
||||
dependencies:
|
||||
diacritics: 1.3.0
|
||||
|
|
@ -31255,6 +31576,8 @@ snapshots:
|
|||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
isexe@3.1.1: {}
|
||||
|
||||
iso-3166-1@2.1.1: {}
|
||||
|
||||
iso-datestring-validator@2.2.2: {}
|
||||
|
|
@ -32642,6 +32965,15 @@ snapshots:
|
|||
dependencies:
|
||||
fs-monkey: 1.1.0
|
||||
|
||||
memfs@4.51.1:
|
||||
dependencies:
|
||||
'@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1)
|
||||
'@jsonjoy.com/util': 1.9.0(tslib@2.8.1)
|
||||
glob-to-regex.js: 1.2.0(tslib@2.8.1)
|
||||
thingies: 2.5.0(tslib@2.8.1)
|
||||
tree-dump: 1.1.0(tslib@2.8.1)
|
||||
tslib: 2.8.1
|
||||
|
||||
memoize-one@5.2.1: {}
|
||||
|
||||
memoizerific@1.11.3:
|
||||
|
|
@ -33298,6 +33630,8 @@ snapshots:
|
|||
|
||||
ms@2.1.3: {}
|
||||
|
||||
ms@3.0.0-canary.1: {}
|
||||
|
||||
msgpackr-extract@3.0.3:
|
||||
dependencies:
|
||||
node-gyp-build-optional-packages: 5.2.2
|
||||
|
|
@ -33396,6 +33730,18 @@ snapshots:
|
|||
'@nestjs/common': 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
'@supercharge/request-ip': 1.2.0
|
||||
|
||||
nestjs-temporal-core@3.2.0(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@10.4.20)(@temporalio/client@1.14.0)(@temporalio/common@1.14.0)(@temporalio/worker@1.14.0(@swc/helpers@0.5.13)(esbuild@0.25.12))(@temporalio/workflow@1.14.0)(reflect-metadata@0.1.14)(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@nestjs/common': 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
'@nestjs/core': 10.4.20(@nestjs/common@10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/microservices@10.4.20)(@nestjs/platform-express@10.4.20)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
'@temporalio/client': 1.14.0
|
||||
'@temporalio/common': 1.14.0
|
||||
'@temporalio/worker': 1.14.0(@swc/helpers@0.5.13)(esbuild@0.25.12)
|
||||
'@temporalio/workflow': 1.14.0
|
||||
ms: 2.1.3
|
||||
reflect-metadata: 0.1.14
|
||||
rxjs: 7.8.2
|
||||
|
||||
netmask@2.0.2: {}
|
||||
|
||||
next-plausible@3.12.5(next@14.2.35(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
|
|
@ -33432,6 +33778,8 @@ snapshots:
|
|||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
nexus-rpc@0.0.1: {}
|
||||
|
||||
nice-grpc-client-middleware-retry@3.1.13:
|
||||
dependencies:
|
||||
abort-controller-x: 0.4.3
|
||||
|
|
@ -34524,6 +34872,10 @@ snapshots:
|
|||
|
||||
proto-list@1.2.4: {}
|
||||
|
||||
proto3-json-serializer@2.0.2:
|
||||
dependencies:
|
||||
protobufjs: 7.5.4
|
||||
|
||||
protobufjs@7.5.4:
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
|
|
@ -36055,6 +36407,12 @@ snapshots:
|
|||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map-loader@4.0.2(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)):
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
source-map-js: 1.2.1
|
||||
webpack: 5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)
|
||||
|
||||
source-map-support@0.5.13:
|
||||
dependencies:
|
||||
buffer-from: 1.1.2
|
||||
|
|
@ -36374,6 +36732,12 @@ snapshots:
|
|||
|
||||
swagger-ui-dist@5.17.14: {}
|
||||
|
||||
swc-loader@0.2.6(@swc/core@1.5.7(@swc/helpers@0.5.13))(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)):
|
||||
dependencies:
|
||||
'@swc/core': 1.5.7(@swc/helpers@0.5.13)
|
||||
'@swc/counter': 0.1.3
|
||||
webpack: 5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)
|
||||
|
||||
sweetalert2@11.4.8: {}
|
||||
|
||||
swr@2.3.8(react@18.3.1):
|
||||
|
|
@ -36449,6 +36813,18 @@ snapshots:
|
|||
dependencies:
|
||||
memoizerific: 1.11.3
|
||||
|
||||
terser-webpack-plugin@5.3.16(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 4.3.3
|
||||
serialize-javascript: 6.0.2
|
||||
terser: 5.44.1
|
||||
webpack: 5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)
|
||||
optionalDependencies:
|
||||
'@swc/core': 1.5.7(@swc/helpers@0.5.13)
|
||||
esbuild: 0.25.12
|
||||
|
||||
terser-webpack-plugin@5.3.16(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)(webpack@5.87.0(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
|
|
@ -36486,6 +36862,10 @@ snapshots:
|
|||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
|
||||
thingies@2.5.0(tslib@2.8.1):
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
thread-stream@0.15.2:
|
||||
dependencies:
|
||||
real-require: 0.1.0
|
||||
|
|
@ -36625,6 +37005,10 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
tree-dump@1.1.0(tslib@2.8.1):
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
tree-kill@1.2.2: {}
|
||||
|
||||
trim-lines@3.0.1: {}
|
||||
|
|
@ -36963,6 +37347,10 @@ snapshots:
|
|||
trough: 2.2.0
|
||||
vfile: 6.0.3
|
||||
|
||||
unionfs@4.6.0:
|
||||
dependencies:
|
||||
fs-monkey: 1.1.0
|
||||
|
||||
unist-util-filter@5.0.1:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
|
@ -37469,6 +37857,38 @@ snapshots:
|
|||
|
||||
webpack-virtual-modules@0.5.0: {}
|
||||
|
||||
webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12):
|
||||
dependencies:
|
||||
'@types/eslint-scope': 3.7.7
|
||||
'@types/estree': 1.0.8
|
||||
'@types/json-schema': 7.0.15
|
||||
'@webassemblyjs/ast': 1.14.1
|
||||
'@webassemblyjs/wasm-edit': 1.14.1
|
||||
'@webassemblyjs/wasm-parser': 1.14.1
|
||||
acorn: 8.15.0
|
||||
acorn-import-phases: 1.0.4(acorn@8.15.0)
|
||||
browserslist: 4.28.1
|
||||
chrome-trace-event: 1.0.4
|
||||
enhanced-resolve: 5.18.4
|
||||
es-module-lexer: 2.0.0
|
||||
eslint-scope: 5.1.1
|
||||
events: 3.3.0
|
||||
glob-to-regexp: 0.4.1
|
||||
graceful-fs: 4.2.11
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
loader-runner: 4.3.1
|
||||
mime-types: 2.1.35
|
||||
neo-async: 2.6.2
|
||||
schema-utils: 4.3.3
|
||||
tapable: 2.3.0
|
||||
terser-webpack-plugin: 5.3.16(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12)(webpack@5.104.1(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12))
|
||||
watchpack: 2.4.4
|
||||
webpack-sources: 3.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
- esbuild
|
||||
- uglify-js
|
||||
|
||||
webpack@5.87.0(@swc/core@1.5.7(@swc/helpers@0.5.13))(esbuild@0.25.12):
|
||||
dependencies:
|
||||
'@types/eslint-scope': 3.7.7
|
||||
|
|
@ -37585,6 +38005,10 @@ snapshots:
|
|||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
which@4.0.0:
|
||||
dependencies:
|
||||
isexe: 3.1.1
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"@gitroom/react/*": ["libraries/react-shared-libraries/src/*"],
|
||||
"@gitroom/plugins/*": ["libraries/plugins/src/*"],
|
||||
"@gitroom/workers/*": ["apps/workers/src/*"],
|
||||
"@gitroom/orchestrator/*": ["apps/orchestrator/src/*"],
|
||||
"@gitroom/extension/*": ["apps/extension/src/*"]
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue