npm audit fix
This commit is contained in:
parent
b40a530413
commit
1fd6ef704e
@ -17,4 +17,4 @@
|
||||
},
|
||||
"packageManager": "pnpm@8.15.6",
|
||||
"name": "design-system"
|
||||
}
|
||||
}
|
||||
218
packages/ai-tools/dist/types_kbot.d.ts
vendored
218
packages/ai-tools/dist/types_kbot.d.ts
vendored
@ -31,96 +31,95 @@ export interface IKBotOptions {
|
||||
[35m[1m[22m[39m
|
||||
[35m[1m OpenRouter models:[22m[39m
|
||||
[35m[1m[22m[39m
|
||||
agentica-org/deepcoder-14b-preview | paid
|
||||
agentica-org/deepcoder-14b-preview:free | free
|
||||
ai21/jamba-large-1.7 | paid
|
||||
ai21/jamba-mini-1.7 | paid
|
||||
aion-labs/aion-1.0 | paid
|
||||
aion-labs/aion-1.0-mini | paid
|
||||
aion-labs/aion-rp-llama-3.1-8b | paid
|
||||
alfredpros/codellama-7b-instruct-solidity | paid
|
||||
allenai/molmo-7b-d | 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-micro-v1 | paid
|
||||
amazon/nova-premier-v1 | paid
|
||||
amazon/nova-pro-v1 | paid
|
||||
anthropic/claude-3-haiku | paid
|
||||
anthropic/claude-3-opus | paid
|
||||
anthropic/claude-3.5-haiku | paid
|
||||
anthropic/claude-3.5-haiku-20241022 | 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:thinking | paid
|
||||
anthropic/claude-haiku-4.5 | paid
|
||||
anthropic/claude-opus-4 | paid
|
||||
anthropic/claude-opus-4.1 | paid
|
||||
anthropic/claude-opus-4.5 | paid
|
||||
anthropic/claude-sonnet-4 | paid
|
||||
anthropic/claude-sonnet-4.5 | paid
|
||||
arcee-ai/coder-large | paid
|
||||
arcee-ai/maestro-reasoning | paid
|
||||
arcee-ai/spotlight | paid
|
||||
arcee-ai/trinity-mini | paid
|
||||
arcee-ai/trinity-mini:free | free
|
||||
arcee-ai/virtuoso-large | paid
|
||||
arliai/qwq-32b-arliai-rpr-v1 | paid
|
||||
arliai/qwq-32b-arliai-rpr-v1:free | free
|
||||
openrouter/auto | 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-vl-28b-a3b | 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
|
||||
deepcogito/cogito-v2-preview-llama-109b-moe | paid
|
||||
cohere/command | paid
|
||||
cohere/command-a | paid
|
||||
cohere/command-r | paid
|
||||
cohere/command-r-03-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-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-r1-0528-qwen3-8b | paid
|
||||
deepseek/deepseek-r1-0528-qwen3-8b:free | free
|
||||
deepseek/deepseek-chat | 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:free | free
|
||||
deepseek/deepseek-v3.1-base | paid
|
||||
deepseek/deepseek-v3.1-terminus | 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:free | free
|
||||
deepseek/deepseek-r1-0528 | paid
|
||||
deepseek/deepseek-r1-0528:free | free
|
||||
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:free | free
|
||||
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
|
||||
essentialai/rnj-1-instruct | 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-exp:free | free
|
||||
google/gemini-2.0-flash-lite-001 | 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-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-preview-05-06 | 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-9b-it | paid
|
||||
google/gemma-2-9b-it:free | free
|
||||
google/gemma-3-12b-it | paid
|
||||
google/gemma-3-12b-it:free | free
|
||||
google/gemma-3-27b-it | paid
|
||||
@ -130,14 +129,16 @@ export interface IKBotOptions {
|
||||
google/gemma-3n-e2b-it:free | free
|
||||
google/gemma-3n-e4b-it | paid
|
||||
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-coder | paid
|
||||
inflection/inflection-3-pi | paid
|
||||
inflection/inflection-3-productivity | paid
|
||||
liquid/lfm-3b | paid
|
||||
liquid/lfm-7b | paid
|
||||
kwaipilot/kat-coder-pro:free | free
|
||||
liquid/lfm-2.2-6b | paid
|
||||
liquid/lfm2-8b-a1b | paid
|
||||
meta-llama/llama-guard-3-8b | paid
|
||||
anthracite-org/magnum-v2-72b | paid
|
||||
anthracite-org/magnum-v4-72b | paid
|
||||
mancer/weaver | 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.3-70b-instruct | paid
|
||||
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:free | free
|
||||
meta-llama/llama-4-scout | paid
|
||||
meta-llama/llama-4-scout:free | free
|
||||
meta-llama/llama-guard-4-12b | 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-multimodal-instruct | paid
|
||||
microsoft/phi-4-reasoning-plus | paid
|
||||
microsoft/phi-3-medium-128k-instruct | paid
|
||||
microsoft/phi-3-mini-128k-instruct | paid
|
||||
microsoft/phi-3.5-mini-128k-instruct | paid
|
||||
sophosympatheia/midnight-rose-70b | paid
|
||||
minimax/minimax-m1 | paid
|
||||
minimax/minimax-m2 | paid
|
||||
minimax/minimax-m2.1 | paid
|
||||
minimax/minimax-01 | paid
|
||||
mistralai/mistral-large | paid
|
||||
mistralai/mistral-large-2407 | paid
|
||||
mistralai/mistral-large-2411 | paid
|
||||
mistralai/mistral-small | paid
|
||||
mistralai/mistral-tiny | paid
|
||||
mistralai/codestral-2501 | paid
|
||||
mistralai/codestral-2508 | paid
|
||||
mistralai/devstral-2512 | paid
|
||||
mistralai/devstral-2512:free | free
|
||||
mistralai/devstral-medium | paid
|
||||
mistralai/devstral-small | paid
|
||||
mistralai/devstral-small-2505 | paid
|
||||
mistralai/devstral-small-2505:free | free
|
||||
mistralai/magistral-medium-2506 | paid
|
||||
mistralai/magistral-medium-2506:thinking | paid
|
||||
mistralai/magistral-small-2506 | paid
|
||||
mistralai/ministral-14b-2512 | paid
|
||||
mistralai/ministral-3b-2512 | paid
|
||||
mistralai/ministral-8b-2512 | paid
|
||||
mistralai/ministral-3b | paid
|
||||
mistralai/ministral-8b | paid
|
||||
mistralai/mistral-7b-instruct | paid
|
||||
mistralai/mistral-7b-instruct:free | free
|
||||
mistralai/mistral-7b-instruct-v0.1 | paid
|
||||
mistralai/mistral-7b-instruct-v0.2 | paid
|
||||
mistralai/mistral-7b-instruct-v0.3 | paid
|
||||
mistralai/mistral-large-2512 | paid
|
||||
mistralai/mistral-medium-3 | paid
|
||||
mistralai/mistral-medium-3.1 | paid
|
||||
mistralai/mistral-nemo | paid
|
||||
mistralai/mistral-nemo:free | free
|
||||
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:free | free
|
||||
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-8x7b-instruct | paid
|
||||
mistralai/pixtral-12b | paid
|
||||
mistralai/pixtral-large-2411 | paid
|
||||
mistralai/mistral-saba | paid
|
||||
mistralai/voxtral-small-24b-2507 | paid
|
||||
moonshotai/kimi-dev-72b | paid
|
||||
moonshotai/kimi-dev-72b:free | free
|
||||
moonshotai/kimi-k2 | paid
|
||||
moonshotai/kimi-k2:free | free
|
||||
moonshotai/kimi-k2-0905 | paid
|
||||
moonshotai/kimi-vl-a3b-thinking | paid
|
||||
moonshotai/kimi-vl-a3b-thinking:free | free
|
||||
moonshotai/kimi-k2-0905:exacto | paid
|
||||
moonshotai/kimi-k2-thinking | paid
|
||||
morph/morph-v3-fast | paid
|
||||
morph/morph-v3-large | paid
|
||||
gryphe/mythomax-l2-13b | paid
|
||||
neversleep/llama-3-lumimaid-70b | paid
|
||||
neversleep/llama-3.1-lumimaid-8b | paid
|
||||
nex-agi/deepseek-v3.1-nex-n1:free | free
|
||||
neversleep/noromaid-20b | paid
|
||||
nousresearch/deephermes-3-llama-3-8b-preview:free | free
|
||||
nousresearch/deephermes-3-mistral-24b-preview | 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-4-405b | paid
|
||||
nousresearch/hermes-4-70b | paid
|
||||
nousresearch/hermes-2-pro-llama-3-8b | 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: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:free | free
|
||||
openai/chatgpt-4o-latest | paid
|
||||
@ -259,28 +259,44 @@ export interface IKBotOptions {
|
||||
openai/gpt-4o-mini-search-preview | paid
|
||||
openai/gpt-5 | 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-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:exacto | paid
|
||||
openai/gpt-oss-120b:free | free
|
||||
openai/gpt-oss-20b | paid
|
||||
openai/gpt-oss-20b:free | free
|
||||
openai/gpt-oss-safeguard-20b | paid
|
||||
openai/o1 | paid
|
||||
openai/o1-mini | paid
|
||||
openai/o1-mini-2024-09-12 | paid
|
||||
openai/o1-pro | paid
|
||||
openai/o3 | paid
|
||||
openai/o3-deep-research | paid
|
||||
openai/o3-mini | paid
|
||||
openai/o3-mini-high | paid
|
||||
openai/o3-pro | paid
|
||||
openai/o4-mini | paid
|
||||
openai/o4-mini-deep-research | paid
|
||||
openai/o4-mini-high | paid
|
||||
perplexity/r1-1776 | paid
|
||||
opengvlab/internvl3-78b | paid
|
||||
perplexity/sonar | paid
|
||||
perplexity/sonar-deep-research | paid
|
||||
perplexity/sonar-pro | paid
|
||||
perplexity/sonar-pro-search | paid
|
||||
perplexity/sonar-reasoning | paid
|
||||
perplexity/sonar-reasoning-pro | paid
|
||||
prime-intellect/intellect-3 | paid
|
||||
qwen/qwen-plus-2025-07-28 | paid
|
||||
qwen/qwen-plus-2025-07-28:thinking | paid
|
||||
qwen/qwen-vl-max | paid
|
||||
@ -288,85 +304,92 @@ export interface IKBotOptions {
|
||||
qwen/qwen-max | paid
|
||||
qwen/qwen-plus | 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:free | free
|
||||
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:free | free
|
||||
qwen/qwen3-14b | paid
|
||||
qwen/qwen3-14b:free | free
|
||||
qwen/qwen3-235b-a22b | paid
|
||||
qwen/qwen3-235b-a22b:free | free
|
||||
qwen/qwen3-235b-a22b-2507 | paid
|
||||
qwen/qwen3-235b-a22b-thinking-2507 | paid
|
||||
qwen/qwen3-30b-a3b | paid
|
||||
qwen/qwen3-30b-a3b:free | free
|
||||
qwen/qwen3-30b-a3b-instruct-2507 | paid
|
||||
qwen/qwen3-30b-a3b-thinking-2507 | paid
|
||||
qwen/qwen3-32b | paid
|
||||
qwen/qwen3-4b:free | free
|
||||
qwen/qwen3-8b | paid
|
||||
qwen/qwen3-8b:free | free
|
||||
qwen/qwen3-coder-30b-a3b-instruct | paid
|
||||
qwen/qwen3-coder | paid
|
||||
qwen/qwen3-coder:exacto | paid
|
||||
qwen/qwen3-coder:free | free
|
||||
qwen/qwen3-coder-flash | paid
|
||||
qwen/qwen3-coder-plus | paid
|
||||
qwen/qwen3-max | paid
|
||||
qwen/qwen3-next-80b-a3b-instruct | 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:free | free
|
||||
qwen/qwq-32b-preview | 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:free | free
|
||||
rekaai/reka-flash-3:free | free
|
||||
relace/relace-apply-3 | paid
|
||||
relace/relace-search | paid
|
||||
undi95/remm-slerp-l2-13b | paid
|
||||
sao10k/l3-lunaris-8b | paid
|
||||
sao10k/l3-euryale-70b | paid
|
||||
sao10k/l3.1-70b-hanami-x1 | paid
|
||||
sao10k/l3.1-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
|
||||
stepfun-ai/step3 | paid
|
||||
switchpoint/router | paid
|
||||
tencent/hunyuan-a13b-instruct | paid
|
||||
tencent/hunyuan-a13b-instruct:free | free
|
||||
thedrummer/anubis-70b-v1.1 | paid
|
||||
thedrummer/anubis-pro-105b-v1 | paid
|
||||
thedrummer/cydonia-24b-v4.1 | paid
|
||||
thedrummer/rocinante-12b | paid
|
||||
thedrummer/skyfall-36b-v2 | paid
|
||||
thedrummer/unslopnemo-12b | paid
|
||||
thudm/glm-4-32b | paid
|
||||
thudm/glm-4.1v-9b-thinking | paid
|
||||
thudm/glm-z1-32b | paid
|
||||
tngtech/deepseek-r1t-chimera | paid
|
||||
tngtech/deepseek-r1t-chimera:free | free
|
||||
tngtech/deepseek-r1t2-chimera | paid
|
||||
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
|
||||
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-beta | paid
|
||||
x-ai/grok-3-mini | paid
|
||||
x-ai/grok-3-mini-beta | 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
|
||||
xiaomi/mimo-v2-flash:free | free
|
||||
z-ai/glm-4-32b | paid
|
||||
z-ai/glm-4.5 | paid
|
||||
z-ai/glm-4.5-air | paid
|
||||
z-ai/glm-4.5-air:free | free
|
||||
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
|
||||
[35m[1m[22m[39m
|
||||
[35m[1m OpenAI models:[22m[39m
|
||||
[35m[1m[22m[39m
|
||||
babbage-002
|
||||
chatgpt-4o-latest
|
||||
chatgpt-image-latest
|
||||
codex-mini-latest
|
||||
dall-e-2
|
||||
dall-e-3
|
||||
@ -395,7 +418,6 @@ export interface IKBotOptions {
|
||||
gpt-4o-2024-08-06
|
||||
gpt-4o-2024-11-20
|
||||
gpt-4o-audio-preview
|
||||
gpt-4o-audio-preview-2024-10-01
|
||||
gpt-4o-audio-preview-2024-12-17
|
||||
gpt-4o-audio-preview-2025-06-03
|
||||
gpt-4o-mini
|
||||
@ -407,30 +429,56 @@ export interface IKBotOptions {
|
||||
gpt-4o-mini-search-preview
|
||||
gpt-4o-mini-search-preview-2025-03-11
|
||||
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-2025-03-20
|
||||
gpt-4o-mini-tts-2025-12-15
|
||||
gpt-4o-realtime-preview
|
||||
gpt-4o-realtime-preview-2024-10-01
|
||||
gpt-4o-realtime-preview-2024-12-17
|
||||
gpt-4o-realtime-preview-2025-06-03
|
||||
gpt-4o-search-preview
|
||||
gpt-4o-search-preview-2025-03-11
|
||||
gpt-4o-transcribe
|
||||
gpt-4o-transcribe-diarize
|
||||
gpt-5
|
||||
gpt-5-2025-08-07
|
||||
gpt-5-chat-latest
|
||||
gpt-5-codex
|
||||
gpt-5-mini
|
||||
gpt-5-mini-2025-08-07
|
||||
gpt-5-nano
|
||||
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-2025-08-28
|
||||
gpt-audio-mini
|
||||
gpt-audio-mini-2025-10-06
|
||||
gpt-audio-mini-2025-12-15
|
||||
gpt-image-1
|
||||
gpt-image-1-mini
|
||||
gpt-image-1.5
|
||||
gpt-realtime
|
||||
gpt-realtime-2025-08-28
|
||||
gpt-realtime-mini
|
||||
gpt-realtime-mini-2025-10-06
|
||||
gpt-realtime-mini-2025-12-15
|
||||
o1
|
||||
o1-2024-12-17
|
||||
o1-mini
|
||||
o1-mini-2024-09-12
|
||||
o1-pro
|
||||
o1-pro-2025-03-19
|
||||
o3
|
||||
@ -443,6 +491,8 @@ export interface IKBotOptions {
|
||||
o4-mini-deep-research-2025-06-26
|
||||
omni-moderation-2024-09-26
|
||||
omni-moderation-latest
|
||||
sora-2
|
||||
sora-2-pro
|
||||
text-embedding-3-large
|
||||
text-embedding-3-small
|
||||
text-embedding-ada-002
|
||||
|
||||
5127
packages/ai-tools/package-lock.json
generated
5127
packages/ai-tools/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -44,7 +44,7 @@
|
||||
"keyv-file": "^5.1.3",
|
||||
"marked": "^15.0.4",
|
||||
"mime-types": "^2.1.35",
|
||||
"nodemailer": "^6.9.16",
|
||||
"nodemailer": "^7.0.13",
|
||||
"openai": "^5.8.2",
|
||||
"p-map": "^7.0.3",
|
||||
"rotating-file-stream": "^3.2.6",
|
||||
|
||||
2
packages/cache/package-lock.json
generated
vendored
2
packages/cache/package-lock.json
generated
vendored
@ -33,6 +33,7 @@
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
@ -1224,6 +1225,7 @@
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/node": "^22.12.0",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
|
||||
7
packages/cad/package-lock.json
generated
7
packages/cad/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@polymech/cad",
|
||||
"version": "1.8.8",
|
||||
"version": "1.8.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@polymech/cad",
|
||||
"version": "1.8.8",
|
||||
"version": "1.8.9",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@polymech/cache": "file:..\\cache",
|
||||
@ -32,7 +32,7 @@
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"bin": {
|
||||
"polymech-cad": "dist/main.js"
|
||||
"polymech-cad": "dist-in/main.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
@ -7328,6 +7328,7 @@
|
||||
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.27.0",
|
||||
"fdir": "^6.5.0",
|
||||
|
||||
77
packages/fs/package-lock.json
generated
77
packages/fs/package-lock.json
generated
@ -67,6 +67,27 @@
|
||||
"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": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
@ -247,9 +268,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
@ -388,9 +409,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
|
||||
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
@ -419,12 +440,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -456,9 +477,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
|
||||
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
@ -585,12 +606,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
|
||||
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
|
||||
"license": "ISC",
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
|
||||
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
@ -694,14 +715,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/glob": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
|
||||
"integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
|
||||
"license": "ISC",
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
|
||||
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^4.0.1",
|
||||
"minimatch": "^10.0.0",
|
||||
"foreground-child": "^3.3.1",
|
||||
"jackspeak": "^4.1.1",
|
||||
"minimatch": "^10.1.1",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^2.0.0"
|
||||
@ -717,9 +738,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/jackspeak": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.3.tgz",
|
||||
"integrity": "sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
|
||||
"integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
|
||||
2
packages/i18n/package-lock.json
generated
2
packages/i18n/package-lock.json
generated
@ -76,6 +76,7 @@
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
@ -2346,6 +2347,7 @@
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/node": "^22.12.0",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@types/node": "^22.10.9",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-regexp": "^2.7.0",
|
||||
"ts-node": "^10.9.1",
|
||||
|
||||
1
packages/mail/package-lock.json
generated
1
packages/mail/package-lock.json
generated
@ -1944,7 +1944,6 @@
|
||||
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.0.18",
|
||||
"@vitest/mocker": "4.0.18",
|
||||
|
||||
26
packages/media/package-lock.json
generated
26
packages/media/package-lock.json
generated
@ -81,6 +81,7 @@
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
@ -2479,6 +2480,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -2516,6 +2518,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@ -3019,6 +3022,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001733",
|
||||
"electron-to-chromium": "^1.5.199",
|
||||
@ -6599,6 +6603,7 @@
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -7260,6 +7265,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@ -8869,6 +8875,7 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@ -8989,6 +8996,7 @@
|
||||
"integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.6",
|
||||
@ -9189,6 +9197,7 @@
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz",
|
||||
"integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.8",
|
||||
@ -9237,6 +9246,7 @@
|
||||
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz",
|
||||
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@discoveryjs/json-ext": "^0.6.1",
|
||||
"@webpack-cli/configtest": "^3.0.1",
|
||||
@ -10347,6 +10357,7 @@
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/node": "^22.12.0",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
@ -11023,7 +11034,8 @@
|
||||
"acorn": {
|
||||
"version": "8.15.0",
|
||||
"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": {
|
||||
"version": "1.0.4",
|
||||
@ -11044,6 +11056,7 @@
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
@ -11395,6 +11408,7 @@
|
||||
"version": "4.25.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz",
|
||||
"integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001733",
|
||||
"electron-to-chromium": "^1.5.199",
|
||||
@ -13804,7 +13818,8 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"pify": {
|
||||
"version": "4.0.1",
|
||||
@ -14239,6 +14254,7 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
@ -15322,7 +15338,8 @@
|
||||
"typescript": {
|
||||
"version": "5.8.3",
|
||||
"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": {
|
||||
"version": "1.4.3",
|
||||
@ -15386,6 +15403,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz",
|
||||
"integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.6",
|
||||
@ -15468,6 +15486,7 @@
|
||||
"version": "5.101.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz",
|
||||
"integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.7",
|
||||
"@types/estree": "^1.0.8",
|
||||
@ -15500,6 +15519,7 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz",
|
||||
"integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@discoveryjs/json-ext": "^0.6.1",
|
||||
"@webpack-cli/configtest": "^3.0.1",
|
||||
|
||||
7
packages/registry/package-lock.json
generated
7
packages/registry/package-lock.json
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@plastichub/osr-registry",
|
||||
"name": "@polymech/registry",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@plastichub/osr-registry",
|
||||
"name": "@polymech/registry",
|
||||
"version": "0.1.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
@ -39,6 +39,7 @@
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"ansi-regex": "^6.2.2",
|
||||
"env-var": "^7.5.0",
|
||||
"glob": "^10.4.5",
|
||||
"js-yaml": "^4.1.0",
|
||||
@ -121,7 +122,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@types/node": "^22.10.9",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-regexp": "^2.7.0",
|
||||
"ts-node": "^10.9.1",
|
||||
|
||||
49
packages/scripts/install.sh
Normal file
49
packages/scripts/install.sh
Normal 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."
|
||||
8230
packages/search/package-lock.json
generated
8230
packages/search/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -73,5 +73,8 @@
|
||||
"license": "BSD-3-Clause",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
]
|
||||
],
|
||||
"overrides": {
|
||||
"puppeteer": "$puppeteer"
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -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'
|
||||
@ -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
|
||||
}
|
||||
@ -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;
|
||||
});
|
||||
};
|
||||
@ -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()
|
||||
})
|
||||
}
|
||||
@ -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()
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
@ -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
|
||||
}
|
||||
@ -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');
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -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()
|
||||
})
|
||||
}
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
@ -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}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user