@internetderdinge/api 1.224.2 → 1.229.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetderdinge/api",
3
- "version": "1.224.2",
3
+ "version": "1.229.0",
4
4
  "description": "Shared OpenIoT API modules",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsc -p tsconfig.json",
12
+ "deploy:version": "node ./scripts/release-version.mjs",
12
13
  "lint": "eslint .",
13
14
  "lint:fix": "eslint . --fix"
14
15
  },
@@ -23,9 +24,6 @@
23
24
  "@aws-sdk/util-endpoints": "^3.216.0",
24
25
  "@sentry/node": "^10.25.0",
25
26
  "@sentry/profiling-node": "^10.25.0",
26
- "@wirewire/fhir": "^1.212.0",
27
- "@wirewire/fhir-helpers": "^1.212.0",
28
- "@wirewire/helpers": "^1.223.0",
29
27
  "agenda": "^5.0.0",
30
28
  "agendash": "^4.0.0",
31
29
  "auth0": "^4.23.1",
@@ -81,6 +79,7 @@
81
79
  "request": "^2.81.0",
82
80
  "rrule": "^2.7.1",
83
81
  "sharp": "^0.33.5",
82
+ "semver": "^7.7.1",
84
83
  "stripe": "^12.6.0",
85
84
  "swagger-ui-express": "^5.0.1",
86
85
  "ts-node": "^10.9.2",
@@ -0,0 +1,145 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { execSync } from "node:child_process";
5
+ import semver from "semver";
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ const repoRoot = path.resolve(__dirname, "..");
9
+
10
+ const args = process.argv.slice(2);
11
+ const shouldPublish = args.includes("--publish");
12
+ const versionInput = args.find((value) => !value.startsWith("-")) ?? "patch";
13
+
14
+ const readJson = (filePath) => {
15
+ const raw = fs.readFileSync(filePath, "utf8");
16
+ return JSON.parse(raw);
17
+ };
18
+
19
+ const writeJson = (filePath, data) => {
20
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`);
21
+ };
22
+
23
+ const resolveNextVersion = (current, input) => {
24
+ const cleanedCurrent = semver.valid(semver.clean(current));
25
+ if (!cleanedCurrent) {
26
+ throw new Error(`Unsupported version format: ${current}`);
27
+ }
28
+
29
+ const exact = semver.valid(input);
30
+ if (exact) {
31
+ return exact;
32
+ }
33
+
34
+ if (input === "major" || input === "minor" || input === "patch") {
35
+ const bumped = semver.inc(cleanedCurrent, input);
36
+ if (!bumped) {
37
+ throw new Error(`Failed to bump version: ${current}`);
38
+ }
39
+ return bumped;
40
+ }
41
+
42
+ throw new Error(
43
+ `Unknown version input: ${input}. Use major/minor/patch or a semver like 1.2.3.`,
44
+ );
45
+ };
46
+
47
+ const resolveMemoMonoRoot = () => {
48
+ if (process.env.MEMO_MONO_PATH) {
49
+ return path.resolve(process.env.MEMO_MONO_PATH);
50
+ }
51
+
52
+ return path.resolve(repoRoot, "../../memo/memo-mono");
53
+ };
54
+
55
+ const updateDependencyVersion = (
56
+ packageJsonPath,
57
+ dependencyName,
58
+ newVersion,
59
+ expectedVersion,
60
+ ) => {
61
+ const packageJson = readJson(packageJsonPath);
62
+ const dependencies = packageJson.dependencies ?? {};
63
+
64
+ if (!dependencies[dependencyName]) {
65
+ throw new Error(
66
+ `Missing dependency ${dependencyName} in ${packageJsonPath}`,
67
+ );
68
+ }
69
+
70
+ const currentRange = dependencies[dependencyName];
71
+ const currentDependencyMin = semver.minVersion(currentRange);
72
+ if (!currentDependencyMin) {
73
+ throw new Error(
74
+ `Unsupported dependency version for ${dependencyName} in ${packageJsonPath}: ${currentRange}`,
75
+ );
76
+ }
77
+ const currentDependencyVersion = currentDependencyMin.version;
78
+
79
+ if (expectedVersion && currentDependencyVersion !== expectedVersion) {
80
+ throw new Error(
81
+ `${path.basename(path.dirname(packageJsonPath))} dependency is ${currentRange} (expected ${expectedVersion}). Update it before bumping.`,
82
+ );
83
+ }
84
+
85
+ const prefix = currentRange.startsWith("^")
86
+ ? "^"
87
+ : currentRange.startsWith("~")
88
+ ? "~"
89
+ : "";
90
+
91
+ dependencies[dependencyName] = `${prefix}${newVersion}`;
92
+ packageJson.dependencies = dependencies;
93
+ writeJson(packageJsonPath, packageJson);
94
+
95
+ return { previous: currentRange, next: dependencies[dependencyName] };
96
+ };
97
+
98
+ const apiPackagePath = path.join(repoRoot, "package.json");
99
+ const apiPackage = readJson(apiPackagePath);
100
+ const currentVersion = apiPackage.version;
101
+ const cleanedCurrent = semver.valid(semver.clean(currentVersion));
102
+ if (!cleanedCurrent) {
103
+ throw new Error(`Unsupported version format: ${currentVersion}`);
104
+ }
105
+
106
+ const nextVersion = resolveNextVersion(currentVersion, versionInput);
107
+
108
+ const memoMonoRoot = resolveMemoMonoRoot();
109
+ const memoApiPath = path.join(memoMonoRoot, "packages/memo-api/package.json");
110
+ const paperlessApiPath = path.join(
111
+ memoMonoRoot,
112
+ "packages/paperlesspaper-api/package.json",
113
+ );
114
+
115
+ if (!fs.existsSync(memoApiPath) || !fs.existsSync(paperlessApiPath)) {
116
+ throw new Error(
117
+ `Could not find memo-mono package.json files. Set MEMO_MONO_PATH to the repo root.`,
118
+ );
119
+ }
120
+
121
+ const memoUpdate = updateDependencyVersion(
122
+ memoApiPath,
123
+ "@internetderdinge/api",
124
+ nextVersion,
125
+ cleanedCurrent,
126
+ );
127
+ const paperlessUpdate = updateDependencyVersion(
128
+ paperlessApiPath,
129
+ "@internetderdinge/api",
130
+ nextVersion,
131
+ cleanedCurrent,
132
+ );
133
+
134
+ apiPackage.version = nextVersion;
135
+ writeJson(apiPackagePath, apiPackage);
136
+
137
+ console.log(`Updated @internetderdinge/api to ${nextVersion}`);
138
+ console.log(`memo-api: ${memoUpdate.previous} -> ${memoUpdate.next}`);
139
+ console.log(
140
+ `paperlesspaper-api: ${paperlessUpdate.previous} -> ${paperlessUpdate.next}`,
141
+ );
142
+
143
+ if (shouldPublish) {
144
+ execSync("npm publish", { cwd: repoRoot, stdio: "inherit" });
145
+ }
@@ -5,7 +5,7 @@ import iotDevicesService from "../iotdevice/iotdevice.service.js";
5
5
 
6
6
  import { promisify } from "util";
7
7
  import { getSignedFileUrl } from "../files/upload.service";
8
- import { deviceByDeviceName, deviceKindHasFeature } from "@wirewire/helpers";
8
+ import { deviceByDeviceName, deviceKindHasFeature } from "../utils/deviceUtils";
9
9
 
10
10
  import type { DeviceDocument, DeviceInput } from "./devices.model.js";
11
11
  import type { ApiErrorType } from "../utils/ApiError.js";
package/src/i18n/i18n.ts CHANGED
@@ -5,7 +5,7 @@ import { existsSync, readdirSync } from "fs";
5
5
  import i18next from "i18next";
6
6
  import Backend, { setLocalesFolder } from "./saveMissingLocalJsonBackend";
7
7
 
8
- import config from "@wirewire/openiot-api/src/config/config";
8
+ import config from "../config/config";
9
9
 
10
10
  // Fix for __dirname in ES modules
11
11
  const __filename = fileURLToPath(import.meta.url);
@@ -1,7 +1,7 @@
1
1
  import httpStatus from "http-status";
2
2
  import axios from "axios";
3
3
  import AWS from "aws-sdk";
4
- import { deviceKindHasFeature } from "@wirewire/helpers";
4
+ import { deviceKindHasFeature } from "../utils/deviceUtils";
5
5
  import ApiError from "../utils/ApiError";
6
6
  import { getAuth0Token } from "../accounts/auth0.service";
7
7
  import {
@@ -0,0 +1,109 @@
1
+ import { readFileSync } from "fs";
2
+ import path from "path";
3
+
4
+ export type DeviceListEntry = {
5
+ id: string;
6
+ features: string[];
7
+ deviceNameDetection?: string;
8
+ [key: string]: any;
9
+ };
10
+
11
+ export interface InitDeviceListOptions {
12
+ list?: DeviceListEntry[];
13
+ listPath?: string;
14
+ }
15
+
16
+ let deviceList: DeviceListEntry[] | null = null;
17
+
18
+ const parseDeviceList = (value: unknown): DeviceListEntry[] => {
19
+ if (!Array.isArray(value)) {
20
+ throw new Error("Device list must be an array.");
21
+ }
22
+ return value as DeviceListEntry[];
23
+ };
24
+
25
+ const loadDeviceListFromFile = (listPath: string): DeviceListEntry[] => {
26
+ const absolutePath = path.resolve(listPath);
27
+ const raw = readFileSync(absolutePath, "utf8");
28
+ const parsed = JSON.parse(raw) as unknown;
29
+ return parseDeviceList(parsed);
30
+ };
31
+
32
+ export const initDeviceList = (
33
+ options: InitDeviceListOptions = {},
34
+ ): DeviceListEntry[] => {
35
+ if (options.list) {
36
+ deviceList = options.list;
37
+ return deviceList;
38
+ }
39
+ if (options.listPath) {
40
+ deviceList = loadDeviceListFromFile(options.listPath);
41
+ return deviceList;
42
+ }
43
+ throw new Error("initDeviceList requires list or listPath.");
44
+ };
45
+
46
+ const ensureDeviceList = (): DeviceListEntry[] => {
47
+ if (!deviceList) {
48
+ throw new Error(
49
+ "deviceList is not initialized. Call initDeviceList(...) before using device utilities.",
50
+ );
51
+ }
52
+ return deviceList;
53
+ };
54
+
55
+ export { deviceList as default };
56
+
57
+ export function deviceByKind(device): any {
58
+ const list = ensureDeviceList();
59
+ const result = list.find((e) => e.id === device);
60
+ return result;
61
+ }
62
+
63
+ export function deviceByDeviceName(deviceName): any {
64
+ if (!deviceName) return false;
65
+ const list = ensureDeviceList();
66
+ const result = list.find((e) => {
67
+ if (!e.deviceNameDetection) return false;
68
+
69
+ return deviceName.startsWith(e.deviceNameDetection);
70
+ });
71
+ if (!result) return false;
72
+ return result;
73
+ }
74
+
75
+ /**
76
+ * Returns true if the device kind has the given feature
77
+ */
78
+ export function deviceKindHasFeature(
79
+ feature:
80
+ | "analog"
81
+ | "wifi"
82
+ | "epaper"
83
+ | "nbiot"
84
+ | "nouser"
85
+ | "battery-offline"
86
+ | "code7"
87
+ | "sensor"
88
+ | "payment"
89
+ | "anabox-smart"
90
+ | "intakes1"
91
+ | "intakes3"
92
+ | "intakes4"
93
+ | "intakes5"
94
+ | "intakes7"
95
+ | "stationaer"
96
+ | "tray-colors"
97
+ | "nuechtern-bedarf"
98
+ | "week-colors"
99
+ | "day-colors"
100
+ | "alt-device"
101
+ | "battery-level",
102
+ kind?: DeviceListEntry["id"],
103
+ ): boolean {
104
+ if (!kind) return false;
105
+ const list = ensureDeviceList();
106
+ const result = list.find((e) => e.id === kind);
107
+ if (!result) return false;
108
+ return result.features.includes(feature);
109
+ }