@swizzyweb/swerve-manager 0.1.4 → 0.1.7
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/README.md +11 -1
- package/dist/swerve.d.ts +6 -1
- package/dist/swerve.js +44 -13
- package/dist/utils/getFullImportPath.d.ts +2 -0
- package/dist/utils/getFullImportPath.js +82 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/installWebservice.d.ts +0 -1
- package/dist/utils/installWebservice.js +1 -1
- package/package.json +9 -11
- package/src/swerve.ts +51 -15
- package/src/utils/getFullImportPath.ts +91 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/installWebservice.ts +1 -3
- package/test/getArgs.spec.ts +253 -255
- package/test/getFullImportPath.spec.ts +16 -0
- package/jest.config.js +0 -4
package/README.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
swizzy-swerve is a bootstrapper for swizzy web services. This package will bootstrap and run
|
|
4
4
|
independent swizzy web services.
|
|
5
5
|
|
|
6
|
+
## Docs
|
|
7
|
+
|
|
8
|
+
https://swizzyweb.github.io/swerve-manager/
|
|
9
|
+
|
|
6
10
|
### Supported commands
|
|
7
11
|
|
|
8
12
|
swerve: synonym for swerven
|
|
@@ -201,7 +205,7 @@ appDataPath: "/appDataRoot/appdata/serviceName/"
|
|
|
201
205
|
},
|
|
202
206
|
"friendlyImportServiceName": {
|
|
203
207
|
"port": 3002,
|
|
204
|
-
"
|
|
208
|
+
"packageName": "@swizzyweb/dyn-serve-web-service" // running installed web service package
|
|
205
209
|
},
|
|
206
210
|
"friendlyNeighborServiceName": {
|
|
207
211
|
"port": 3002,
|
|
@@ -217,3 +221,9 @@ appDataPath: "/appDataRoot/appdata/serviceName/"
|
|
|
217
221
|
```
|
|
218
222
|
swerve --config my-web-service-config.json
|
|
219
223
|
```
|
|
224
|
+
|
|
225
|
+
# Generate Docs
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
npx typedoc
|
|
229
|
+
```
|
package/dist/swerve.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export type Apps = {
|
|
|
50
50
|
export interface SwerveManagerProps {
|
|
51
51
|
apps?: Apps;
|
|
52
52
|
webServices?: WebService<any>[];
|
|
53
|
+
nodeModulesPath?: string;
|
|
54
|
+
logger?: ILogger<any> | undefined;
|
|
53
55
|
}
|
|
54
56
|
export interface WebServiceConfiguration {
|
|
55
57
|
}
|
|
@@ -60,13 +62,15 @@ export declare class SwerveManager implements ISwerveManager {
|
|
|
60
62
|
apps: Apps;
|
|
61
63
|
webServices: WebService<any>[];
|
|
62
64
|
configurations: WebServiceConfigurations;
|
|
65
|
+
nodeModulesPath: string;
|
|
66
|
+
logger: ILogger<any>;
|
|
63
67
|
constructor(props: SwerveManagerProps);
|
|
64
68
|
run(request: RunRequest): Promise<RunResponse>;
|
|
65
69
|
runWithArgs(request: RunRequest): Promise<WebService<any>[]>;
|
|
66
70
|
private runWithApp;
|
|
67
71
|
installWebService(props: {
|
|
68
72
|
serviceKey: string;
|
|
69
|
-
|
|
73
|
+
servicePath: string;
|
|
70
74
|
app: Application;
|
|
71
75
|
appDataRoot: string;
|
|
72
76
|
packageName: string;
|
|
@@ -76,6 +80,7 @@ export declare class SwerveManager implements ISwerveManager {
|
|
|
76
80
|
[key: string]: any;
|
|
77
81
|
};
|
|
78
82
|
}): Promise<any>;
|
|
83
|
+
getImportName(packageName: string, servicePath: string): Promise<string>;
|
|
79
84
|
stop(request: StopRequest): Promise<void>;
|
|
80
85
|
getRunningWebServices(props: GetRunningWebServiceRequest): Promise<GetRunningWebServiceResponse>;
|
|
81
86
|
}
|
package/dist/swerve.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import express from "@swizzyweb/express";
|
|
3
|
-
import {
|
|
3
|
+
import { getLoggerForService, } from "./utils/index.js";
|
|
4
4
|
import { SwizzyWinstonLogger, } from "@swizzyweb/swizzy-web-service";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import { mkdirSync } from "node:fs";
|
|
9
|
+
import { getFullImportPath, resolvePackageEntry, } from "./utils/getFullImportPath.js";
|
|
9
10
|
export var InstanceType;
|
|
10
11
|
(function (InstanceType) {
|
|
11
12
|
InstanceType["webservice"] = "webservice";
|
|
@@ -15,9 +16,19 @@ export class SwerveManager {
|
|
|
15
16
|
apps;
|
|
16
17
|
webServices;
|
|
17
18
|
configurations;
|
|
19
|
+
nodeModulesPath;
|
|
20
|
+
logger;
|
|
18
21
|
constructor(props) {
|
|
19
22
|
this.apps = props.apps ?? {};
|
|
20
23
|
this.webServices = props.webServices ?? [];
|
|
24
|
+
this.nodeModulesPath = props.nodeModulesPath;
|
|
25
|
+
this.logger =
|
|
26
|
+
props.logger ??
|
|
27
|
+
new SwizzyWinstonLogger({
|
|
28
|
+
appName: "swerve-manager",
|
|
29
|
+
port: -1,
|
|
30
|
+
hostName: os.hostname(),
|
|
31
|
+
});
|
|
21
32
|
}
|
|
22
33
|
async run(request) {
|
|
23
34
|
const { args } = request;
|
|
@@ -50,18 +61,18 @@ export class SwerveManager {
|
|
|
50
61
|
}
|
|
51
62
|
const app = this.apps[`${port}`].app;
|
|
52
63
|
const service = serviceEntry[1];
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
gLogger.debug(`
|
|
64
|
+
const serviceName = serviceEntry[0];
|
|
65
|
+
const packageName = service.packageName;
|
|
66
|
+
gLogger.debug(`servicePath: ${service.servicePath}`);
|
|
56
67
|
const serviceArgs = {
|
|
57
68
|
...service,
|
|
58
69
|
...service.serviceConfiguration,
|
|
59
70
|
...args.serviceArgs,
|
|
60
71
|
};
|
|
61
72
|
const webservice = await this.installWebService({
|
|
62
|
-
serviceKey:
|
|
73
|
+
serviceKey: serviceName,
|
|
63
74
|
packageName,
|
|
64
|
-
|
|
75
|
+
servicePath: service.servicePath,
|
|
65
76
|
port,
|
|
66
77
|
app,
|
|
67
78
|
appDataRoot: args.appDataRoot,
|
|
@@ -118,11 +129,10 @@ export class SwerveManager {
|
|
|
118
129
|
for (const serviceEntry of Object.entries(args.services)) {
|
|
119
130
|
const service = serviceEntry[1];
|
|
120
131
|
const packageName = service.packageName;
|
|
121
|
-
const importPathOrName = service.servicePath ?? service.serviceArgs.servicePath ?? packageName;
|
|
122
132
|
const webservice = await this.installWebService({
|
|
123
133
|
serviceKey: serviceEntry[0],
|
|
124
134
|
packageName,
|
|
125
|
-
|
|
135
|
+
servicePath: service.servicePath,
|
|
126
136
|
port: PORT,
|
|
127
137
|
app,
|
|
128
138
|
appDataRoot: args.appDataRoot,
|
|
@@ -142,13 +152,17 @@ export class SwerveManager {
|
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
154
|
async installWebService(props) {
|
|
145
|
-
|
|
146
|
-
const { app, appDataRoot, packageName, port, gLogger, serviceArgs, importPathOrName, serviceKey, } = props;
|
|
155
|
+
const { app, appDataRoot, packageName, port, gLogger, serviceArgs, servicePath, serviceKey, } = props;
|
|
147
156
|
try {
|
|
148
157
|
gLogger.info(`Getting webservice package ${packageName} and will run on port ${port}`);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
if (packageName) {
|
|
159
|
+
gLogger.debug(`Getting web service with name ${packageName}`);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
gLogger.debug(`Getting webservice with path: ${servicePath}`);
|
|
163
|
+
}
|
|
164
|
+
const fullPath = await this.getImportName(packageName, servicePath);
|
|
165
|
+
const tool = await import(fullPath);
|
|
152
166
|
gLogger.debug(`Got service with require: ${JSON.stringify(tool)}`);
|
|
153
167
|
gLogger.debug(`Getting web service from tool...`);
|
|
154
168
|
const appDataPath = path.join(appDataRoot, "appdata", serviceKey);
|
|
@@ -161,6 +175,7 @@ export class SwerveManager {
|
|
|
161
175
|
port,
|
|
162
176
|
app,
|
|
163
177
|
packageName,
|
|
178
|
+
servicePath,
|
|
164
179
|
serviceArgs: { ...serviceArgs },
|
|
165
180
|
logger,
|
|
166
181
|
});
|
|
@@ -184,6 +199,22 @@ Failed to install web service, is it installed with NPM? Check package exists in
|
|
|
184
199
|
throw e; //new Error(exceptionMessage);
|
|
185
200
|
}
|
|
186
201
|
}
|
|
202
|
+
async getImportName(packageName, servicePath) {
|
|
203
|
+
const nodeModulesPath = this.nodeModulesPath;
|
|
204
|
+
this.logger.debug(`getImportPathName: modulesPath: ${nodeModulesPath}`);
|
|
205
|
+
if (servicePath) {
|
|
206
|
+
return await getFullImportPath(servicePath);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
if (nodeModulesPath) {
|
|
210
|
+
this.logger.debug(`Getting path with nodeModulesPath and packageName ${nodeModulesPath} ${packageName}`);
|
|
211
|
+
return await resolvePackageEntry(path.join(nodeModulesPath, packageName));
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
return packageName;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
187
218
|
async stop(request) {
|
|
188
219
|
const { instanceDetails } = request;
|
|
189
220
|
const { instanceId, instanceType } = instanceDetails;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// cross-runtime getFullImportPath.ts
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
// Runtime detection
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const isDeno = typeof Deno !== "undefined" && "cwd" in Deno;
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
const isBun = typeof Bun !== "undefined";
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
const isNode = !isDeno && !isBun;
|
|
11
|
+
let join;
|
|
12
|
+
let cwd;
|
|
13
|
+
let fromFileUrl;
|
|
14
|
+
// --- Runtime-specific shims ---
|
|
15
|
+
if (isDeno) {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
// const path = await import("https://deno.land/std@0.203.0/path/mod.ts");
|
|
18
|
+
const path = await import("node:path");
|
|
19
|
+
join = path.join;
|
|
20
|
+
const url = await import("node:url");
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
cwd = Deno.cwd;
|
|
23
|
+
fromFileUrl = url.fileURLToPath;
|
|
24
|
+
// fromFileUrl = path.fromFileUrl;
|
|
25
|
+
}
|
|
26
|
+
else if (isNode) {
|
|
27
|
+
const path = await import("node:path");
|
|
28
|
+
const processMod = await import("node:process");
|
|
29
|
+
const url = await import("node:url");
|
|
30
|
+
join = path.join;
|
|
31
|
+
cwd = processMod.cwd;
|
|
32
|
+
fromFileUrl = url.fileURLToPath;
|
|
33
|
+
}
|
|
34
|
+
else if (isBun) {
|
|
35
|
+
const path = await import("path");
|
|
36
|
+
join = path.join;
|
|
37
|
+
cwd = () => process.cwd();
|
|
38
|
+
fromFileUrl = (u) => new URL(u).pathname; // Bun auto normalizes
|
|
39
|
+
}
|
|
40
|
+
// --- Universal function ---
|
|
41
|
+
export async function getFullImportPath(importPathOrName) {
|
|
42
|
+
let importPath;
|
|
43
|
+
if (importPathOrName.startsWith(".")) {
|
|
44
|
+
importPath = join(cwd(), importPathOrName);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
importPath = importPathOrName;
|
|
48
|
+
}
|
|
49
|
+
if (importPathOrName === importPath) {
|
|
50
|
+
// Turn into a full absolute path
|
|
51
|
+
const fullUrl = new URL(importPath, import.meta.url).href;
|
|
52
|
+
return fromFileUrl(fullUrl);
|
|
53
|
+
}
|
|
54
|
+
return importPath;
|
|
55
|
+
}
|
|
56
|
+
export async function resolvePackageEntry(pkgDir) {
|
|
57
|
+
const pkgJsonPath = join(pkgDir, "package.json");
|
|
58
|
+
let entry;
|
|
59
|
+
try {
|
|
60
|
+
const pkgJsonRaw = await fs.readFile(pkgJsonPath, "utf-8");
|
|
61
|
+
const pkgJson = JSON.parse(pkgJsonRaw);
|
|
62
|
+
if (pkgJson.exports && typeof pkgJson.exports === "string") {
|
|
63
|
+
// Simple "exports": "./esm/index.js"
|
|
64
|
+
entry = pkgJson.exports;
|
|
65
|
+
}
|
|
66
|
+
else if (pkgJson.module) {
|
|
67
|
+
entry = pkgJson.module;
|
|
68
|
+
}
|
|
69
|
+
else if (pkgJson.main) {
|
|
70
|
+
entry = pkgJson.main;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// no package.json, fallback below
|
|
75
|
+
}
|
|
76
|
+
if (!entry) {
|
|
77
|
+
// fallback to index.js
|
|
78
|
+
entry = "index.js";
|
|
79
|
+
}
|
|
80
|
+
const absPath = join(pkgDir, entry);
|
|
81
|
+
return pathToFileURL(absPath).href; // usable in await import()
|
|
82
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { ILogger } from "@swizzyweb/swizzy-common";
|
|
2
2
|
export declare function installWebService(appName: string, importPathOrName: string, port: number, expressApp: any, serviceArgs: any, gLogger: ILogger<any>): Promise<any>;
|
|
3
|
-
export declare function getFullImportPath(importPathOrName: string): Promise<string>;
|
|
4
3
|
export declare function getLoggerForService(serviceArgs: any, appName: string, port: number, gLogger: ILogger<any>): ILogger<any>;
|
|
@@ -45,7 +45,7 @@ Failed to install web service, is it installed with NPM? Check package exists in
|
|
|
45
45
|
throw Error(exceptionMessage); //new Error(exceptionMessage);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
async function getFullImportPath(importPathOrName) {
|
|
49
49
|
const importPath = importPathOrName.startsWith(".")
|
|
50
50
|
? path.join(process.cwd(), importPathOrName)
|
|
51
51
|
: importPathOrName;
|
package/package.json
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swizzyweb/swerve-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "swizzy-swerve is a bootstrapper for swizzy web services. This package will bootstrap and run independent swizzy web services.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsc",
|
|
10
|
-
"server:ts": "ts-node ./src/bootstrap.ts",
|
|
11
10
|
"server": "node dist/bootstrap.js",
|
|
12
|
-
"test": "node
|
|
11
|
+
"test": "npm run test:node && npm run test:bun && npm run test:deno",
|
|
12
|
+
"test:node": "node --test ./test**/*.spec.ts",
|
|
13
|
+
"test:deno": "deno test test/** --allow-env --allow-write --allow-read",
|
|
14
|
+
"test:bun": "bun test",
|
|
13
15
|
"coverage": "jest --coverage"
|
|
14
16
|
},
|
|
15
17
|
"author": "Jason Gallagher",
|
|
16
18
|
"license": "Apache-2.0",
|
|
17
19
|
"devDependencies": {
|
|
18
20
|
"@swizzyweb/express": "^4.19.2",
|
|
19
|
-
"@types/jest": "^29.5.14",
|
|
20
21
|
"@types/node": "^22.7.7",
|
|
21
|
-
"jest": "^29.7.0",
|
|
22
|
-
"ts-jest": "^29.3.2",
|
|
23
22
|
"typescript": "^5.6.3"
|
|
24
23
|
},
|
|
25
24
|
"dependencies": {
|
|
26
25
|
"@swizzyweb/swizzy-common": "^0.3.2",
|
|
27
26
|
"@swizzyweb/swizzy-web-service": "^0.5.3",
|
|
28
27
|
"bun": "^1.2.15",
|
|
29
|
-
"deno": "^2.3.6"
|
|
30
|
-
"ts-node": "^10.9.2"
|
|
28
|
+
"deno": "^2.3.6"
|
|
31
29
|
},
|
|
32
30
|
"repository": {
|
|
33
31
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/swizzyweb/swerve.git"
|
|
32
|
+
"url": "git+https://github.com/swizzyweb/swerve-manager.git"
|
|
35
33
|
},
|
|
36
34
|
"keywords": [
|
|
37
35
|
"swizzy",
|
|
@@ -43,7 +41,7 @@
|
|
|
43
41
|
"runner"
|
|
44
42
|
],
|
|
45
43
|
"bugs": {
|
|
46
|
-
"url": "https://github.com/swizzyweb/swerve/issues"
|
|
44
|
+
"url": "https://github.com/swizzyweb/swerve-manager/issues"
|
|
47
45
|
},
|
|
48
|
-
"homepage": "https://github.com/swizzyweb/swerve#readme"
|
|
46
|
+
"homepage": "https://github.com/swizzyweb/swerve-manager#readme"
|
|
49
47
|
}
|
package/src/swerve.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import express, { Application } from "@swizzyweb/express";
|
|
3
3
|
import {
|
|
4
|
-
getFullImportPath,
|
|
5
4
|
getLoggerForService,
|
|
6
5
|
installWebService,
|
|
7
6
|
SwerveArgs,
|
|
@@ -17,6 +16,10 @@ import process from "node:process";
|
|
|
17
16
|
import { ILogger } from "@swizzyweb/swizzy-common";
|
|
18
17
|
import path from "node:path";
|
|
19
18
|
import { mkdirSync } from "node:fs";
|
|
19
|
+
import {
|
|
20
|
+
getFullImportPath,
|
|
21
|
+
resolvePackageEntry,
|
|
22
|
+
} from "./utils/getFullImportPath.js";
|
|
20
23
|
|
|
21
24
|
export interface ISwerveManager {
|
|
22
25
|
run(request: RunRequest): Promise<RunResponse>;
|
|
@@ -74,6 +77,8 @@ export type Apps = {
|
|
|
74
77
|
export interface SwerveManagerProps {
|
|
75
78
|
apps?: Apps;
|
|
76
79
|
webServices?: WebService<any>[];
|
|
80
|
+
nodeModulesPath?: string;
|
|
81
|
+
logger?: ILogger<any> | undefined;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
export interface WebServiceConfiguration {}
|
|
@@ -86,9 +91,19 @@ export class SwerveManager implements ISwerveManager {
|
|
|
86
91
|
apps: Apps;
|
|
87
92
|
webServices: WebService<any>[];
|
|
88
93
|
configurations: WebServiceConfigurations;
|
|
94
|
+
nodeModulesPath: string;
|
|
95
|
+
logger: ILogger<any>;
|
|
89
96
|
constructor(props: SwerveManagerProps) {
|
|
90
97
|
this.apps = props.apps ?? {};
|
|
91
98
|
this.webServices = props.webServices ?? [];
|
|
99
|
+
this.nodeModulesPath = props.nodeModulesPath;
|
|
100
|
+
this.logger =
|
|
101
|
+
props.logger ??
|
|
102
|
+
new SwizzyWinstonLogger({
|
|
103
|
+
appName: "swerve-manager",
|
|
104
|
+
port: -1,
|
|
105
|
+
hostName: os.hostname(),
|
|
106
|
+
});
|
|
92
107
|
}
|
|
93
108
|
|
|
94
109
|
async run(request: RunRequest): Promise<RunResponse> {
|
|
@@ -126,9 +141,9 @@ export class SwerveManager implements ISwerveManager {
|
|
|
126
141
|
const app = this.apps[`${port}`].app;
|
|
127
142
|
|
|
128
143
|
const service = serviceEntry[1];
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
gLogger.debug(`
|
|
144
|
+
const serviceName = serviceEntry[0];
|
|
145
|
+
const packageName = service.packageName;
|
|
146
|
+
gLogger.debug(`servicePath: ${service.servicePath}`);
|
|
132
147
|
const serviceArgs: SwerveArgs = {
|
|
133
148
|
...service,
|
|
134
149
|
...service.serviceConfiguration,
|
|
@@ -136,9 +151,9 @@ export class SwerveManager implements ISwerveManager {
|
|
|
136
151
|
};
|
|
137
152
|
|
|
138
153
|
const webservice = await this.installWebService({
|
|
139
|
-
serviceKey:
|
|
154
|
+
serviceKey: serviceName,
|
|
140
155
|
packageName,
|
|
141
|
-
|
|
156
|
+
servicePath: service.servicePath,
|
|
142
157
|
port,
|
|
143
158
|
app,
|
|
144
159
|
appDataRoot: args.appDataRoot,
|
|
@@ -203,12 +218,10 @@ export class SwerveManager implements ISwerveManager {
|
|
|
203
218
|
for (const serviceEntry of Object.entries(args.services)) {
|
|
204
219
|
const service = serviceEntry[1];
|
|
205
220
|
const packageName = service.packageName;
|
|
206
|
-
const importPathOrName =
|
|
207
|
-
service.servicePath ?? service.serviceArgs.servicePath ?? packageName;
|
|
208
221
|
const webservice = await this.installWebService({
|
|
209
222
|
serviceKey: serviceEntry[0],
|
|
210
223
|
packageName,
|
|
211
|
-
|
|
224
|
+
servicePath: service.servicePath,
|
|
212
225
|
port: PORT,
|
|
213
226
|
app,
|
|
214
227
|
appDataRoot: args.appDataRoot,
|
|
@@ -232,7 +245,7 @@ export class SwerveManager implements ISwerveManager {
|
|
|
232
245
|
async installWebService(props: {
|
|
233
246
|
//
|
|
234
247
|
serviceKey: string;
|
|
235
|
-
|
|
248
|
+
servicePath: string;
|
|
236
249
|
app: Application;
|
|
237
250
|
appDataRoot: string;
|
|
238
251
|
packageName: string;
|
|
@@ -240,7 +253,6 @@ export class SwerveManager implements ISwerveManager {
|
|
|
240
253
|
gLogger: ILogger<any>;
|
|
241
254
|
serviceArgs: { [key: string]: any };
|
|
242
255
|
}) {
|
|
243
|
-
// const packageName = importPathOrName;
|
|
244
256
|
const {
|
|
245
257
|
app,
|
|
246
258
|
appDataRoot,
|
|
@@ -248,7 +260,7 @@ export class SwerveManager implements ISwerveManager {
|
|
|
248
260
|
port,
|
|
249
261
|
gLogger,
|
|
250
262
|
serviceArgs,
|
|
251
|
-
|
|
263
|
+
servicePath,
|
|
252
264
|
serviceKey,
|
|
253
265
|
} = props;
|
|
254
266
|
|
|
@@ -257,10 +269,14 @@ export class SwerveManager implements ISwerveManager {
|
|
|
257
269
|
`Getting webservice package ${packageName} and will run on port ${port}`,
|
|
258
270
|
);
|
|
259
271
|
|
|
260
|
-
|
|
272
|
+
if (packageName) {
|
|
273
|
+
gLogger.debug(`Getting web service with name ${packageName}`);
|
|
274
|
+
} else {
|
|
275
|
+
gLogger.debug(`Getting webservice with path: ${servicePath}`);
|
|
276
|
+
}
|
|
261
277
|
|
|
262
|
-
const fullPath = await
|
|
263
|
-
const tool = await import(fullPath);
|
|
278
|
+
const fullPath = await this.getImportName(packageName, servicePath);
|
|
279
|
+
const tool = await import(fullPath);
|
|
264
280
|
|
|
265
281
|
gLogger.debug(`Got service with require: ${JSON.stringify(tool)}`);
|
|
266
282
|
gLogger.debug(`Getting web service from tool...`);
|
|
@@ -281,6 +297,7 @@ export class SwerveManager implements ISwerveManager {
|
|
|
281
297
|
port,
|
|
282
298
|
app,
|
|
283
299
|
packageName,
|
|
300
|
+
servicePath,
|
|
284
301
|
serviceArgs: { ...serviceArgs },
|
|
285
302
|
logger,
|
|
286
303
|
});
|
|
@@ -309,6 +326,25 @@ Failed to install web service, is it installed with NPM? Check package exists in
|
|
|
309
326
|
}
|
|
310
327
|
}
|
|
311
328
|
|
|
329
|
+
async getImportName(packageName: string, servicePath: string) {
|
|
330
|
+
const nodeModulesPath = this.nodeModulesPath;
|
|
331
|
+
this.logger.debug(`getImportPathName: modulesPath: ${nodeModulesPath}`);
|
|
332
|
+
if (servicePath) {
|
|
333
|
+
return await getFullImportPath(servicePath);
|
|
334
|
+
} else {
|
|
335
|
+
if (nodeModulesPath) {
|
|
336
|
+
this.logger.debug(
|
|
337
|
+
`Getting path with nodeModulesPath and packageName ${nodeModulesPath} ${packageName}`,
|
|
338
|
+
);
|
|
339
|
+
return await resolvePackageEntry(
|
|
340
|
+
path.join(nodeModulesPath, packageName),
|
|
341
|
+
);
|
|
342
|
+
} else {
|
|
343
|
+
return packageName;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
312
348
|
async stop(request: StopRequest) {
|
|
313
349
|
const { instanceDetails } = request;
|
|
314
350
|
const { instanceId, instanceType } = instanceDetails;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// cross-runtime getFullImportPath.ts
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
|
|
5
|
+
// Runtime detection
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
const isDeno = typeof Deno !== "undefined" && "cwd" in Deno;
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
const isBun = typeof Bun !== "undefined";
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const isNode = !isDeno && !isBun;
|
|
12
|
+
|
|
13
|
+
let join: (a: string, b: string) => string;
|
|
14
|
+
let cwd: () => string;
|
|
15
|
+
let fromFileUrl: (url: string) => string;
|
|
16
|
+
|
|
17
|
+
// --- Runtime-specific shims ---
|
|
18
|
+
if (isDeno) {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
// const path = await import("https://deno.land/std@0.203.0/path/mod.ts");
|
|
21
|
+
|
|
22
|
+
const path = await import("node:path");
|
|
23
|
+
join = path.join;
|
|
24
|
+
const url = await import("node:url");
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
cwd = Deno.cwd;
|
|
27
|
+
fromFileUrl = url.fileURLToPath;
|
|
28
|
+
// fromFileUrl = path.fromFileUrl;
|
|
29
|
+
} else if (isNode) {
|
|
30
|
+
const path = await import("node:path");
|
|
31
|
+
const processMod = await import("node:process");
|
|
32
|
+
const url = await import("node:url");
|
|
33
|
+
join = path.join;
|
|
34
|
+
cwd = processMod.cwd;
|
|
35
|
+
fromFileUrl = url.fileURLToPath;
|
|
36
|
+
} else if (isBun) {
|
|
37
|
+
const path = await import("path");
|
|
38
|
+
join = path.join;
|
|
39
|
+
cwd = () => process.cwd();
|
|
40
|
+
fromFileUrl = (u: string) => new URL(u).pathname; // Bun auto normalizes
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// --- Universal function ---
|
|
44
|
+
export async function getFullImportPath(
|
|
45
|
+
importPathOrName: string,
|
|
46
|
+
): Promise<string> {
|
|
47
|
+
let importPath: string;
|
|
48
|
+
|
|
49
|
+
if (importPathOrName.startsWith(".")) {
|
|
50
|
+
importPath = join(cwd(), importPathOrName);
|
|
51
|
+
} else {
|
|
52
|
+
importPath = importPathOrName;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (importPathOrName === importPath) {
|
|
56
|
+
// Turn into a full absolute path
|
|
57
|
+
const fullUrl = new URL(importPath, import.meta.url).href;
|
|
58
|
+
return fromFileUrl(fullUrl);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return importPath;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function resolvePackageEntry(pkgDir: string): Promise<string> {
|
|
65
|
+
const pkgJsonPath = join(pkgDir, "package.json");
|
|
66
|
+
let entry: string | undefined;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const pkgJsonRaw = await fs.readFile(pkgJsonPath, "utf-8");
|
|
70
|
+
const pkgJson = JSON.parse(pkgJsonRaw);
|
|
71
|
+
|
|
72
|
+
if (pkgJson.exports && typeof pkgJson.exports === "string") {
|
|
73
|
+
// Simple "exports": "./esm/index.js"
|
|
74
|
+
entry = pkgJson.exports;
|
|
75
|
+
} else if (pkgJson.module) {
|
|
76
|
+
entry = pkgJson.module;
|
|
77
|
+
} else if (pkgJson.main) {
|
|
78
|
+
entry = pkgJson.main;
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// no package.json, fallback below
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!entry) {
|
|
85
|
+
// fallback to index.js
|
|
86
|
+
entry = "index.js";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const absPath = join(pkgDir, entry);
|
|
90
|
+
return pathToFileURL(absPath).href; // usable in await import()
|
|
91
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -79,9 +79,7 @@ Failed to install web service, is it installed with NPM? Check package exists in
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
importPathOrName: string,
|
|
84
|
-
): Promise<string> {
|
|
82
|
+
async function getFullImportPath(importPathOrName: string): Promise<string> {
|
|
85
83
|
const importPath = importPathOrName.startsWith(".")
|
|
86
84
|
? path.join(process.cwd(), importPathOrName)
|
|
87
85
|
: importPathOrName;
|
package/test/getArgs.spec.ts
CHANGED
|
@@ -15,67 +15,95 @@ const logger = new SwizzyWinstonLogger({
|
|
|
15
15
|
pid: process.pid,
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
test("
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
18
|
+
test.it("Sets port and custom arg", async () => {
|
|
19
|
+
const args = [
|
|
20
|
+
"/path/to/package/",
|
|
21
|
+
"run.js",
|
|
22
|
+
"--port",
|
|
23
|
+
"80",
|
|
24
|
+
//"--appDataRoot",
|
|
25
|
+
// ".",
|
|
26
|
+
"--someCustomArg",
|
|
27
|
+
"JasonIsTheBest",
|
|
28
|
+
];
|
|
29
|
+
let result: any = await getArgs(args, logger);
|
|
30
|
+
assert.equal(result.port, 80);
|
|
31
|
+
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
32
|
+
});
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
test.it("sets appDataRoot", async () => {
|
|
35
|
+
const args = [
|
|
36
|
+
"/path/to/package/",
|
|
37
|
+
"run.js",
|
|
38
|
+
"--port",
|
|
39
|
+
"80",
|
|
40
|
+
"--appDataRoot",
|
|
41
|
+
".",
|
|
42
|
+
"--someCustomArg",
|
|
43
|
+
"JasonIsTheBest",
|
|
44
|
+
];
|
|
45
|
+
let result: any = await getArgs(args, logger);
|
|
46
|
+
assert.equal(result.port, 80);
|
|
47
|
+
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
48
|
+
});
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
50
|
+
test.it("Throws on invalid config file path", async () => {
|
|
51
|
+
const configPath = "/some/invalid/path";
|
|
52
|
+
const args = [
|
|
53
|
+
"/path/to/package/",
|
|
54
|
+
"run.js",
|
|
55
|
+
"--port",
|
|
56
|
+
"80",
|
|
57
|
+
"--appDataRoot",
|
|
58
|
+
".",
|
|
59
|
+
"--someCustomArg",
|
|
60
|
+
"JasonIsTheBest",
|
|
61
|
+
"--config",
|
|
62
|
+
configPath,
|
|
63
|
+
];
|
|
64
|
+
try {
|
|
65
|
+
let result: any = await getArgs(args, logger);
|
|
66
|
+
} catch (e: any) {
|
|
67
|
+
assert.deepEqual(
|
|
68
|
+
{ message: e?.message, configFilePath: configPath },
|
|
69
|
+
{
|
|
70
|
+
message:
|
|
71
|
+
"Unexpected error occurred when attempting to read serviceConfiguration file",
|
|
72
|
+
configFilePath: configPath,
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
test.it("Should read config values from config", async () => {
|
|
78
|
+
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
79
|
+
const args = [
|
|
80
|
+
"/path/to/package/",
|
|
81
|
+
"run.js",
|
|
82
|
+
"--port",
|
|
83
|
+
"80",
|
|
84
|
+
"--appDataRoot",
|
|
85
|
+
".",
|
|
86
|
+
"--someCustomArg",
|
|
87
|
+
"JasonIsTheBest",
|
|
88
|
+
"--config",
|
|
89
|
+
configPath,
|
|
90
|
+
];
|
|
91
|
+
let result: any = await getArgs(args, logger);
|
|
92
|
+
assert.equal(result.port, 3000);
|
|
93
|
+
const service = result.services["my-first-web-service1"];
|
|
94
|
+
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
95
|
+
|
|
96
|
+
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
97
|
+
assert.equal(service.shouldTimeout, true);
|
|
98
|
+
assert.deepEqual(service.nestedJson, {
|
|
99
|
+
hello: "world",
|
|
100
|
+
none: false,
|
|
77
101
|
});
|
|
78
|
-
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test.it(
|
|
105
|
+
"Should override parameters in order of args, config file last",
|
|
106
|
+
async () => {
|
|
79
107
|
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
80
108
|
const args = [
|
|
81
109
|
"/path/to/package/",
|
|
@@ -86,246 +114,216 @@ test("getArgs", () => {
|
|
|
86
114
|
".",
|
|
87
115
|
"--someCustomArg",
|
|
88
116
|
"JasonIsTheBest",
|
|
117
|
+
"--someNumberINeed",
|
|
118
|
+
"1000",
|
|
89
119
|
"--config",
|
|
90
120
|
configPath,
|
|
91
121
|
];
|
|
92
|
-
let result = await getArgs(args, logger);
|
|
93
|
-
|
|
122
|
+
let result: any = await getArgs(args, logger);
|
|
123
|
+
|
|
94
124
|
const service = result.services["my-first-web-service1"];
|
|
125
|
+
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
126
|
+
|
|
127
|
+
assert.equal(result.port, 3000);
|
|
95
128
|
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
96
129
|
|
|
97
|
-
assert.equal(
|
|
130
|
+
assert.equal(result.serviceArgs?.someNumberINeed, 1000);
|
|
98
131
|
assert.equal(service.shouldTimeout, true);
|
|
99
132
|
assert.deepEqual(service.nestedJson, {
|
|
100
133
|
hello: "world",
|
|
101
134
|
none: false,
|
|
102
135
|
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
test.it(
|
|
106
|
-
"Should override parameters in order of args, config file last",
|
|
107
|
-
async () => {
|
|
108
|
-
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
109
|
-
const args = [
|
|
110
|
-
"/path/to/package/",
|
|
111
|
-
"run.js",
|
|
112
|
-
"--port",
|
|
113
|
-
"80",
|
|
114
|
-
"--appDataRoot",
|
|
115
|
-
".",
|
|
116
|
-
"--someCustomArg",
|
|
117
|
-
"JasonIsTheBest",
|
|
118
|
-
"--someNumberINeed",
|
|
119
|
-
"1000",
|
|
120
|
-
"--config",
|
|
121
|
-
configPath,
|
|
122
|
-
];
|
|
123
|
-
let result = await getArgs(args, logger);
|
|
124
|
-
|
|
125
|
-
const service = result.services["my-first-web-service1"];
|
|
126
|
-
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
127
|
-
|
|
128
|
-
assert.equal(result.port, 3000);
|
|
129
|
-
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
136
|
+
},
|
|
137
|
+
);
|
|
130
138
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
none: false,
|
|
136
|
-
});
|
|
137
|
-
},
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
test.it(
|
|
141
|
-
"Should override parameters in order of args, config file first",
|
|
142
|
-
async () => {
|
|
143
|
-
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
144
|
-
const args = [
|
|
145
|
-
"/path/to/package/",
|
|
146
|
-
"run.js",
|
|
147
|
-
"--port",
|
|
148
|
-
"80",
|
|
149
|
-
"--appDataRoot",
|
|
150
|
-
".",
|
|
151
|
-
"--someCustomArg",
|
|
152
|
-
"JasonIsTheBest",
|
|
153
|
-
"--config",
|
|
154
|
-
configPath,
|
|
155
|
-
"--someNumberINeed",
|
|
156
|
-
"1000",
|
|
157
|
-
];
|
|
158
|
-
let result = await getArgs(args, logger);
|
|
159
|
-
const service = result.services["my-first-web-service1"];
|
|
160
|
-
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
161
|
-
assert.equal(result.port, 3000);
|
|
162
|
-
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
163
|
-
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
164
|
-
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
165
|
-
|
|
166
|
-
assert.equal(result.serviceArgs?.someNumberINeed, 1000);
|
|
167
|
-
assert.equal(service.shouldTimeout, true);
|
|
168
|
-
assert.deepEqual(service.nestedJson, {
|
|
169
|
-
hello: "world",
|
|
170
|
-
none: false,
|
|
171
|
-
});
|
|
172
|
-
},
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
test.it("Should getService from args", async () => {
|
|
139
|
+
test.it(
|
|
140
|
+
"Should override parameters in order of args, config file first",
|
|
141
|
+
async () => {
|
|
142
|
+
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
176
143
|
const args = [
|
|
177
144
|
"/path/to/package/",
|
|
178
145
|
"run.js",
|
|
179
|
-
path.join(__dirname, "../package.json"),
|
|
180
146
|
"--port",
|
|
181
147
|
"80",
|
|
182
148
|
"--appDataRoot",
|
|
183
149
|
".",
|
|
184
150
|
"--someCustomArg",
|
|
185
151
|
"JasonIsTheBest",
|
|
152
|
+
"--config",
|
|
153
|
+
configPath,
|
|
154
|
+
"--someNumberINeed",
|
|
155
|
+
"1000",
|
|
186
156
|
];
|
|
187
|
-
let result = await getArgs(args, logger);
|
|
188
|
-
assert.equal(result.port, 80);
|
|
189
|
-
|
|
157
|
+
let result: any = await getArgs(args, logger);
|
|
190
158
|
const service = result.services["my-first-web-service1"];
|
|
191
|
-
|
|
159
|
+
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
160
|
+
assert.equal(result.port, 3000);
|
|
161
|
+
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
162
|
+
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
192
163
|
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
193
|
-
});
|
|
194
164
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
"80",
|
|
204
|
-
"--someCustomArg",
|
|
205
|
-
"JasonIsTheBest",
|
|
206
|
-
"--config",
|
|
207
|
-
configPath,
|
|
208
|
-
"--someNumberINeed",
|
|
209
|
-
"1000",
|
|
210
|
-
];
|
|
211
|
-
let result = await getArgs(args, logger);
|
|
165
|
+
assert.equal(result.serviceArgs?.someNumberINeed, 1000);
|
|
166
|
+
assert.equal(service.shouldTimeout, true);
|
|
167
|
+
assert.deepEqual(service.nestedJson, {
|
|
168
|
+
hello: "world",
|
|
169
|
+
none: false,
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
);
|
|
212
173
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
174
|
+
test.it("Should getService from args", async () => {
|
|
175
|
+
const args = [
|
|
176
|
+
"/path/to/package/",
|
|
177
|
+
"run.js",
|
|
178
|
+
path.join(__dirname, "../package.json"),
|
|
179
|
+
"--port",
|
|
180
|
+
"80",
|
|
181
|
+
"--appDataRoot",
|
|
182
|
+
".",
|
|
183
|
+
"--someCustomArg",
|
|
184
|
+
"JasonIsTheBest",
|
|
185
|
+
];
|
|
186
|
+
let result: any = await getArgs(args, logger);
|
|
187
|
+
assert.equal(result.port, 80);
|
|
218
188
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
)
|
|
227
|
-
test.it("Should create multiple services", async () => {
|
|
189
|
+
const service = result.services["my-first-web-service1"];
|
|
190
|
+
// expect(result.serviceArgs.appDataRoot, ".");
|
|
191
|
+
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test.it(
|
|
195
|
+
"Should set appDataRoot to current package root by default",
|
|
196
|
+
async () => {
|
|
228
197
|
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
229
198
|
const args = [
|
|
230
199
|
"/path/to/package/",
|
|
231
200
|
"run.js",
|
|
232
|
-
".",
|
|
233
201
|
"--port",
|
|
234
202
|
"80",
|
|
235
203
|
"--someCustomArg",
|
|
236
204
|
"JasonIsTheBest",
|
|
237
|
-
|
|
238
|
-
|
|
205
|
+
"--config",
|
|
206
|
+
configPath,
|
|
239
207
|
"--someNumberINeed",
|
|
240
208
|
"1000",
|
|
241
|
-
".",
|
|
242
|
-
"--port",
|
|
243
|
-
"91",
|
|
244
209
|
];
|
|
245
|
-
let result = await getArgs(args, logger);
|
|
210
|
+
let result: any = await getArgs(args, logger);
|
|
246
211
|
|
|
247
212
|
const service = result.services["my-first-web-service1"];
|
|
248
|
-
assert.equal(
|
|
213
|
+
assert.equal(service.someOtherArgFromConfig, "ThisIsTheArgValue");
|
|
214
|
+
assert.equal(result.port, 3000);
|
|
249
215
|
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
250
|
-
|
|
216
|
+
assert.equal(result.serviceArgs?.someCustomArg!, "JasonIsTheBest");
|
|
251
217
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
"
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
appDataRoot,
|
|
280
|
-
];
|
|
281
|
-
let result = await getArgs(args, logger);
|
|
282
|
-
assert.equal(result.appDataRoot, appDataRoot);
|
|
283
|
-
});
|
|
218
|
+
assert.equal(result.serviceArgs?.someNumberINeed!, 1000);
|
|
219
|
+
assert.equal(service.shouldTimeout, true);
|
|
220
|
+
assert.deepEqual(service.nestedJson, {
|
|
221
|
+
hello: "world",
|
|
222
|
+
none: false,
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
);
|
|
226
|
+
test.it("Should create multiple services", async () => {
|
|
227
|
+
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
228
|
+
const args = [
|
|
229
|
+
"/path/to/package/",
|
|
230
|
+
"run.js",
|
|
231
|
+
".",
|
|
232
|
+
"--port",
|
|
233
|
+
"80",
|
|
234
|
+
"--someCustomArg",
|
|
235
|
+
"JasonIsTheBest",
|
|
236
|
+
// "--config",
|
|
237
|
+
// configPath,
|
|
238
|
+
"--someNumberINeed",
|
|
239
|
+
"1000",
|
|
240
|
+
".",
|
|
241
|
+
"--port",
|
|
242
|
+
"91",
|
|
243
|
+
];
|
|
244
|
+
let result: any = await getArgs(args, logger);
|
|
284
245
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
config.services["@swizzyweb/swerve-manager"].packageJson.name,
|
|
290
|
-
"@swizzyweb/swerve-manager",
|
|
291
|
-
);
|
|
292
|
-
});
|
|
246
|
+
const service = result.services["my-first-web-service1"];
|
|
247
|
+
assert.equal(result.port, 91);
|
|
248
|
+
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
249
|
+
// expect(service.someCustomArg, "JasonIsTheBest");
|
|
293
250
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
327
|
-
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
251
|
+
// expect(service.someNumberINeed, 1000);
|
|
252
|
+
// expect(service.shouldTimeout, true);
|
|
253
|
+
// expect(service.nestedJson, {
|
|
254
|
+
// hello: "world",
|
|
255
|
+
// none: false,
|
|
256
|
+
// });
|
|
257
|
+
// expect(result.services.length, 2);
|
|
258
|
+
});
|
|
259
|
+
test.it("Should create absolute path appdata directory", async () => {
|
|
260
|
+
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
261
|
+
const appDataRoot = "/tmp/swizzy-dyn-serve-web-service";
|
|
262
|
+
const args = [
|
|
263
|
+
"/path/to/package/",
|
|
264
|
+
"run.js",
|
|
265
|
+
".",
|
|
266
|
+
"--port",
|
|
267
|
+
"80",
|
|
268
|
+
"--someCustomArg",
|
|
269
|
+
"JasonIsTheBest",
|
|
270
|
+
//"--config",
|
|
271
|
+
//configPath,
|
|
272
|
+
"--someNumberINeed",
|
|
273
|
+
"1000",
|
|
274
|
+
".",
|
|
275
|
+
"--port",
|
|
276
|
+
"91",
|
|
277
|
+
"--appDataRoot",
|
|
278
|
+
appDataRoot,
|
|
279
|
+
];
|
|
280
|
+
let result: any = await getArgs(args, logger);
|
|
281
|
+
assert.equal(result.appDataRoot, appDataRoot);
|
|
282
|
+
});
|
|
328
283
|
|
|
329
|
-
|
|
330
|
-
|
|
284
|
+
test.it("Should resolve package.json from package name", async () => {
|
|
285
|
+
const config: any = await getArgs(["@swizzyweb/swerve-manager"], logger);
|
|
286
|
+
assert(config.services["@swizzyweb/swerve-manager"].packageJson);
|
|
287
|
+
assert.equal(
|
|
288
|
+
config.services["@swizzyweb/swerve-manager"].packageJson.name,
|
|
289
|
+
"@swizzyweb/swerve-manager",
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test.it("Should resolve package.json from absolute path", async () => {
|
|
294
|
+
const config: any = await getArgs([path.join(__dirname, "..")], logger);
|
|
295
|
+
assert(config.services["@swizzyweb/swerve-manager"].packageJson);
|
|
296
|
+
assert.equal(
|
|
297
|
+
config.services["@swizzyweb/swerve-manager"].packageJson.name,
|
|
298
|
+
"@swizzyweb/swerve-manager",
|
|
299
|
+
);
|
|
300
|
+
});
|
|
301
|
+
test.it("Should not throw with no args", async () => {
|
|
302
|
+
const config: any = await getArgs([], logger);
|
|
303
|
+
assert(config.services["@swizzyweb/swerve-manager"].packageJson);
|
|
304
|
+
assert.equal(
|
|
305
|
+
config.services["@swizzyweb/swerve-manager"].packageJson.name,
|
|
306
|
+
"@swizzyweb/swerve-manager",
|
|
307
|
+
);
|
|
308
|
+
});
|
|
309
|
+
test.it("Should work with no port", async () => {
|
|
310
|
+
const configPath = path.join(__dirname, "./config/serviceConfig.json");
|
|
311
|
+
const args = [
|
|
312
|
+
"/path/to/package/",
|
|
313
|
+
"run.js",
|
|
314
|
+
"--appDataRoot",
|
|
315
|
+
".",
|
|
316
|
+
"--someCustomArg",
|
|
317
|
+
"JasonIsTheBest",
|
|
318
|
+
"--someNumberINeed",
|
|
319
|
+
"1000",
|
|
320
|
+
];
|
|
321
|
+
let result: any = await getArgs(args, logger);
|
|
322
|
+
const service = result.services["my-first-web-service1"];
|
|
323
|
+
assert.equal(result.port, 3005);
|
|
324
|
+
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
325
|
+
assert.equal(result.appDataRoot, path.join(__dirname, ".."));
|
|
326
|
+
assert.equal(result.serviceArgs?.someCustomArg, "JasonIsTheBest");
|
|
327
|
+
|
|
328
|
+
assert.equal(result.serviceArgs?.someNumberINeed, 1000);
|
|
331
329
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import { getFullImportPath } from "../dist/utils/getFullImportPath.js";
|
|
3
|
+
import assert from "node:assert";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
test("Should get full path with relative path", async () => {
|
|
7
|
+
const fullPath = await getFullImportPath("../");
|
|
8
|
+
assert(path.isAbsolute(fullPath));
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("Should get full path from packageName", async () => {
|
|
12
|
+
const fullPath = await getFullImportPath(
|
|
13
|
+
"@swizzyweb/swap-cache-db-web-service",
|
|
14
|
+
);
|
|
15
|
+
assert(path.isAbsolute(fullPath));
|
|
16
|
+
});
|
package/jest.config.js
DELETED