npm audit fix

This commit is contained in:
lovebird 2026-01-30 18:17:57 +01:00
parent b40a530413
commit 1fd6ef704e
33 changed files with 4469 additions and 11861 deletions

View File

@ -17,4 +17,4 @@
}, },
"packageManager": "pnpm@8.15.6", "packageManager": "pnpm@8.15.6",
"name": "design-system" "name": "design-system"
} }

View File

@ -31,96 +31,95 @@ export interface IKBotOptions {
 
 OpenRouter models:  OpenRouter models:
 
agentica-org/deepcoder-14b-preview | paid
agentica-org/deepcoder-14b-preview:free | free
ai21/jamba-large-1.7 | paid ai21/jamba-large-1.7 | paid
ai21/jamba-mini-1.7 | paid ai21/jamba-mini-1.7 | paid
aion-labs/aion-1.0 | paid aion-labs/aion-1.0 | paid
aion-labs/aion-1.0-mini | paid aion-labs/aion-1.0-mini | paid
aion-labs/aion-rp-llama-3.1-8b | paid aion-labs/aion-rp-llama-3.1-8b | paid
alfredpros/codellama-7b-instruct-solidity | paid alfredpros/codellama-7b-instruct-solidity | paid
allenai/molmo-7b-d | paid
allenai/olmo-2-0325-32b-instruct | paid allenai/olmo-2-0325-32b-instruct | paid
allenai/olmo-3-32b-think:free | free
allenai/olmo-3-7b-instruct | paid
allenai/olmo-3-7b-think | paid
allenai/olmo-3.1-32b-think:free | free
amazon/nova-2-lite-v1 | paid
amazon/nova-lite-v1 | paid amazon/nova-lite-v1 | paid
amazon/nova-micro-v1 | paid amazon/nova-micro-v1 | paid
amazon/nova-premier-v1 | paid
amazon/nova-pro-v1 | paid amazon/nova-pro-v1 | paid
anthropic/claude-3-haiku | paid anthropic/claude-3-haiku | paid
anthropic/claude-3-opus | paid anthropic/claude-3-opus | paid
anthropic/claude-3.5-haiku | paid anthropic/claude-3.5-haiku | paid
anthropic/claude-3.5-haiku-20241022 | paid anthropic/claude-3.5-haiku-20241022 | paid
anthropic/claude-3.5-sonnet | paid anthropic/claude-3.5-sonnet | paid
anthropic/claude-3.5-sonnet-20240620 | paid
anthropic/claude-3.7-sonnet | paid anthropic/claude-3.7-sonnet | paid
anthropic/claude-3.7-sonnet:thinking | paid anthropic/claude-3.7-sonnet:thinking | paid
anthropic/claude-haiku-4.5 | paid
anthropic/claude-opus-4 | paid anthropic/claude-opus-4 | paid
anthropic/claude-opus-4.1 | paid anthropic/claude-opus-4.1 | paid
anthropic/claude-opus-4.5 | paid
anthropic/claude-sonnet-4 | paid anthropic/claude-sonnet-4 | paid
anthropic/claude-sonnet-4.5 | paid
arcee-ai/coder-large | paid arcee-ai/coder-large | paid
arcee-ai/maestro-reasoning | paid arcee-ai/maestro-reasoning | paid
arcee-ai/spotlight | paid arcee-ai/spotlight | paid
arcee-ai/trinity-mini | paid
arcee-ai/trinity-mini:free | free
arcee-ai/virtuoso-large | paid arcee-ai/virtuoso-large | paid
arliai/qwq-32b-arliai-rpr-v1 | paid arliai/qwq-32b-arliai-rpr-v1 | paid
arliai/qwq-32b-arliai-rpr-v1:free | free
openrouter/auto | paid openrouter/auto | paid
baidu/ernie-4.5-21b-a3b | paid baidu/ernie-4.5-21b-a3b | paid
baidu/ernie-4.5-21b-a3b-thinking | paid
baidu/ernie-4.5-300b-a47b | paid baidu/ernie-4.5-300b-a47b | paid
baidu/ernie-4.5-vl-28b-a3b | paid baidu/ernie-4.5-vl-28b-a3b | paid
baidu/ernie-4.5-vl-424b-a47b | paid baidu/ernie-4.5-vl-424b-a47b | paid
bytedance/seed-oss-36b-instruct | paid openrouter/bodybuilder | paid
bytedance-seed/seed-1.6 | paid
bytedance-seed/seed-1.6-flash | paid
bytedance/ui-tars-1.5-7b | paid bytedance/ui-tars-1.5-7b | paid
deepcogito/cogito-v2-preview-llama-109b-moe | paid deepcogito/cogito-v2-preview-llama-109b-moe | paid
cohere/command | paid
cohere/command-a | paid cohere/command-a | paid
cohere/command-r | paid
cohere/command-r-03-2024 | paid
cohere/command-r-08-2024 | paid cohere/command-r-08-2024 | paid
cohere/command-r-plus | paid
cohere/command-r-plus-04-2024 | paid
cohere/command-r-plus-08-2024 | paid cohere/command-r-plus-08-2024 | paid
cohere/command-r7b-12-2024 | paid cohere/command-r7b-12-2024 | paid
deepcogito/cogito-v2-preview-deepseek-671b | paid deepcogito/cogito-v2-preview-llama-405b | paid
deepcogito/cogito-v2-preview-llama-70b | paid
deepcogito/cogito-v2.1-671b | paid
deepseek/deepseek-prover-v2 | paid deepseek/deepseek-prover-v2 | paid
deepseek/deepseek-r1-0528-qwen3-8b | paid deepseek/deepseek-r1-0528-qwen3-8b | paid
deepseek/deepseek-r1-0528-qwen3-8b:free | free
deepseek/deepseek-chat | paid deepseek/deepseek-chat | paid
deepseek/deepseek-chat-v3-0324 | paid deepseek/deepseek-chat-v3-0324 | paid
deepseek/deepseek-chat-v3-0324:free | free
deepseek/deepseek-chat-v3.1 | paid deepseek/deepseek-chat-v3.1 | paid
deepseek/deepseek-chat-v3.1:free | free deepseek/deepseek-v3.1-terminus | paid
deepseek/deepseek-v3.1-base | paid deepseek/deepseek-v3.1-terminus:exacto | paid
deepseek/deepseek-v3.2 | paid
deepseek/deepseek-v3.2-exp | paid
deepseek/deepseek-v3.2-speciale | paid
deepseek/deepseek-r1 | paid deepseek/deepseek-r1 | paid
deepseek/deepseek-r1:free | free
deepseek/deepseek-r1-0528 | paid deepseek/deepseek-r1-0528 | paid
deepseek/deepseek-r1-0528:free | free deepseek/deepseek-r1-0528:free | free
deepseek/deepseek-r1-distill-llama-70b | paid deepseek/deepseek-r1-distill-llama-70b | paid
deepseek/deepseek-r1-distill-llama-70b:free | free
deepseek/deepseek-r1-distill-llama-8b | paid
deepseek/deepseek-r1-distill-qwen-14b | paid deepseek/deepseek-r1-distill-qwen-14b | paid
deepseek/deepseek-r1-distill-qwen-14b:free | free
deepseek/deepseek-r1-distill-qwen-32b | paid deepseek/deepseek-r1-distill-qwen-32b | paid
cognitivecomputations/dolphin-mixtral-8x22b | paid
cognitivecomputations/dolphin3.0-mistral-24b | paid
cognitivecomputations/dolphin3.0-mistral-24b:free | free
cognitivecomputations/dolphin3.0-r1-mistral-24b | paid
cognitivecomputations/dolphin3.0-r1-mistral-24b:free | free
eleutherai/llemma_7b | paid eleutherai/llemma_7b | paid
essentialai/rnj-1-instruct | paid
alpindale/goliath-120b | paid alpindale/goliath-120b | paid
google/gemini-flash-1.5 | paid
google/gemini-flash-1.5-8b | paid
google/gemini-pro-1.5 | paid
google/gemini-2.0-flash-001 | paid google/gemini-2.0-flash-001 | paid
google/gemini-2.0-flash-exp:free | free google/gemini-2.0-flash-exp:free | free
google/gemini-2.0-flash-lite-001 | paid google/gemini-2.0-flash-lite-001 | paid
google/gemini-2.5-flash | paid google/gemini-2.5-flash | paid
google/gemini-2.5-flash-image | paid
google/gemini-2.5-flash-image-preview | paid google/gemini-2.5-flash-image-preview | paid
google/gemini-2.5-flash-lite | paid google/gemini-2.5-flash-lite | paid
google/gemini-2.5-flash-lite-preview-06-17 | paid google/gemini-2.5-flash-lite-preview-09-2025 | paid
google/gemini-2.5-flash-preview-09-2025 | paid
google/gemini-2.5-pro | paid google/gemini-2.5-pro | paid
google/gemini-2.5-pro-preview-05-06 | paid google/gemini-2.5-pro-preview-05-06 | paid
google/gemini-2.5-pro-preview | paid google/gemini-2.5-pro-preview | paid
google/gemini-3-flash-preview | paid
google/gemini-3-pro-preview | paid
google/gemma-2-27b-it | paid google/gemma-2-27b-it | paid
google/gemma-2-9b-it | paid google/gemma-2-9b-it | paid
google/gemma-2-9b-it:free | free
google/gemma-3-12b-it | paid google/gemma-3-12b-it | paid
google/gemma-3-12b-it:free | free google/gemma-3-12b-it:free | free
google/gemma-3-27b-it | paid google/gemma-3-27b-it | paid
@ -130,14 +129,16 @@ export interface IKBotOptions {
google/gemma-3n-e2b-it:free | free google/gemma-3n-e2b-it:free | free
google/gemma-3n-e4b-it | paid google/gemma-3n-e4b-it | paid
google/gemma-3n-e4b-it:free | free google/gemma-3n-e4b-it:free | free
google/gemini-3-pro-image-preview | paid
ibm-granite/granite-4.0-h-micro | paid
inception/mercury | paid inception/mercury | paid
inception/mercury-coder | paid inception/mercury-coder | paid
inflection/inflection-3-pi | paid inflection/inflection-3-pi | paid
inflection/inflection-3-productivity | paid inflection/inflection-3-productivity | paid
liquid/lfm-3b | paid kwaipilot/kat-coder-pro:free | free
liquid/lfm-7b | paid liquid/lfm-2.2-6b | paid
liquid/lfm2-8b-a1b | paid
meta-llama/llama-guard-3-8b | paid meta-llama/llama-guard-3-8b | paid
anthracite-org/magnum-v2-72b | paid
anthracite-org/magnum-v4-72b | paid anthracite-org/magnum-v4-72b | paid
mancer/weaver | paid mancer/weaver | paid
meituan/longcat-flash-chat | paid meituan/longcat-flash-chat | paid
@ -155,82 +156,81 @@ export interface IKBotOptions {
meta-llama/llama-3.2-90b-vision-instruct | paid meta-llama/llama-3.2-90b-vision-instruct | paid
meta-llama/llama-3.3-70b-instruct | paid meta-llama/llama-3.3-70b-instruct | paid
meta-llama/llama-3.3-70b-instruct:free | free meta-llama/llama-3.3-70b-instruct:free | free
meta-llama/llama-3.3-8b-instruct:free | free
meta-llama/llama-4-maverick | paid meta-llama/llama-4-maverick | paid
meta-llama/llama-4-maverick:free | free
meta-llama/llama-4-scout | paid meta-llama/llama-4-scout | paid
meta-llama/llama-4-scout:free | free
meta-llama/llama-guard-4-12b | paid meta-llama/llama-guard-4-12b | paid
meta-llama/llama-guard-2-8b | paid meta-llama/llama-guard-2-8b | paid
microsoft/mai-ds-r1 | paid
microsoft/mai-ds-r1:free | free
microsoft/phi-4 | paid microsoft/phi-4 | paid
microsoft/phi-4-multimodal-instruct | paid microsoft/phi-4-multimodal-instruct | paid
microsoft/phi-4-reasoning-plus | paid microsoft/phi-4-reasoning-plus | paid
microsoft/phi-3-medium-128k-instruct | paid microsoft/phi-3-medium-128k-instruct | paid
microsoft/phi-3-mini-128k-instruct | paid microsoft/phi-3-mini-128k-instruct | paid
microsoft/phi-3.5-mini-128k-instruct | paid microsoft/phi-3.5-mini-128k-instruct | paid
sophosympatheia/midnight-rose-70b | paid
minimax/minimax-m1 | paid minimax/minimax-m1 | paid
minimax/minimax-m2 | paid
minimax/minimax-m2.1 | paid
minimax/minimax-01 | paid minimax/minimax-01 | paid
mistralai/mistral-large | paid mistralai/mistral-large | paid
mistralai/mistral-large-2407 | paid mistralai/mistral-large-2407 | paid
mistralai/mistral-large-2411 | paid mistralai/mistral-large-2411 | paid
mistralai/mistral-small | paid
mistralai/mistral-tiny | paid mistralai/mistral-tiny | paid
mistralai/codestral-2501 | paid
mistralai/codestral-2508 | paid mistralai/codestral-2508 | paid
mistralai/devstral-2512 | paid
mistralai/devstral-2512:free | free
mistralai/devstral-medium | paid mistralai/devstral-medium | paid
mistralai/devstral-small | paid mistralai/devstral-small | paid
mistralai/devstral-small-2505 | paid mistralai/devstral-small-2505 | paid
mistralai/devstral-small-2505:free | free mistralai/ministral-14b-2512 | paid
mistralai/magistral-medium-2506 | paid mistralai/ministral-3b-2512 | paid
mistralai/magistral-medium-2506:thinking | paid mistralai/ministral-8b-2512 | paid
mistralai/magistral-small-2506 | paid
mistralai/ministral-3b | paid mistralai/ministral-3b | paid
mistralai/ministral-8b | paid mistralai/ministral-8b | paid
mistralai/mistral-7b-instruct | paid mistralai/mistral-7b-instruct | paid
mistralai/mistral-7b-instruct:free | free mistralai/mistral-7b-instruct:free | free
mistralai/mistral-7b-instruct-v0.1 | paid mistralai/mistral-7b-instruct-v0.1 | paid
mistralai/mistral-7b-instruct-v0.2 | paid
mistralai/mistral-7b-instruct-v0.3 | paid mistralai/mistral-7b-instruct-v0.3 | paid
mistralai/mistral-large-2512 | paid
mistralai/mistral-medium-3 | paid mistralai/mistral-medium-3 | paid
mistralai/mistral-medium-3.1 | paid mistralai/mistral-medium-3.1 | paid
mistralai/mistral-nemo | paid mistralai/mistral-nemo | paid
mistralai/mistral-nemo:free | free
mistralai/mistral-small-24b-instruct-2501 | paid mistralai/mistral-small-24b-instruct-2501 | paid
mistralai/mistral-small-24b-instruct-2501:free | free
mistralai/mistral-small-3.1-24b-instruct | paid mistralai/mistral-small-3.1-24b-instruct | paid
mistralai/mistral-small-3.1-24b-instruct:free | free mistralai/mistral-small-3.1-24b-instruct:free | free
mistralai/mistral-small-3.2-24b-instruct | paid mistralai/mistral-small-3.2-24b-instruct | paid
mistralai/mistral-small-3.2-24b-instruct:free | free mistralai/mistral-small-creative | paid
mistralai/mixtral-8x22b-instruct | paid mistralai/mixtral-8x22b-instruct | paid
mistralai/mixtral-8x7b-instruct | paid mistralai/mixtral-8x7b-instruct | paid
mistralai/pixtral-12b | paid mistralai/pixtral-12b | paid
mistralai/pixtral-large-2411 | paid mistralai/pixtral-large-2411 | paid
mistralai/mistral-saba | paid mistralai/mistral-saba | paid
mistralai/voxtral-small-24b-2507 | paid
moonshotai/kimi-dev-72b | paid moonshotai/kimi-dev-72b | paid
moonshotai/kimi-dev-72b:free | free
moonshotai/kimi-k2 | paid moonshotai/kimi-k2 | paid
moonshotai/kimi-k2:free | free moonshotai/kimi-k2:free | free
moonshotai/kimi-k2-0905 | paid moonshotai/kimi-k2-0905 | paid
moonshotai/kimi-vl-a3b-thinking | paid moonshotai/kimi-k2-0905:exacto | paid
moonshotai/kimi-vl-a3b-thinking:free | free moonshotai/kimi-k2-thinking | paid
morph/morph-v3-fast | paid morph/morph-v3-fast | paid
morph/morph-v3-large | paid morph/morph-v3-large | paid
gryphe/mythomax-l2-13b | paid gryphe/mythomax-l2-13b | paid
neversleep/llama-3-lumimaid-70b | paid
neversleep/llama-3.1-lumimaid-8b | paid neversleep/llama-3.1-lumimaid-8b | paid
nex-agi/deepseek-v3.1-nex-n1:free | free
neversleep/noromaid-20b | paid neversleep/noromaid-20b | paid
nousresearch/deephermes-3-llama-3-8b-preview:free | free
nousresearch/deephermes-3-mistral-24b-preview | paid nousresearch/deephermes-3-mistral-24b-preview | paid
nousresearch/hermes-3-llama-3.1-405b | paid nousresearch/hermes-3-llama-3.1-405b | paid
nousresearch/hermes-3-llama-3.1-405b:free | free
nousresearch/hermes-3-llama-3.1-70b | paid nousresearch/hermes-3-llama-3.1-70b | paid
nousresearch/hermes-4-405b | paid nousresearch/hermes-4-405b | paid
nousresearch/hermes-4-70b | paid nousresearch/hermes-4-70b | paid
nousresearch/hermes-2-pro-llama-3-8b | paid nousresearch/hermes-2-pro-llama-3-8b | paid
nvidia/llama-3.1-nemotron-70b-instruct | paid nvidia/llama-3.1-nemotron-70b-instruct | paid
nvidia/llama-3.1-nemotron-ultra-253b-v1 | paid nvidia/llama-3.1-nemotron-ultra-253b-v1 | paid
nvidia/llama-3.1-nemotron-ultra-253b-v1:free | free nvidia/llama-3.3-nemotron-super-49b-v1.5 | paid
nvidia/nemotron-3-nano-30b-a3b | paid
nvidia/nemotron-3-nano-30b-a3b:free | free
nvidia/nemotron-nano-12b-v2-vl | paid
nvidia/nemotron-nano-12b-v2-vl:free | free
nvidia/nemotron-nano-9b-v2 | paid nvidia/nemotron-nano-9b-v2 | paid
nvidia/nemotron-nano-9b-v2:free | free nvidia/nemotron-nano-9b-v2:free | free
openai/chatgpt-4o-latest | paid openai/chatgpt-4o-latest | paid
@ -259,28 +259,44 @@ export interface IKBotOptions {
openai/gpt-4o-mini-search-preview | paid openai/gpt-4o-mini-search-preview | paid
openai/gpt-5 | paid openai/gpt-5 | paid
openai/gpt-5-chat | paid openai/gpt-5-chat | paid
openai/gpt-5-codex | paid
openai/gpt-5-image | paid
openai/gpt-5-image-mini | paid
openai/gpt-5-mini | paid openai/gpt-5-mini | paid
openai/gpt-5-nano | paid openai/gpt-5-nano | paid
openai/gpt-5-pro | paid
openai/gpt-5.1 | paid
openai/gpt-5.1-chat | paid
openai/gpt-5.1-codex | paid
openai/gpt-5.1-codex-max | paid
openai/gpt-5.1-codex-mini | paid
openai/gpt-5.2 | paid
openai/gpt-5.2-chat | paid
openai/gpt-5.2-pro | paid
openai/gpt-oss-120b | paid openai/gpt-oss-120b | paid
openai/gpt-oss-120b:exacto | paid
openai/gpt-oss-120b:free | free openai/gpt-oss-120b:free | free
openai/gpt-oss-20b | paid openai/gpt-oss-20b | paid
openai/gpt-oss-20b:free | free openai/gpt-oss-20b:free | free
openai/gpt-oss-safeguard-20b | paid
openai/o1 | paid openai/o1 | paid
openai/o1-mini | paid
openai/o1-mini-2024-09-12 | paid
openai/o1-pro | paid openai/o1-pro | paid
openai/o3 | paid openai/o3 | paid
openai/o3-deep-research | paid
openai/o3-mini | paid openai/o3-mini | paid
openai/o3-mini-high | paid openai/o3-mini-high | paid
openai/o3-pro | paid openai/o3-pro | paid
openai/o4-mini | paid openai/o4-mini | paid
openai/o4-mini-deep-research | paid
openai/o4-mini-high | paid openai/o4-mini-high | paid
perplexity/r1-1776 | paid opengvlab/internvl3-78b | paid
perplexity/sonar | paid perplexity/sonar | paid
perplexity/sonar-deep-research | paid perplexity/sonar-deep-research | paid
perplexity/sonar-pro | paid perplexity/sonar-pro | paid
perplexity/sonar-pro-search | paid
perplexity/sonar-reasoning | paid perplexity/sonar-reasoning | paid
perplexity/sonar-reasoning-pro | paid perplexity/sonar-reasoning-pro | paid
prime-intellect/intellect-3 | paid
qwen/qwen-plus-2025-07-28 | paid qwen/qwen-plus-2025-07-28 | paid
qwen/qwen-plus-2025-07-28:thinking | paid qwen/qwen-plus-2025-07-28:thinking | paid
qwen/qwen-vl-max | paid qwen/qwen-vl-max | paid
@ -288,85 +304,92 @@ export interface IKBotOptions {
qwen/qwen-max | paid qwen/qwen-max | paid
qwen/qwen-plus | paid qwen/qwen-plus | paid
qwen/qwen-turbo | paid qwen/qwen-turbo | paid
qwen/qwen-2.5-7b-instruct | paid
qwen/qwen2.5-coder-7b-instruct | paid
qwen/qwen2.5-vl-32b-instruct | paid qwen/qwen2.5-vl-32b-instruct | paid
qwen/qwen2.5-vl-32b-instruct:free | free
qwen/qwen2.5-vl-72b-instruct | paid qwen/qwen2.5-vl-72b-instruct | paid
qwen/qwen2.5-vl-72b-instruct:free | free
qwen/qwen-2.5-vl-7b-instruct | paid qwen/qwen-2.5-vl-7b-instruct | paid
qwen/qwen-2.5-vl-7b-instruct:free | free
qwen/qwen3-14b | paid qwen/qwen3-14b | paid
qwen/qwen3-14b:free | free
qwen/qwen3-235b-a22b | paid qwen/qwen3-235b-a22b | paid
qwen/qwen3-235b-a22b:free | free
qwen/qwen3-235b-a22b-2507 | paid qwen/qwen3-235b-a22b-2507 | paid
qwen/qwen3-235b-a22b-thinking-2507 | paid qwen/qwen3-235b-a22b-thinking-2507 | paid
qwen/qwen3-30b-a3b | paid qwen/qwen3-30b-a3b | paid
qwen/qwen3-30b-a3b:free | free
qwen/qwen3-30b-a3b-instruct-2507 | paid qwen/qwen3-30b-a3b-instruct-2507 | paid
qwen/qwen3-30b-a3b-thinking-2507 | paid qwen/qwen3-30b-a3b-thinking-2507 | paid
qwen/qwen3-32b | paid qwen/qwen3-32b | paid
qwen/qwen3-4b:free | free qwen/qwen3-4b:free | free
qwen/qwen3-8b | paid qwen/qwen3-8b | paid
qwen/qwen3-8b:free | free
qwen/qwen3-coder-30b-a3b-instruct | paid qwen/qwen3-coder-30b-a3b-instruct | paid
qwen/qwen3-coder | paid qwen/qwen3-coder | paid
qwen/qwen3-coder:exacto | paid
qwen/qwen3-coder:free | free qwen/qwen3-coder:free | free
qwen/qwen3-coder-flash | paid
qwen/qwen3-coder-plus | paid
qwen/qwen3-max | paid qwen/qwen3-max | paid
qwen/qwen3-next-80b-a3b-instruct | paid qwen/qwen3-next-80b-a3b-instruct | paid
qwen/qwen3-next-80b-a3b-thinking | paid qwen/qwen3-next-80b-a3b-thinking | paid
qwen/qwen3-vl-235b-a22b-instruct | paid
qwen/qwen3-vl-235b-a22b-thinking | paid
qwen/qwen3-vl-30b-a3b-instruct | paid
qwen/qwen3-vl-30b-a3b-thinking | paid
qwen/qwen3-vl-32b-instruct | paid
qwen/qwen3-vl-8b-instruct | paid
qwen/qwen3-vl-8b-thinking | paid
qwen/qwq-32b | paid qwen/qwq-32b | paid
qwen/qwq-32b:free | free
qwen/qwq-32b-preview | paid
qwen/qwen-2.5-72b-instruct | paid qwen/qwen-2.5-72b-instruct | paid
qwen/qwen-2.5-72b-instruct:free | free
qwen/qwen-2.5-7b-instruct | paid
qwen/qwen-2.5-coder-32b-instruct | paid qwen/qwen-2.5-coder-32b-instruct | paid
qwen/qwen-2.5-coder-32b-instruct:free | free relace/relace-apply-3 | paid
rekaai/reka-flash-3:free | free relace/relace-search | paid
undi95/remm-slerp-l2-13b | paid undi95/remm-slerp-l2-13b | paid
sao10k/l3-lunaris-8b | paid sao10k/l3-lunaris-8b | paid
sao10k/l3-euryale-70b | paid sao10k/l3-euryale-70b | paid
sao10k/l3.1-70b-hanami-x1 | paid
sao10k/l3.1-euryale-70b | paid sao10k/l3.1-euryale-70b | paid
sao10k/l3.3-euryale-70b | paid sao10k/l3.3-euryale-70b | paid
shisa-ai/shisa-v2-llama3.3-70b | paid
shisa-ai/shisa-v2-llama3.3-70b:free | free
openrouter/sonoma-dusk-alpha | paid
openrouter/sonoma-sky-alpha | paid
raifle/sorcererlm-8x22b | paid raifle/sorcererlm-8x22b | paid
stepfun-ai/step3 | paid stepfun-ai/step3 | paid
switchpoint/router | paid switchpoint/router | paid
tencent/hunyuan-a13b-instruct | paid tencent/hunyuan-a13b-instruct | paid
tencent/hunyuan-a13b-instruct:free | free thedrummer/cydonia-24b-v4.1 | paid
thedrummer/anubis-70b-v1.1 | paid
thedrummer/anubis-pro-105b-v1 | paid
thedrummer/rocinante-12b | paid thedrummer/rocinante-12b | paid
thedrummer/skyfall-36b-v2 | paid thedrummer/skyfall-36b-v2 | paid
thedrummer/unslopnemo-12b | paid thedrummer/unslopnemo-12b | paid
thudm/glm-4-32b | paid
thudm/glm-4.1v-9b-thinking | paid thudm/glm-4.1v-9b-thinking | paid
thudm/glm-z1-32b | paid
tngtech/deepseek-r1t-chimera | paid tngtech/deepseek-r1t-chimera | paid
tngtech/deepseek-r1t-chimera:free | free tngtech/deepseek-r1t-chimera:free | free
tngtech/deepseek-r1t2-chimera | paid
tngtech/deepseek-r1t2-chimera:free | free tngtech/deepseek-r1t2-chimera:free | free
tngtech/tng-r1t-chimera | paid
tngtech/tng-r1t-chimera:free | free
alibaba/tongyi-deepresearch-30b-a3b | paid
alibaba/tongyi-deepresearch-30b-a3b:free | free
cognitivecomputations/dolphin-mistral-24b-venice-edition:free | free cognitivecomputations/dolphin-mistral-24b-venice-edition:free | free
microsoft/wizardlm-2-8x22b | paid microsoft/wizardlm-2-8x22b | paid
x-ai/grok-2-1212 | paid
x-ai/grok-2-vision-1212 | paid
x-ai/grok-3 | paid x-ai/grok-3 | paid
x-ai/grok-3-beta | paid x-ai/grok-3-beta | paid
x-ai/grok-3-mini | paid x-ai/grok-3-mini | paid
x-ai/grok-3-mini-beta | paid x-ai/grok-3-mini-beta | paid
x-ai/grok-4 | paid x-ai/grok-4 | paid
x-ai/grok-4-fast | paid
x-ai/grok-4.1-fast | paid
x-ai/grok-code-fast-1 | paid x-ai/grok-code-fast-1 | paid
xiaomi/mimo-v2-flash:free | free
z-ai/glm-4-32b | paid z-ai/glm-4-32b | paid
z-ai/glm-4.5 | paid z-ai/glm-4.5 | paid
z-ai/glm-4.5-air | paid z-ai/glm-4.5-air | paid
z-ai/glm-4.5-air:free | free z-ai/glm-4.5-air:free | free
z-ai/glm-4.5v | paid z-ai/glm-4.5v | paid
z-ai/glm-4.6 | paid
z-ai/glm-4.6:exacto | paid
z-ai/glm-4.6v | paid
z-ai/glm-4.7 | paid
 
 OpenAI models:  OpenAI models:
 
babbage-002 babbage-002
chatgpt-4o-latest chatgpt-4o-latest
chatgpt-image-latest
codex-mini-latest codex-mini-latest
dall-e-2 dall-e-2
dall-e-3 dall-e-3
@ -395,7 +418,6 @@ export interface IKBotOptions {
gpt-4o-2024-08-06 gpt-4o-2024-08-06
gpt-4o-2024-11-20 gpt-4o-2024-11-20
gpt-4o-audio-preview gpt-4o-audio-preview
gpt-4o-audio-preview-2024-10-01
gpt-4o-audio-preview-2024-12-17 gpt-4o-audio-preview-2024-12-17
gpt-4o-audio-preview-2025-06-03 gpt-4o-audio-preview-2025-06-03
gpt-4o-mini gpt-4o-mini
@ -407,30 +429,56 @@ export interface IKBotOptions {
gpt-4o-mini-search-preview gpt-4o-mini-search-preview
gpt-4o-mini-search-preview-2025-03-11 gpt-4o-mini-search-preview-2025-03-11
gpt-4o-mini-transcribe gpt-4o-mini-transcribe
gpt-4o-mini-transcribe-2025-03-20
gpt-4o-mini-transcribe-2025-12-15
gpt-4o-mini-tts gpt-4o-mini-tts
gpt-4o-mini-tts-2025-03-20
gpt-4o-mini-tts-2025-12-15
gpt-4o-realtime-preview gpt-4o-realtime-preview
gpt-4o-realtime-preview-2024-10-01
gpt-4o-realtime-preview-2024-12-17 gpt-4o-realtime-preview-2024-12-17
gpt-4o-realtime-preview-2025-06-03 gpt-4o-realtime-preview-2025-06-03
gpt-4o-search-preview gpt-4o-search-preview
gpt-4o-search-preview-2025-03-11 gpt-4o-search-preview-2025-03-11
gpt-4o-transcribe gpt-4o-transcribe
gpt-4o-transcribe-diarize
gpt-5 gpt-5
gpt-5-2025-08-07 gpt-5-2025-08-07
gpt-5-chat-latest gpt-5-chat-latest
gpt-5-codex
gpt-5-mini gpt-5-mini
gpt-5-mini-2025-08-07 gpt-5-mini-2025-08-07
gpt-5-nano gpt-5-nano
gpt-5-nano-2025-08-07 gpt-5-nano-2025-08-07
gpt-5-pro
gpt-5-pro-2025-10-06
gpt-5-search-api
gpt-5-search-api-2025-10-14
gpt-5.1
gpt-5.1-2025-11-13
gpt-5.1-chat-latest
gpt-5.1-codex
gpt-5.1-codex-max
gpt-5.1-codex-mini
gpt-5.2
gpt-5.2-2025-12-11
gpt-5.2-chat-latest
gpt-5.2-pro
gpt-5.2-pro-2025-12-11
gpt-audio gpt-audio
gpt-audio-2025-08-28 gpt-audio-2025-08-28
gpt-audio-mini
gpt-audio-mini-2025-10-06
gpt-audio-mini-2025-12-15
gpt-image-1 gpt-image-1
gpt-image-1-mini
gpt-image-1.5
gpt-realtime gpt-realtime
gpt-realtime-2025-08-28 gpt-realtime-2025-08-28
gpt-realtime-mini
gpt-realtime-mini-2025-10-06
gpt-realtime-mini-2025-12-15
o1 o1
o1-2024-12-17 o1-2024-12-17
o1-mini
o1-mini-2024-09-12
o1-pro o1-pro
o1-pro-2025-03-19 o1-pro-2025-03-19
o3 o3
@ -443,6 +491,8 @@ export interface IKBotOptions {
o4-mini-deep-research-2025-06-26 o4-mini-deep-research-2025-06-26
omni-moderation-2024-09-26 omni-moderation-2024-09-26
omni-moderation-latest omni-moderation-latest
sora-2
sora-2-pro
text-embedding-3-large text-embedding-3-large
text-embedding-3-small text-embedding-3-small
text-embedding-ada-002 text-embedding-ada-002

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@
"keyv-file": "^5.1.3", "keyv-file": "^5.1.3",
"marked": "^15.0.4", "marked": "^15.0.4",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"nodemailer": "^6.9.16", "nodemailer": "^7.0.13",
"openai": "^5.8.2", "openai": "^5.8.2",
"p-map": "^7.0.3", "p-map": "^7.0.3",
"rotating-file-stream": "^3.2.6", "rotating-file-stream": "^3.2.6",

2
packages/cache/package-lock.json generated vendored
View File

@ -33,6 +33,7 @@
"@polymech/fs": "file:../fs", "@polymech/fs": "file:../fs",
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -1224,6 +1225,7 @@
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"@types/node": "^22.12.0", "@types/node": "^22.12.0",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",

View File

@ -1,12 +1,12 @@
{ {
"name": "@polymech/cad", "name": "@polymech/cad",
"version": "1.8.8", "version": "1.8.9",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@polymech/cad", "name": "@polymech/cad",
"version": "1.8.8", "version": "1.8.9",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@polymech/cache": "file:..\\cache", "@polymech/cache": "file:..\\cache",
@ -32,7 +32,7 @@
"zod": "^4.3.6" "zod": "^4.3.6"
}, },
"bin": { "bin": {
"polymech-cad": "dist/main.js" "polymech-cad": "dist-in/main.js"
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
@ -7328,6 +7328,7 @@
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.27.0", "esbuild": "^0.27.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",

View File

@ -67,6 +67,27 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
"license": "MIT",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@isaacs/brace-expansion": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
"license": "MIT",
"dependencies": {
"@isaacs/balanced-match": "^4.0.1"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@isaacs/cliui": { "node_modules/@isaacs/cliui": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -247,9 +268,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
@ -388,9 +409,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/diff": { "node_modules/diff": {
"version": "4.0.2", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
@ -419,12 +440,12 @@
} }
}, },
"node_modules/foreground-child": { "node_modules/foreground-child": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cross-spawn": "^7.0.0", "cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1" "signal-exit": "^4.0.1"
}, },
"engines": { "engines": {
@ -456,9 +477,9 @@
} }
}, },
"node_modules/glob": { "node_modules/glob": {
"version": "10.4.5", "version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
@ -585,12 +606,12 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "10.0.1", "version": "10.1.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
"license": "ISC", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "@isaacs/brace-expansion": "^5.0.0"
}, },
"engines": { "engines": {
"node": "20 || >=22" "node": "20 || >=22"
@ -694,14 +715,14 @@
} }
}, },
"node_modules/rimraf/node_modules/glob": { "node_modules/rimraf/node_modules/glob": {
"version": "11.0.1", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
"integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"license": "ISC", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.3.1",
"jackspeak": "^4.0.1", "jackspeak": "^4.1.1",
"minimatch": "^10.0.0", "minimatch": "^10.1.1",
"minipass": "^7.1.2", "minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0", "package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0" "path-scurry": "^2.0.0"
@ -717,9 +738,9 @@
} }
}, },
"node_modules/rimraf/node_modules/jackspeak": { "node_modules/rimraf/node_modules/jackspeak": {
"version": "4.0.3", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
"integrity": "sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==", "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"@isaacs/cliui": "^8.0.2" "@isaacs/cliui": "^8.0.2"

View File

@ -76,6 +76,7 @@
"@polymech/fs": "file:../fs", "@polymech/fs": "file:../fs",
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -2346,6 +2347,7 @@
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"@types/node": "^22.12.0", "@types/node": "^22.12.0",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",

View File

@ -30,7 +30,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.18.0", "@eslint/js": "^9.18.0",
"@types/node": "^22.10.9", "@types/node": "^22.10.9",
"eslint": "^8.57.1", "eslint": "^9.39.2",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-regexp": "^2.7.0", "eslint-plugin-regexp": "^2.7.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",

View File

@ -1944,7 +1944,6 @@
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@vitest/expect": "4.0.18", "@vitest/expect": "4.0.18",
"@vitest/mocker": "4.0.18", "@vitest/mocker": "4.0.18",

View File

@ -81,6 +81,7 @@
"@polymech/fs": "file:../fs", "@polymech/fs": "file:../fs",
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -2479,6 +2480,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -2516,6 +2518,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1", "fast-uri": "^3.0.1",
@ -3019,6 +3022,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001733", "caniuse-lite": "^1.0.30001733",
"electron-to-chromium": "^1.5.199", "electron-to-chromium": "^1.5.199",
@ -6599,6 +6603,7 @@
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -7260,6 +7265,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
}, },
@ -8869,6 +8875,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -8989,6 +8996,7 @@
"integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==", "integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.6", "fdir": "^6.4.6",
@ -9189,6 +9197,7 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz",
"integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==", "integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.7", "@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8", "@types/estree": "^1.0.8",
@ -9237,6 +9246,7 @@
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz",
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@discoveryjs/json-ext": "^0.6.1", "@discoveryjs/json-ext": "^0.6.1",
"@webpack-cli/configtest": "^3.0.1", "@webpack-cli/configtest": "^3.0.1",
@ -10347,6 +10357,7 @@
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"@types/node": "^22.12.0", "@types/node": "^22.12.0",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -11023,7 +11034,8 @@
"acorn": { "acorn": {
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==" "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"peer": true
}, },
"acorn-import-phases": { "acorn-import-phases": {
"version": "1.0.4", "version": "1.0.4",
@ -11044,6 +11056,7 @@
"version": "8.17.1", "version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"peer": true,
"requires": { "requires": {
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1", "fast-uri": "^3.0.1",
@ -11395,6 +11408,7 @@
"version": "4.25.2", "version": "4.25.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz",
"integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==",
"peer": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30001733", "caniuse-lite": "^1.0.30001733",
"electron-to-chromium": "^1.5.199", "electron-to-chromium": "^1.5.199",
@ -13804,7 +13818,8 @@
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true "dev": true,
"peer": true
}, },
"pify": { "pify": {
"version": "4.0.1", "version": "4.0.1",
@ -14239,6 +14254,7 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"peer": true,
"requires": { "requires": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
@ -15322,7 +15338,8 @@
"typescript": { "typescript": {
"version": "5.8.3", "version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==" "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"peer": true
}, },
"unbzip2-stream": { "unbzip2-stream": {
"version": "1.4.3", "version": "1.4.3",
@ -15386,6 +15403,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz",
"integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==", "integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.6", "fdir": "^6.4.6",
@ -15468,6 +15486,7 @@
"version": "5.101.1", "version": "5.101.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz",
"integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==", "integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==",
"peer": true,
"requires": { "requires": {
"@types/eslint-scope": "^3.7.7", "@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8", "@types/estree": "^1.0.8",
@ -15500,6 +15519,7 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz",
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
"peer": true,
"requires": { "requires": {
"@discoveryjs/json-ext": "^0.6.1", "@discoveryjs/json-ext": "^0.6.1",
"@webpack-cli/configtest": "^3.0.1", "@webpack-cli/configtest": "^3.0.1",

View File

@ -1,11 +1,11 @@
{ {
"name": "@plastichub/osr-registry", "name": "@polymech/registry",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@plastichub/osr-registry", "name": "@polymech/registry",
"version": "0.1.0", "version": "0.1.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
@ -39,6 +39,7 @@
"@polymech/fs": "file:../fs", "@polymech/fs": "file:../fs",
"@repo/typescript-config": "file:../typescript-config", "@repo/typescript-config": "file:../typescript-config",
"@schemastore/package": "^0.0.10", "@schemastore/package": "^0.0.10",
"ansi-regex": "^6.2.2",
"env-var": "^7.5.0", "env-var": "^7.5.0",
"glob": "^10.4.5", "glob": "^10.4.5",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@ -121,7 +122,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.18.0", "@eslint/js": "^9.18.0",
"@types/node": "^22.10.9", "@types/node": "^22.10.9",
"eslint": "^8.57.1", "eslint": "^9.39.2",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-regexp": "^2.7.0", "eslint-plugin-regexp": "^2.7.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",

View File

@ -0,0 +1,49 @@
#!/bin/bash
# This script runs 'npm install' in a predefined list of directories.
# Exit immediately if a command exits with a non-zero status.
set -e
# List of directories to process
DIRECTORIES=(
"core"
"fs"
"cache"
"ai"
"commons"
"log"
"ai-tools"
"i18n"
"cad"
"media"
"mail"
"tasks"
"sync"
"search"
"registry"
"kbot"
)
# Get the current working directory
CWD=$(pwd)
# Loop through all the directories in the list
for dir in "${DIRECTORIES[@]}"; do
# Check if it's a directory
if [ -d "$dir" ]; then
if [ -d "$dir/node_modules" ]; then
echo "==> Skipping '$dir', node_modules already exists."
else
echo "==> Changing to directory '$dir' and running 'npm install'"
cd "$dir"
npm install
cd "$CWD"
echo "<== Done with '$dir'"
fi
else
echo "Warning: '$dir' is not a directory. Skipping."
fi
done
echo "All installations complete."

File diff suppressed because it is too large Load Diff

View File

@ -73,5 +73,8 @@
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"keywords": [ "keywords": [
"typescript" "typescript"
] ],
"overrides": {
"puppeteer": "$puppeteer"
}
} }

View File

@ -1,69 +0,0 @@
import * as pMap from 'p-map'
import * as path from 'path'
import { isArray } from '@plastichub/core/primitives'
import { convert as cadConvert } from '@plastichub/osr-cad/cad/sw-lib'
import { SolidworkOptions } from '@plastichub/osr-cad'
import { sanitize } from '@plastichub/osr-cad/sw_argv'
import { resolve } from '@plastichub/osr-commons'
import { logger } from '../src'
import { option } from '../library'
export interface ICadTask {
src: string | string[]
output: string
options: any
}
const create_cad_options = (src: string, dst: string, options: SolidworkOptions) => {
return { ...options, src, dst }
}
const convert = async (src, options, output) => {
const args = create_cad_options(src, output, options);
const syncArgs = sanitize({
...args,
...options
})
return cadConvert(syncArgs)
}
const convertFiles = async (items, options, output) => {
return (pMap as any)(items, async (s) => {
return convert(s, options, output)
}, {
concurrency: 1
})
}
export const register = (grunt) => {
grunt.registerMultiTask('cad', 'converts CAD files', function () {
const done = this.async()
const task_options = this.data.options || {}
const options: SolidworkOptions = {
...this.data.options,
root: option('root', task_options, grunt, path.resolve('./')),
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
sw: option('sw', task_options, grunt),
swv: option('swv', task_options, grunt),
args: option('args', task_options, grunt),
dry: option('dry', task_options, grunt),
onNode: option('onNode', task_options, grunt),
cache: option('cache', task_options, grunt, true),
report: option('report', task_options, grunt),
configuration: option('configuration', task_options, grunt),
hidden: option('hidden', task_options, grunt),
quality: option('quality', task_options, grunt),
renderer: option('renderer', task_options, grunt),
view: option('view', task_options, grunt),
close: option('close', task_options, grunt, true),
logLevel: option('logLevel', task_options, grunt, 'warn')
}
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
try {
convertFiles(src, options, this.data.output).then(done)
} catch (e) {
logger.error('Error converting files', e)
}
})
}

View File

@ -1,385 +0,0 @@
import * as path from 'path'
import * as md5 from 'md5'
import * as pMap from 'p-map'
import { IOptions, ICompileOptions, compilerOptions } from '@plastichub/osrl/types'
import { Engine as engine } from '@plastichub/osrl/Engine'
import { parse } from '@plastichub/osrl/options'
import { get_cached, set_cached } from '@plastichub/osr-cache/lib'
import { OSR_CACHE, OSR_ROOT } from '@plastichub/osr-commons/config'
import { isFile, resolve, substitute, pathInfo, pathInfoEx } from '@plastichub/osr-commons'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as read } from '@plastichub/fs/read'
import { sync as write } from '@plastichub/fs/write'
import { sync as rm } from '@plastichub/fs/remove'
import { taskOptions } from '../src/zod_schema'
import { ICompileTaskOptions } from '../src/zod_types'
import { logger } from '../src'
import { option, gruntOptions } from '../library'
import {
MODULE_NAME
} from '../src/constants'
import { TLogLevelName } from 'tslog'
import { I18N_STORE } from '../src/config'
const chokidar = require("chokidar")
const lockMap = {}
const fileAsBuffer = (path: string) => read(path, 'buffer') as Buffer || Buffer.from("-")
export type onCompileDone = (source: string, target: string, options: IOptions, content: string) => Promise<void>
export type ICompileTaskOptions2 = IOptions & {
watchContent?: boolean
debugWatch?: boolean
clear?: boolean
onCompile?: (options: IOptions) => Promise<IOptions | null>
onCompiled?: (source: string, target: string, content: string) => Promise<string | null>
onCompileDone?: (source: string, target: string, options: IOptions, content: string) => Promise<void>
}
export interface ICompileTaskData {
options: ICompileTaskOptions
src: string[]
}
export const createContent = async (file: string, _options: any) => {
if (!exists(file)) {
logger.error(`Source file ${file} not found`)
return false
}
const parts = path.parse(file)
const rel = path.relative(_options.root, file)
let output = _options.output
let outputInfo = pathInfo(_options.output)
const variables = {
root: _options.root || '.',
cwd: _options.cwd || path.resolve('.'),
..._options.variables
}
if (!outputInfo.FILE_EXT) {
output = path.resolve(`${_options.output}/${path.parse(rel).dir}/${parts.name}.md`)
} else {
output = path.resolve(resolve(output, false, variables));
}
const defaults: any = {
language: _options.language,
debug: _options.debug,
profile: _options.profile,
output: output,
plugins: _options.plugins,
env: _options.env || 'library',
cwd: _options.cwd || path.resolve('.'),
source: file,
variables,
user: _options.user,
template: _options.template,
targetLanguage: _options.targetLanguage,
sourceLanguage: _options.sourceLanguage
}
const options = parse(defaults, defaults)
debugger
let eOptions = {
...options,
root: [
...options.profile.includes,
path.parse(file).dir
],
toHTML: false,
cache: false,
keepOutputType: true,
trimTagRight: false,
trimTagLeft: false,
trimOutputRight: false,
trimOutputLeft: false,
greedy: false
} as IOptions
const Engine = new engine(eOptions)
if (_options.onCompile) {
const newOpts = await _options.onCompile(options)
if (newOpts) {
eOptions = newOpts
}
}
options.source = path.resolve(options.source)
const osr_cache = OSR_CACHE()
let dst = path.resolve(resolve(output, false, options.variables))
const cache_key = {
file,
dst,
targetLanguage: eOptions.targetLanguage,
sourceLanguage: eOptions.sourceLanguage,
language: eOptions.language,
format: eOptions.format
}
const done = async (content) => {
const contentCompiled = await _options.onCompiled(options.source, output, content)
if(contentCompiled) {
content = contentCompiled
}else{
logger.warn(`onCompiled returned nothing : ${options.source}`)
}
if (_options.onCompileDone) {
await _options.onCompileDone(options.source, dst, options, content)
}
}
let cached = await get_cached(options.source, cache_key, _options.module || MODULE_NAME)
if (osr_cache && cached && _options.cache !== false) {
let md5Src = md5(Buffer.from(cached));
let md5Dst = md5(fileAsBuffer(options.output));
if (!exists(options.output) || md5Src !== md5Dst) {
write(options.output, cached);
}
logger.debug(`Compile file ${file} : serving from cache`)
lockMap[file] = false
cached = await done(cached)
return cached
}
let content = await Engine.render(options.source, options.variables)
if (!content) {
logger.error(`Error compiling ${options.source} to ${options.output}`)
lockMap[file] = false
return false
}
if (_options.onCompiled) {
const contentCompiled = await _options.onCompiled(options.source, output, content)
if(contentCompiled) {
content = contentCompiled
}else{
logger.warn(`onCompiled returned nothing : ${options.source}`)
}
}
if (osr_cache && _options.cache !== false) {
logger.debug('Write output to cache', output)
await set_cached(options.source, cache_key, _options.module || MODULE_NAME, content)
}
dst && content && write(dst, content)
if (_options.onCompileDone) {
await _options.onCompileDone(options.source, dst, options, content)
}
lockMap[file] = false
logger.info(`Compiled ${file} to: ${dst} `)
return content
}
const watch = async (src, options) => {
const dInfo = pathInfo(src, false, options.cwd)
src = path.resolve(src)
const dir = dInfo.IS_GLOB ? dInfo.DIR : src
const watcher = chokidar.watch(`${dir}`, {
ignored: /(^|[\/\\])\../,
persistent: true,
ignoreInitial: false,
followSymlinks: true,
disableGlobbing: false,
usePolling: false,
interval: 1000,
binaryInterval: 300,
alwaysStat: false,
depth: 99,
awaitWriteFinish: {
stabilityThreshold: 2500,
pollInterval: 2000
},
ignorePermissionErrors: false,
atomic: 2000
})
watcher.on('addDir', path => logger.debug(`Directory ${path} has been added`))
.on('unlinkDir', path => logger.debug(`Directory ${path} has been removed`))
.on('error', error => logger.debug(`Watcher error: ${error}`))
.on('raw', (event, _path, details) => {
if (!_path.endsWith(dInfo.FILE_EXT)) {
return
}
switch (event) {
case 'rename': {
const rel = path.relative(dir, path.parse(details.watchedPath).dir)
const dst = path.resolve(`${options.output}/${rel}/${_path}`)
if (exists(dst)) {
rm(dst)
}
const _src = path.resolve(`${details.watchedPath}`)
if (lockMap[_src]) {
return
}
if (exists(_src) && isFile(_src)) {
lockMap[_src] = true
createContent(_src, { ...options })
}
break
}
case 'change': {
let _src = ''
if (isFile(details.watchedPath)) {
_src = `${details.watchedPath}`
} else {
_src = path.resolve(`${details.watchedPath}/${_path}`)
}
if (!exists(details.watchedPath)) {
return
}
if (lockMap[_src]) {
return
}
if (exists(_src) && isFile(_src)) {
lockMap[_src] = true
createContent(_src, { ...options })
setTimeout(() => { lockMap[_src] = false }, 3000)
}
break;
}
}
})
return watcher
}
const compileAllEx = async (files, options) => await pMap(files, (f: string) => createContent(f, options), { concurrency: 1 })
export const register = (grunt) => {
grunt.registerMultiTask('compile', 'Compile ', async function () {
const done = this.async()
const task_options = this.data.options
const cwd = path.resolve(option('cwd', task_options, grunt, process.cwd()))
const options: ICompileTaskOptions2 = {
...this.data.options,
cache: option('cache', task_options, grunt, true),
clear: option('clear', task_options, grunt, false),
debug: option('debug', task_options, grunt),
debugWatch: option('debugWatch', task_options, grunt),
env: option('env', task_options, grunt),
format: option('format', task_options, grunt, 'html'),
lang: option('lang', task_options, grunt, 'osr'),
language: option('language', task_options, grunt, 'en'),
sourceLanguage: option('sourceLanguage', task_options, grunt, 'en'),
targetLanguage: option('targetLanguage', task_options, grunt, 'en'),
logLevel: option('logLevel', task_options, grunt, 'warn'),
module: option('module', task_options, grunt),
onCompiled: option('onCompiled', task_options, grunt),
onCompileDone: option('onCompileDone', task_options, grunt),
onCompile: option('onCompile', task_options, grunt),
plugins: option('plugins', task_options, grunt, ['${root}/osr/plugins']),
profile: option('profile', task_options, grunt, '${OSR_ROOT}/.osrl.json'),
root: option('root', task_options, grunt, path.resolve('./')),
template: option('template', task_options, grunt),
variables: option('variables', task_options, grunt, {}),
watchContent: option('watchContent', task_options, grunt, false)
}
logger.setSettings({ minLevel: options.logLevel as TLogLevelName })
if (task_options.watchContent) {
this.data.src.map(f => watch(f, options))
}
let _files = []
this.data.src.map(f => {
const fInfo = pathInfoEx(f, false, { cwd: cwd, absolute: true })
_files = _files.concat(fInfo.FILES)
})
if (!_files.length) {
logger.error(`Have no files or glob in ${cwd}`, this.data.src)
done()
return
}
logger.debug(`Compile - task data`, _files, this.data.options)
if (options.clear !== false) {
if (exists(options.output)) {
rm(options.output)
}
}
const all = await compileAllEx(_files, options)
grunt.event.emit('compile.done', { all, options })
if (!task_options.watchContent) {
logger.info('Done compiling all!')
done()
}
return new Promise((resolve) => {
if (!task_options.watchContent) {
resolve(true)
done()
}
})
})
}
export const contentTasks = (
grunt: IGrunt,
taskOpts: ICompileTaskOptions,
compilerOpts: ICompileOptions) => {
taskOpts =
{
...taskOptions().parse({
...taskOpts,
...gruntOptions(grunt)
})
}
compilerOpts = compilerOptions().parse(compilerOpts as any) as ICompileOptions
logger.setSettings({ minLevel: taskOpts.logLevel, prefix: [MODULE_NAME] })
// logger.warn(`Registering content tasks for ${taskOpts.taskPrefix}`,taskOpts)
const tasks = {}
const taskLanguages = taskOpts.languages as string[]
const taskLanguage = (lang) => {
const taskName = `${taskOpts.taskPrefix}-${lang}`
const config = {}
const taskVariables =
{
...compilerOpts.variables,
...gruntOptions(grunt),
targetLanguage: lang,
sourceLanguage: taskOpts.sourceLanguage,
i18n: I18N_STORE(OSR_ROOT(), lang)
}
config[taskName] = {
src: taskOpts.src,
options:
{
...compilerOpts as any,
variables: { ...taskVariables },
output: path.resolve(resolve(compilerOpts.output, false, taskVariables)),
...taskOpts,
...gruntOptions(grunt)
}
};
(grunt as any).extendConfig({ compile: config })
const substituteTask = (task: string) => substitute(false, task, {
...config[taskName].options.variables,
taskSuffix: taskOpts.taskSuffix,
taskPrefix: taskOpts.taskPrefix,
task
})
const tasksBefore = taskOpts.tasksBefore.map(substituteTask)
const tasksAfter = taskOpts.tasksAfter.map(substituteTask)
const languageTasks = [
...tasksBefore,
`compile:${taskName}`,
...tasksAfter,
]
grunt.registerTask(taskName, languageTasks)
tasks[lang] = {
taskName,
tasks: languageTasks
}
}
taskLanguages.forEach(taskLanguage)
return tasks
}
export * from '../src/zod_types'

View File

@ -1,51 +0,0 @@
import * as path from 'path'
import { JSONPath } from 'jsonpath-plus'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { resolve } from '@plastichub/osr-commons'
import {
MAIL_CONTACTS_ROOT,
QUERY_TEMPLATES
} from './config'
import { logger } from '../src'
import { cleanArray } from './utils'
export const resolveContactsPath = (mailerOptions) => {
if (!mailerOptions.contacts) {
return false
}
let contactFiles = path.resolve(resolve(mailerOptions.contacts))
if (!exists(contactFiles)) {
contactFiles = path.join(MAIL_CONTACTS_ROOT(), mailerOptions.contacts)
}
return contactFiles
}
export const getContacts = (mailerOptions) => {
let contactFiles = resolveContactsPath(mailerOptions)
if (!contactFiles) {
return []
}
logger.debug(`Reading Contact File : ${contactFiles}`)
let contacts = read(contactFiles, 'json') as any[]
if (!contacts) {
logger.error(`Cannot read contacts file ${contactFiles}`)
return []
}
return contacts
}
export const filterContacts = (grunt, contacts, mailerOptions) => {
if (!mailerOptions.query) {
return contacts
}
if (QUERY_TEMPLATES[mailerOptions.query]) {
mailerOptions.query = QUERY_TEMPLATES[mailerOptions.query](grunt.option('queryExtra'))
}
let queryResult = JSONPath({ path: mailerOptions.query, json: contacts })
logger.debug(`Query Result : ${queryResult.length} contacts : \n\t ${mailerOptions.query}`)
queryResult = cleanArray(queryResult)
return queryResult
}

View File

@ -1,30 +0,0 @@
import { logger } from '../src'
import { option } from '../library'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons/config'
import { resolve } from '@plastichub/osr-commons'
import { IOSRConfig } from '@plastichub/osr-commons'
export const register = (grunt) => {
grunt.registerMultiTask('cscart', 'Deploy product to CSCart', async function () {
const done = this.async();
const task_options = this.data.options || {}
const config = CONFIG_DEFAULT() as IOSRConfig
const options = {
...this.data.options,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
vendor: option('vendor', task_options, grunt)
}
const src = this.data.src.map(f => (resolve(f)))
options.debug && logger.info('Compile - task data ', process.cwd(), this.data, src)
// let ret = await updateProducts(src, config.cscart, options.vendor)
debugger;
});
};

View File

@ -1,63 +0,0 @@
import { simpleGit } from 'simple-git'
import { resolve } from '@plastichub/osr-commons'
import { logger } from '../src/index'
import { option } from '../library'
const GIT_MESSAGE_PREFIX = (rel: string) => `Updating - ${rel}`
export async function git_update(options) {
const { cwd, rel, message, debug } = options
const git = simpleGit(cwd)
let commit: any = null
let push: any = null
try {
debug && logger.debug("commit " + rel + " in " + cwd)
commit = await git.add(rel)
}
catch (e) {
logger.error('Error Git Commit', e)
}
try {
debug && logger.debug("commit " + rel + " in " + cwd)
commit = await git.commit(message || GIT_MESSAGE_PREFIX(rel), rel)
}
catch (e) {
logger.error('Error Git Commit', e)
}
try {
push = await git.push()
}
catch (e) {
logger.error('Error Git Push', e)
}
return { commit, push }
}
export const register = (grunt) => {
grunt.registerMultiTask('git', 'Adds, commits and pushes folders', async function () {
const done = this.async()
const task_options = this.data || {}
const logLevel = option('logLevel', task_options, grunt, 'warn')
logger.setSettings({ minLevel: logLevel })
let rel: string = this.data.rel
const variables = {
...task_options.variables || {}
}
const options = {
rel: resolve(rel, false, variables),
cwd: resolve(option('cwd', task_options, grunt), false),
message: option('message', task_options, grunt),
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
logLevel
}
logger.info('Git - task data ', this.data)
await git_update(options)
done()
})
}

View File

@ -1,55 +0,0 @@
import * as path from 'path'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
import { resolve } from '@plastichub/osr-commons'
import { IOptions } from '@plastichub/osr-i18n/types'
import { translate } from '@plastichub/osr-i18n/lib/translate'
import { sanitize } from '@plastichub/osr-i18n/_cli'
import { isArray } from '@plastichub/core/primitives'
import { logger } from '../src'
import { option } from '../library'
import * as pMap from 'p-map'
const _translate = async (src, dst, options) => {
const i18nOptions = sanitize(
{
...options,
src: src,
dst: dst,
debug: options.debug,
verbose: options.verbose,
dry: options.dry
}
) as IOptions
if (!i18nOptions) {
logger.error('Invalid i18n options')
return
}
return await translate(i18nOptions)
}
const translateAll = async (files, options, dst: string) => {
return pMap(files, async (f) => _translate(f, dst, options), { concurrency: 1 })
}
export const register = (grunt) => {
grunt.registerMultiTask('i18n', 'translate files via osr-i18n', async function () {
const done = this.async();
const task_options = this.data.options || {}
const config: any = CONFIG_DEFAULT()
const options = {
...this.data.options,
root: option('root', task_options, grunt, path.resolve('./')),
debug: option('debug', task_options, grunt , false),
logLevel: option('logLevel', task_options, grunt , 'warn'),
api_key: config.deepl.auth_key
}
logger.setSettings({ minLevel: options.logLevel })
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
logger.debug('Translate - task data ', this.data)
await translateAll(src, options, this.data.options.dst)
logger.info(`Translate - task done : \n\t ${src.join('\n\t')}`)
done()
})
}

View File

@ -1,55 +0,0 @@
import { Promise as BPromise } from 'bluebird'
import { isArray } from '@plastichub/core/primitives'
import { resolve } from '@plastichub/osr-commons'
import { IOptions as IResizeOptions } from '@plastichub/osr-media/types'
import { sanitize } from '@plastichub/osr-media/_cli'
import { resize } from '@plastichub/osr-media/lib/media/images'
import { logger } from '../src'
import { option } from '../library'
const convert = async (src, dst, options) => {
const resizeOptions = sanitize(
{
src: src,
dst: dst,
debug: options.debug,
verbose: options.verbose,
dry: options.dry
}
) as IResizeOptions
return await resize(resizeOptions)
}
const resizeFiles = async (items, dst, options) => {
return BPromise.resolve(items).map((s) => {
return convert(s, options, dst)
}, {
concurrency: 1
})
}
export const register = (grunt) => {
grunt.registerMultiTask('images-resize', 'resizes images', function () {
const done = this.async()
const task_options = this.data.options || {}
const options = {
...this.data.options,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
dry: option('dry', task_options, grunt)
}
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
src = src.map(f => (resolve(f)))
options.debug && logger.info('Images-Resize : Task data ', process.cwd(), this.data, src)
resizeFiles(src, options, this.data.dst).then(done)
})
}

View File

@ -1,213 +0,0 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { resolve, isFolder } from '@plastichub/osr-commons'
import { isArray } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { sync } from '@plastichub/osr-sync'
import { IAssemblyData } from '@plastichub/osr-cad/cad/sw-types'
import {
CAD_MAIN_PATTERN,
MainAssembly,
file_path_with_ext_ex,
forward_slash,
unique_by,
option
} from '../library'
import { logger } from '../src'
export const regexLaserFile = /^(\d+)_([a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+)*)_x(\d+)_(\d+)mm_(\w+)$/;
export const laserDetails = (input: string) => {
if(!input) {
return false
}
const match = (path.parse(input).name).match(regexLaserFile)
if (!match) {
const idMatch = input.match(/^(\d+)_/)
const nameMatch = input.match(/_(\w+)_/)
const quantityMatch = input.match(/_x\d+_/)
const thicknessMatch = input.match(/_\d+mm_/)
const materialMatch = input.match(/_\w+$/)
let errorMessage = 'Invalid input format:'
if (!idMatch) {
errorMessage += '\n- Leading ID (digits) is missing or invalid';
}
if (!nameMatch) {
errorMessage += '\n- Name (letters) is missing or invalid';
}
if (!quantityMatch) {
errorMessage += '\n- Quantity (x followed by digits) is missing or invalid';
}
if (!thicknessMatch) {
errorMessage += '\n- Thickness (digits followed by "mm") is missing or invalid';
}
if (!materialMatch) {
errorMessage += '\n- Material (alphanumeric characters) is missing or invalid';
}
logger.error(errorMessage)
return
}
const [_, id, name, quantity, thickness, material] = match
return {
id: parseInt(id),
name,
quantity: parseInt(quantity),
thickness: parseInt(thickness),
material
}
}
const parts_with_laser = (model) => {
let parts = [...model.filter((f) => f.IsLaser === "1"), ...model]
return parts.filter((f) => {
const _path = path.resolve(resolve(f['File Path']))
if (_path && exists(_path)) {
const dir = path.parse(_path).dir
const laser = path.resolve(path.join(dir, 'laser'))
if (exists(laser)) {
return f
}
}
})
}
const createLaserFiles = async (root, product, options, grunt) => {
if (!exists(root)) {
options.debug && logger.info("Create Laser Files : Root doesnt exists" + root)
}
const PRODUCT_ROOT = path.resolve(path.join(root, product))
if (!exists(PRODUCT_ROOT)) {
logger.warn(`Invalid product root : ${PRODUCT_ROOT}`)
return false
}
const main = MainAssembly(PRODUCT_ROOT, options.filePattern)
if (!main) {
logger.warn("Have no main assembly at " + PRODUCT_ROOT);
return false
}
const modelFilePath = file_path_with_ext_ex(main, 'json')
if (!modelFilePath || !exists(modelFilePath)) {
logger.warn("Have no model at " + modelFilePath)
return false
}
const model = read(modelFilePath, 'json')
let tree : IAssemblyData = null
const treeFilePath = file_path_with_ext_ex(main, 'tree.json')
if (!treeFilePath || !exists(treeFilePath)) {
logger.warn("Have no tree at " + treeFilePath)
}else{
tree = read(treeFilePath, 'json') as IAssemblyData
}
const laserParts = parts_with_laser(model)
let laserDirectories: any[] = [
...new Set(laserParts.map((f) => {
const _path = path.resolve(resolve(f['File Path']))
const dir = path.parse(_path).dir
const ret = {
target: forward_slash(path.relative(PRODUCT_ROOT, dir)).
replace('../components/', '').
replace('components', '').
replace('cad', '').
replace('../', ''),
path: dir + '/laser'
}
return ret
}))
]
const config: any = read(path.join(PRODUCT_ROOT, 'config.json'), 'json')
if (!config) {
return []
}
laserDirectories = unique_by(laserDirectories, 'path')
logger.debug('Create laser files for ', laserDirectories)
return (pMap as any)(laserDirectories, async (item) => {
return (pMap as any)(['en','es'], async (lCode) => {
const renamer = (from, to) => {
if (isFolder(from)) { return }
const lParts = laserDetails(from)
if(!lParts){
logger.warn(`Invalid laser file in ${PRODUCT_ROOT} : ${from}`)
}
const fromParts = path.parse('' + from)
const toParts = path.parse('' + to)
const pCode = config.code || ''
const toFileParts = ('' + toParts.name).split('_')
const fromFileParts = ('' + fromParts.name).split('_')
const thickness = fromFileParts[3]
let qty = fromFileParts[2]
let material = fromFileParts[4]
if (!material) {
logger.error('logger.error : invalid material ', from + ' : ' + ' to : ' + to, toFileParts)
return to
}
if (lCode === 'en') {
material = material.toLowerCase().replace("ferro", "Steel").replace("inox", "Stainless")
}
const newName = path.resolve(
toParts.dir + '/' +
material + '/' +
thickness + '/' +
pCode + '-' +
toFileParts[0] + '_' +
toFileParts[1] + '_' +
qty +
toParts.ext)
return newName
}
return sync({
renamer: renamer,
clear: options.clear,
source: path.resolve(item.path),
target: `${PRODUCT_ROOT}/laser/${lCode}/${item.target}`,
debug: options.debug,
verbose: options.verbose,
profile: options.profile
})
}, {concurrency: 1})
},{concurrency: 1})
}
const create = async (item, options, grunt) => {
try {
return createLaserFiles(options.cwd || '.', item, options, grunt);
} catch (e) {
logger.error(e)
return []
}
}
export const register = (grunt) => {
grunt.registerMultiTask('laser', 'Create laser files', function () {
const done = this.async()
const task_options = this.data.options || {};
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
let p
src.forEach((item) => {
try {
p = create(item, {
verbose: option('verbose', task_options, grunt, false),
clear: option('clear', task_options, grunt, true),
debug: option('debug', task_options, grunt, true),
filePattern: option('filePattern', task_options, grunt, CAD_MAIN_PATTERN),
profile: option('profile', task_options, grunt, {
"matching": ["*"]
}),
module: option('module', task_options, grunt, 'osr-tasks'),
cwd: option('cwd', task_options, grunt, process.cwd())
}, grunt)
} catch (e) {
logger.error(e)
}
})
if (p) {
p.then((result) => {
done(true)
})
}
})
}

View File

@ -1,278 +0,0 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { resolve, isFolder } from '@plastichub/osr-commons'
import { isArray } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { sync } from '@plastichub/osr-sync'
import {
CAD_MAIN_PATTERN,
MainAssembly,
file_path_with_ext_ex,
forward_slash,
unique_by,
option
} from '../library'
import { logger } from '../src'
import { IAssemblyData, ITreeNode } from '@plastichub/osr-cad/cad/sw-types'
export const regexLaserFile = /^(\d+)_([a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+)*)_x(\d+)_(\d+)mm_(\w+)$/;
export const laserDetails = (input: string) => {
if (!input) {
return false
}
const fileName = (path.parse(input).name)
const match = fileName.match(regexLaserFile)
if (!match) {
const idMatch = input.match(/^(\d+)_/)
const nameMatch = input.match(/_(\w+)_/)
const quantityMatch = input.match(/_x\d+_/)
const thicknessMatch = input.match(/_\d+mm_/)
const materialMatch = input.match(/_\w+$/)
let errorMessage = 'Invalid input format:'
if (!idMatch) {
errorMessage += `\n- Leading ID (digits) is missing or invalid : ${fileName}`
}
if (!nameMatch) {
errorMessage += `\n- Name (letters) is missing or invalid ${fileName}`
}
if (!quantityMatch) {
errorMessage += `\n- Quantity (x followed by digits) is missing or invalid ${fileName}`
}
if (!thicknessMatch) {
errorMessage += `\n- Thickness (digits followed by "mm") is missing or invalid ${fileName}`
}
if (!materialMatch) {
errorMessage += `\n- Material (alphanumeric characters) is missing or invalid ${fileName}`
}
logger.error(errorMessage)
return
}
const [_, id, name, quantity, thickness, material] = match
return {
id: parseInt(id),
name,
quantity: parseInt(quantity),
thickness: parseInt(thickness),
material
}
}
const parts_with_laser = (model) => {
if(!model){
return []
}
let parts = [...model.filter((f) => f.IsLaser === "1"), ...model]
return parts.filter((f) => {
const _path = path.resolve(resolve(f['File Path']))
if (_path && exists(_path)) {
const dir = path.parse(_path).dir
const laser = path.resolve(path.join(dir, 'laser'))
if (exists(laser)) {
return f
}
}
})
}
export const createLaserFiles = async (root, product, options, grunt) => {
if (!exists(root)) {
options.debug && logger.info("Create Laser Files : Root doesnt exists" + root)
}
const PRODUCT_ROOT = path.resolve(path.join(root, product))
if (!exists(PRODUCT_ROOT)) {
logger.warn(`Invalid product root : ${PRODUCT_ROOT}`)
return false
}
const main = MainAssembly(PRODUCT_ROOT, options.filePattern)
if (!main) {
logger.warn("Have no main assembly at " + PRODUCT_ROOT);
return false
}
const modelFilePath = file_path_with_ext_ex(main, 'json')
if (!modelFilePath || !exists(modelFilePath)) {
logger.warn("Have no model at " + modelFilePath)
return false
}
const model = read(modelFilePath, 'json')
let tree: IAssemblyData = null
const treeFilePath = file_path_with_ext_ex(main, 'tree.json')
if (!treeFilePath || !exists(treeFilePath)) {
logger.warn("Have no tree at " + treeFilePath)
} else {
tree = read(treeFilePath, 'json') as IAssemblyData
}
const laserParts = parts_with_laser(model)
let laserDirectories: any[] = [
...new Set(laserParts.map((f) => {
const _path = path.resolve(resolve(f['File Path']))
const dir = path.parse(_path).dir
const ret = {
target: forward_slash(path.relative(PRODUCT_ROOT, dir)).
replace('../components/', '').
replace('components', '').
replace('cad', '').
replace('../', ''),
path: path.resolve(dir + '/laser')
}
return ret
}))
]
const config: any = read(path.join(PRODUCT_ROOT, 'config.json'), 'json')
if (!config) {
logger.warn("Have no config at " + PRODUCT_ROOT)
return []
}
laserDirectories = unique_by(laserDirectories, 'path')
logger.debug('Create laser files for ', laserDirectories)
const qtyTotal = (qty, filePath) => {
if (tree) {
const { Components } = tree.assembly
if (!Components) {
return qty
}
const c = Components.filter((c) => {
const partPath = path.parse(c.Path).name.toLowerCase()
const laserFilePath = path.parse(filePath).name.toLowerCase()
return partPath === laserFilePath && !c.IsSuppressed
}).length
if (c){
return c
}else{
debugger
logger.warn(`Cant find instances of file : ${path.parse(filePath).name} : \n\t${filePath} in tree : \n\t${treeFilePath}`)
}
}
return qty
}
const qtyTotal2 = (qty, filePath) => {
if (tree) {
const { Components } = tree.assembly
if (!Components) {
return qty
}
if(filePath.includes('7_Side_x2_6mm_FERRO')){
debugger
}
let count = 1;
const chlidren = tree.root.Children;
if(chlidren){
const items = chlidren.filter((c: ITreeNode) => {
const partPath = path.parse(c.Path).name.toLowerCase()
const laserFilePath = path.parse(filePath).name.toLowerCase()
return partPath === laserFilePath && !c.IsSuppressed
})
count = items.length;
}
if (count){
return count
}else{
logger.warn(`Cant find instances of file : ${path.parse(filePath).name} : \n\t${filePath} in tree : \n\t${treeFilePath}`)
}
}
return qty
}
return (pMap as any)(laserDirectories, async (item) => {
return (pMap as any)(['en', 'es'], async (lCode) => {
const renamer = (from, to) => {
if (isFolder(from)) {
return
}
const lParts: any = laserDetails(from) || {}
if (!lParts) {
logger.warn(`Invalid laser file in ${PRODUCT_ROOT} : ${from}`)
}
const fromParts = path.parse('' + from)
const toParts = path.parse('' + to)
const pCode = config.code || ''
const toFileParts = ('' + toParts.name).split('_')
const fromFileParts = ('' + fromParts.name).split('_')
let qty = qtyTotal2(lParts.quantity, from)
let material = fromFileParts[4]
if (!material) {
logger.error('logger.error : invalid material ', from + ' : ' + ' to : ' + to, toFileParts)
return to
}
if (lCode === 'en') {
material = material.toLowerCase().replace("ferro", "Steel").replace("inox", "Stainless")
}
const newName = path.resolve(
toParts.dir + '/' +
material + '/' +
`${lParts.thickness}mm` + '/' +
pCode + '-' +
toFileParts[0] + '_' +
toFileParts[1] + '_' +
`x${qty}` +
toParts.ext.toLowerCase())
return newName
}
const target = `${PRODUCT_ROOT}/laser/${lCode}/${item.target}`
logger.debug(`Create laser files for ${item.path} ${lCode} : to ${target}`)
return sync({
renamer: renamer,
clear: options.clear,
source: path.resolve(item.path),
target,
debug: options.debug,
verbose: options.verbose,
profile: options.profile,
logLevel: options.logLevel || 'warn'
})
}, { concurrency: 1 })
}, { concurrency: 1 })
}
const create = async (item, options, grunt) => {
try {
return createLaserFiles(options.cwd || '.', item, options, grunt);
} catch (e) {
logger.error(e)
return []
}
}
export const register = (grunt) => {
grunt.registerMultiTask('laser2', 'Create laser files', function () {
const done = this.async()
const task_options = this.data.options || {};
let src: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
let p
src.forEach((item) => {
try {
p = create(item, {
verbose: option('verbose', task_options, grunt, false),
clear: option('clear', task_options, grunt, true),
debug: option('debug', task_options, grunt, true),
filePattern: option('filePattern', task_options, grunt, CAD_MAIN_PATTERN),
profile: option('profile', task_options, grunt, {
"matching": ["*"]
}),
module: option('module', task_options, grunt, 'osr-tasks'),
cwd: option('cwd', task_options, grunt, process.cwd())
}, grunt)
} catch (e) {
logger.error(e)
}
})
if (p) {
p.then((result) => {
done(true)
})
}
})
}

View File

@ -1,221 +0,0 @@
import * as path from 'path'
import * as sharp from 'sharp'
import { sync as dir } from '@plastichub/fs/dir'
import { sync as exists } from '@plastichub/fs/exists'
import { files as _glob } from '@plastichub/osr-commons'
import { logger } from '../src'
const fg = require('fast-glob')
export const getFormats = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/webp`,
format: 'webp',
}];
}
/*
const updateImages = async (root, product_root, content) => {
// Feed the content into JSDOM
const dom = new JSDOM(content);
const document = dom.window.document;
// Find the image elements via `querySelectorAll`, replace this selector with your own custom one
const imageElems = document.querySelectorAll('img');
// If there are no matching elements, just return the original content :)
if (imageElems.length === 0) {
return content;
}
for (const imgElem of imageElems) {
// Get the `src` of the image element
const imgSrc = imgElem.getAttribute('src');
// Only add this transform for internal images
if (imgSrc.startsWith('https') || imgSrc.startsWith('http')) {
let srcSet = [];
// Replace all of the image sources with a new one that matches the results of the Sharp build
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
if (imgSrc.indexOf('.png') !== -1) {
continue;
}
const parsed = URI.parse(decodeURIComponent(imgSrc));
const pParsed = path.parse(parsed.path);
const imageName = (url) => {
return decodeURIComponent(pParsed.base);
}
// const parts = url.parse(imgSrc);
// Get the metadata for the file and add it as the `${width}w` needed in defining a `srcset` in HTML for `<img>`
const name = imageName(imgSrc);
const _path = decodeURIComponent(parsed.path).replace('//', '');
const imageSrcPath = `${root}/${_path}`;
if (!exists(imageSrcPath)) {
console.log('image doesnt exists : ' + imageSrcPath + ' \n\t' + imgSrc);
return;
}
const imageSrcPathParts = path.parse(imageSrcPath);
const imgSrc80 = imgSrc.replace(name, '80/' + name);
const imgSrc60 = imgSrc.replace(name, '60/' + name);
const imgSrc40 = imgSrc.replace(name, '40/' + name);
const imgSrc20 = imgSrc.replace(name, '20/' + name);
const _set = (res) => {
return path.resolve(imageSrcPathParts.dir + '/' + res + '/' + name);
}
if (!exists(_set(80))) {
console.error('doesnt exists ', _set(80), imgSrc);
continue;
}
if (!exists(_set(60))) {
console.error('doesnt exists ', _set(60), imgSrc);
continue;
}
if (!exists(_set(40))) {
console.error('doesnt exists ', _set(40), imgSrc);
continue;
}
if (!exists(_set(20))) {
console.error('doesnt exists ', _set(20), imgSrc);
continue;
}
const img80 = await sharp(_set(80));
const md80 = await img80.metadata();
srcSet.push(`${imgSrc80.replace(/\s/g,'%20')} ${md80.width}w`);
// Repeat
const img60 = await sharp(_set(60));
const md60 = await img60.metadata();
srcSet.push(`${imgSrc60.replace(/\s/g,'%20')} ${md60.width}w`);
// Repeat
const img40 = await sharp(_set(40));
const md40 = await img40.metadata();
srcSet.push(`${imgSrc40.replace(/\s/g,'%20')} ${md40.width}w`);
// Repeat
const img20 = await sharp(_set(20));
const md20 = await img20.metadata();
srcSet.push(`${imgSrc20.replace(/\s/g,'%20')} ${md20.width}w`);
// Join the `srcset` into a string. that can be added to the `<img>` tag
srcSet = srcSet.join(', ');
// Set the `srcset` attribute
imgElem.setAttribute('srcset', srcSet);
// Find the new `src` for the WebP image
let webpSrc = imgSrc.replace(name, 'webp/' + encodeURIComponent(name)).replace('.png', '.webp').replace('.jpg', '.webp');
// const webpSrc = imgSrc
// .replace('/images/', '/images/webp/')
// .replace('.png', '.webp');
// Create a separate `source` element for the WebP with feature detection via `type`
const webpElement = document.createElement('source');
webpElement.setAttribute('srcset', webpSrc);
webpElement.setAttribute('type', 'image/webp');
// Wrap the `<img>` and the `<source>` into one `<picture>` tag in order for it to work
const pictureElement = document.createElement('picture');
pictureElement.appendChild(webpElement);
pictureElement.appendChild(imgElem.cloneNode());
// Replace the `<img>` with the `<picture>`
imgElem.replaceWith(pictureElement);
}
}
return document.documentElement.outerHTML;
}
*/
export const format = (formats) => {
return formats.forEach((format) => {
if (!exists(format.dist)) {
dir(format.dist)
}
// Find all files matching the glob patterns specified in `src`
let _files = fg.sync(format.src)
_files.forEach((file) => {
let filename = path.basename(file);
if (exists(path.resolve(`${format.dist}/${filename.replace('jpg', format.format)}`))) {
return;
}
const image = sharp(file);
// Convert to WebP via Sharp's inferencing automatically of extensions
image
.toFile(`${format.dist}/${filename.replace('jpg', format.format)}`)
.catch((err) => {
console.log(err);
});
});
});
}
export const getResizePatterns = (product, folder) => {
return [{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/80`,
percent: 80,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/60`,
percent: 60,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/40`,
percent: 40,
},
{
src: `${product}/${folder}/*.jpg`,
dist: `${product}/${folder}/20`,
percent: 20,
},
];
}
const resize = (patterns) => {
return patterns.forEach((resize) => {
if (!exists(resize.dist)) {
dir(resize.dist)
}
let _files = fg.sync(resize.src)
_files.forEach((file) => {
let filename = path.basename(file)
const image = sharp(file)
if (exists(`${resize.dist}/${filename}`)) {
return
}
image
.metadata()
.then((metadata) => {
return image
.resize(Math.round(metadata.width * (resize.percent / 100)))
.png()
.toFile(`${resize.dist}/${filename}`)
.catch(logger.error);
})
.catch(logger.error)
})
})
}

View File

@ -1,257 +0,0 @@
import * as path from 'path'
import * as pMap from 'p-map'
import { sync as write } from '@plastichub/fs/write'
import { substitute } from '@plastichub/core'
import { isArray, isObject } from '@plastichub/core/primitives'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { resolve, filesEx } from '@plastichub/osr-commons'
import { test as send } from '@plastichub/osr-mail/lib/nodemailer'
import {
MAIL_LOG_LEVEL,
MAIL_ENV_DEV,
MAIL_LANGUAGES,
MAIL_PROFILE,
MAIL_SOURCE_FILE,
MAIL_SRC_LANGUAGE,
MAIL_TEMPLATE,
MAIL_COMPILE_CACHE,
MAIL_ASSETS_ROOT,
MAIL_I18N_CACHE,
MAIL_DEFAULT_OUTPUT_PATH as SHEET_TRANSLATION_PATH
} from './config'
import { sheetTranslationTask } from './sheets'
import { onCompiledMail } from './mail_utils'
import { gruntOptions } from '../library'
import { ICompileOptions } from './compile'
import { I18N_STORE, OSR_ROOT } from './config'
import { logger } from '../src'
import { getOutputFileName, prepMailQueue } from './mail_utils'
import { mailOptionSchema, enumerateHelpStrings, mailCompileSchema } from './utils'
import { resolveContactsPath, getContacts, filterContacts } from './contacts'
const getSubject = (language: string) => {
const subjectPath = path.resolve(resolve(`${OSR_ROOT()}/products/company/campaign/content/subject-${language}.md`))
if (!exists(subjectPath)) {
logger.error(`Cannot read subject file ${subjectPath}`)
return 'Default Subject'
}
return read(subjectPath) || 'Default Subject'
}
const sendOptions = (grunt, language: string = 'en') => {
const subject = getSubject(language)
return {
from: 'PlasticHub <newsletter@osr-plastic.org>',
transport: 'newsletter',
subject,
contacts: '',
filter: true,
query: null,
to: null,
source: `${OSR_ROOT()}/products/products/assets/newsletter/mail/mail_2024_09_public_${language}.html`,
...gruntOptions(grunt)
}
}
const sendMailQueue = async (grunt) => {
const mailerOptions = sendOptions(grunt, grunt.option('lang') || 'en')
const source = read(path.resolve(resolve(mailerOptions.source)))
if (!source) {
logger.error(`Cannot read source file ${mailerOptions.source}`)
return
}
let contacts = getContacts(mailerOptions)
if (!contacts) {
logger.error(`Invalid contacts: ${resolveContactsPath(mailerOptions)}`)
return
}
if (!isArray(contacts) && isObject(contacts)) {
contacts = Object.keys(contacts).map((k) => contacts[k])
}
const total = contacts.length
contacts = filterContacts(grunt, contacts, mailerOptions)
if (mailerOptions.filter !== false) {
contacts = contacts.filter((contact) => contact.email && contact.email.length > 0)
contacts = contacts.filter((contact) => contact.status !== 'sent')
}
const sendMail = async (contact, options) => {
const subject = getSubject(grunt.option('lang'))
if (!contact.email) {
logger.error(`Invalid contact : ${contact}`)
return
}
logger.info(`Sending mail to ${contact.email}`)
const opts = {
...options,
from: 'Lovebird <newsletter@osr-plastic.org>',
subject: subject,
transport: "newsletter",
to: contact.email,
html: substitute(source, {
unsubscribe_email: contact.email
})
}
const mail = await send(opts)
contact.mail = mail
contact.status = 'sent'
const contactsFile = resolveContactsPath(mailerOptions)
if (mailerOptions.contacts && contactsFile) {
const last = read(contactsFile, 'json')
last[contact.title] = contact
write(contactsFile, last)
}
logger.info(`Sent mail to ${contact.email}`)
return mail
}
if (contacts.length === 0 && mailerOptions.to) {
contacts = [{ email: mailerOptions.to }]
}
if (grunt.option('dry')) {
logger.info(`Dry : Sending ${contacts.length} mails in total, of ${total} contacts`)
return false
} else {
logger.debug(`Sending ${path.resolve(resolve(mailerOptions.source))} to ${contacts.length} mails`)
}
const mails = await pMap(contacts, async (contact) => {
return sendMail(contact, mailerOptions)
}, { concurrency: 1 })
logger.info(`Sent ${mails.length} mails`)
return mails
}
export const getOutputFile = (grunt, root, slug, options = {}, language: string = 'en') => {
const env = grunt.option('env') || MAIL_ENV_DEV
const isDebug = env === MAIL_ENV_DEV
const outFile = getOutputFileName(isDebug, slug, language)
const output = path.resolve(path.join(root, outFile))
return output
}
export const mailCompileOptions = (grunt: any, root, slug, options = {}, language: string = 'en') => {
const template = grunt.option('template') ?
path.resolve(resolve(grunt.option('template'))) : path.join(root, slug, MAIL_TEMPLATE)
const env = grunt.option('env') || MAIL_ENV_DEV
const isDebug = env === MAIL_ENV_DEV
const outFile = getOutputFileName(isDebug, slug, language)
const output = grunt.option('output') ?
path.resolve(resolve(grunt.option('output'))) : path.resolve(path.join(root, outFile))
root = path.join(root, slug)
const onCompiled = async (src, dst, content) => {
const ret = await onCompiledMail(src, dst, content)
if (grunt.option('send') && !grunt.option('contacts')) {
const opts = {
from: 'Lovebird <newsletter@osr-plastic.org>',
to: grunt.option('to') || 'cgoflyn@gmail.com',
html: substitute(ret, {
unsubscribe_email: 'cgoflyn@gmail.com'
}),
subject: `Test Mail : - ${language} : - ` + Math.random(),
transport: "newsletter",
...gruntOptions(grunt)
}
await send(opts)
}
return ret
}
const ret: ICompileOptions = {
cache: MAIL_COMPILE_CACHE,
root,
cwd: root,
env,
format: 'html',
language: 'osr',
logLevel: grunt.option('logLevel') || MAIL_LOG_LEVEL,
module: 'plastichub-mail',
profile: MAIL_PROFILE as any,
template,
output,
// onCompiled: !isDebug || grunt.option('send') ? onCompiled : undefined,
variables: {
cwd: root,
root,
targetLanguage: language as any,
sourceLanguage: MAIL_SRC_LANGUAGE,
i18n: I18N_STORE(OSR_ROOT(), language),
...gruntOptions(grunt)
},
...options,
...gruntOptions(grunt)
}
return ret
}
export const mailSendTask = (grunt, root, directory, options: any = {}, newsletter_tasks) => {
grunt.registerTask(`prepare-mail-contacts`, async () => {
prepMailQueue(grunt, root, directory, options)
})
grunt.registerTask(`send-mail-queue`, "help", async function () {
this.async()
try {
await sendMailQueue(grunt)
} catch (e) {
logger.error(`Error sending mail : ${e.message}`, e.stack)
}
})
if (grunt.option('describe')) {
grunt.registerTask(`send-mail`, () => {
logger.setSettings({
displayFunctionName: false,
displayInstanceName: false,
displayLogLevel: false,
displayLoggerName: false,
displayDateTime: false,
displayFilePath: "hidden"
})
logger.debug(`\nOptions : ${mailOptionSchema._def.description}`)
logger.info(`send mail options: Directory:${directory}`, enumerateHelpStrings(mailOptionSchema, [], logger))
logger.debug(`\nOptions : ${mailCompileSchema(grunt)._def.description}`)
logger.info(`send compile schema options:`, enumerateHelpStrings(mailCompileSchema(grunt), [], logger))
})
return
} else {
grunt.registerTask(`send-mail`, [`mail-tasks`, "send-mail-queue"])
}
}
export const mailTask = (grunt, root, directory, options: any = {}, newsletter_tasks) => {
const mailAssets = filesEx(MAIL_ASSETS_ROOT(), '*-en.xlsx')
const mailAssetTasks = []
const languages: string[] = grunt.option('languages') ? grunt.option('languages').split(',') : MAIL_LANGUAGES
sheetTranslationTask(grunt, 'mail-assets',
mailAssets, languages, mailAssetTasks,
{
dst: SHEET_TRANSLATION_PATH,
cache: MAIL_I18N_CACHE,
query: "$[*][0,1,2,3,4,5]"
})
////////////////////////////////
// Content Compile Tasks
const config = {}
const slug = directory.replace(/\//g, '-')
const extraOptions = {}
const source = grunt.option('source') ?
path.resolve(resolve(grunt.option('source'))) : path.join(root, directory, MAIL_SOURCE_FILE)
languages.forEach((lang) => {
config[`${slug}-${lang}`] = {
src: [source],
options: mailCompileOptions(grunt, root, directory, extraOptions, lang)
}
grunt.extendConfig({ compile: config })
write('./tmp/compile-mail/options.json', config)
grunt.registerTask(`${slug}-${lang}`, [`mail-assets-${lang}`, `compile:${slug}-${lang}`])
newsletter_tasks.push(`compile:${slug}-${lang}`)
})
grunt.registerTask(`mail-tasks`, newsletter_tasks)
}

View File

@ -1,85 +0,0 @@
import * as path from 'path'
import * as juice from 'juice'
import { minify } from 'html-minifier-terser'
import { filesEx } from '@plastichub/osr-commons/_glob'
import { sync as write } from '@plastichub/fs/write'
import * as XLSX from 'xlsx'
import { logger } from '../src'
import { gruntOptions } from '../library'
import {
MAIL_OUTPUT_DIR,
MAIL_OUTPUT_FILE_EXT,
MAIL_OUTPUT_FILE_NAME,
MAIL_OUTPUT_FILE_NAME_PROD,
PRODUCT_ROOT
} from './config'
type TableData = (string | null)[][]
export const prepMailQueue = async (grunt, root, directory, options: any = {},) => {
logger.info(`Sending mail queue from ${directory}`)
const mailRoot = path.join(root, directory)
const mailContentRoot = path.join(mailRoot, 'data')
const contactFiles = filesEx(mailContentRoot, '*.xlsx')
contactFiles.forEach((file) => {
const workbook = XLSX.readFile(file)
const worksheet = workbook.Sheets[workbook.SheetNames[0]]
const raw_data: any[] = XLSX.utils.sheet_to_json(worksheet, { header: 1, blankrows: false, raw: false, skipHidden: false })
const contacts = convertToJSON(raw_data)
const dst = path.join(mailContentRoot, path.parse(file).name + '.json')
logger.info(`Writing contacts from ${file} to ${dst}`)
write(dst, JSON.stringify(contacts, null, 2))
})
}
export const convertToJSON = (data: TableData): object[] => {
const [fields, ...rows] = data;
return rows.map(row => {
const jsonObject: any = {};
row.forEach((value, index) => {
let fieldName = fields[index];
if (fieldName?.toLowerCase().includes('mail')) {
fieldName = 'email';
} else if (fieldName?.toLowerCase().includes('name')) {
fieldName = 'name';
}
jsonObject[fieldName] = value;
});
return jsonObject;
});
}
export const sendOptions = (grunt, root, slug, options = {}, language: string = 'en', contacts) => {
return {
from: 'PlasticHub <newsletter@osr-plastic.org>',
transport: 'newsletter',
subject: 'New Sheetpresses, Extruders, Shredders and Injectors',
contacts,
source: `${PRODUCT_ROOT()}/${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME}_public_${language}.html`,
...gruntOptions(grunt)
}
}
export const getOutputFileName = (isDebug: boolean, slug: string, lang: string = 'en') => {
return isDebug ?
`${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME}_${lang}${MAIL_OUTPUT_FILE_EXT}` :
`${MAIL_OUTPUT_DIR}/${MAIL_OUTPUT_FILE_NAME_PROD}_${lang}${MAIL_OUTPUT_FILE_EXT}`
}
export const mailDefault = async (content) => {
const options: juice.Options = {}
content = juice(content, options)
content = await minify(content, {
collapseWhitespace: true,
removeComments: true,
minifyCSS: true,
minifyJS: true
})
return content
}
export const onCompiledMail = async (src, dst, content) =>
mailDefault(content)

View File

@ -1,49 +0,0 @@
import * as path from 'path'
import { contentTasks, ICompileOptions, ICompileTaskOptions } from './compile'
import { option } from '../library'
import { logger } from '../src/'
import {
I18N_SOURCE_LANGUAGE,
NEWSLETTER_COMPILE_CACHE,
NEWSLETTER_DEFAULT_ENV,
NEWSLETTER_LOG_LEVEL} from './config'
export const newsletterTasks = (
grunt,
taskPrefix = 'newsletter',
root,
template,
src,
dst,
taskOptions: ICompileTaskOptions = {},
compilerOptions: ICompileOptions = {}
) => {
logger.info(`Registering newsletter tasks for ${taskPrefix}`)
const env = option('env', {}, grunt, NEWSLETTER_DEFAULT_ENV)
const newsletter_tasks = contentTasks(grunt,
{
sourceLanguage: I18N_SOURCE_LANGUAGE,
src: [path.join(root, src)],
taskPrefix,
...taskOptions
},
{
cache: option('cache', {}, grunt, NEWSLETTER_COMPILE_CACHE),
root,
env,
logLevel: option('logLevel', {}, grunt, NEWSLETTER_LOG_LEVEL),
output: dst,
template:path.join(root, template),
variables: {
env,
prefix: env,
root,
targetLanguage: I18N_SOURCE_LANGUAGE,
sourceLanguage: I18N_SOURCE_LANGUAGE
},
...compilerOptions
})
grunt.registerTask(taskPrefix, Object.keys(newsletter_tasks).map((lang: any) => newsletter_tasks[lang].taskName))
return newsletter_tasks
}

View File

@ -1,290 +0,0 @@
import * as semver from 'semver'
import * as child_process from 'child_process'
let DESC = 'Increment the version, commit, tag and push.'
export const register = (grunt) => {
grunt.registerTask('bump', DESC, function(versionType, incOrCommitOnly) {
const opts = this.options({
bumpVersion: true,
commit: true,
commitFiles: ['package.json'], // '-a' for all files
commitMessage: 'Release v%VERSION%',
createTag: true,
dryRun: false,
files: ['package.json'],
gitCommitOptions: '',
gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d',
globalReplace: false,
prereleaseName: false,
metadata: '',
push: true,
pushTo: 'upstream',
regExp: false,
setVersion: false,
tagMessage: 'Version %VERSION%',
tagName: 'v%VERSION%',
updateConfigs: [], // array of config properties to update (with files)
versionType: false
});
if (versionType === 'bump-only' || versionType === 'commit-only') {
incOrCommitOnly = versionType;
versionType = '';
}
versionType = versionType || opts.versionType;
const dryRun = grunt.option('dry-run') || opts.dryRun;
let setVersion = grunt.option('setversion') || opts.setVersion;
if (setVersion && !semver.valid(setVersion)) {
setVersion = false;
}
let globalVersion; // when bumping multiple files
let gitVersion; // when bumping using `git describe`
let VERSION_REGEXP = (typeof opts.regExp === 'function') ? opts.regExp(opts.prereleaseName) : opts.regExp || new RegExp(
'([\'|\"]?version[\'|\"]?[ ]*:[ ]*[\'|\"]?)(\\d+\\.\\d+\\.\\d+(-' +
opts.prereleaseName +
'\\.\\d+)?(-\\d+)?)[\\d||A-a|.|-]*([\'|\"]?)', 'i'
);
if (opts.globalReplace) {
VERSION_REGEXP = new RegExp(VERSION_REGEXP.source, 'gi');
}
const done = this.async();
const queue = [];
const next = function() {
if (!queue.length) {
grunt.config.set('bump.version', globalVersion);
return done();
}
queue.shift()();
};
const runIf = function(condition, behavior) {
if (condition) {
queue.push(behavior);
}
};
if (dryRun) {
grunt.log.writeln('Running grunt-bump in dry mode!');
}
if (incOrCommitOnly === 'bump-only') {
grunt.verbose.writeln('Only incrementing the version.');
opts.commit = false;
opts.createTag = false;
opts.push = false;
}
if (incOrCommitOnly === 'commit-only') {
grunt.verbose.writeln('Only committing/tagging/pushing.');
opts.bumpVersion = false;
}
// GET VERSION FROM GIT
runIf(opts.bumpVersion && versionType === 'git', function() {
child_process.execFile('git describe ' + opts.gitDescribeOptions, function(err, stdout) {
if (err) {
grunt.fatal('Can not get a version number using `git describe`');
}
gitVersion = stdout.trim();
next();
});
});
// BUMP ALL FILES
runIf(opts.bumpVersion, function() {
grunt.file.expand(opts.files).forEach(function(file, idx) {
let version = null;
const content = grunt.file.read(file).replace(
VERSION_REGEXP,
function(match, prefix, parsedVersion, namedPre, noNamePre, suffix) {
const type = versionType === 'git' ? 'prerelease' : versionType;
version = setVersion || semver.inc(
parsedVersion, type || 'patch', gitVersion || opts.prereleaseName
);
if (opts.metadata) {
if (!/^([0-9a-zA-Z-]+\.{0,1})*$/.test(opts.metadata)) {
grunt.fatal(
'Metadata can only contain letters, numbers, dashes ' +
'(-) and dots (.)'
);
}
version += '+' + opts.metadata;
}
return prefix + version + (suffix || '');
}
);
if (!version) {
grunt.fatal('Can not find a version to bump in ' + file);
}
const logMsg = 'Version bumped to ' + version + ' (in ' + file + ')';
if (!dryRun) {
grunt.file.write(file, content);
grunt.log.ok(logMsg);
} else {
grunt.log.ok('bump-dry: ' + logMsg);
}
if (!globalVersion) {
globalVersion = version;
} else if (globalVersion !== version) {
grunt.warn('Bumping multiple files with different versions!');
}
const configProperty = opts.updateConfigs[idx];
if (!configProperty) {
return;
}
const cfg = grunt.config(configProperty);
if (!cfg) {
return grunt.warn(
'Can not update "' + configProperty + '" config, it does not exist!'
);
}
cfg.version = version;
grunt.config(configProperty, cfg);
grunt.log.ok(configProperty + '\'s version updated');
});
next();
});
// when only committing, read the version from package.json / pkg config
runIf(!opts.bumpVersion, function() {
const configVersion = grunt.config.get('bump.version');
if (configVersion) {
globalVersion = configVersion;
}
else if (opts.updateConfigs.length) {
globalVersion = grunt.config(opts.updateConfigs[0]).version;
} else {
globalVersion = grunt.file.readJSON(opts.files[0]).version;
}
next();
});
// COMMIT
runIf(opts.commit, function() {
const commitMessage = opts.commitMessage.replace(
'%VERSION%', globalVersion
);
let cmd = 'git commit ' + opts.gitCommitOptions + ' ' + opts.commitFiles.join(' ');
cmd += ' -m "' + commitMessage + '"';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not create the commit:\n ' + stderr);
}
grunt.log.ok('Committed as "' + commitMessage + '"');
next();
});
}
});
// CREATE TAG
runIf(opts.createTag, function() {
const tagName = opts.tagName.replace('%VERSION%', globalVersion);
const tagMessage = opts.tagMessage.replace('%VERSION%', globalVersion);
const cmd = 'git tag -a ' + tagName + ' -m "' + tagMessage + '"';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd , function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not create the tag:\n ' + stderr);
}
grunt.log.ok('Tagged as "' + tagName + '"');
next();
});
}
});
// PUSH CHANGES
runIf(opts.push, function() {
let cmd;
if (opts.push === 'git' && !opts.pushTo) {
cmd = 'git push';
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal(
'Can not push to the git default settings:\n ' + stderr
);
}
grunt.log.ok('Pushed to the git default settings');
next();
});
}
return;
}
child_process.execFile('git rev-parse --abbrev-ref HEAD', function(err, ref, stderr) {
if (err) {
grunt.fatal('Can not get ref for HEAD:\n' + stderr);
}
cmd = [];
if (opts.push === true || opts.push === 'branch') {
cmd.push('git push ' + opts.pushTo + ' ' + ref.trim());
}
if (opts.createTag && (opts.push === true || opts.push === 'tag')) {
const tagName = opts.tagName.replace('%VERSION%', globalVersion);
cmd.push('git push ' + opts.pushTo + ' ' + tagName);
}
cmd = cmd.join(' && ');
if (dryRun) {
grunt.log.ok('bump-dry: ' + cmd);
next();
} else {
child_process.execFile(cmd, function(err, stdout, stderr) {
if (err) {
grunt.fatal('Can not push to ' + opts.pushTo + ':\n ' + stderr);
}
grunt.log.ok('Pushed to ' + opts.pushTo);
next();
});
}
});
});
next();
});
// ALIASES
DESC = 'Increment the version only.';
grunt.registerTask('bump-only', DESC, function(versionType) {
grunt.task.run('bump:' + (versionType || '') + ':bump-only');
});
DESC = 'Commit, tag, push without incrementing the version.';
grunt.registerTask('bump-commit', DESC, 'bump::commit-only');
}

View File

@ -1,93 +0,0 @@
import { sanitize } from '@plastichub/osr-i18n/_cli'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
import { IOptions as IOptionsI18n } from '@plastichub/osr-i18n/types'
import { translate } from '@plastichub/osr-i18n/lib/translate'
import * as pMap from 'p-map'
import {
I18N_SOURCE_LANGUAGE, I18N_STORE,
MAIL_DEFAULT_OUTPUT_PATH,
OSR_ROOT
} from './config'
import { logger } from '../src'
export const defaultSheetOptions = (srcLang, dstLang, dst: string, logLevel: string, options: {} = {}) => {
const i18nOptions: IOptionsI18n = {
srcLang,
dstLang,
store: I18N_STORE(OSR_ROOT(), dstLang),
dst,
cache: true,
logLevel,
...options
}
return i18nOptions
}
export const translateSheets = async (
languages: string[],
files: string[],
srcLang: string,
dstLanguage: string,
query: string = "$[*][0,1,2,3,4]",
dst: string = MAIL_DEFAULT_OUTPUT_PATH,
logLevel = 'info',
options: any = {}) => {
const config: any = CONFIG_DEFAULT()
if (dstLanguage === I18N_SOURCE_LANGUAGE) {
return
}
return await pMap(languages, async (dstLanguage) => {
return await pMap(files, async (src) => {
const i18nOptions: IOptionsI18n = {
srcLang: srcLang,
dstLang: dstLanguage,
src: src,
store: I18N_STORE(OSR_ROOT(), dstLanguage),
dst: dst,
query: query,
cache: true,
api_key: config.deepl.auth_key,
logLevel: logLevel,
...options
}
logger.debug('Translate Sheet ' + src + ' ' + dstLanguage, i18nOptions)
const ret = await translate(sanitize(i18nOptions) as any)
return ret
})
})
}
export const sheetTranslationTask = (grunt, slug: string, files: string[], languages: string[], translationTasks: string[], options: {} = {}) => {
const config = {}
const key: any = (CONFIG_DEFAULT() as any).deepl.auth_key
languages.forEach((lang: string) => {
config[`${slug}-${lang}`] = {
src: files,
options: defaultSheetOptions(I18N_SOURCE_LANGUAGE, lang, `${OSR_ROOT()}/content/${lang}`, 'warn', { api_key: key, ...options })
}
grunt.extendConfig({ i18n: config })
grunt.registerTask(`${slug}-${lang}`, `i18n:${slug}-${lang}`)
translationTasks.push(`i18n:${slug}-${lang}`)
})
grunt.registerTask(`${slug}-tasks`, translationTasks)
}
export const register = (grunt) => {
grunt.registerMultiTask('sheets-i18n', 'Translate Sheets ', async function () {
const done = this.async()
const task_options = this.data.options
// const cwd = path.resolve(option('cwd', task_options, grunt, process.cwd()))
return new Promise((resolve) => {
if (!task_options.watchContent) {
resolve(true)
done()
}
})
})
}

View File

@ -1,156 +0,0 @@
import { Client } from 'ssh2'
import { isArray } from '@plastichub/core/primitives'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons/config'
import { logger } from '../src'
import { option } from '../library'
const parseConnectionOptions = function (options: any) {
const connectionOptions: any = {
host: options.host,
port: options.port,
username: options.user,
readyTimeout: options.readyTimeout,
agentForward: options.agentForward
}
if (options.privateKey) {
connectionOptions.privateKey = options.privateKey.trim();
if (options.passphrase) {
connectionOptions.passphrase = options.passphrase.trim();
}
}
else if (options.password) {
connectionOptions.password = options.password;
if (options.agent) {
connectionOptions.agent = options.agent;
}
} else {
connectionOptions.agent = options.agent;
}
return connectionOptions
}
const exce = async (commands: string[], options: any) => {
return new Promise((resolve, reject) => {
const c = new Client()
const { debug, verbose } = options
c.on('keyboard-interactive', function () {
const prompts = arguments[3]
const reply = arguments[4]
prompts.forEach(function (question) {
const msg = question.prompt.toLowerCase()
if (msg.indexOf('password') !== -1) {
reply([options.password])
}
})
})
c.on('connect', () => logger.info('Connection :: connect'))
c.on('ready', () => {
logger.info('Connection :: ready')
execCommand()
})
c.on('error', (err) => logger.error('Connection :: error :: ' + err) && resolve(false))
c.on('end', () => logger.info('Connection :: end') && resolve(false))
const execCommand = () => {
if (commands.length === 0) {
c.end()
} else {
const command = commands.shift()
logger.info('Executing :: ' + command)
c.exec(command, options, function (err, stream) {
if (err) {
reject(err)
}
let out
stream.on('data', (data, extended) => {
out = String(data);
if (extended === 'stderr') {
if (!options.suppressRemoteErrors) {
logger.warn(out);
}
else {
logger.warn(out);
}
} else {
logger.info(out)
}
})
stream.on('end', () => {
resolve(out)
})
stream.on('close', (code, signal) => {
debug && logger.info('Stream :: close :: code: ' + code + ', signal: ' + signal)
if (!options.ignoreErrors && code !== 0) {
logger.error('Error executing task ' + command, code, signal)
c.end()
reject({ signal, code })
} else {
execCommand()
}
})
})
}
}
const connectionOptions = parseConnectionOptions(options)
connectionOptions.tryKeyboard = true;
const proxyHost = (options.proxy || {}).host
if (proxyHost) {
const proxyConnectionOptions = parseConnectionOptions(options.proxy)
const proxyConnection = new Client()
proxyConnection.on('connect', function () {
logger.info('Proxy connection :: connect')
})
proxyConnection.on('error', function (err) {
logger.error('Proxy connection :: error :: ' + err)
})
proxyConnection.on('ready', function () {
logger.info('Proxy connection :: ready')
proxyConnection.exec('nc ' + connectionOptions.host + ' ' + connectionOptions.port, function (err, stream) {
if (err) {
proxyConnection.end()
reject(err)
}
connectionOptions.sock = stream;
c.connect(connectionOptions)
})
})
proxyConnection.connect(proxyConnectionOptions)
}
else {
c.connect(connectionOptions)
}
})
}
export const register = (grunt) => {
grunt.registerMultiTask('sshexec', 'Runs commands on SSH', async function () {
let done = this.async()
const task_options = this.data || {}
const sshConfig = (CONFIG_DEFAULT() as any || {}).ssh || {}
const opts = {
...sshConfig,
debug: option('debug', task_options, grunt),
verbose: option('verbose', task_options, grunt),
port: option('port', task_options, grunt, sshConfig.port),
host: option('host', task_options, grunt, sshConfig.host),
user: option('user', task_options, grunt, sshConfig.user),
password: option('password', task_options, grunt, sshConfig.password),
logLevel: option('logLevel', task_options, grunt,'warn')
}
logger.setSettings({ minLevel: opts.logLevel })
logger.info('Git - task data ', this.data)
let commands: string[] = isArray(this.data.commands) ? this.data.commands : [this.data.commands]
const ret = await exce(commands, opts)
logger.info(`Exce : ${[this.data.command].join('\n')} : `, ret)
done()
})
}

View File

@ -1,37 +0,0 @@
import { isArray } from '@plastichub/core/primitives'
import { sync } from '@plastichub/osr-sync/lib/sync'
import { resolve } from '@plastichub/osr-commons'
import { option } from '../library'
import { logger } from '../src'
export const register = (grunt) => {
grunt.registerMultiTask('sync', 'Synchronizes folders, using osr-sync', function () {
const done = this.async()
const task_options = this.data || {}
let source: string[] = isArray(this.data.src) ? this.data.src : [this.data.src]
const variables = { ...task_options.variables || {} }
logger.setSettings({ minLevel: option('logLevel', task_options, grunt, 'warn') })
source = source.map(f => resolve(f, false, variables))
const options = {
source,
target: resolve(option('target', task_options, grunt), variables),
root: option('root', task_options, grunt),
clear: option('clear', task_options, grunt),
debug: false,
verbose: false,
//debug: option('debug', task_options, grunt),
//verbose: option('verbose', task_options, grunt, false),
profile: option('profile', task_options, grunt),
logLevel: option('logLevel', task_options, grunt, 'warn'),
variables: variables
}
try {
sync(options)
} catch (e) {
logger.error(`Error while syncing : ${source.join('\n')} : ${e.messsage}`, e)
}
done()
return true
})
}

View File

@ -1,186 +0,0 @@
import { z, ZodObject, ZodTypeAny } from "zod"
import { MAIL_SOURCE_FILE } from "./config"
export const cleanArray = (arr: any[]): any[] => {
// Use a Set to eliminate duplicates
const uniqueItems = Array.from(new Set(arr.map(item => JSON.stringify(item))))
.map(item => JSON.parse(item))
return uniqueItems.filter(item => {
if (Array.isArray(item)) {
return item.length > 0; // Exclude empty arrays
} else if (typeof item === 'object' && item !== null) {
return Object.keys(item).length > 0; // Exclude empty objects
} else if (typeof item === 'string') {
// Remove URL parameters from strings
return item
}
return true; // Keep other types (e.g., numbers, etc.)
}).map(item => {
// Apply the URL cleanup on strings if they haven't been filtered out
if (typeof item === 'string') {
return item
}
return item
})
}
export const mailOptionSchema = z.object({
from: z
.string()
.default("'PlasticHub-Barcelona <newsletter@osr-plastic.org>'")
.describe("The sender email address formatted as a string."),
transport: z
.string()
.default("newsletter")
.describe("The transport profile, e.g., 'newsletter'."),
subject: z
.string()
.default("Mejora tu Carpintería: Prensas de Planchas, Extrusoras e Inyectores para Procesamiento de Plástico")
.describe("The subject of the email being sent."),
contacts: z
.string()
.default("${OSR_ROOT}/osr-directory/meta/index.json")
.describe("Path to the contacts directory or file."),
filter: z
.boolean()
.default(true)
.describe("Indicates whether a filter should be applied: true filters out already sent emails."),
query: z
.string()
.default("QT_CARPENTERS_SPAIN_ALL_EMAIL")
.describe("The query string used to select recipients. From profile or string"),
to: z
.string()
.nullable()
.default(null)
.describe("Optional recipient address; can be null if not specified."),
send: z
.boolean()
.default(true)
.describe("Indicates whether the email should be sent."),
dry: z
.boolean()
.default(false)
.describe("For testing purposes"),
logLevel: z
.string()
.default("debug")
.describe("The level of logging detail, e.g., 'debug', 'info', 'error'.")
}, { description: "Options for sending an email." })
export const compileVariablesSchema = (grunt) => z.object({
cwd: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The current working directory for the process."),
root: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The root directory for the project."),
targetLanguage: z
.string()
.default("es")
.describe("The target language code for the output."),
sourceLanguage: z
.string()
.default("en")
.describe("The source language code for the input."),
i18n: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr/i18n-store/store-es.json")
.describe("The path to the internationalization (i18n) store file.")
});
export const mailCompileSchema = (grunt) => z.object({
cache: z
.boolean()
.default(false)
.describe("Indicates whether caching is enabled."),
cwd: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The current working directory for the process."),
env: z
.string()
.default("hugo-release")
.describe("The environment for the process, e.g., 'hugo-release'."),
format: z
.string()
.default("html")
.describe("The format of the output file."),
language: z
.string()
.default("osr")
.describe("The language code or identifier used for processing."),
logLevel: z
.string()
.default("debug")
.describe("The level of logging detail, e.g., 'debug', 'info', 'error'."),
module: z
.string()
.default("plastichub-mail")
.describe("The module being used for the process."),
profile: z
.string()
.default("${OSR_ROOT}/osr-templates/osrl/.osrl.json")
.describe("The path to the profile configuration file."),
root: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08")
.describe("The root directory for the project."),
sourceLanguage: z
.string()
.default("en")
.describe("The source language code for the input."),
targetLanguage: z
.string()
.default("en")
.describe("The target language code for the output."),
template: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\company\\mail\\2024\\08\\root.osr")
.describe("The path to the template file being used."),
output: z
.string()
.default("C:\\Users\\mc007\\Desktop\\osr\\products\\products\\assets\\newsletter\\mail\\mail_2024_09_public_es.html")
.describe("The path to the output file."),
source: z
.string()
.default(MAIL_SOURCE_FILE || grunt.option('source'))
.describe("The path to the source file."),
variables: compileVariablesSchema(grunt).describe("An object containing variable paths and language codes for processing.")
})
export const enumerateHelpStrings = (schema: ZodTypeAny, path: string[] = [], logger: any): void => {
if (schema instanceof ZodObject) {
for (const key in schema.shape) {
const nestedSchema = schema.shape[key];
enumerateHelpStrings(nestedSchema, [...path, key], logger)
}
} else {
const description = schema._def.description
const fieldDef = schema._def
const innerType = fieldDef.innerType
let type: 'string' | 'boolean' | 'number' | undefined
if (innerType._def.typeName === 'ZodString') {
type = 'string'
} else if (innerType._def.typeName === 'ZodBoolean') {
type = 'boolean'
} else if (innerType._def.typeName === 'ZodNumber') {
type = 'number'
}
let defaultValue = fieldDef.defaultValue
defaultValue = defaultValue !== undefined ? defaultValue() : undefined
if (type === 'boolean') {
defaultValue = defaultValue === 'true'
}
if (description) {
logger.debug(`\t ${path.join('.')}: ${description} \t Default: ${defaultValue}`)
}
}
}