Cavnas: Implement basic service discovery logic

Change-Id: I71b25076dba94d6491ad4db748b259870991c526
diff --git a/apps/canvas/back/src/lib/env.ts b/apps/canvas/back/src/lib/env.ts
new file mode 100644
index 0000000..9b58ae1
--- /dev/null
+++ b/apps/canvas/back/src/lib/env.ts
@@ -0,0 +1,28 @@
+const regex = /(?<!\\)\${([^{}]+)}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
+
+export function expandValue(value: string): string[] {
+	const vars = new Set<string>();
+	const matches = [...value.matchAll(regex)];
+	while (matches.length > 0) {
+		const match = matches.shift();
+		if (match == null) {
+			break;
+		}
+		const [_, bracedExpression, unbracedExpression] = match;
+		const expression = bracedExpression || unbracedExpression;
+		const opRegex = /(:\+|\+|:-|-)/;
+		const opMatch = expression.match(opRegex);
+		const splitter = opMatch ? opMatch[0] : null;
+		let r: string[];
+		if (splitter != null) {
+			r = expression.split(splitter);
+		} else {
+			r = [expression];
+		}
+		const key = r.shift();
+		if (key != null) {
+			vars.add(key);
+		}
+	}
+	return [...vars];
+}