Skip to content

Commit 87f2873

Browse files
committed
feat: init cli package
1 parent bf723ab commit 87f2873

File tree

5 files changed

+203
-0
lines changed

5 files changed

+203
-0
lines changed

packages/cli/README.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# @qifi/generate
2+
3+
<!-- Some beautiful tags -->
4+
<p align="left">
5+
<a href="https://www.npmjs.com/package/@qifi/generate">
6+
<img alt="npm" src="https://badgen.net/npm/v/@qifi/generate">
7+
</a>
8+
<a href="#usage">
9+
<img alt="docs" src="https://img.shields.io/badge/-docs%20%26%20demos-1e8a7a">
10+
</a>
11+
<a href="https://github.com/sponsors/LittleSound">
12+
<img alt="docs" src="https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86">
13+
</a>
14+
</p>
15+
16+
Stream Generated QR Codes for data transmission
17+
18+
## Sponsors
19+
20+
<p align="center">
21+
<a href="https://github.com/sponsors/LittleSound">
22+
<img src="https://cdn.jsdelivr.net/gh/littlesound/sponsors/sponsors.svg"/>
23+
</a>
24+
</p>
25+
26+
<p align="center">
27+
This project is made possible by all the sponsors supporting my work <br>
28+
You can join them at my sponsors profile:
29+
</p>
30+
<p align="center"><a href="https://github.com/sponsors/LittleSound"><img src="https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86&style=for-the-badge" /></a></p>
31+
32+
## Usage
33+
34+
```javascript
35+
import {
36+
createGeneraterANSI,
37+
createGeneraterUnicode,
38+
createGeneraterUnicodeCompact,
39+
createGeneraterSVG,
40+
createGeneraterQRCodeArray,
41+
} from '@qifi/generate'
42+
43+
const generaterSvg = createGeneraterSVG(new Uint8Array(file.buffer))
44+
45+
const generaterANSI = createGeneraterANSI(new Uint8Array(file.buffer), {
46+
// Size of each data slice
47+
sliceSize: 250,
48+
// Error correction level
49+
ecc: 'L',
50+
// Border width
51+
border: 2,
52+
})
53+
54+
// display QR Code in terminal
55+
for (const blockQRCode of generaterANSI()) {
56+
console.log(blockQRCode)
57+
}
58+
59+
```

packages/cli/build.config.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { defineBuildConfig } from 'unbuild'
2+
3+
export default defineBuildConfig({
4+
entries: [
5+
'src/index.ts',
6+
],
7+
declaration: true,
8+
rollup: {
9+
emitCJS: false,
10+
dts: {
11+
compilerOptions: {
12+
paths: {},
13+
},
14+
},
15+
},
16+
externals: [
17+
'pako',
18+
],
19+
})

packages/cli/package.json

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "@qifi/cli",
3+
"type": "module",
4+
"version": "0.0.3",
5+
"description": "Stream Generated QR Codes for file transmission in your terminal",
6+
"author": "Rizumu Ayaka <[email protected]>",
7+
"license": "MIT",
8+
"homepage": "https://github.com/qifi-dev/qrs#readme",
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/qifi-dev/qrs.git",
12+
"directory": "packages/cli"
13+
},
14+
"bug": "https://github.com/qifi-dev/qrs/issues",
15+
"sideEffects": false,
16+
"exports": {
17+
".": {
18+
"types": "./dist/index.d.mts",
19+
"default": "./dist/index.mjs"
20+
}
21+
},
22+
"main": "./dist/index.mjs",
23+
"module": "./dist/index.mjs",
24+
"types": "./dist/index.d.mts",
25+
"files": [
26+
"dist"
27+
],
28+
"scripts": {
29+
"dev": "tsx ./src",
30+
"build": "unbuild",
31+
"stub": "unbuild --stub"
32+
},
33+
"dependencies": {
34+
"@qifi/generate": "workspace:*",
35+
"mime": "^4.0.4",
36+
"tsx": "^4.19.1"
37+
}
38+
}

packages/cli/src/index.ts

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env tsx
2+
3+
import fs from 'node:fs'
4+
import path from 'node:path'
5+
import process from 'node:process'
6+
import { appendFileHeaderMetaToBuffer, createGeneraterANSI } from '@qifi/generate'
7+
import mime from 'mime'
8+
9+
// Function to read file and generate QR codes
10+
async function generateQRCodes(filePath: string, sliceSize: number = 80, fps: number = 20) {
11+
const fullPath = path.resolve(filePath)
12+
13+
console.log('fullPath:', fullPath)
14+
await new Promise(resolve => setTimeout(resolve, 1000))
15+
if (!fs.existsSync(fullPath)) {
16+
console.error(`File not found: ${fullPath}`)
17+
process.exit(1)
18+
}
19+
20+
const fileBuffer = fs.readFileSync(fullPath)
21+
const data = new Uint8Array(fileBuffer)
22+
const meta = {
23+
filename: path.basename(fullPath),
24+
contentType: mime.getType(fullPath) || 'application/octet-stream',
25+
}
26+
27+
const merged = appendFileHeaderMetaToBuffer(data, meta)
28+
29+
const generator = createGeneraterANSI(merged, {
30+
urlPrefix: 'https://qrss.netlify.app/#',
31+
sliceSize,
32+
border: 2,
33+
})
34+
35+
// Clear console function
36+
const clearConsole = () => process.stdout.write('\x1Bc')
37+
38+
// Display QR codes
39+
for (const blockQRCode of generator.fountain()) {
40+
clearConsole()
41+
console.log(blockQRCode)
42+
console.log(`${meta.filename} (${meta.contentType})`, '|', 'size:', data.length, 'bytes')
43+
await new Promise(resolve => setTimeout(resolve, 1000 / fps)) // Display each QR code for 1 second
44+
}
45+
}
46+
47+
// Parse command line arguments
48+
const args = process.argv.slice(2)
49+
if (args.length < 1) {
50+
console.error('Usage: qr-file-transfer <file-path> [slice-size]')
51+
process.exit(1)
52+
}
53+
54+
const [filePath, sliceSizeStr, fpsStr] = args
55+
const sliceSize = sliceSizeStr ? Number.parseInt(sliceSizeStr, 10) : undefined
56+
const fps = fpsStr ? Number.parseInt(fpsStr, 10) : undefined
57+
58+
if (!filePath) {
59+
console.error('File path is required')
60+
process.exit(1)
61+
}
62+
63+
generateQRCodes(filePath, sliceSize, fps)

pnpm-lock.yaml

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)