Implement

This commit is contained in:
yuto-yuto
2021-07-09 03:49:18 +02:00
parent ed05952bd1
commit 9211a8308a
26 changed files with 3596 additions and 301 deletions

28
lib/PasswordGenerator.ts Normal file
View File

@@ -0,0 +1,28 @@
import * as crypto from "crypto";
import { promisify } from "util";
const AsciiRange = {
/** space */
min: 32,
/** childe mark ~ */
max: 126,
}
export async function generatePassword(size: number): Promise<string> {
let result = "";
while (true) {
const bytes = await promisify(crypto.randomBytes)(size * 2);
const byteArray = Array.from(bytes);
const filtered = byteArray.filter(isInAsciiRange);
result += String.fromCharCode(...filtered);
if (result.length >= size) {
result = result.slice(0, size);
break;
}
}
return result;
}
function isInAsciiRange(value: number) {
return AsciiRange.min <= value && value <= AsciiRange.max;
}

View File

@@ -0,0 +1,26 @@
<script type="text/html" data-template-name="password-generator">
<div class="form-row">
<label for="node-input-key"><i class="fa fa-key"></i> Key prop</label>
<input type="text" id="node-input-key" placeholder="payload.key">
</div>
<div class="form-row">
<label for="node-input-size"><i class="fa fa-database"></i> Size</label>
<input type="text" id="node-input-size">
</div>
<div class="form-row">
<label for="node-input-to"><i class="fa fa-database"></i> to</label>
<input type="text" id="node-input-to">
</div>
</script>
<script type="text/html" data-help-name="password-generator">
<p>Send incoming message only when the value of the specified key path changes.</p>
<h3>Configuration</h3>
<dl class="message-properties">
<dt>size</dt>
<dd> The output size of the string. </dd>
<dt>to</dt>
<dd> The property to set password. </dd>
</dl>
</script>

View File

@@ -0,0 +1,26 @@
import * as nodered from "node-red";
import { generatePassword } from "./PasswordGenerator";
import { PasswordGeneratorNodeDef } from "./PasswordGeneratorNodeDef";
import * as yutolity from "yutolity";
// it can't set to the input event listener now
// using any is workaround but not good
interface PayloadType extends nodered.NodeMessageInFlow {
to: string;
}
export = (RED: nodered.NodeAPI): void => {
RED.nodes.registerType("password-generator",
function (this: nodered.Node, config: PasswordGeneratorNodeDef): void {
RED.nodes.createNode(this, config);
this.on("input", async (msg: any, send, done) => {
const password = await generatePassword(config.size);
const valueSetPath = msg.to || config.setTo || "payload";
yutolity.setValue(msg, valueSetPath, password);
send(msg);
done();
});
});
}

View File

@@ -0,0 +1,13 @@
import * as nodered from "node-red";
export interface PasswordGeneratorNodeDef
extends nodered.NodeDef {
size: number;
setTo?: string;
}
export interface PasswordGeneratorNodeProperties
extends nodered.EditorNodeProperties {
size: number;
setTo?: string;
}

View File

@@ -0,0 +1,20 @@
import * as nodered from "node-red";
import { PasswordGeneratorNodeProperties } from "./PasswordGeneratorNodeDef";
declare const RED: nodered.EditorRED;
const nodeName = "password-generator";
RED.nodes.registerType<PasswordGeneratorNodeProperties>(nodeName, {
category: "function",
color: "#a6bbcf",
defaults: {
name: { value: "" },
size: { value: "", validate: RED.validators.number() },
setTo: { value: "" },
},
inputs: 1,
outputs: 1,
icon: "fas fa-not-equal",
label: function () {
return this.name || nodeName;
},
});

View File

@@ -1,29 +0,0 @@
import isEqual from "fast-deep-equal";
interface KeyValue {
key: unknown;
value: unknown;
}
export class ValueChangeDetector {
private currentValues = new Map<string, unknown>();
public isUpdated(args: KeyValue): boolean {
const current = this.currentValues.get(this.toString(args.key));
if (current === undefined) {
return true;
}
return !isEqual(current, args.value);
}
public update(args: KeyValue): void {
this.currentValues.set(this.toString(args.key), args.value);
}
private toString(object: unknown): string {
if (typeof object === "string") {
return object;
}
return String(object);
}
}

View File

@@ -1,36 +0,0 @@
<script type="text/javascript">
RED.nodes.registerType('value-change-detector', {
category: 'function',
color: '#a6bbcf',
defaults: {
name: { value: "" },
key: { value: "", required: true },
value: { value: "", required: true },
},
inputs: 1,
outputs: 1,
icon: "file.png",
label: function () {
return this.name || "value-change-detector";
}
});
</script>
<script type="text/html" data-template-name="value-change-detector">
<div class="form-row">
<label for="node-input-key"><i class="fa fa-tag"></i> Key prop</label>
<input type="text" id="node-input-key" placeholder="payload.key">
</div>
<div class="form-row">
<label for="node-input-value"><i class="fa fa-tag"></i> Value prop</label>
<input type="text" id="node-input-value" placeholder="payload.value">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="value-change-detector">
<p>Send incoming message only when the value changes.</p>
</script>

View File

@@ -1,20 +0,0 @@
import * as nodered from "node-red";
import * as yutolity from "yutolity";
import { ValueChangeDetector } from "./ValueChangeDetector";
import { ValueChangeDetectorNodeProperties } from "./ValueChangeDetectorNodeProperties";
export = (RED: nodered.NodeAPI) => {
RED.nodes.registerType("value-change-detector",
function (this: nodered.Node, config: ValueChangeDetectorNodeProperties): void {
RED.nodes.createNode(this, config);
const detector = new ValueChangeDetector();
this.on('input', (msg: any) => {
const targetValue = yutolity.getValueOf(msg.payload, config.key);
this.send(msg);
});
});
}

View File

@@ -1,6 +0,0 @@
import * as nodered from "node-red";
export interface ValueChangeDetectorNodeProperties extends nodered.NodeDef {
key: string;
value: string;
}