Merge pull request #786 from gitroomhq/feat/carusel
LinkedIn post as carousel
This commit is contained in:
commit
9192cc4c85
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
|
|
@ -1,10 +1,40 @@
|
|||
import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider';
|
||||
export default withProvider(
|
||||
null,
|
||||
import { Checkbox } from '@gitroom/react/form/checkbox';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
|
||||
import { LinkedinDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/linkedin.dto';
|
||||
|
||||
const LinkedInSettings = () => {
|
||||
const t = useT();
|
||||
const { watch, register, formState, control } = useSettings();
|
||||
|
||||
return (
|
||||
<div className="mb-[20px]">
|
||||
<Checkbox
|
||||
variant="hollow"
|
||||
label={t('post_as_images_carousel', 'Post as images carousel')}
|
||||
{...register('post_as_images_carousel', {
|
||||
value: false,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default withProvider<LinkedinDto>(
|
||||
LinkedInSettings,
|
||||
undefined,
|
||||
undefined,
|
||||
async (posts) => {
|
||||
LinkedinDto,
|
||||
async (posts, vals) => {
|
||||
const [firstPost, ...restPosts] = posts;
|
||||
|
||||
if (
|
||||
vals.post_as_images_carousel &&
|
||||
(firstPost.length < 2 ||
|
||||
firstPost.some((p) => p.path.indexOf('mp4') > -1))
|
||||
) {
|
||||
return 'LinkedIn carousel can only be created with 2 or more images and no videos.';
|
||||
}
|
||||
|
||||
if (
|
||||
firstPost.length > 1 &&
|
||||
firstPost.some((p) => p.path.indexOf('mp4') > -1)
|
||||
|
|
|
|||
|
|
@ -487,3 +487,4 @@ checksums:
|
|||
start_7_days_free_trial: e9c42510c2cc750fabe704ebc0a9e768
|
||||
change_language: c798f65b78e23b2cf8fc29a1a24a182f
|
||||
that_a_wrap: 0ecf5b5a1fbac9c2653f2642baf5d4a5
|
||||
post_as_images_carousel: 2f82f0f6adbf03abfeec3389800d7232
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import { IsBoolean, IsOptional } from 'class-validator';
|
||||
|
||||
export class LinkedinDto {
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
post_as_images_carousel: boolean;
|
||||
}
|
||||
|
|
@ -11,6 +11,9 @@ import { readOrFetch } from '@gitroom/helpers/utils/read.or.fetch';
|
|||
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
|
||||
import { Integration } from '@prisma/client';
|
||||
import { PostPlug } from '@gitroom/helpers/decorators/post.plug';
|
||||
import { LinkedinDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/linkedin.dto';
|
||||
import imageToPDF from 'image-to-pdf';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
||||
identifier = 'linkedin';
|
||||
|
|
@ -199,13 +202,24 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
picture: any,
|
||||
type = 'personal' as 'company' | 'personal'
|
||||
) {
|
||||
// Determine the appropriate endpoint based on file type
|
||||
const isVideo = fileName.indexOf('mp4') > -1;
|
||||
const isPdf = fileName.toLowerCase().indexOf('pdf') > -1;
|
||||
|
||||
let endpoint: string;
|
||||
if (isVideo) {
|
||||
endpoint = 'videos';
|
||||
} else if (isPdf) {
|
||||
endpoint = 'documents';
|
||||
} else {
|
||||
endpoint = 'images';
|
||||
}
|
||||
|
||||
const {
|
||||
value: { uploadUrl, image, video, uploadInstructions, ...all },
|
||||
value: { uploadUrl, image, video, document, uploadInstructions, ...all },
|
||||
} = await (
|
||||
await this.fetch(
|
||||
`https://api.linkedin.com/v2/${
|
||||
fileName.indexOf('mp4') > -1 ? 'videos' : 'images'
|
||||
}?action=initializeUpload`,
|
||||
`https://api.linkedin.com/rest/${endpoint}?action=initializeUpload`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
@ -220,7 +234,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
type === 'personal'
|
||||
? `urn:li:person:${personId}`
|
||||
: `urn:li:organization:${personId}`,
|
||||
...(fileName.indexOf('mp4') > -1
|
||||
...(isVideo
|
||||
? {
|
||||
fileSizeBytes: picture.length,
|
||||
uploadCaptions: false,
|
||||
|
|
@ -234,7 +248,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
).json();
|
||||
|
||||
const sendUrlRequest = uploadInstructions?.[0]?.uploadUrl || uploadUrl;
|
||||
const finalOutput = video || image;
|
||||
const finalOutput = video || image || document;
|
||||
|
||||
const etags = [];
|
||||
for (let i = 0; i < picture.length; i += 1024 * 1024 * 2) {
|
||||
|
|
@ -244,8 +258,10 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'LinkedIn-Version': '202501',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
...(fileName.indexOf('mp4') > -1
|
||||
...(isVideo
|
||||
? { 'Content-Type': 'application/octet-stream' }
|
||||
: isPdf
|
||||
? { 'Content-Type': 'application/pdf' }
|
||||
: {}),
|
||||
},
|
||||
body: picture.slice(i, i + 1024 * 1024 * 2),
|
||||
|
|
@ -254,9 +270,9 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
etags.push(upload.headers.get('etag'));
|
||||
}
|
||||
|
||||
if (fileName.indexOf('mp4') > -1) {
|
||||
if (isVideo) {
|
||||
const a = await this.fetch(
|
||||
'https://api.linkedin.com/v2/videos?action=finalizeUpload',
|
||||
'https://api.linkedin.com/rest/videos?action=finalizeUpload',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
|
|
@ -314,147 +330,347 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
|
|||
return connectAll.join('');
|
||||
}
|
||||
|
||||
async post(
|
||||
id: string,
|
||||
private async convertImagesToPdfCarousel(
|
||||
postDetails: PostDetails<LinkedinDto>[],
|
||||
firstPost: PostDetails<LinkedinDto>
|
||||
): Promise<PostDetails<LinkedinDto>[]> {
|
||||
// Collect all images from all posts
|
||||
const allImages = postDetails.flatMap(
|
||||
(post) =>
|
||||
post.media?.filter(
|
||||
(media) =>
|
||||
media.url.toLowerCase().includes('.jpg') ||
|
||||
media.url.toLowerCase().includes('.jpeg') ||
|
||||
media.url.toLowerCase().includes('.png')
|
||||
) || []
|
||||
);
|
||||
|
||||
if (allImages.length === 0) {
|
||||
return postDetails;
|
||||
}
|
||||
|
||||
// Convert images to buffers and get dimensions
|
||||
const imageData = await Promise.all(
|
||||
allImages.map(async (media) => {
|
||||
const buffer = await readOrFetch(media.url);
|
||||
const image = sharp(buffer, {
|
||||
animated: lookup(media.url) === 'image/gif',
|
||||
});
|
||||
const metadata = await image.metadata();
|
||||
|
||||
return {
|
||||
buffer,
|
||||
width: metadata.width || 0,
|
||||
height: metadata.height || 0,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Use the dimensions of the first image for the PDF page size
|
||||
// You could also use the largest dimensions if you prefer
|
||||
const firstImageDimensions = imageData[0];
|
||||
const pageSize = [firstImageDimensions.width, firstImageDimensions.height];
|
||||
|
||||
// Convert images to PDF with exact image dimensions
|
||||
const pdfStream = imageToPDF(
|
||||
imageData.map((data) => data.buffer),
|
||||
pageSize
|
||||
);
|
||||
|
||||
// Convert stream to buffer
|
||||
const pdfBuffer = await this.streamToBuffer(pdfStream);
|
||||
|
||||
// Create a temporary file-like object for the PDF
|
||||
const pdfMedia = {
|
||||
url: 'carousel.pdf',
|
||||
buffer: pdfBuffer,
|
||||
};
|
||||
|
||||
// Return modified post details with PDF instead of images
|
||||
const modifiedFirstPost = {
|
||||
...firstPost,
|
||||
media: [pdfMedia] as any[],
|
||||
};
|
||||
|
||||
// Remove media from other posts since we're combining everything into one PDF
|
||||
const modifiedRestPosts = postDetails.slice(1).map((post) => ({
|
||||
...post,
|
||||
media: [] as any[],
|
||||
}));
|
||||
|
||||
return [modifiedFirstPost, ...modifiedRestPosts];
|
||||
}
|
||||
|
||||
private async streamToBuffer(stream: Readable): Promise<Buffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
stream.on('data', (chunk) => chunks.push(chunk));
|
||||
stream.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
stream.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
private async processMediaForPosts(
|
||||
postDetails: PostDetails<LinkedinDto>[],
|
||||
accessToken: string,
|
||||
postDetails: PostDetails[],
|
||||
integration: Integration,
|
||||
type = 'personal' as 'company' | 'personal'
|
||||
): Promise<PostResponse[]> {
|
||||
const [firstPost, ...restPosts] = postDetails;
|
||||
personId: string,
|
||||
type: 'company' | 'personal'
|
||||
): Promise<Record<string, string[]>> {
|
||||
const mediaUploads = await Promise.all(
|
||||
postDetails.flatMap(
|
||||
(post) =>
|
||||
post.media?.map(async (media) => {
|
||||
let mediaBuffer: Buffer;
|
||||
|
||||
// Check if media has a buffer (from PDF conversion)
|
||||
if (
|
||||
media &&
|
||||
typeof media === 'object' &&
|
||||
'buffer' in media &&
|
||||
Buffer.isBuffer(media.buffer)
|
||||
) {
|
||||
mediaBuffer = (media as any).buffer;
|
||||
} else {
|
||||
mediaBuffer = await this.prepareMediaBuffer(media.url);
|
||||
}
|
||||
|
||||
const uploadedMediaId = await this.uploadPicture(
|
||||
media.url,
|
||||
accessToken,
|
||||
personId,
|
||||
mediaBuffer,
|
||||
type
|
||||
);
|
||||
|
||||
const uploadAll = (
|
||||
await Promise.all(
|
||||
postDetails.flatMap((p) =>
|
||||
p?.media?.flatMap(async (m) => {
|
||||
return {
|
||||
id: await this.uploadPicture(
|
||||
m.url,
|
||||
accessToken,
|
||||
id,
|
||||
m.url.indexOf('mp4') > -1
|
||||
? Buffer.from(await readOrFetch(m.url))
|
||||
: await sharp(await readOrFetch(m.url), {
|
||||
animated: lookup(m.url) === 'image/gif',
|
||||
})
|
||||
.toFormat('jpeg')
|
||||
.resize({
|
||||
width: 1000,
|
||||
})
|
||||
.toBuffer(),
|
||||
type
|
||||
),
|
||||
postId: p.id,
|
||||
id: uploadedMediaId,
|
||||
postId: post.id,
|
||||
};
|
||||
})
|
||||
)
|
||||
}) || []
|
||||
)
|
||||
).reduce((acc, val) => {
|
||||
if (!val?.id) {
|
||||
return acc;
|
||||
}
|
||||
acc[val.postId] = acc[val.postId] || [];
|
||||
acc[val.postId].push(val.id);
|
||||
);
|
||||
|
||||
return mediaUploads.reduce((acc, upload) => {
|
||||
if (!upload?.id) return acc;
|
||||
|
||||
acc[upload.postId] = acc[upload.postId] || [];
|
||||
acc[upload.postId].push(upload.id);
|
||||
return acc;
|
||||
}, {} as Record<string, string[]>);
|
||||
}
|
||||
|
||||
const media_ids = (uploadAll[firstPost.id] || []).filter((f) => f);
|
||||
private async prepareMediaBuffer(mediaUrl: string): Promise<Buffer> {
|
||||
const isVideo = mediaUrl.indexOf('mp4') > -1;
|
||||
|
||||
const data = await this.fetch('https://api.linkedin.com/v2/posts', {
|
||||
if (isVideo) {
|
||||
return Buffer.from(await readOrFetch(mediaUrl));
|
||||
}
|
||||
|
||||
return await sharp(await readOrFetch(mediaUrl), {
|
||||
animated: lookup(mediaUrl) === 'image/gif',
|
||||
})
|
||||
.toFormat('jpeg')
|
||||
.resize({ width: 1000 })
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
private buildPostContent(isPdf: boolean, mediaIds: string[]) {
|
||||
if (mediaIds.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (mediaIds.length === 1) {
|
||||
return {
|
||||
content: {
|
||||
media: {
|
||||
...(isPdf ? { title: 'slides.pdf' } : {}),
|
||||
id: mediaIds[0],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
content: {
|
||||
multiImage: {
|
||||
images: mediaIds.map((id) => ({ id })),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private createLinkedInPostPayload(
|
||||
id: string,
|
||||
type: 'company' | 'personal',
|
||||
message: string,
|
||||
mediaIds: string[],
|
||||
isPdf: boolean
|
||||
) {
|
||||
const author =
|
||||
type === 'personal' ? `urn:li:person:${id}` : `urn:li:organization:${id}`;
|
||||
|
||||
return {
|
||||
author,
|
||||
commentary: this.fixText(message),
|
||||
visibility: 'PUBLIC',
|
||||
distribution: {
|
||||
feedDistribution: 'MAIN_FEED',
|
||||
targetEntities: [] as string[],
|
||||
thirdPartyDistributionChannels: [] as string[],
|
||||
},
|
||||
...this.buildPostContent(isPdf, mediaIds),
|
||||
lifecycleState: 'PUBLISHED',
|
||||
isReshareDisabledByAuthor: false,
|
||||
};
|
||||
}
|
||||
|
||||
private async createMainPost(
|
||||
id: string,
|
||||
accessToken: string,
|
||||
firstPost: PostDetails,
|
||||
mediaIds: string[],
|
||||
type: 'company' | 'personal',
|
||||
isPdf: boolean
|
||||
): Promise<string> {
|
||||
const postPayload = this.createLinkedInPostPayload(
|
||||
id,
|
||||
type,
|
||||
firstPost.message,
|
||||
mediaIds,
|
||||
isPdf
|
||||
);
|
||||
|
||||
const response = await this.fetch('https://api.linkedin.com/rest/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'LinkedIn-Version': '202501',
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
author:
|
||||
type === 'personal'
|
||||
? `urn:li:person:${id}`
|
||||
: `urn:li:organization:${id}`,
|
||||
commentary: this.fixText(firstPost.message),
|
||||
visibility: 'PUBLIC',
|
||||
distribution: {
|
||||
feedDistribution: 'MAIN_FEED',
|
||||
targetEntities: [],
|
||||
thirdPartyDistributionChannels: [],
|
||||
},
|
||||
...(media_ids.length > 0
|
||||
? {
|
||||
content: {
|
||||
...(media_ids.length === 0
|
||||
? {}
|
||||
: media_ids.length === 1
|
||||
? {
|
||||
media: {
|
||||
id: media_ids[0],
|
||||
},
|
||||
}
|
||||
: {
|
||||
multiImage: {
|
||||
images: media_ids.map((id) => ({
|
||||
id,
|
||||
})),
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
lifecycleState: 'PUBLISHED',
|
||||
isReshareDisabledByAuthor: false,
|
||||
}),
|
||||
body: JSON.stringify(postPayload),
|
||||
});
|
||||
|
||||
if (data.status !== 201 && data.status !== 200) {
|
||||
if (response.status !== 201 && response.status !== 200) {
|
||||
throw new Error('Error posting to LinkedIn');
|
||||
}
|
||||
|
||||
const topPostId = data.headers.get('x-restli-id')!;
|
||||
return response.headers.get('x-restli-id')!;
|
||||
}
|
||||
|
||||
const ids = [
|
||||
private async createCommentPost(
|
||||
id: string,
|
||||
accessToken: string,
|
||||
post: PostDetails,
|
||||
parentPostId: string,
|
||||
type: 'company' | 'personal'
|
||||
): Promise<string> {
|
||||
const actor =
|
||||
type === 'personal' ? `urn:li:person:${id}` : `urn:li:organization:${id}`;
|
||||
|
||||
const response = await this.fetch(
|
||||
`https://api.linkedin.com/v2/socialActions/${decodeURIComponent(
|
||||
parentPostId
|
||||
)}/comments`,
|
||||
{
|
||||
status: 'posted',
|
||||
postId: topPostId,
|
||||
id: firstPost.id,
|
||||
releaseURL: `https://www.linkedin.com/feed/update/${topPostId}`,
|
||||
},
|
||||
];
|
||||
for (const post of restPosts) {
|
||||
const { object } = await (
|
||||
await this.fetch(
|
||||
`https://api.linkedin.com/v2/socialActions/${decodeURIComponent(
|
||||
topPostId
|
||||
)}/comments`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
actor:
|
||||
type === 'personal'
|
||||
? `urn:li:person:${id}`
|
||||
: `urn:li:organization:${id}`,
|
||||
object: topPostId,
|
||||
message: {
|
||||
text: this.fixText(post.message),
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
).json();
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
actor,
|
||||
object: parentPostId,
|
||||
message: {
|
||||
text: this.fixText(post.message),
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
ids.push({
|
||||
status: 'posted',
|
||||
postId: object,
|
||||
id: post.id,
|
||||
releaseURL: `https://www.linkedin.com/embed/feed/update/${object}`,
|
||||
});
|
||||
const { object } = await response.json();
|
||||
return object;
|
||||
}
|
||||
|
||||
private createPostResponse(
|
||||
postId: string,
|
||||
originalPostId: string,
|
||||
isMainPost: boolean = false
|
||||
): PostResponse {
|
||||
const baseUrl = isMainPost
|
||||
? 'https://www.linkedin.com/feed/update/'
|
||||
: 'https://www.linkedin.com/embed/feed/update/';
|
||||
|
||||
return {
|
||||
status: 'posted',
|
||||
postId,
|
||||
id: originalPostId,
|
||||
releaseURL: `${baseUrl}${postId}`,
|
||||
};
|
||||
}
|
||||
|
||||
async post(
|
||||
id: string,
|
||||
accessToken: string,
|
||||
postDetails: PostDetails<LinkedinDto>[],
|
||||
integration: Integration,
|
||||
type = 'personal' as 'company' | 'personal'
|
||||
): Promise<PostResponse[]> {
|
||||
let processedPostDetails = postDetails;
|
||||
const [firstPost] = postDetails;
|
||||
|
||||
// Check if we should convert images to PDF carousel
|
||||
if (firstPost.settings?.post_as_images_carousel) {
|
||||
processedPostDetails = await this.convertImagesToPdfCarousel(
|
||||
postDetails,
|
||||
firstPost
|
||||
);
|
||||
}
|
||||
|
||||
return ids;
|
||||
const [processedFirstPost, ...restPosts] = processedPostDetails;
|
||||
|
||||
// Process and upload media for all posts
|
||||
const uploadedMedia = await this.processMediaForPosts(
|
||||
processedPostDetails,
|
||||
accessToken,
|
||||
id,
|
||||
type
|
||||
);
|
||||
|
||||
// Get media IDs for the main post
|
||||
const mainPostMediaIds = (
|
||||
uploadedMedia[processedFirstPost.id] || []
|
||||
).filter(Boolean);
|
||||
|
||||
// Create the main LinkedIn post
|
||||
const mainPostId = await this.createMainPost(
|
||||
id,
|
||||
accessToken,
|
||||
processedFirstPost,
|
||||
mainPostMediaIds,
|
||||
type,
|
||||
!!firstPost.settings?.post_as_images_carousel
|
||||
);
|
||||
|
||||
// Build response array starting with main post
|
||||
const responses: PostResponse[] = [
|
||||
this.createPostResponse(mainPostId, processedFirstPost.id, true),
|
||||
];
|
||||
|
||||
// Create comment posts for remaining posts
|
||||
for (const post of restPosts) {
|
||||
const commentPostId = await this.createCommentPost(
|
||||
id,
|
||||
accessToken,
|
||||
post,
|
||||
mainPostId,
|
||||
type
|
||||
);
|
||||
|
||||
responses.push(this.createPostResponse(commentPostId, post.id, false));
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
@PostPlug({
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 يومًا",
|
||||
"start_7_days_free_trial": "ابدأ تجربة مجانية لمدة 7 أيام",
|
||||
"change_language": "تغيير اللغة",
|
||||
"that_a_wrap": "انتهينا!\n\nإذا أعجبك هذا التسلسل:\n\n1. تابعني على @{{username}} للمزيد من هذه المواضيع\n2. أعد تغريد التغريدة أدناه لمشاركة هذا التسلسل مع جمهورك\n"
|
||||
"that_a_wrap": "انتهينا!\n\nإذا أعجبك هذا التسلسل:\n\n1. تابعني على @{{username}} للمزيد من هذه المواضيع\n2. أعد تغريد التغريدة أدناه لمشاركة هذا التسلسل مع جمهورك\n",
|
||||
"post_as_images_carousel": "انشر كعرض شرائح للصور"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "৯০ দিন",
|
||||
"start_7_days_free_trial": "৭ দিনের বিনামূল্যে ট্রায়াল শুরু করুন",
|
||||
"change_language": "ভাষা পরিবর্তন করুন",
|
||||
"that_a_wrap": "এটাই শেষ!\n\nযদি আপনি এই থ্রেডটি উপভোগ করে থাকেন:\n\n১. আরও এমন পোস্টের জন্য আমাকে @{{username}} ফলো করুন\n২. আপনার অডিয়েন্সের সাথে এই থ্রেডটি শেয়ার করতে নিচের টুইটটি রিটুইট করুন\n"
|
||||
"that_a_wrap": "এটাই শেষ!\n\nযদি আপনি এই থ্রেডটি উপভোগ করে থাকেন:\n\n১. আরও এমন পোস্টের জন্য আমাকে @{{username}} ফলো করুন\n২. আপনার অডিয়েন্সের সাথে এই থ্রেডটি শেয়ার করতে নিচের টুইটটি রিটুইট করুন\n",
|
||||
"post_as_images_carousel": "ছবির ক্যারোসেল হিসেবে পোস্ট করুন"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 Tage",
|
||||
"start_7_days_free_trial": "7-tägige kostenlose Testversion starten",
|
||||
"change_language": "Sprache ändern",
|
||||
"that_a_wrap": "Das war's!\n\nWenn dir dieser Thread gefallen hat:\n\n1. Folge mir @{{username}} für mehr davon\n2. Retweete den untenstehenden Tweet, um diesen Thread mit deinem Publikum zu teilen\n"
|
||||
"that_a_wrap": "Das war's!\n\nWenn dir dieser Thread gefallen hat:\n\n1. Folge mir @{{username}} für mehr davon\n2. Retweete den untenstehenden Tweet, um diesen Thread mit deinem Publikum zu teilen\n",
|
||||
"post_as_images_carousel": "Als Bilderkarussell posten"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 Days",
|
||||
"start_7_days_free_trial": "Start 7 days free trial",
|
||||
"change_language": "Change Language",
|
||||
"that_a_wrap": "That's a wrap!\n\nIf you enjoyed this thread:\n\n1. Follow me @{{username}} for more of these\n2. RT the tweet below to share this thread with your audience\n"
|
||||
"that_a_wrap": "That's a wrap!\n\nIf you enjoyed this thread:\n\n1. Follow me @{{username}} for more of these\n2. RT the tweet below to share this thread with your audience\n",
|
||||
"post_as_images_carousel": "Post as images carousel"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 días",
|
||||
"start_7_days_free_trial": "Comienza la prueba gratuita de 7 días",
|
||||
"change_language": "Cambiar idioma",
|
||||
"that_a_wrap": "¡Eso es todo!\n\nSi te gustó este hilo:\n\n1. Sígueme en @{{username}} para más contenido como este\n2. Haz RT al tuit de abajo para compartir este hilo con tu audiencia\n"
|
||||
"that_a_wrap": "¡Eso es todo!\n\nSi te gustó este hilo:\n\n1. Sígueme en @{{username}} para más contenido como este\n2. Haz RT al tuit de abajo para compartir este hilo con tu audiencia\n",
|
||||
"post_as_images_carousel": "Publicar como carrusel de imágenes"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 jours",
|
||||
"start_7_days_free_trial": "Commencez l’essai gratuit de 7 jours",
|
||||
"change_language": "Changer de langue",
|
||||
"that_a_wrap": "C'est terminé !\n\nSi vous avez aimé ce fil :\n\n1. Suivez-moi @{{username}} pour en voir d'autres\n2. Retweetez le tweet ci-dessous pour partager ce fil avec votre audience\n"
|
||||
"that_a_wrap": "C'est terminé !\n\nSi vous avez aimé ce fil :\n\n1. Suivez-moi @{{username}} pour en voir d'autres\n2. Retweetez le tweet ci-dessous pour partager ce fil avec votre audience\n",
|
||||
"post_as_images_carousel": "Publier en carrousel d’images"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 ימים",
|
||||
"start_7_days_free_trial": "התחל תקופת ניסיון חינם ל-7 ימים",
|
||||
"change_language": "שנה שפה",
|
||||
"that_a_wrap": "זה הסוף!\n\nאם נהנית מהשרשור הזה:\n\n1. עקוב אחרי @{{username}} לעוד תכנים כאלה\n2. רטווט את הציוץ למטה כדי לשתף את השרשור עם הקהל שלך\n"
|
||||
"that_a_wrap": "זה הסוף!\n\nאם נהנית מהשרשור הזה:\n\n1. עקוב אחרי @{{username}} לעוד תכנים כאלה\n2. רטווט את הציוץ למטה כדי לשתף את השרשור עם הקהל שלך\n",
|
||||
"post_as_images_carousel": "פרסם כתמונות בגלריה"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 giorni",
|
||||
"start_7_days_free_trial": "Inizia la prova gratuita di 7 giorni",
|
||||
"change_language": "Cambia lingua",
|
||||
"that_a_wrap": "È tutto!\n\nSe ti è piaciuto questo thread:\n\n1. Seguimi su @{{username}} per altri contenuti come questo\n2. Ritwitta il tweet qui sotto per condividere questo thread con il tuo pubblico\n"
|
||||
"that_a_wrap": "È tutto!\n\nSe ti è piaciuto questo thread:\n\n1. Seguimi su @{{username}} per altri contenuti come questo\n2. Ritwitta il tweet qui sotto per condividere questo thread con il tuo pubblico\n",
|
||||
"post_as_images_carousel": "Pubblica come carosello di immagini"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90日間",
|
||||
"start_7_days_free_trial": "7日間の無料トライアルを開始",
|
||||
"change_language": "言語を変更",
|
||||
"that_a_wrap": "以上で終了です!\n\nこのスレッドを楽しんでいただけたなら:\n\n1. @{{username}} をフォローして、さらに多くの投稿をご覧ください\n2. 下のツイートをリツイートして、このスレッドをあなたのフォロワーと共有してください\n"
|
||||
"that_a_wrap": "以上で終了です!\n\nこのスレッドを楽しんでいただけたなら:\n\n1. @{{username}} をフォローして、さらに多くの投稿をご覧ください\n2. 下のツイートをリツイートして、このスレッドをあなたのフォロワーと共有してください\n",
|
||||
"post_as_images_carousel": "画像カルーセルとして投稿"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90일",
|
||||
"start_7_days_free_trial": "7일 무료 체험 시작하기",
|
||||
"change_language": "언어 변경",
|
||||
"that_a_wrap": "여기까지입니다!\n\n이 스레드가 유익하셨다면:\n\n1. 더 많은 정보를 원하시면 @{{username}}를 팔로우하세요\n2. 아래 트윗을 리트윗해서 이 스레드를 여러분의 팔로워들과 공유하세요\n"
|
||||
"that_a_wrap": "여기까지입니다!\n\n이 스레드가 유익하셨다면:\n\n1. 더 많은 정보를 원하시면 @{{username}}를 팔로우하세요\n2. 아래 트윗을 리트윗해서 이 스레드를 여러분의 팔로워들과 공유하세요\n",
|
||||
"post_as_images_carousel": "이미지 캐러셀로 게시"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 Dias",
|
||||
"start_7_days_free_trial": "Comece o teste gratuito de 7 dias",
|
||||
"change_language": "Mudar idioma",
|
||||
"that_a_wrap": "É isso aí!\n\nSe você gostou deste fio:\n\n1. Siga-me @{{username}} para ver mais conteúdos como este\n2. Dê RT no tweet abaixo para compartilhar este fio com seu público\n"
|
||||
"that_a_wrap": "É isso aí!\n\nSe você gostou deste fio:\n\n1. Siga-me @{{username}} para ver mais conteúdos como este\n2. Dê RT no tweet abaixo para compartilhar este fio com seu público\n",
|
||||
"post_as_images_carousel": "Publicar como carrossel de imagens"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 дней",
|
||||
"start_7_days_free_trial": "Начать 7-дневную бесплатную пробную версию",
|
||||
"change_language": "Сменить язык",
|
||||
"that_a_wrap": "На этом всё!\n\nЕсли вам понравилась эта серия:\n\n1. Подпишитесь на меня @{{username}}, чтобы не пропустить новые посты\n2. Ретвитните твит ниже, чтобы поделиться этой серией со своей аудиторией\n"
|
||||
"that_a_wrap": "На этом всё!\n\nЕсли вам понравилась эта серия:\n\n1. Подпишитесь на меня @{{username}}, чтобы не пропустить новые посты\n2. Ретвитните твит ниже, чтобы поделиться этой серией со своей аудиторией\n",
|
||||
"post_as_images_carousel": "Опубликовать как карусель изображений"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 Gün",
|
||||
"start_7_days_free_trial": "7 gün ücretsiz denemeyi başlat",
|
||||
"change_language": "Dili Değiştir",
|
||||
"that_a_wrap": "Bu iş burada bitti!\n\nEğer bu diziyi beğendiyseniz:\n\n1. Daha fazlası için beni @{{username}} hesabından takip edin\n2. Aşağıdaki tweet'i RT'leyerek bu diziyi kendi kitlenizle paylaşın\n"
|
||||
"that_a_wrap": "Bu iş burada bitti!\n\nEğer bu diziyi beğendiyseniz:\n\n1. Daha fazlası için beni @{{username}} hesabından takip edin\n2. Aşağıdaki tweet'i RT'leyerek bu diziyi kendi kitlenizle paylaşın\n",
|
||||
"post_as_images_carousel": "Görselleri kaydırmalı gönder olarak paylaş"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90 ngày",
|
||||
"start_7_days_free_trial": "Bắt đầu dùng thử miễn phí 7 ngày",
|
||||
"change_language": "Thay đổi ngôn ngữ",
|
||||
"that_a_wrap": "Kết thúc rồi!\n\nNếu bạn thích chuỗi bài này:\n\n1. Hãy theo dõi tôi @{{username}} để xem thêm nhiều nội dung như vậy\n2. Retweet bài bên dưới để chia sẻ chuỗi này với mọi người\n"
|
||||
"that_a_wrap": "Kết thúc rồi!\n\nNếu bạn thích chuỗi bài này:\n\n1. Hãy theo dõi tôi @{{username}} để xem thêm nhiều nội dung như vậy\n2. Retweet bài bên dưới để chia sẻ chuỗi này với mọi người\n",
|
||||
"post_as_images_carousel": "Đăng dưới dạng băng chuyền hình ảnh"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,5 +482,6 @@
|
|||
"90_days": "90天",
|
||||
"start_7_days_free_trial": "开始7天免费试用",
|
||||
"change_language": "切换语言",
|
||||
"that_a_wrap": "本帖到此结束!\n\n如果你喜欢这个话题:\n\n1. 关注我 @{{username}},获取更多类似内容\n2. 转发下方推文,与更多人分享本帖\n"
|
||||
"that_a_wrap": "本帖到此结束!\n\n如果你喜欢这个话题:\n\n1. 关注我 @{{username}},获取更多类似内容\n2. 转发下方推文,与更多人分享本帖\n",
|
||||
"post_as_images_carousel": "以图片轮播的形式发布"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
"i18next": "^25.2.1",
|
||||
"i18next-browser-languagedetector": "^8.1.0",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"image-to-pdf": "^3.0.2",
|
||||
"ioredis": "^5.3.2",
|
||||
"json-to-graphql-query": "^2.2.5",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
|
|
|
|||
178
pnpm-lock.yaml
178
pnpm-lock.yaml
|
|
@ -324,6 +324,9 @@ importers:
|
|||
i18next-resources-to-backend:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
image-to-pdf:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
ioredis:
|
||||
specifier: ^5.3.2
|
||||
version: 5.6.1
|
||||
|
|
@ -5552,6 +5555,9 @@ packages:
|
|||
'@swc/counter@0.1.3':
|
||||
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
|
||||
|
||||
'@swc/helpers@0.3.17':
|
||||
resolution: {integrity: sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==}
|
||||
|
||||
'@swc/helpers@0.5.13':
|
||||
resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==}
|
||||
|
||||
|
|
@ -7182,6 +7188,10 @@ packages:
|
|||
base-x@5.0.1:
|
||||
resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==}
|
||||
|
||||
base64-js@0.0.8:
|
||||
resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
|
|
@ -7290,6 +7300,9 @@ packages:
|
|||
brorand@1.1.0:
|
||||
resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==}
|
||||
|
||||
brotli@1.3.3:
|
||||
resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==}
|
||||
|
||||
browserify-aes@1.2.0:
|
||||
resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==}
|
||||
|
||||
|
|
@ -8202,6 +8215,10 @@ packages:
|
|||
resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
deep-equal@2.2.3:
|
||||
resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
|
|
@ -8318,6 +8335,9 @@ packages:
|
|||
devlop@1.1.0:
|
||||
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
|
||||
|
||||
dfa@1.2.0:
|
||||
resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==}
|
||||
|
||||
diacritics@1.3.0:
|
||||
resolution: {integrity: sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==}
|
||||
|
||||
|
|
@ -8555,6 +8575,9 @@ packages:
|
|||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-get-iterator@1.1.3:
|
||||
resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
|
||||
|
||||
es-iterator-helpers@1.2.1:
|
||||
resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -9137,6 +9160,9 @@ packages:
|
|||
debug:
|
||||
optional: true
|
||||
|
||||
fontkit@1.9.0:
|
||||
resolution: {integrity: sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==}
|
||||
|
||||
for-each@0.3.5:
|
||||
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -9845,6 +9871,9 @@ packages:
|
|||
engines: {node: '>=16.x'}
|
||||
hasBin: true
|
||||
|
||||
image-to-pdf@3.0.2:
|
||||
resolution: {integrity: sha512-6/IQCt4f384zjQ1w8P7FHIN/tF0mau8RbAIydT/+wyfZ1RAb8E2fiKe9t/k0V880h0d3zRpw9Q1bM5AIgVL/4g==}
|
||||
|
||||
immer@9.0.21:
|
||||
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
|
||||
|
||||
|
|
@ -10453,6 +10482,9 @@ packages:
|
|||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
jpeg-exif@1.1.4:
|
||||
resolution: {integrity: sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==}
|
||||
|
||||
js-base64@3.7.7:
|
||||
resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
|
||||
|
||||
|
|
@ -10932,6 +10964,9 @@ packages:
|
|||
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
linebreak@1.1.0:
|
||||
resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==}
|
||||
|
||||
lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
|
|
@ -11719,10 +11754,12 @@ packages:
|
|||
multer@1.4.4-lts.1:
|
||||
resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
deprecated: Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.
|
||||
|
||||
multer@1.4.5-lts.2:
|
||||
resolution: {integrity: sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
deprecated: Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.
|
||||
|
||||
multicast-dns@7.2.5:
|
||||
resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==}
|
||||
|
|
@ -12248,6 +12285,9 @@ packages:
|
|||
package-json-from-dist@1.0.1:
|
||||
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
|
||||
|
||||
pako@0.2.9:
|
||||
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
||||
|
||||
param-case@3.0.4:
|
||||
resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
|
||||
|
||||
|
|
@ -12370,6 +12410,9 @@ packages:
|
|||
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
pdfkit@0.15.2:
|
||||
resolution: {integrity: sha512-s3GjpdBFSCaeDSX/v73MI5UsPqH1kjKut2AXCgxQ5OH10lPVOu5q5vLAG0OCpz/EYqKsTSw1WHpENqMvp43RKg==}
|
||||
|
||||
peberminta@0.9.0:
|
||||
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
|
||||
|
||||
|
|
@ -12468,6 +12511,9 @@ packages:
|
|||
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
png-js@1.0.0:
|
||||
resolution: {integrity: sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==}
|
||||
|
||||
pngjs@5.0.0:
|
||||
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
|
@ -13508,6 +13554,9 @@ packages:
|
|||
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
restructure@2.0.1:
|
||||
resolution: {integrity: sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==}
|
||||
|
||||
retry-axios@2.6.0:
|
||||
resolution: {integrity: sha512-pOLi+Gdll3JekwuFjXO3fTq+L9lzMQGcSq7M5gIjExcl3Gu1hd4XXuf5o3+LuSBsaULQH7DiNbsqPd1chVpQGQ==}
|
||||
engines: {node: '>=10.7.0'}
|
||||
|
|
@ -14038,6 +14087,10 @@ packages:
|
|||
resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
stop-iteration-iterator@1.1.0:
|
||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
store2@2.14.4:
|
||||
resolution: {integrity: sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw==}
|
||||
|
||||
|
|
@ -14407,6 +14460,9 @@ packages:
|
|||
tiny-case@1.0.3:
|
||||
resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
|
||||
|
||||
tiny-inflate@1.0.3:
|
||||
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
|
||||
|
||||
tiny-invariant@1.0.6:
|
||||
resolution: {integrity: sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==}
|
||||
|
||||
|
|
@ -14813,10 +14869,16 @@ packages:
|
|||
resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
unicode-properties@1.4.1:
|
||||
resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
|
||||
|
||||
unicode-property-aliases-ecmascript@2.1.0:
|
||||
resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
unicode-trie@2.0.0:
|
||||
resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
|
||||
|
||||
unidragger@3.0.1:
|
||||
resolution: {integrity: sha512-RngbGSwBFmqGBWjkaH+yB677uzR95blSQyxq6hYbrQCejH3Mx1nm8DVOuh3M9k2fQyTstWUG5qlgCnNqV/9jVw==}
|
||||
|
||||
|
|
@ -19540,6 +19602,21 @@ snapshots:
|
|||
- typescript
|
||||
- verdaccio
|
||||
|
||||
'@nrwl/js@19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@nx/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4)
|
||||
transitivePeerDependencies:
|
||||
- '@babel/traverse'
|
||||
- '@swc-node/register'
|
||||
- '@swc/core'
|
||||
- '@swc/wasm'
|
||||
- '@types/node'
|
||||
- debug
|
||||
- nx
|
||||
- supports-color
|
||||
- typescript
|
||||
- verdaccio
|
||||
|
||||
'@nrwl/nest@19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(chokidar@3.5.3)(eslint@8.57.0)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.5.4))(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@nx/nest': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(chokidar@3.5.3)(eslint@8.57.0)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(ts-node@10.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.5.4))(typescript@5.5.4)
|
||||
|
|
@ -19886,7 +19963,7 @@ snapshots:
|
|||
'@babel/preset-env': 7.27.1(@babel/core@7.27.1)
|
||||
'@babel/preset-typescript': 7.27.1(@babel/core@7.27.1)
|
||||
'@babel/runtime': 7.27.1
|
||||
'@nrwl/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.4.5)
|
||||
'@nrwl/js': 19.7.2(@babel/traverse@7.27.1)(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))(typescript@5.5.4)
|
||||
'@nx/devkit': 19.7.2(nx@19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13)))
|
||||
'@nx/workspace': 19.7.2(@swc-node/register@1.9.2(@swc/core@1.5.7(@swc/helpers@0.5.13))(@swc/types@0.1.7)(typescript@5.5.4))(@swc/core@1.5.7(@swc/helpers@0.5.13))
|
||||
babel-plugin-const-enum: 1.2.0(@babel/core@7.27.1)
|
||||
|
|
@ -22453,6 +22530,10 @@ snapshots:
|
|||
|
||||
'@swc/counter@0.1.3': {}
|
||||
|
||||
'@swc/helpers@0.3.17':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@swc/helpers@0.5.13':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
|
@ -24777,6 +24858,8 @@ snapshots:
|
|||
|
||||
base-x@5.0.1: {}
|
||||
|
||||
base64-js@0.0.8: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
base64url@3.0.1: {}
|
||||
|
|
@ -24909,6 +24992,10 @@ snapshots:
|
|||
|
||||
brorand@1.1.0: {}
|
||||
|
||||
brotli@1.3.3:
|
||||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
|
||||
browserify-aes@1.2.0:
|
||||
dependencies:
|
||||
buffer-xor: 1.0.3
|
||||
|
|
@ -25940,6 +26027,27 @@ snapshots:
|
|||
object-keys: 1.1.1
|
||||
regexp.prototype.flags: 1.5.4
|
||||
|
||||
deep-equal@2.2.3:
|
||||
dependencies:
|
||||
array-buffer-byte-length: 1.0.2
|
||||
call-bind: 1.0.8
|
||||
es-get-iterator: 1.1.3
|
||||
get-intrinsic: 1.3.0
|
||||
is-arguments: 1.2.0
|
||||
is-array-buffer: 3.0.5
|
||||
is-date-object: 1.1.0
|
||||
is-regex: 1.2.1
|
||||
is-shared-array-buffer: 1.0.4
|
||||
isarray: 2.0.5
|
||||
object-is: 1.1.6
|
||||
object-keys: 1.1.1
|
||||
object.assign: 4.1.7
|
||||
regexp.prototype.flags: 1.5.4
|
||||
side-channel: 1.1.0
|
||||
which-boxed-primitive: 1.1.1
|
||||
which-collection: 1.0.2
|
||||
which-typed-array: 1.1.19
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
deepmerge@2.2.1: {}
|
||||
|
|
@ -26031,6 +26139,8 @@ snapshots:
|
|||
dependencies:
|
||||
dequal: 2.0.3
|
||||
|
||||
dfa@1.2.0: {}
|
||||
|
||||
diacritics@1.3.0: {}
|
||||
|
||||
didyoumean@1.2.2: {}
|
||||
|
|
@ -26320,6 +26430,18 @@ snapshots:
|
|||
|
||||
es-errors@1.3.0: {}
|
||||
|
||||
es-get-iterator@1.1.3:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
get-intrinsic: 1.3.0
|
||||
has-symbols: 1.1.0
|
||||
is-arguments: 1.2.0
|
||||
is-map: 2.0.3
|
||||
is-set: 2.0.3
|
||||
is-string: 1.1.1
|
||||
isarray: 2.0.5
|
||||
stop-iteration-iterator: 1.1.0
|
||||
|
||||
es-iterator-helpers@1.2.1:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
|
|
@ -27174,6 +27296,18 @@ snapshots:
|
|||
optionalDependencies:
|
||||
debug: 4.4.0(supports-color@5.5.0)
|
||||
|
||||
fontkit@1.9.0:
|
||||
dependencies:
|
||||
'@swc/helpers': 0.3.17
|
||||
brotli: 1.3.3
|
||||
clone: 2.1.2
|
||||
deep-equal: 2.2.3
|
||||
dfa: 1.2.0
|
||||
restructure: 2.0.1
|
||||
tiny-inflate: 1.0.3
|
||||
unicode-properties: 1.4.1
|
||||
unicode-trie: 2.0.0
|
||||
|
||||
for-each@0.3.5:
|
||||
dependencies:
|
||||
is-callable: 1.2.7
|
||||
|
|
@ -28190,6 +28324,10 @@ snapshots:
|
|||
dependencies:
|
||||
queue: 6.0.2
|
||||
|
||||
image-to-pdf@3.0.2:
|
||||
dependencies:
|
||||
pdfkit: 0.15.2
|
||||
|
||||
immer@9.0.21: {}
|
||||
|
||||
immutable@4.3.7: {}
|
||||
|
|
@ -29026,6 +29164,8 @@ snapshots:
|
|||
|
||||
joycon@3.1.1: {}
|
||||
|
||||
jpeg-exif@1.1.4: {}
|
||||
|
||||
js-base64@3.7.7: {}
|
||||
|
||||
js-beautify@1.15.4:
|
||||
|
|
@ -29516,6 +29656,11 @@ snapshots:
|
|||
|
||||
lilconfig@3.1.3: {}
|
||||
|
||||
linebreak@1.1.0:
|
||||
dependencies:
|
||||
base64-js: 0.0.8
|
||||
unicode-trie: 2.0.0
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
lines-and-columns@2.0.3: {}
|
||||
|
|
@ -31399,6 +31544,8 @@ snapshots:
|
|||
|
||||
package-json-from-dist@1.0.1: {}
|
||||
|
||||
pako@0.2.9: {}
|
||||
|
||||
param-case@3.0.4:
|
||||
dependencies:
|
||||
dot-case: 3.0.4
|
||||
|
|
@ -31529,6 +31676,14 @@ snapshots:
|
|||
safe-buffer: 5.2.1
|
||||
sha.js: 2.4.11
|
||||
|
||||
pdfkit@0.15.2:
|
||||
dependencies:
|
||||
crypto-js: 4.2.0
|
||||
fontkit: 1.9.0
|
||||
jpeg-exif: 1.1.4
|
||||
linebreak: 1.1.0
|
||||
png-js: 1.0.0
|
||||
|
||||
peberminta@0.9.0: {}
|
||||
|
||||
peek-readable@4.1.0: {}
|
||||
|
|
@ -31636,6 +31791,8 @@ snapshots:
|
|||
|
||||
pluralize@8.0.0: {}
|
||||
|
||||
png-js@1.0.0: {}
|
||||
|
||||
pngjs@5.0.0: {}
|
||||
|
||||
polotno@2.22.2(@types/react@18.3.1)(@types/sortablejs@1.15.8)(react-dom@18.3.1(react@18.3.1))(react-native@0.79.2(@babel/core@7.27.1)(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1):
|
||||
|
|
@ -32890,6 +33047,8 @@ snapshots:
|
|||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
|
||||
restructure@2.0.1: {}
|
||||
|
||||
retry-axios@2.6.0(axios@1.9.0):
|
||||
dependencies:
|
||||
axios: 1.9.0(debug@4.4.0)
|
||||
|
|
@ -33539,6 +33698,11 @@ snapshots:
|
|||
|
||||
stealthy-require@1.1.1: {}
|
||||
|
||||
stop-iteration-iterator@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
internal-slot: 1.1.0
|
||||
|
||||
store2@2.14.4: {}
|
||||
|
||||
storybook-source-link@4.0.1(@storybook/addons@7.6.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
|
|
@ -33966,6 +34130,8 @@ snapshots:
|
|||
|
||||
tiny-case@1.0.3: {}
|
||||
|
||||
tiny-inflate@1.0.3: {}
|
||||
|
||||
tiny-invariant@1.0.6: {}
|
||||
|
||||
tiny-invariant@1.2.0: {}
|
||||
|
|
@ -34362,8 +34528,18 @@ snapshots:
|
|||
|
||||
unicode-match-property-value-ecmascript@2.2.0: {}
|
||||
|
||||
unicode-properties@1.4.1:
|
||||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
unicode-trie: 2.0.0
|
||||
|
||||
unicode-property-aliases-ecmascript@2.1.0: {}
|
||||
|
||||
unicode-trie@2.0.0:
|
||||
dependencies:
|
||||
pako: 0.2.9
|
||||
tiny-inflate: 1.0.3
|
||||
|
||||
unidragger@3.0.1:
|
||||
dependencies:
|
||||
ev-emitter: 2.1.2
|
||||
|
|
|
|||
Loading…
Reference in New Issue