mirror of
https://github.com/CorentinTh/enclosed.git
synced 2026-01-09 07:44:26 +08:00
feat(cli): added view command (#71)
This commit is contained in:
parent
3f536403db
commit
b5c89a4de5
10
README.md
10
README.md
@ -139,6 +139,16 @@ cat file.txt | enclosed create
|
||||
enclosed create --deleteAfterReading --password "password" --ttl 3600 "Hello, World!"
|
||||
```
|
||||
|
||||
### View a note
|
||||
|
||||
```bash
|
||||
# The password will be prompted if the note is password-protected
|
||||
enclosed view <note-url>
|
||||
|
||||
# Or you can provide the password directly
|
||||
enclosed view --password "password" <note-url>
|
||||
```
|
||||
|
||||
### Configure the enclosed instance to use
|
||||
|
||||
```bash
|
||||
|
||||
@ -45,6 +45,16 @@ cat file.txt | enclosed create
|
||||
enclosed create --deleteAfterReading --password "password" --ttl 3600 "Hello, World!"
|
||||
```
|
||||
|
||||
### View a note
|
||||
|
||||
```bash
|
||||
# The password will be prompted if the note is password-protected
|
||||
enclosed view <note-url>
|
||||
|
||||
# Or you can provide the password directly
|
||||
enclosed view --password "password" <note-url>
|
||||
```
|
||||
|
||||
### Configure the enclosed instance to use
|
||||
|
||||
```bash
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@enclosed/cli",
|
||||
"type": "module",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"packageManager": "pnpm@9.9.0",
|
||||
"description": "Enclosed cli to create secure notes.",
|
||||
"author": "Corentin Thomasset <corentinth@proton.me> (https://corentin.tech)",
|
||||
@ -34,6 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@enclosed/lib": "workspace:*",
|
||||
"@inquirer/prompts": "^5.3.8",
|
||||
"citty": "^0.1.6",
|
||||
"conf": "^13.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { defineCommand, runMain } from 'citty';
|
||||
import { createNoteCommand } from './create-note/create-note.command';
|
||||
import { configCommand } from './config/config.command';
|
||||
import { viewNoteCommand } from './view-note/view-note.command';
|
||||
|
||||
const main = defineCommand({
|
||||
meta: {
|
||||
@ -9,6 +10,7 @@ const main = defineCommand({
|
||||
},
|
||||
subCommands: {
|
||||
create: createNoteCommand,
|
||||
view: viewNoteCommand,
|
||||
config: configCommand,
|
||||
},
|
||||
});
|
||||
|
||||
58
packages/cli/src/view-note/view-note.command.ts
Normal file
58
packages/cli/src/view-note/view-note.command.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { defineCommand } from 'citty';
|
||||
import { decryptNote, fetchNote, isApiClientErrorWithStatusCode, parseNoteUrl } from '@enclosed/lib';
|
||||
import picocolors from 'picocolors';
|
||||
import { getInstanceUrl } from '../config/config.usecases';
|
||||
import { promptForPassword } from './view-note.models';
|
||||
|
||||
export const viewNoteCommand = defineCommand({
|
||||
meta: {
|
||||
name: 'view',
|
||||
description: 'View a note',
|
||||
},
|
||||
args: {
|
||||
noteUrl: {
|
||||
description: 'Note URL',
|
||||
type: 'positional',
|
||||
required: true,
|
||||
},
|
||||
password: {
|
||||
description: 'Password to decrypt the note (will be prompted if needed and not provided)',
|
||||
valueHint: 'password',
|
||||
alias: 'p',
|
||||
type: 'string',
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
run: async ({ args }) => {
|
||||
const { noteUrl, password } = args;
|
||||
|
||||
try {
|
||||
const { noteId, encryptionKey } = parseNoteUrl({ noteUrl });
|
||||
|
||||
const { content: encryptedContent, isPasswordProtected } = await fetchNote({
|
||||
noteId,
|
||||
apiBaseUrl: getInstanceUrl(),
|
||||
});
|
||||
|
||||
const { decryptedContent } = await decryptNote({
|
||||
encryptedContent,
|
||||
encryptionKey,
|
||||
password: isPasswordProtected ? password ?? await promptForPassword() : undefined,
|
||||
});
|
||||
|
||||
console.log(decryptedContent);
|
||||
} catch (error) {
|
||||
if (isApiClientErrorWithStatusCode({ error, statusCode: 404 })) {
|
||||
console.error(picocolors.red('Note not found'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isApiClientErrorWithStatusCode({ error, statusCode: 429 })) {
|
||||
console.error(picocolors.red('Api rate limit reached, please try again later'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(picocolors.red('Failed to fetch or decrypt note'));
|
||||
}
|
||||
},
|
||||
});
|
||||
13
packages/cli/src/view-note/view-note.models.ts
Normal file
13
packages/cli/src/view-note/view-note.models.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { password as prompt } from '@inquirer/prompts';
|
||||
|
||||
export { promptForPassword };
|
||||
|
||||
async function promptForPassword(): Promise<string> {
|
||||
const password = await prompt({
|
||||
message: 'Enter the password',
|
||||
});
|
||||
|
||||
console.log(''); // Add a new line after the password prompt
|
||||
|
||||
return password;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@enclosed/lib",
|
||||
"type": "module",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"packageManager": "pnpm@9.9.0",
|
||||
"description": "Enclosed lib to create secure notes.",
|
||||
"author": "Corentin Thomasset <corentinth@proton.me> (https://corentin.tech)",
|
||||
@ -58,7 +58,9 @@
|
||||
"main": "./dist/index.node.cjs",
|
||||
"module": "./dist/index.web.mjs",
|
||||
"types": "./dist/index.web.d.ts",
|
||||
"files": ["dist"],
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=22.0.0"
|
||||
},
|
||||
@ -75,10 +77,12 @@
|
||||
"prepublishOnly": "pnpm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21",
|
||||
"ofetch": "^1.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.27.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@vitest/coverage-v8": "^2.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^9.9.0",
|
||||
|
||||
52
packages/lib/src/api/api.client.ts
Normal file
52
packages/lib/src/api/api.client.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { ofetch } from 'ofetch';
|
||||
import { DEFAULT_API_BASE_URL } from './api.constants';
|
||||
|
||||
export { apiClient };
|
||||
|
||||
async function tryToGetBody({ response }: { response: Response }): Promise<unknown> {
|
||||
try {
|
||||
const contentType = response.headers.get('content-type');
|
||||
|
||||
if (contentType?.includes('application/json')) {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
return await response.text();
|
||||
} catch (_error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
async function apiClient<T>({
|
||||
path,
|
||||
method,
|
||||
body,
|
||||
baseUrl = DEFAULT_API_BASE_URL,
|
||||
}: {
|
||||
path: string;
|
||||
method: string;
|
||||
body?: Record<string, unknown>;
|
||||
baseUrl?: string;
|
||||
}): Promise<T> {
|
||||
const data = await ofetch<T>(
|
||||
path,
|
||||
{
|
||||
method,
|
||||
body,
|
||||
baseURL: baseUrl,
|
||||
onResponseError: async ({ response }) => {
|
||||
throw Object.assign(
|
||||
new Error('Failed to fetch note'),
|
||||
{
|
||||
response: {
|
||||
status: response.status,
|
||||
body: tryToGetBody({ response }),
|
||||
},
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
1
packages/lib/src/api/api.constants.ts
Normal file
1
packages/lib/src/api/api.constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const DEFAULT_API_BASE_URL = 'https://enclosed.cc';
|
||||
46
packages/lib/src/api/api.models.test.ts
Normal file
46
packages/lib/src/api/api.models.test.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { isApiClientErrorWithCode, isApiClientErrorWithStatusCode } from './api.models';
|
||||
|
||||
describe('api models', () => {
|
||||
describe('isApiClientErrorWithStatusCode', () => {
|
||||
test('permit to check if an error raised by the api client has a specific status code as response', () => {
|
||||
const error = Object.assign(new Error('Failed to fetch note'), {
|
||||
response: {
|
||||
status: 404,
|
||||
},
|
||||
});
|
||||
|
||||
expect(isApiClientErrorWithStatusCode({ error, statusCode: 404 })).to.eql(true);
|
||||
expect(isApiClientErrorWithStatusCode({ error, statusCode: 500 })).to.eql(false);
|
||||
});
|
||||
|
||||
test('the error must be an instance of Error and have a response object', () => {
|
||||
expect(isApiClientErrorWithStatusCode({ error: {}, statusCode: 404 })).to.eql(false);
|
||||
expect(isApiClientErrorWithStatusCode({ error: new Error('Failed to fetch note'), statusCode: 404 })).to.eql(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isApiClientErrorWithCode', () => {
|
||||
test('permit to check if an error raised by the api client has a specific code in the error body', () => {
|
||||
const error = Object.assign(new Error('Failed to fetch note'), {
|
||||
response: {
|
||||
body: {
|
||||
error: {
|
||||
code: 'NOT_FOUND',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(isApiClientErrorWithCode({ error, code: 'NOT_FOUND' })).to.eql(true);
|
||||
expect(isApiClientErrorWithCode({ error, code: 'INTERNAL_ERROR' })).to.eql(false);
|
||||
});
|
||||
|
||||
test('the error must be an instance of Error and have a response object with a body object', () => {
|
||||
expect(isApiClientErrorWithCode({ error: {}, code: 'NOT_FOUND' })).to.eql(false);
|
||||
expect(isApiClientErrorWithCode({ error: new Error('Failed to fetch note'), code: 'NOT_FOUND' })).to.eql(false);
|
||||
expect(isApiClientErrorWithCode({ error: { response: {} }, code: 'NOT_FOUND' })).to.eql(false);
|
||||
expect(isApiClientErrorWithCode({ error: { response: { body: {} } }, code: 'NOT_FOUND' })).to.eql(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
19
packages/lib/src/api/api.models.ts
Normal file
19
packages/lib/src/api/api.models.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { get, isError } from 'lodash-es';
|
||||
|
||||
export { isApiClientErrorWithStatusCode, isApiClientErrorWithCode };
|
||||
|
||||
function isApiClientErrorWithStatusCode({ error, statusCode }: { error: unknown; statusCode: number }): boolean {
|
||||
if (!isError(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get(error, 'response.status') === statusCode;
|
||||
}
|
||||
|
||||
function isApiClientErrorWithCode({ error, code }: { error: unknown; code: string }): boolean {
|
||||
if (!isError(error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get(error, 'response.body.error.code') === code;
|
||||
}
|
||||
@ -1,9 +1,12 @@
|
||||
import { createEnclosedLib } from './notes/notes.usecases';
|
||||
import { decryptNoteContent, deriveMasterKey, encryptNoteContent, generateBaseKey } from './crypto/node/crypto.node.usecases';
|
||||
import { storeNote } from './notes/notes.services';
|
||||
import { fetchNote, storeNote } from './notes/notes.services';
|
||||
import { createDecryptUsecase, createEncryptUsecase } from './crypto/crypto.usecases';
|
||||
import { isApiClientErrorWithCode, isApiClientErrorWithStatusCode } from './api/api.models';
|
||||
|
||||
export const { encryptNote } = createEncryptUsecase({ generateBaseKey, deriveMasterKey, encryptNoteContent });
|
||||
export const { decryptNote } = createDecryptUsecase({ deriveMasterKey, decryptNoteContent });
|
||||
|
||||
export const { createNote } = createEnclosedLib({ encryptNote, storeNote });
|
||||
export const { createNote, createNoteUrl, parseNoteUrl } = createEnclosedLib({ encryptNote, storeNote });
|
||||
|
||||
export { fetchNote, storeNote, isApiClientErrorWithStatusCode, isApiClientErrorWithCode };
|
||||
|
||||
9
packages/lib/src/index.test.ts
Normal file
9
packages/lib/src/index.test.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import * as nodeLib from './index.node';
|
||||
import * as webLib from './index.web';
|
||||
|
||||
describe('lib api', () => {
|
||||
test('the web lib exports the same functions as the node lib', () => {
|
||||
expect(Object.keys(nodeLib)).to.eql(Object.keys(webLib));
|
||||
});
|
||||
});
|
||||
@ -1,9 +1,12 @@
|
||||
import { createEnclosedLib } from './notes/notes.usecases';
|
||||
import { decryptNoteContent, deriveMasterKey, encryptNoteContent, generateBaseKey } from './crypto/web/crypto.web.usecases';
|
||||
import { storeNote } from './notes/notes.services';
|
||||
import { fetchNote, storeNote } from './notes/notes.services';
|
||||
import { createDecryptUsecase, createEncryptUsecase } from './crypto/crypto.usecases';
|
||||
import { isApiClientErrorWithCode, isApiClientErrorWithStatusCode } from './api/api.models';
|
||||
|
||||
export const { encryptNote } = createEncryptUsecase({ generateBaseKey, deriveMasterKey, encryptNoteContent });
|
||||
export const { decryptNote } = createDecryptUsecase({ deriveMasterKey, decryptNoteContent });
|
||||
|
||||
export const { createNote } = createEnclosedLib({ encryptNote, storeNote });
|
||||
export const { createNote, createNoteUrl, parseNoteUrl } = createEnclosedLib({ encryptNote, storeNote });
|
||||
|
||||
export { fetchNote, storeNote, isApiClientErrorWithStatusCode, isApiClientErrorWithCode };
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { createNoteUrl } from './notes.models';
|
||||
import { createNoteUrl, parseNoteUrl } from './notes.models';
|
||||
|
||||
describe('note models', () => {
|
||||
describe('createNoteUrl', () => {
|
||||
@ -19,4 +19,51 @@ describe('note models', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseNoteUrl', () => {
|
||||
test('retreives the note id and encryption key from a sharable note url', () => {
|
||||
expect(
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/123#abc' }),
|
||||
).to.eql({
|
||||
noteId: '123',
|
||||
encryptionKey: 'abc',
|
||||
});
|
||||
});
|
||||
|
||||
test('trailing slash in the base url is handled', () => {
|
||||
expect(
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/123/#abc' }),
|
||||
).to.eql({
|
||||
noteId: '123',
|
||||
encryptionKey: 'abc',
|
||||
});
|
||||
});
|
||||
|
||||
test('in case of nested paths, the last path segment is considered the note id', () => {
|
||||
expect(
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/123/456#abc' }),
|
||||
).to.eql({
|
||||
noteId: '456',
|
||||
encryptionKey: 'abc',
|
||||
});
|
||||
});
|
||||
|
||||
test('throws an error if their is no note id or encryption key', () => {
|
||||
expect(() => {
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/#abc' });
|
||||
}).to.throw('Invalid note url');
|
||||
|
||||
expect(() => {
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/123#' });
|
||||
}).to.throw('Invalid note url');
|
||||
|
||||
expect(() => {
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/123' });
|
||||
}).to.throw('Invalid note url');
|
||||
|
||||
expect(() => {
|
||||
parseNoteUrl({ noteUrl: 'https://example.com/' });
|
||||
}).to.throw('Invalid note url');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export { createNoteUrl };
|
||||
export { createNoteUrl, parseNoteUrl };
|
||||
|
||||
function createNoteUrl({ noteId, encryptionKey, clientBaseUrl }: { noteId: string; encryptionKey: string; clientBaseUrl: string }): { noteUrl: string } {
|
||||
const url = new URL(`/${noteId}`, clientBaseUrl);
|
||||
@ -8,3 +8,16 @@ function createNoteUrl({ noteId, encryptionKey, clientBaseUrl }: { noteId: strin
|
||||
|
||||
return { noteUrl };
|
||||
}
|
||||
|
||||
function parseNoteUrl({ noteUrl }: { noteUrl: string }): { noteId: string; encryptionKey: string } {
|
||||
const url = new URL(noteUrl);
|
||||
|
||||
const noteId = url.pathname.split('/').filter(Boolean).pop();
|
||||
const encryptionKey = url.hash.replace(/^#/, '');
|
||||
|
||||
if (!noteId || !encryptionKey) {
|
||||
throw new Error('Invalid note url');
|
||||
}
|
||||
|
||||
return { noteId, encryptionKey };
|
||||
}
|
||||
|
||||
@ -1,35 +1,47 @@
|
||||
import { ofetch } from 'ofetch';
|
||||
import { apiClient } from '../api/api.client';
|
||||
|
||||
export { storeNote };
|
||||
export { storeNote, fetchNote };
|
||||
|
||||
async function storeNote({
|
||||
content,
|
||||
isPasswordProtected,
|
||||
ttlInSeconds,
|
||||
deleteAfterReading,
|
||||
noteCreationApiUrl,
|
||||
apiBaseUrl,
|
||||
}: {
|
||||
content: string;
|
||||
isPasswordProtected: boolean;
|
||||
ttlInSeconds: number;
|
||||
deleteAfterReading: boolean;
|
||||
noteCreationApiUrl: string;
|
||||
apiBaseUrl?: string;
|
||||
}): Promise<{ noteId: string }> {
|
||||
const { noteId } = await ofetch<{ noteId: string }>(
|
||||
noteCreationApiUrl,
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
content,
|
||||
isPasswordProtected,
|
||||
ttlInSeconds,
|
||||
deleteAfterReading,
|
||||
},
|
||||
onResponseError: async ({ response }) => {
|
||||
throw Object.assign(new Error('Failed to create note'), { response });
|
||||
},
|
||||
const { noteId } = await apiClient<{ noteId: string }>({
|
||||
path: 'api/notes',
|
||||
baseUrl: apiBaseUrl,
|
||||
method: 'POST',
|
||||
body: {
|
||||
content,
|
||||
isPasswordProtected,
|
||||
ttlInSeconds,
|
||||
deleteAfterReading,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
return { noteId };
|
||||
}
|
||||
|
||||
async function fetchNote({
|
||||
noteId,
|
||||
apiBaseUrl,
|
||||
}: {
|
||||
noteId: string;
|
||||
apiBaseUrl?: string;
|
||||
}) {
|
||||
const { note } = await apiClient<{ note: { content: string; isPasswordProtected: boolean } }>({
|
||||
path: `api/notes/${noteId}`,
|
||||
baseUrl: apiBaseUrl,
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { createNoteUrl as createNoteUrlImpl } from './notes.models';
|
||||
import { createNoteUrl as createNoteUrlImpl, parseNoteUrl } from './notes.models';
|
||||
|
||||
export { createEnclosedLib };
|
||||
|
||||
@ -7,28 +7,35 @@ const BASE_URL = 'https://enclosed.cc';
|
||||
|
||||
function createEnclosedLib({
|
||||
encryptNote,
|
||||
// decryptNote,
|
||||
storeNote: storeNoteImpl,
|
||||
// fetchNote: fetchNoteImpl,
|
||||
}: {
|
||||
encryptNote: (args: { content: string; password?: string }) => Promise<{ encryptedContent: string; encryptionKey: string }>;
|
||||
storeNote: (params: { content: string; isPasswordProtected: boolean; ttlInSeconds: number; deleteAfterReading: boolean; noteCreationApiUrl: string }) => Promise<{ noteId: string }>;
|
||||
// decryptNote: (args: { encryptedContent: string; encryptionKey: string }) => Promise<{ content: string }>;
|
||||
storeNote: (params: { content: string; isPasswordProtected: boolean; ttlInSeconds: number; deleteAfterReading: boolean; apiBaseUrl?: string }) => Promise<{ noteId: string }>;
|
||||
// fetchNote: (params: { noteId: string; apiBaseUrl?: string }) => Promise<{ content: string; isPasswordProtected: boolean }>;
|
||||
}) {
|
||||
return {
|
||||
parseNoteUrl,
|
||||
createNoteUrl: createNoteUrlImpl,
|
||||
|
||||
createNote: async ({
|
||||
content,
|
||||
password,
|
||||
ttlInSeconds = ONE_HOUR_IN_SECONDS,
|
||||
deleteAfterReading = false,
|
||||
clientBaseUrl = BASE_URL,
|
||||
noteCreationApiUrl = new URL('/api/notes', clientBaseUrl).toString(),
|
||||
apiBaseUrl = clientBaseUrl,
|
||||
createNoteUrl = createNoteUrlImpl,
|
||||
storeNote = params => storeNoteImpl({ ...params, noteCreationApiUrl }),
|
||||
storeNote = params => storeNoteImpl({ ...params, apiBaseUrl }),
|
||||
}: {
|
||||
content: string;
|
||||
password?: string;
|
||||
ttlInSeconds?: number;
|
||||
deleteAfterReading?: boolean;
|
||||
clientBaseUrl?: string;
|
||||
noteCreationApiUrl?: string;
|
||||
apiBaseUrl?: string;
|
||||
createNoteUrl?: (args: { noteId: string; encryptionKey: string; clientBaseUrl: string }) => { noteUrl: string };
|
||||
storeNote?: (params: { content: string; isPasswordProtected: boolean; ttlInSeconds: number; deleteAfterReading: boolean }) => Promise<{ noteId: string }>;
|
||||
}) => {
|
||||
|
||||
12
packages/lib/tsconfig.json
Normal file
12
packages/lib/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
253
pnpm-lock.yaml
generated
253
pnpm-lock.yaml
generated
@ -156,6 +156,9 @@ importers:
|
||||
'@enclosed/lib':
|
||||
specifier: workspace:*
|
||||
version: link:../lib
|
||||
'@inquirer/prompts':
|
||||
specifier: ^5.3.8
|
||||
version: 5.3.8
|
||||
citty:
|
||||
specifier: ^0.1.6
|
||||
version: 0.1.6
|
||||
@ -207,6 +210,9 @@ importers:
|
||||
|
||||
packages/lib:
|
||||
dependencies:
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
ofetch:
|
||||
specifier: ^1.3.4
|
||||
version: 1.3.4
|
||||
@ -214,6 +220,9 @@ importers:
|
||||
'@antfu/eslint-config':
|
||||
specifier: ^2.27.0
|
||||
version: 2.27.3(@typescript-eslint/utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4))(@vue/compiler-sfc@3.4.38)(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)(vitest@2.0.5(@types/node@22.5.1)(jsdom@25.0.0)(terser@5.31.6))
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.12
|
||||
version: 4.17.12
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(vitest@2.0.5(@types/node@22.5.1)(jsdom@25.0.0)(terser@5.31.6))
|
||||
@ -1140,6 +1149,62 @@ packages:
|
||||
'@iconify/utils@2.1.32':
|
||||
resolution: {integrity: sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==}
|
||||
|
||||
'@inquirer/checkbox@2.4.7':
|
||||
resolution: {integrity: sha512-5YwCySyV1UEgqzz34gNsC38eKxRBtlRDpJLlKcRtTjlYA/yDKuc1rfw+hjw+2WJxbAZtaDPsRl5Zk7J14SBoBw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/confirm@3.1.22':
|
||||
resolution: {integrity: sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/core@9.0.10':
|
||||
resolution: {integrity: sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/editor@2.1.22':
|
||||
resolution: {integrity: sha512-K1QwTu7GCK+nKOVRBp5HY9jt3DXOfPGPr6WRDrPImkcJRelG9UTx2cAtK1liXmibRrzJlTWOwqgWT3k2XnS62w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/expand@2.1.22':
|
||||
resolution: {integrity: sha512-wTZOBkzH+ItPuZ3ZPa9lynBsdMp6kQ9zbjVPYEtSBG7UulGjg2kQiAnUjgyG4SlntpTce5bOmXAPvE4sguXjpA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/figures@1.0.5':
|
||||
resolution: {integrity: sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/input@2.2.9':
|
||||
resolution: {integrity: sha512-7Z6N+uzkWM7+xsE+3rJdhdG/+mQgejOVqspoW+w0AbSZnL6nq5tGMEVASaYVWbkoSzecABWwmludO2evU3d31g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/number@1.0.10':
|
||||
resolution: {integrity: sha512-kWTxRF8zHjQOn2TJs+XttLioBih6bdc5CcosXIzZsrTY383PXI35DuhIllZKu7CdXFi2rz2BWPN9l0dPsvrQOA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/password@2.1.22':
|
||||
resolution: {integrity: sha512-5Fxt1L9vh3rAKqjYwqsjU4DZsEvY/2Gll+QkqR4yEpy6wvzLxdSgFhUcxfDAOtO4BEoTreWoznC0phagwLU5Kw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/prompts@5.3.8':
|
||||
resolution: {integrity: sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/rawlist@2.2.4':
|
||||
resolution: {integrity: sha512-pb6w9pWrm7EfnYDgQObOurh2d2YH07+eDo3xQBsNAM2GRhliz6wFXGi1thKQ4bN6B0xDd6C3tBsjdr3obsCl3Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/search@1.0.7':
|
||||
resolution: {integrity: sha512-p1wpV+3gd1eST/o5N3yQpYEdFNCzSP0Klrl+5bfD3cTTz8BGG6nf4Z07aBW0xjlKIj1Rp0y3x/X4cZYi6TfcLw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/select@2.4.7':
|
||||
resolution: {integrity: sha512-JH7XqPEkBpNWp3gPCqWqY8ECbyMoFcCZANlL6pV9hf59qK6dGmkOlx1ydyhY+KZ0c5X74+W6Mtp+nm2QX0/MAQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@inquirer/type@1.5.2':
|
||||
resolution: {integrity: sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@internationalized/date@3.5.5':
|
||||
resolution: {integrity: sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==}
|
||||
|
||||
@ -1565,6 +1630,9 @@ packages:
|
||||
'@types/mdast@3.0.15':
|
||||
resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
|
||||
|
||||
'@types/mute-stream@0.0.4':
|
||||
resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==}
|
||||
|
||||
'@types/node-cron@3.0.11':
|
||||
resolution: {integrity: sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==}
|
||||
|
||||
@ -1583,6 +1651,9 @@ packages:
|
||||
'@types/unist@2.0.11':
|
||||
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
||||
|
||||
'@types/wrap-ansi@3.0.0':
|
||||
resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.3.0':
|
||||
resolution: {integrity: sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@ -1819,6 +1890,10 @@ packages:
|
||||
ajv@8.17.1:
|
||||
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@ -1973,6 +2048,9 @@ packages:
|
||||
character-reference-invalid@1.1.4:
|
||||
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
|
||||
|
||||
chardet@0.7.0:
|
||||
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
|
||||
|
||||
check-error@2.1.1:
|
||||
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
|
||||
engines: {node: '>= 16'}
|
||||
@ -2003,6 +2081,10 @@ packages:
|
||||
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cli-width@4.1.0:
|
||||
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
clipboardy@4.0.0:
|
||||
resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==}
|
||||
engines: {node: '>=18'}
|
||||
@ -2522,6 +2604,10 @@ packages:
|
||||
resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
external-editor@3.1.0:
|
||||
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
fast-copy@3.0.2:
|
||||
resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==}
|
||||
|
||||
@ -2743,6 +2829,10 @@ packages:
|
||||
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -3168,6 +3258,10 @@ packages:
|
||||
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
|
||||
hasBin: true
|
||||
|
||||
mute-stream@1.0.0:
|
||||
resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
|
||||
nanoid@3.3.7:
|
||||
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@ -3246,6 +3340,10 @@ packages:
|
||||
resolution: {integrity: sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
os-tmpdir@1.0.2:
|
||||
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
p-limit@2.3.0:
|
||||
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
||||
engines: {node: '>=6'}
|
||||
@ -3962,6 +4060,10 @@ packages:
|
||||
resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tmp@0.0.33:
|
||||
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
|
||||
to-fast-properties@2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
@ -4008,6 +4110,10 @@ packages:
|
||||
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
type-fest@0.21.3:
|
||||
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
type-fest@0.6.0:
|
||||
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -4305,6 +4411,10 @@ packages:
|
||||
'@cloudflare/workers-types':
|
||||
optional: true
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
@ -4370,6 +4480,10 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yoctocolors-cjs@2.1.2:
|
||||
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
youch@3.3.3:
|
||||
resolution: {integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==}
|
||||
|
||||
@ -5080,6 +5194,103 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@inquirer/checkbox@2.4.7':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/figures': 1.0.5
|
||||
'@inquirer/type': 1.5.2
|
||||
ansi-escapes: 4.3.2
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/confirm@3.1.22':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
|
||||
'@inquirer/core@9.0.10':
|
||||
dependencies:
|
||||
'@inquirer/figures': 1.0.5
|
||||
'@inquirer/type': 1.5.2
|
||||
'@types/mute-stream': 0.0.4
|
||||
'@types/node': 22.5.1
|
||||
'@types/wrap-ansi': 3.0.0
|
||||
ansi-escapes: 4.3.2
|
||||
cli-spinners: 2.9.2
|
||||
cli-width: 4.1.0
|
||||
mute-stream: 1.0.0
|
||||
signal-exit: 4.1.0
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 6.2.0
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/editor@2.1.22':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
external-editor: 3.1.0
|
||||
|
||||
'@inquirer/expand@2.1.22':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/figures@1.0.5': {}
|
||||
|
||||
'@inquirer/input@2.2.9':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
|
||||
'@inquirer/number@1.0.10':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
|
||||
'@inquirer/password@2.1.22':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
ansi-escapes: 4.3.2
|
||||
|
||||
'@inquirer/prompts@5.3.8':
|
||||
dependencies:
|
||||
'@inquirer/checkbox': 2.4.7
|
||||
'@inquirer/confirm': 3.1.22
|
||||
'@inquirer/editor': 2.1.22
|
||||
'@inquirer/expand': 2.1.22
|
||||
'@inquirer/input': 2.2.9
|
||||
'@inquirer/number': 1.0.10
|
||||
'@inquirer/password': 2.1.22
|
||||
'@inquirer/rawlist': 2.2.4
|
||||
'@inquirer/search': 1.0.7
|
||||
'@inquirer/select': 2.4.7
|
||||
|
||||
'@inquirer/rawlist@2.2.4':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/type': 1.5.2
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/search@1.0.7':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/figures': 1.0.5
|
||||
'@inquirer/type': 1.5.2
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/select@2.4.7':
|
||||
dependencies:
|
||||
'@inquirer/core': 9.0.10
|
||||
'@inquirer/figures': 1.0.5
|
||||
'@inquirer/type': 1.5.2
|
||||
ansi-escapes: 4.3.2
|
||||
yoctocolors-cjs: 2.1.2
|
||||
|
||||
'@inquirer/type@1.5.2':
|
||||
dependencies:
|
||||
mute-stream: 1.0.0
|
||||
|
||||
'@internationalized/date@3.5.5':
|
||||
dependencies:
|
||||
'@swc/helpers': 0.5.12
|
||||
@ -5507,6 +5718,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
|
||||
'@types/mute-stream@0.0.4':
|
||||
dependencies:
|
||||
'@types/node': 22.5.1
|
||||
|
||||
'@types/node-cron@3.0.11': {}
|
||||
|
||||
'@types/node-forge@1.3.11':
|
||||
@ -5523,6 +5738,8 @@ snapshots:
|
||||
|
||||
'@types/unist@2.0.11': {}
|
||||
|
||||
'@types/wrap-ansi@3.0.0': {}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.3.0(@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.11.0
|
||||
@ -5895,6 +6112,10 @@ snapshots:
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
|
||||
ansi-escapes@4.3.2:
|
||||
dependencies:
|
||||
type-fest: 0.21.3
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.0.1: {}
|
||||
@ -6049,6 +6270,8 @@ snapshots:
|
||||
|
||||
character-reference-invalid@1.1.4: {}
|
||||
|
||||
chardet@0.7.0: {}
|
||||
|
||||
check-error@2.1.1: {}
|
||||
|
||||
chokidar@3.6.0:
|
||||
@ -6083,6 +6306,8 @@ snapshots:
|
||||
|
||||
cli-spinners@2.9.2: {}
|
||||
|
||||
cli-width@4.1.0: {}
|
||||
|
||||
clipboardy@4.0.0:
|
||||
dependencies:
|
||||
execa: 8.0.1
|
||||
@ -6762,6 +6987,12 @@ snapshots:
|
||||
|
||||
exit-hook@2.2.1: {}
|
||||
|
||||
external-editor@3.1.0:
|
||||
dependencies:
|
||||
chardet: 0.7.0
|
||||
iconv-lite: 0.4.24
|
||||
tmp: 0.0.33
|
||||
|
||||
fast-copy@3.0.2: {}
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
@ -6974,6 +7205,10 @@ snapshots:
|
||||
|
||||
human-signals@5.0.0: {}
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
@ -7402,6 +7637,8 @@ snapshots:
|
||||
|
||||
mustache@4.2.0: {}
|
||||
|
||||
mute-stream@1.0.0: {}
|
||||
|
||||
nanoid@3.3.7: {}
|
||||
|
||||
natural-compare-lite@1.4.0: {}
|
||||
@ -7484,6 +7721,8 @@ snapshots:
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
os-tmpdir@1.0.2: {}
|
||||
|
||||
p-limit@2.3.0:
|
||||
dependencies:
|
||||
p-try: 2.2.0
|
||||
@ -8183,6 +8422,10 @@ snapshots:
|
||||
|
||||
tinyspy@3.0.0: {}
|
||||
|
||||
tmp@0.0.33:
|
||||
dependencies:
|
||||
os-tmpdir: 1.0.2
|
||||
|
||||
to-fast-properties@2.0.0: {}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
@ -8225,6 +8468,8 @@ snapshots:
|
||||
|
||||
type-fest@0.20.2: {}
|
||||
|
||||
type-fest@0.21.3: {}
|
||||
|
||||
type-fest@0.6.0: {}
|
||||
|
||||
type-fest@0.8.1: {}
|
||||
@ -8562,6 +8807,12 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
@ -8612,6 +8863,8 @@ snapshots:
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
yoctocolors-cjs@2.1.2: {}
|
||||
|
||||
youch@3.3.3:
|
||||
dependencies:
|
||||
cookie: 0.5.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user