Убрал лишние проверки. Убрал дефолтные значения env переменных. Скорректировал dockerfile

This commit is contained in:
Первов Артем
2026-06-19 10:30:13 +03:00
parent cbe33500cf
commit 9b53f602ce
10 changed files with 52 additions and 105 deletions

View File

@@ -1,2 +1,4 @@
node_modules
dist
.env
.env.*

View File

@@ -1,13 +1,15 @@
FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json ./
RUN npm ci
COPY tsconfig.json ./
COPY public ./public
# Runtime mappers read JSON files from src/mappings, so they must be copied into the image.
COPY src ./src
CMD ["npm", "run", "start"]
RUN npm run build && npm prune --omit=dev
CMD ["node", "dist/index.js"]

38
app/package-lock.json generated
View File

@@ -6,11 +6,13 @@
"": {
"name": "mqtt-worker",
"dependencies": {
"@types/node": "^25.9.1",
"mqtt": "^5.15.1",
"tsx": "^4.22.4",
"typescript": "^6.0.3",
"ws": "^8.21.0"
},
"devDependencies": {
"@types/node": "^25.9.1",
"tsx": "^4.22.4",
"typescript": "^6.0.3"
}
},
"node_modules/@babel/runtime": {
@@ -29,6 +31,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -45,6 +48,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -61,6 +65,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -77,6 +82,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -93,6 +99,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -109,6 +116,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -125,6 +133,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -141,6 +150,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -157,6 +167,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -173,6 +184,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -189,6 +201,7 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -205,6 +218,7 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -221,6 +235,7 @@
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -237,6 +252,7 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -253,6 +269,7 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -269,6 +286,7 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -285,6 +303,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -301,6 +320,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -317,6 +337,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -333,6 +354,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -349,6 +371,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -365,6 +388,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -381,6 +405,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -397,6 +422,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -413,6 +439,7 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -429,6 +456,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -607,6 +635,7 @@
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -679,6 +708,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -923,6 +953,7 @@
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz",
"integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.28.0"
@@ -947,6 +978,7 @@
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -5,13 +5,15 @@
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "tsx src/index.ts"
"start": "node dist/index.js"
},
"dependencies": {
"@types/node": "^25.9.1",
"mqtt": "^5.15.1",
"tsx": "^4.22.4",
"typescript": "^6.0.3",
"ws": "^8.21.0"
},
"devDependencies": {
"@types/node": "^25.9.1",
"tsx": "^4.22.4",
"typescript": "^6.0.3"
}
}

View File

@@ -7,20 +7,9 @@ export const TOPIC = 'data/edge5/modbus/v2'
const mapper = createMetricMapper({
filePath: process.env.EDGE5_MODBUS_V2_MAPPING_FILE as string,
})
const REGISTER_COUNT = mapper.tagCount
function parseValues(payload: Buffer): number[] {
const value = JSON.parse(payload.toString('utf8')) as unknown
if (
Array.isArray(value) &&
value.length === REGISTER_COUNT &&
value.every((item) => typeof item === 'number' && Number.isFinite(item))
) {
return value
}
throw new Error(`Expected JSON number[${REGISTER_COUNT}]`)
return JSON.parse(payload.toString('utf8')) as number[]
}
async function postMetrics(metrics: MappedMetric[]): Promise<void> {

View File

@@ -4,7 +4,6 @@ import type { TopicHandler } from '../types.js'
export const TOPIC = 'data/edge5/modbus/v1'
const EDGE = 'edge5'
const REGISTER_COUNT = 125
type Edge5ModbusMetric = {
edge: string
@@ -14,23 +13,7 @@ type Edge5ModbusMetric = {
}
function parseValues(payload: Buffer): number[] {
let value: unknown
try {
value = JSON.parse(payload.toString('utf8')) as unknown
} catch {
throw new Error(`Expected JSON number[${REGISTER_COUNT}]`)
}
if (
Array.isArray(value) &&
value.length === REGISTER_COUNT &&
value.every((item) => typeof item === 'number' && Number.isFinite(item))
) {
return value
}
throw new Error(`Expected JSON number[${REGISTER_COUNT}]`)
return JSON.parse(payload.toString('utf8')) as number[]
}
function toMetrics(values: number[], timestamp: number): Edge5ModbusMetric[] {
@@ -47,12 +30,7 @@ async function postMetrics(metrics: Edge5ModbusMetric[]): Promise<void> {
if (!response.ok) {
const text = await response.text()
console.error('edge5.modbus.post_error', {
status: response.status,
statusText: response.statusText,
body: text.slice(0, 500),
})
return
throw new Error(text)
}
console.log('edge5.modbus.posted', { count: metrics.length })
@@ -61,15 +39,7 @@ async function postMetrics(metrics: Edge5ModbusMetric[]): Promise<void> {
export const handleEdge5Modbus: TopicHandler = async (topic, payload) => {
console.log('edge5.modbus.received', { topic, bytes: payload.length })
let values: number[]
try {
values = parseValues(payload)
} catch (err) {
console.warn('edge5.modbus.invalid_payload', { topic, err })
return
}
const values = parseValues(payload)
const metrics = toMetrics(values, Date.now())
await postMetrics(metrics)
}

View File

@@ -7,14 +7,6 @@ export function parseJson<T = unknown>(payload: Buffer): T {
return JSON.parse(text) as T
}
export function parseJsonArray(payload: Buffer): unknown[] {
const value = parseJson(payload)
if (!Array.isArray(value)) {
throw new Error('Expected JSON array')
}
return value
}
export function decodeBase64(payload: Buffer): Buffer {
return Buffer.from(payload.toString('utf8'), 'base64')
}

View File

@@ -1,39 +0,0 @@
const EXPECTED_CHUNK_LENGTH = 125
export function isNonEmptyString(value: unknown): value is string {
return typeof value === 'string' && value.length > 0
}
export function isFiniteNumber(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value)
}
export function isArrayOfLength(
value: unknown,
length: number,
): value is unknown[] {
return Array.isArray(value) && value.length === length
}
export function isArrayOfLength125(value: unknown): value is unknown[] {
return isArrayOfLength(value, EXPECTED_CHUNK_LENGTH)
}
export function isArrayOfChunks125(
value: unknown,
): value is unknown[][] {
if (!Array.isArray(value)) {
return false
}
return value.every((chunk) => isArrayOfLength125(chunk))
}
export function assertValid<T>(
value: unknown,
guard: (v: unknown) => v is T,
label: string,
): asserts value is T {
if (!guard(value)) {
throw new Error(`Invalid payload: ${label}`)
}
}

View File

@@ -14,7 +14,6 @@ type MappingConfig = {
export type MetricMapper = {
edge: string
tagCount: number
mapValues: (values: number[], timestamp: number) => MappedMetric[]
}
@@ -34,7 +33,6 @@ export function createMetricMapper(options: MetricMapperOptions): MetricMapper {
return {
edge: config.edge,
tagCount: config.tags.length,
mapValues: (values, timestamp) =>
values.map((value, index) => ({
edge: config.edge,

View File

@@ -7,8 +7,7 @@
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src",
"noEmit": true
"rootDir": "src"
},
"include": ["src/**/*.ts"]
}