open-index/open-npm huggingface dataset:
npm package: @jkyu/create-monet-app
Description: 微服务工程初始化
Author: Jenkin.Yu
Latest version: 1.6.0

# Create Monet APP

## 🙋‍♂️ 快速开始
+ 初始化 CMA 项目： `npx @jkyu/create-monet-app init`

## 📦 安装 
`npm i -g @jkyu/create-monet-app` or `yarn global add @jkyu/create-monet-app` 

## 👨‍🔧 功能迭代 
[更新文档](CHANGELOG.md)

## 👨‍💻 指令 
+ `mjd info` 查看当前运行环境
+ `mjd init` 初始化 CMA 基础框架
+ `mjd` help
npm package: @jkyu/monet-studio
Description: webpack5 脚手架
Author: Jenkin.Yu
Latest version: 1.5.0

# Monet Studio

## 🙋‍♂️ 快速开始
+ 初始化 CMA 项目： `npx @jkyu/create-monet-app init`

## 📦 安装 
`npm i -g @jkyu/create-monet-app` or `yarn global add @jkyu/create-monet-app` 

## 👨‍🔧 功能迭代 
[更新文档](CHANGELOG.md)

## 👨‍💻 指令 
+ `mjd info` 查看当前运行环境
+ `mjd dev` 调试
  + `mjd dev --env test` 运行环境
  + `mjd dev --no-quiet` 关闭webpack错误或警告信息
+ `mjd build` 构建
  + `mjd build --env test` 指定 部署环境
+ `mjd` help
npm package: @jkyu/monet-studio-cli
Description: 莫奈工作室
Author: Jenkin.Yu
Latest version: 2.5.0

# Monet Studio

## 🙋‍♂️ 快速开始
+ 初始化 CMA 项目： `npx @jkyu/create-monet-app init`

## 📦 安装 
`npm i -g @jkyu/create-monet-app` or `yarn global add @jkyu/create-monet-app` 

## 👨‍🔧 功能迭代 
[更新文档](CHANGELOG.md)

## 👨‍💻 指令
+ `jdm dev` 调试
+ `jdm build` 构建
npm package: @jkyu/uc-react-scripts
Description: React CRA 快速升级Webpack5
Author: Jenkin.Yu
Latest version: 2.1.6

# Webpack5 React Scripts

## 👨‍🏫 描述
+ uc-react-scripts 主要解决基于create-react-app的项目，快速升级Webpack 5使用

## 🙋‍♂️ 快速开始
+ 初始化 CMA 项目： `npx @jkyu/create-monet-app init`

## 📦 安装 
`npm i -g @jkyu/create-monet-app` or `yarn global add @jkyu/create-monet-app` 

## 👨‍🔧 功能迭代 
[更新文档](CHANGELOG.md)

## 👨‍💻 指令 
+ `uc-react-scripts info` 查看当前运行环境
+ `uc-react-scripts dev` 调试
  + `uc-react-scripts dev --env test` 运行环境
  + `uc-react-scripts dev --verbose` 关闭webpack错误或警告信息 默认为 false
+ `uc-react-scripts build` 构建
  + `uc-react-scripts build --env test` 指定 部署环境
+ `uc-react-scripts` help 

## 🧑‍💻 如何使用uc-react-scripts项目
#### 1) 安装 react-app-rewired
```bash
$ npm install @jkyu/uc-react-scripts --save-dev
```
#### 2) 在根目录中创建一个 mjd-config-overrides.js 文件
```javascript
/* mjd-config-overrides.js */
module.exports = {
  webpack: (config, env) => config,
  devServer: (configFunction) =>{
    return function(proxy, allowedHost) {
      // configFunction --> dev config
      return configFunction(proxy, allowedHost);
    };
  },
  paths:(paths, env) => paths,
  custom: {}, // 根据webpack结构，对配置进行覆盖
  override: (config) => config // 根据已经生成的config，进行修改
};
```
```
+-- your-project
|   +-- mjd-config-overrides.js
|   +-- node_modules
|   +-- package.json
|   +-- public
|   +-- README.md
|   +-- src
```
#### 3) 替换 package.json 中 scripts 执行部分
```diff
  /* package.json */

  "scripts": {
-   "start": "react-scripts start",
+   "start": "uc-react-scripts dev",
-   "build": "react-scripts build",
+   "build": "uc-react-scripts build",
}
```
#### 4) 启动 Dev Server
```bash
$ npm start
```
#### 5) 构建你的应用程序

```bash
$ npm run build
```
npm package: @jkz/mpvue
Description: Vue Runtime for mini program
Author: meituan.com
Latest version: 1.0.11

# mpvue

> This package is auto-generated. For pull requests please see [src/platforms/mp/entry-runtime.js](https://github.com/Meituan-Dianping/mpvue/blob/master/src/platforms/mp/entry-runtime.js).
npm package: @jkz/mpvue-loader
Description: mpvue single-file component loader for Webpack
Author: anchengjian
Latest version: 1.0.11

# mpvue-loader

>Webpack loader for mpvue components

本仓库是 fork 自 [vue-loader](https://github.com/vuejs/vue-loader) 修改而来，主要为 webpack 打包 mpvue components 提供能力。

更多详细文档请查阅 [mpvue-loader](http://mpvue.com/build/mpvue-loader)。

bug 或者交流建议等请反馈到 [mpvue/issues](https://github.com/Meituan-Dianping/mpvue/issues)。
npm package: @jl-org/data-to-ts
Description: JSON 或者 JS 转 TS
Author: CJL
Latest version: 0.1.1

# JS | JSON 转 TS

对 `json-to-ts` 包的增强  
扩展原先不存在的功能

1. 支持 *JavaScript* 对象转 *TS*
2. 支持 *JavaScript* 包含变量声明的对象转 *TS*
3. 支持导出配置

---

## 安装
```bash
npm i @jl-org/data-to-ts
```

## 使用

```ts
import { dataToTs } form '@jl-org/data-to-ts'

/** 标准 JSON */
const json = `{
    "lease": {
        "term": "36 months",
        "monthlyPayment": "$199",
        "dueAtSigning": "$3,000"
    },
    "purchase": {
        "price": "$21,570",
        "downPayment": "$2,500"
    }
}`

console.log(dataToTs(json, {
    enableExport: false,
    useTypeAlias: false,
    rootName: 'Test'
}).join('\n'))


/** JavaScript 对象字面量 */
const js1 = `const data = {
    lease: {
        term: '36 months',
        monthlyPayment: '$199',
        dueAtSigning: '$3,000'
    },
    purchase: {
        price: '$21,570',
        downPayment: '$2,500'
    }
}`
console.log(dataToTs(js1).join('\n'))


/** 混合单双引号的对象 */
const js2 = `var data = {
    "lease": {
        term: '36 months',
        monthlyPayment: '$199',
        dueAtSigning: '$3,000'
    },
    'purchase': {
        price: '$21,570',
        downPayment: '$2,500'
    }
}`
console.log(dataToTs(js2).join('\n'))


/** 没有命名的对象 */
const js3 = `{
    lease: {
        term: '36 months',
        monthlyPayment: '$199',
        dueAtSigning: '$3,000'
    },
    purchase: {
        price: '$21,570',
        downPayment: '$2,500'
    }
}`
console.log(dataToTs(js3).join('\n'))


/** 未声明的全局变量 */
const js4 = `a = {
    lease: {
        term: '36 months',
        monthlyPayment: '$199',
        dueAtSigning: '$3,000'
    },
    purchase: {
        price: '$21,570',
        downPayment: '$2,500'
    }
}`
console.log(dataToTs(js4).join('\n'))


/** 值带有冒号的 */
const js5 = `{
    jobName: "",
    "createdTime": "2024-04-28 14:24:54",
    "createdBy": ""
}`
console.log(dataToTs(js5).join('\n'))
```
npm package: @jl-org/eslint-plugins
Description: Eslint plugins
Author: CJL
Latest version: 1.0.0

# Eslint9 插件

## 已有插件

- 转文档注释
- React v-if
- 三目运算强制三行
- JSX 括号空格检测


## 安装

```bash
pnpm i @jl-org/eslint-plugins -D
# 推荐使用 antfu 的 eslint
pnpm i @antfu/eslint-config -D
```

`eslint.config.mjs`
```js
import antfu from '@antfu/eslint-config'
import {
  docComment,
  forceTernary,
  reactVIf,
  spacedJsxBraces
} from '@jl-org/eslint-plugins'

export default antfu({
  /** ... */

  /** 自定义插件 */
  plugins: {
    spacedJsxBraces, /** 自定义插件：在 JSX 花括号中添加空格 */
    forceTernary, /** 自定义插件：三目运算分为三行 */
    docComment, /** 自定义插件：将注释转换为文档注释 */
    reactVIf, /** 自定义插件：v-if 转 JSX */
  },

  /** 自定义规则 */
  rules: {
    'spacedJsxBraces/spacedJsxBraces': 'warn', /** 在 JSX 花括号中未添加空格时发出警告 */
    'forceTernary/forceTernary': 'warn', /** 三目运算分为三行 */
    /** 将 中文 或者 NOTE: 开头的注释转换为文档注释 */
    'docComment/docComment': ['warn', { pattern: '^(?:[\\u4E00-\\u9FA5\\u3000-\\u303F\\uFF00-\\uFFEF]|NOTE:)' }],
    'reactVIf/reactVIf': 'error', /** v-if 转 JSX */
  },
})
```
npm package: @jl-org/flip
Description: Flip 动画
Author: CJL
Latest version: 0.0.2

# Filp 动画

> 给原生 HTML 添加丝滑的拖拽交换效果

---

## 安装
```bash
npm i @jl-org/flip
```

> `iife` 模式下，全局对象名为：*_flip*

## 使用

```ts
import { toDrag } form '@jl-org/flip'

toDrag('.list', {
    draggingClass: 'dragging',
    duration: 500,
})
```

```html
<div class="list">
    <div class="list-item">1</div>
    <div class="list-item">2</div>
    <div class="list-item">3</div>
    <div class="list-item">4</div>
    <div class="list-item">5</div>
    <div class="list-item">6</div>
</div>

<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    body {
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .list {
        width: 300px;
        display: flex;
        flex-wrap: wrap;
        gap: 10px;
    }

    .list-item {
        margin: 5px 0;
        padding: 0 20px;
        line-height: 40px;
        height: 40px;
        background: linear-gradient(to right, #267871, #136a8a);
        color: #fff;
        cursor: move;
        user-select: none;
        border-radius: 5px;
        width: 40%;
    }

    .list-item.dragging {
        background: transparent;
        color: transparent;
        border: 1px dashed #ccc;
    }
</style>
```
npm package: @jl-org/optimize-assets-size
Description: Raster image optimization: auto pick smallest JPEG/PNG/WebP/AVIF encoding, rewrite imports | 栅格图体积优化：自动优选编码、重写 import 路径
Author: CJL
Latest version: 0.0.4

# optimize-assets-size

栅格图体积优化工具：在 JPEG / PNG / WebP / AVIF 间自动优选最小编码 / 自动重写 import 路径

直接写回源文件以减小 Git 体积（与 Vite 构建期 imagetools 等无关）

[English](./README.en.md) | **中文**

## 安装

```bash
pnpm add @jl-org/optimize-assets-size sharp -D
```

## CLI 用法

```bash
npx optimize-assets-size --dirs=src/assets,public [options]
```

### 参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `--dirs=a,b` | **必填**，逗号分隔多个根目录（相对 cwd） | - |
| `--tsconfig=path` | 指定 tsconfig 路径读取 paths | 自动查找 `tsconfig.json` / `tsconfig.app.json` |
| `--alias kv` | kv 映射覆盖 alias（优先级最高），如 `@/=src,hooks=lib` | - |
| `--dry-run` | 预览模式，不实际写文件 | `false` |
| `--force` | 强制覆盖（即使压后更大） | `false` |
| `--rewrite-imports` | 自动替换源码中的 alias 路径 | `false` |
| `--max-width=N` | 限制最大宽度（>= 16） | 不限制 |
| `--formats=a,b` | 参与优选的**额外**输出格式：`webp` / `png` / `jpg` / `jpeg` / `avif`（与同格式重压缩一起比体积） | `webp,png` |
| `--formats=` | 空值：不做跨格式编码，**仅**同格式重压缩 | - |

### 示例

```bash
# 预览压缩效果
npx optimize-assets-size --dirs=src --dry-run

# 自动优选编码 + 重写 import（扩展名变化时从 tsconfig 读 alias）
npx optimize-assets-size --dirs=src,public \
  --tsconfig=tsconfig.app.json \
  --rewrite-imports

# 手动指定 alias 映射（优先级高于 tsconfig）
npx optimize-assets-size --dirs=src \
  --alias "@/=src,hooks=../hooks/src" \
  --rewrite-imports

# 限制最大宽度为 1920px
npx optimize-assets-size --dirs=src --max-width=1920

# 只在 webp / avif 中选（并与同格式比较）
npx optimize-assets-size --dirs=src --formats=webp,avif

# 只做同格式压缩，不转其它格式
npx optimize-assets-size --dirs=src --formats=
```

### Alias 解析优先级

1. `--alias` kv 映射 — **最高优先级**，直接覆盖
2. `--tsconfig` 读取 `compilerOptions.paths` — 未指定时自动查找 `tsconfig.json` → `tsconfig.app.json`

## API 用法

```ts
import {
  chooseBestRasterEncoding,
  collectRasterFiles,
  computeAliasRewrites,
  encodeWebp,
  optimizeSameFormat,
  parseArgs,
  resolveAliasPaths,
  stripJsonComments,
} from 'optimize-assets-size'
import fs from 'node:fs'

// 解析 tsconfig 获取 alias 映射
const aliasPaths = resolveAliasPaths(null, 'tsconfig.app.json')

// 收集所有栅格图文件
const files = await collectRasterFiles(['src/assets'])

const buf = fs.readFileSync('photo.jpg')

// 同格式压缩
const optimized = await optimizeSameFormat(buf, '.jpg', 1920)

// 默认与同格式一起比较 webp + png；传 [] 则仅同格式
const best = await chooseBestRasterEncoding(buf, '.jpg', 1920)
const bestAvif = await chooseBestRasterEncoding(buf, '.jpg', 1920, {
  formatAllowlist: ['webp', 'avif'],
})
const sameOnly = await chooseBestRasterEncoding(buf, '.jpg', 1920, {
  formatAllowlist: [],
})

// 仅转 WebP（程序 API）
const webp = await encodeWebp(buf, 1920)

// 计算 import 路径替换对（目标扩展名以 best.outExt 为准）
const rewrites = computeAliasRewrites(
  '/project/src/assets/logo.png',
  '/project/src/assets/logo.webp',
  aliasPaths,
)
```

## 压缩参数

| 格式 | 参数 |
|------|------|
| JPEG | quality: 82, mozjpeg: true |
| PNG | compressionLevel: 9, quality: 85, effort: 10 |
| WebP | quality: 82, effort: 4 |
| AVIF | quality: 70, effort: 4 |

## License

MIT
npm package: @jl-org/ssg
Description: 一键把单页应用转换成静态网站
Author: CJL
Latest version: 0.0.3

# 一键把单页应用转换成静态网站

支持任何前端框架，如 React、Vue、Angular、Svelte 等

## 安装

```bash
npm i @jl-org/ssg puppeteer-core -D
```


## 快速上手

1. **生成静态 HTML**
`scripts/ssg.cjs`
```js
const path = require('node:path')
const { ssg } = require('@jl-org/ssg')
const puppeteer = require('puppeteer-core')


const PORT = '4173'
main()

async function main() {
  await ssg({
    port: PORT,
    /**
     * 创建浏览器实例的函数，默认需要你自行下载 puppeteer-core 或者 puppeteer
     * ### 因为 puppeteer 会自动下载浏览器，所以提供此配置。你可以使用自己浏览器的路径，节省内存
     * @example
     * puppeteer.launch({ headless: true, ... })
     */
    createBrowser: () => puppeteer.launch({
      executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe',
      headless: true
    }),
    ssgPages: [
      {
        url: `http://localhost:${PORT}`,
        target: path.resolve(__dirname, '../dist/index.html')
      },
      {
        url: `http://localhost:${PORT}/pricing`,
        target: path.resolve(__dirname, '../dist/pricing.html')
      },
      {
        url: `http://localhost:${PORT}/about`,
        target: path.resolve(__dirname, '../dist/about.html')
      },
    ]
  })

  process.exit(0)
}
```

2. **修改 Nginx 配置，并且重启服务**
```nginx
server {
  listen 80;
  server_name yourdomain.com;

  # pages
  location /pricing {
    root /Your_Root_Dir;
    index pricing.html;
    try_files $uri $uri/ /pricing.html;
  }
  location /about {
    root /Your_Root_Dir;
    index about.html;
    try_files $uri $uri/ /about.html;
  }
}
```

3. **测试生效**
```bash
# 查看返回内容，是否为整个 HTML
curl http://yourdomain.com/pricing
```

---


## 配置项

```ts

export interface SSGOptions {
  ssgPages: SSGPage[]

  /**
   * 启动服务器的端口
   * @default '4173'
   */
  port?: string
  /**
   * spawn 启动服务器的命令的第一个参数
   * @default 'npx'
   */
  startServerCmd?: string
  /**
   * spawn 启动服务器的命令的参数列表
   * @default 
   * ['vite', 'preview', '--port', PORT]
   */
  startServerArgs?: readonly string[]

  /**
   * 是否需要压缩 HTML 文件
   * @default true
   */
  needMinify?: boolean
  /**
   * 压缩 HTML 文件的配置
   * @default
   * {
   *   collapseWhitespace: true, // 删除多余的空格
   *   removeComments: true, // 删除注释
   *   removeAttributeQuotes: false, // 删除属性的引号（当安全时）
   *   minifyCSS: true, // 压缩内联 CSS
   *   minifyJS: true, // 压缩内联 JS
   * }
   */
  minifyOptions?: Options

  /**
   * 创建浏览器实例的函数，默认需要你自行下载 puppeteer-core 或者 puppeteer
   * ### 因为 puppeteer 会自动下载浏览器，所以提供此配置。你可以使用自己浏览器的路径，节省内存
   * @example
   * await puppeteer.launch({ headless: true, ... })
   */
  createBrowser: () => Promise<Browser>
  /**
   * 页面打开前的回调函数，可以用来设置一些页面的配置
   */
  onBeforeOpenPage?: (page: Page) => Promise<void>
}
```

---


## 原理

- 项目打包后有一个 `dist` 文件夹，此脚本会启动一个本地服务器，默认用 `vite preview` 来查看
- 然后调用 puppeteer 模拟打开浏览器，访问每个页面，生成静态 HTML 文件
- 最后将生成的 HTML 文件放到指定目录，并替换掉原来的 HTML 文件
npm package: @jl-org/ts-tool
Description: 为 Typescript 扩展的实用泛型工具，以及类型体操
Author: CJL
Latest version: 0.0.8

# TS 实用泛型工具

## 安装
```bash
npm i -D @jl-org/ts-tool
```

## 目录
- [工具](#工具)
- [数组工具](#数组工具)
- [字符串工具](#字符串工具)

**全都有文档注释**

```ts
type O = {
    a: string
    b: number
    c: boolean
    d: {
        e: {
            f: any
        }
    }
}

type Arr = [string, number, boolean, { e: { f: any } }]

type NestedPromise = Promise<Promise<Promise<string>>>
```

---

### 工具
```ts
import type {
    DeepReadonly,
    DeepPartial,
    DeepRequired,
    RemoveReadonly,

    UnPacked,
    Optional,
    PartRequired,

    Getters,
    Setters,
    GetterAndSetters,

    PickReadonlyKeys,
    PickPropType,
} from '@jl-org/ts-tool'


/* 部分可选 */
type PartialO = Optional<O, 'a'>
/* 部分必填 */
type RequiredO = PartRequired<O, 'a'>

/** 深度只读 */
type DeepReadonlyO = DeepReadonly<O>
/** 去除 readonly */
type RemoveReadonlyO = RemoveReadonly<DeepReadonlyO>

/** 深度可选 */
type DeepPartialO = DeepPartial<O>
/** 深度必选 */
type DeepRequiredO = DeepRequired<O>

/** ======================================================== */

/** 究极解包，支持获取`数组 | 函数返回值 | Promise<Promise<...>>` 里的类型 */
type GetArrType = UnPacked<Arr>  // string | number | boolean | { e: { f: any } }
type GetPromiseType = UnPacked<NestedPromise>  // string
type GetFuncType = UnPacked<() => string>  // string

/** ======================================================== */

/**
 * 下面就是类型体操范畴了
 */

/** Getters */
type GenGetters = Getters<O>
/** Setters */
type GenSetters = Setters<O>
/** GetterAndSetters */
type GenGetterAndSetters = GetterAndSetters<O>

/** 取出只读的键 */
type PickReadonlyKeysO = PickReadonlyKeys<Readonly<O>>  // "a" | "b" | "c" | "d"

/** 取出结构体某个类型 */
type PickPropTypeO = PickPropType<O, 'd.e'>  // { f: any }

/** 获取对象的所有属性，排除函数 */
type PickAllPropO = PickProps<O>
```

### 数组工具
```ts
import type {
    FirstArr,
    PopArr,
    ReverseArr,
} from '@jl-org/ts-tool'


/** 首个元组类型 */
type First = FirstArr<Arr>  // string

/** 删除元组末尾类型 */
type Pop = PopArr<Arr>  // [string, number, boolean]

/* 元组反转 */
type Reverse = ReverseArr<Arr>  // [{ e: { f: any } }, boolean, number, string]
```

### 字符串工具
```ts
import type {
    SplitStr,
    GetStrLen,
    StartsWith,
    PickStartsWith,
    QueryKV,
    CamelCase,
    ToSnake,
} from '@jl-org/ts-tool'


/** 是否以 `xx` 开头 */
type StartsWithX = StartsWith<'apple', 'a'>  // apple
/** 取出以 `xx` 开头的键值对，例如取出事件 */
type PickStartsWithX = PickStartsWith<{
    onChange: () => void
    onClick: () => void
    other: () => void
}, 'on'>

/** 把 Query 字符串，转为键值对 */
type QueryKVType = QueryKV<'name=kn&sex=f&language=ts'>

/** 蛇形转驼峰 */
type CamelCaseStr = CamelCase<'hello_world'>  // helloWorld
/** 驼峰转蛇形 */
type ToSnakeStr = ToSnake<'helloWorld'>  // hello_world

/** 获取字符串长度 */
type StrLen = GetStrLen<'hello'>  // 5

/** 字符串分割成联合类型 */
type Split = SplitStr<'abc'>  // 'a' | 'b' | 'c'
```
npm package: @jl15988/echarts-builder
Description: An echarts builder
Author: jl15988
Latest version: 1.0.1

# echarts-builder

因为直接使用 echarts 太过繁杂，即使目前 echarts 支持 ts 语法，但配置仍然过于繁重，所以我们对其进行了优化增强。

使用前请先安装 echarts

```
npm i echarts
```

然后安装 echarts-builder

```
npm i @jl15988/echarts-builder
```

使用很简单，只需通过 builder 传入组件 id 或组件即可开始构建 echarts

```ts
import {BarSeriesDataOption, EchartsBuilder, EchartsLineStyle, LineSeriesDataOption} from "@jl15988/echarts-builder";
import {BarSeriesOption, LineSeriesOption} from "echarts";

const echartsBuilder = EchartsBuilder.builder("ech")
    .assign(EchartsLineStyle.smooth())
    .assign(EchartsLineStyle.gradient(
        [
            ['rgb(128, 255, 165)', 'rgb(1, 191, 236)']
        ]
    ))
    .title("echarts图表数据")
    .xAxis({
        boundaryGap: true,
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    })
    .legend(['折线', '柱状'])
    // .yAxis()
    .series<LineSeriesOption, LineSeriesDataOption>("line", [150, 230, 224, 218, 135, 147, 260], '折线')
    .series<BarSeriesOption, BarSeriesDataOption>("bar", [150, 230, 224, 218, 135, 147, 260], '柱状')
console.log(echartsBuilder)
echartsBuilder.build()
```

当然，你也可以在项目入口处，通过 EchartsBuilder 进行全局化处理

```js
EchartsBuilder.defaultTooltip({
    trigger: "item"
})
EchartsBuilder.defaultXAxis({
    boundaryGap: true
})
```
npm package: @jl15988/node-action
Description: A Nodejs server helper.
Author: jl15988
Latest version: 0.0.1-alpha.17

# node-action

### 介绍

利用 node 快速构建高可用、高效率、高健全的 server

## 安装

```shell
npm install @jl15988/node-action
```

## 简单使用

index.js
```js
const {nodeAction, Action, actionInterceptor} = require("@jl15988/node-action");

const userInfo = {
    "id": 1,
    "username": "admin",
    "nickname": "管理员",
    "email": "aoteman@126.com",
    "mobile": "15612345678",
    "sex": 1,
    "avatar": null,
    "loginIp": "192.168.0.8",
    "loginDate": 1731468594935,
    "createTime": 1609837427000,
    "roles": [
        {
            "id": 1,
            "name": "超级管理员"
        },
        {
            "id": 2,
            "name": "普通角色"
        }
    ],
    "dept": null,
    "posts": [
        {
            "id": 1,
            "name": "董事长"
        }
    ],
    "socialUsers": []
}

// 创建用户控制器
const UserAction = new Action('UserAction', (action) => {

    // 设置 user action 的路由前缀
    action.mapping('/user')

    // 获取用户信息接口
    action.get('/get', (requestInfo) => {
        // 请求参数
        console.log(requestInfo.params)
        // 返回用户信息
        return userInfo
    })

    // 修改用户信息接口
    action.post('/update', (requestInfo) => {
        // 请求体
        console.log(requestInfo.body)
        // 返回修改结果
        return {
            code: 200,
            message: '修改成功'
        }
    })
})

const interceptors = [{
    // 拦截器名
    name: 'onLoad',
    // 执行排序，如果重复则按添加的顺序，没有顺序的优先级最低
    sort: 0,
    // 解析路由之前的拦截器
    load: (requestInfo, response) => {
        return true
    },
    // 执行路由处理方法之前的拦截器
    before: (requestInfo, response, routeInfo) => {
        return true
    },
    // 执行路由处理方法之后的拦截器
    after: (requestInfo, response, routeInfo, handleResult) => {
        return true
    }
}]

// 统一异常处理器
nodeAction.actionErrorHandler = (request, response, error) => {
    console.error(error)
}

// 统一返回数据处理器
nodeAction.actionResultHandler = (request, response, res) => {
    console.log(res)
    return res
}

nodeAction
    // 控制器
    .actions([UserAction])
    // 拦截器
    .interceptors(interceptors)
    // 端口号
    .port(3000)
    // 启动
    .start()
```

执行 `node src/index.js` 启动

浏览器访问：http://{本地地址}:3000/user/get
npm package: @jlacarelle/modern-search-extensibility
Description: Base library for creating PnP Modern Search extensions
Latest version: 1.22.1

## PnP Search Extensibility library

PnP Modern Search uses the concept of 'extensibility libraries'. These are SharePoint Framework library components you put in the global or site collection app catalog that will be loaded automatically by Web Parts to enhance the experience and options (ex: new data source with new options, custom layout, etc.). Simple as that!

## Get started

More information to get started can be found in the documentation for PnP Moderns Search at https://microsoft-search.github.io/pnp-modern-search/extensibility/.

## Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

## "Sharing is Caring"

## Disclaimer

**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
npm package: @jlaf/storyblok-cac
Description: StoryBlok Components as Code
Author: Jessie Liauw A Fong
Latest version: 0.0.12

# StoryBlok Components as Code

Define StoryBlok components using the typesafety of TypeScript!

## Installation

```
npm install --save @jlaf/storyblok-cac
```

## Usage

First define your components:

```typescript
// src/components.ts
import { type StoryblokComponent, arrayToStoryBlokOptions } from '@jlaf/storyblok-cac'

export default [
	{
		name: 'page',
		schema: {
			body: {
				type: 'bloks',
			},
		},
		is_root: true,
		is_nestable: false,
	},
	{
		name: 'content',
		schema: {
			content: {
				type: 'richtext',
			},
			textAlign: {
				type: 'option',
				options: arrayToStoryBlokOptions(['left', 'center', 'right']),
				default_value: 'left',
			},
		}
	},
] as StoryblokComponent[]
```

### Component generation

Now you can generate the components using:

```
yarn run storyblok-cac components --input-file src/components.ts
```

This will output a `components.json` file which can be uploaded to Storyblok using the [Storyblok CLI](https://www.storyblok.com/tp/storyblok-cli-best-practices)

**CLI Parameters**

| Parameter       | Default           | Description                    | Example               |
|-----------------|-------------------|--------------------------------|-----------------------|
| `--input-file`  | -                 | File containing the components | `src/components.ts`   |
| `--output-path` | `components.json` | Output of the json file        | `src/components.json` |

### Presets generation

Now you can generate the presets using:

```
yarn run storyblok-cac presets --input-file src/components.ts --space-id 12345 --token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

**CLI Parameters**

| Parameter       | Default        | Description                                                                                                          | Example                        |
|-----------------|----------------|----------------------------------------------------------------------------------------------------------------------|--------------------------------|
| `--input-file`  | -              | File containing the components                                                                                       | `src/components.ts`            |
| `--space-id`    | -              | Storyblok Space ID                                                                                                   | `12234`                        |
| `--token`       | -              | Personal access token. See [storyblok](https://www.storyblok.com/docs/api/management/getting-started/authentication) | `xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
| `--output-path` | `presets.json` | Output of the json file                                                                                              | `src/presets.json`             |

## Helpers

### `arrayToStoryBlokOptions`

This function creates an array which can be used by the Storyblok CLI. See usage above.

## Starter

The starter used is [antfu/starter-ts](https://github.com/antfu/starter-ts)
npm package: @jlaf/zod-forms
Description: A TypeScript library for generating form fields based on Zod schemas.
Author: Jessie Liauw A Fong
Latest version: 0.0.8

# @jlaf/zod-forms

## Overview
This TypeScript library aims to simplify the task of generating form fields based on Zod schemas. If you're building forms and using Zod for validation, this library will automate much of the heavy lifting. It provides functionalities to generate form fields with meta-information that could be used for rendering the fields on the frontend.

## Installation

```
npm install zod @jlaf/zod-forms
```

## Example

Below shows an example in svelte

```svelte
<script lang="ts">
  import { z } from 'zod';
  import { generateForm } from '@jlaf/zod-forms';

  const userSchema = z.object({
    name: z.string(),
    age: z.number(),
  });

  const formFields = generateForm(userSchema, {
    name: {
      label: 'First name'
    }
  })

  let value: z.infer<userSchema> = userSchema.default()
</script>

{#each Object.entries(formFields) as [key, formField]}
    <label for="key">{formField.meta?.label || key}</label>
    <input type="formField.type" bind:value="value[key]" />
{/each}
```

This setup seems trivial when first looking at it. However, zod-forms is created to work alongside a database layer such as `prisma` or `drizzle` where you don't generate your own zod schemas.

## Usage

This libary revolves around the `FormField` type. The typelooks as follows:

```typescript
interface FormField {
	type: ['string', 'number', 'boolean', 'array', 'date']
	input: ['input', 'boolean', 'select', 'multiselect', 'date', 'range']
	zodType: z.ZodType<any>
	meta?: FieldMeta
}
```

The main function exported by zod-forms is `generateForm`. This function returns a `Record<string, FormField>`. The usage looks as following:

```typescript
import { z } from 'zod'
import { generateForm } from '@jlaf/zod-forms'

const userSchema = z.object({
	name: z.string(),
	age: z.number(),
	gender: z.enum(['Male', 'Female', 'Other'])
})

const formFields = generateForm(userSchema, {
	name: {
		label: 'Firstname'
	}
})
```

The **generated** object will look like the following:

```typescript
const formFields = {
	name: {
		accessor: 'name',
		type: 'string',
		input: 'input',
		validator: z.string(),
		meta: {
			label: 'Firstname'
		}
	},
	age: {
		accessor: 'age',
		type: 'number',
		input: 'input',
		validator: z.number(),
	},
	gender: {
		accessor: 'gender',
		type: 'string',
		input: 'select',
		optionItems: ['Male', 'Female', 'Other'],
		validator: z.enum(['Male', 'Female', 'Other']),
	}
}
```

### Forcing field meta

If you want to force the field meta to be of a certain type because you want to use it for automatic form generation you can use the following overrides:

```typescript
declare module '@jlaf/zod-forms' {
	export interface FieldMeta {
		label: string
	}
}
```

## Contributing
Feel free to open issues or submit PRs to enhance the functionalities.
npm package: @jlalande/number-formatter
Description: [![Build Status](https://travis-ci.org/jlalande/number-formatter.svg?branch=master)](https://travis-ci.org/jlalande/number-formatter)
Author: Jean Lalande
Latest version: 0.0.2

# Number Formatter

[![Build Status](https://travis-ci.org/jlalande/number-formatter.svg?branch=master)](https://travis-ci.org/jlalande/number-formatter)

A small library that adds commas to numbers

See https://medium.com/@jdaudier/how-to-create-and-publish-your-first-node-js-module-444e7585b738

## Installation

  `npm install @jlalande/number-formatter`

## Usage

```
var numFormatter = require('@jdaudier/number-formatter');

var formattedNum = numFormatter(35666);
```

  Output should be `35,666`

## Tests

  `npm test`

## Contributing

In lieu of a formal style guide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code.