@eclosion-tech/syntropy-auth-express 0.1.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/dist/index.cjs +68 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
requireSyntropyAuth: () => requireSyntropyAuth,
|
|
24
|
+
syntropyAuth: () => syntropyAuth
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
var import_syntropy_auth = require("@eclosion-tech/syntropy-auth");
|
|
28
|
+
function syntropyAuth(config) {
|
|
29
|
+
const client = new import_syntropy_auth.SyntropyAuthClient({
|
|
30
|
+
baseUrl: config.baseUrl,
|
|
31
|
+
clientId: config.clientId,
|
|
32
|
+
clientSecret: config.clientSecret,
|
|
33
|
+
redirectUri: "http://localhost"
|
|
34
|
+
// unused for token validation
|
|
35
|
+
});
|
|
36
|
+
return async (req, _res, next) => {
|
|
37
|
+
const authHeader = req.headers.authorization;
|
|
38
|
+
if (!authHeader?.startsWith("Bearer ")) {
|
|
39
|
+
return next();
|
|
40
|
+
}
|
|
41
|
+
const token = authHeader.slice(7);
|
|
42
|
+
try {
|
|
43
|
+
const userInfo = await client.getUserInfo(token);
|
|
44
|
+
req.syntropyUser = userInfo;
|
|
45
|
+
req.syntropyAccessToken = token;
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
next();
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function requireSyntropyAuth(config) {
|
|
52
|
+
const authMiddleware = syntropyAuth(config);
|
|
53
|
+
return async (req, res, next) => {
|
|
54
|
+
await authMiddleware(req, res, () => {
|
|
55
|
+
if (!req.syntropyUser) {
|
|
56
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
next();
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
requireSyntropyAuth,
|
|
66
|
+
syntropyAuth
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Request, Response, NextFunction } from \"express\";\nimport { SyntropyAuthClient } from \"@eclosion-tech/syntropy-auth\";\nimport type { SyntropyUserInfo } from \"@eclosion-tech/syntropy-auth\";\n\ndeclare global {\n namespace Express {\n interface Request {\n syntropyUser?: SyntropyUserInfo;\n syntropyAccessToken?: string;\n }\n }\n}\n\nexport interface SyntropyAuthExpressConfig {\n /** Base URL of Syntropy Auth (e.g. https://auth.syntropy.chat) */\n baseUrl: string;\n /** OAuth client ID */\n clientId: string;\n /** OAuth client secret */\n clientSecret?: string;\n}\n\n/**\n * Express middleware that validates Bearer tokens against Syntropy Auth.\n *\n * Reads the `Authorization: Bearer <token>` header, calls the userinfo\n * endpoint, and populates `req.syntropyUser` and `req.syntropyAccessToken`.\n *\n * Usage:\n * ```ts\n * import express from \"express\";\n * import { syntropyAuth } from \"@eclosion-tech/syntropy-auth-express\";\n *\n * const app = express();\n * app.use(syntropyAuth({\n * baseUrl: \"https://auth.syntropy.chat\",\n * clientId: \"my-api\",\n * }));\n *\n * app.get(\"/api/me\", (req, res) => {\n * if (!req.syntropyUser) return res.status(401).json({ error: \"Unauthorized\" });\n * res.json(req.syntropyUser);\n * });\n * ```\n */\nexport function syntropyAuth(config: SyntropyAuthExpressConfig) {\n const client = new SyntropyAuthClient({\n baseUrl: config.baseUrl,\n clientId: config.clientId,\n clientSecret: config.clientSecret,\n redirectUri: \"http://localhost\", // unused for token validation\n });\n\n return async (req: Request, _res: Response, next: NextFunction) => {\n const authHeader = req.headers.authorization;\n if (!authHeader?.startsWith(\"Bearer \")) {\n return next();\n }\n\n const token = authHeader.slice(7);\n\n try {\n const userInfo = await client.getUserInfo(token);\n req.syntropyUser = userInfo;\n req.syntropyAccessToken = token;\n } catch {\n // Invalid token — continue without user\n }\n\n next();\n };\n}\n\n/**\n * Express middleware that requires a valid Syntropy Auth token.\n * Returns 401 if no valid token is present.\n */\nexport function requireSyntropyAuth(config: SyntropyAuthExpressConfig) {\n const authMiddleware = syntropyAuth(config);\n\n return async (req: Request, res: Response, next: NextFunction) => {\n await authMiddleware(req, res, () => {\n if (!req.syntropyUser) {\n res.status(401).json({ error: \"Unauthorized\" });\n return;\n }\n next();\n });\n };\n}\n\nexport type { SyntropyUserInfo };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,2BAAmC;AA4C5B,SAAS,aAAa,QAAmC;AAC9D,QAAM,SAAS,IAAI,wCAAmB;AAAA,IACpC,SAAS,OAAO;AAAA,IAChB,UAAU,OAAO;AAAA,IACjB,cAAc,OAAO;AAAA,IACrB,aAAa;AAAA;AAAA,EACf,CAAC;AAED,SAAO,OAAO,KAAc,MAAgB,SAAuB;AACjE,UAAM,aAAa,IAAI,QAAQ;AAC/B,QAAI,CAAC,YAAY,WAAW,SAAS,GAAG;AACtC,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,QAAQ,WAAW,MAAM,CAAC;AAEhC,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,YAAY,KAAK;AAC/C,UAAI,eAAe;AACnB,UAAI,sBAAsB;AAAA,IAC5B,QAAQ;AAAA,IAER;AAEA,SAAK;AAAA,EACP;AACF;AAMO,SAAS,oBAAoB,QAAmC;AACrE,QAAM,iBAAiB,aAAa,MAAM;AAE1C,SAAO,OAAO,KAAc,KAAe,SAAuB;AAChE,UAAM,eAAe,KAAK,KAAK,MAAM;AACnC,UAAI,CAAC,IAAI,cAAc;AACrB,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAC9C;AAAA,MACF;AACA,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AACF;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { SyntropyUserInfo } from '@eclosion-tech/syntropy-auth';
|
|
3
|
+
export { SyntropyUserInfo } from '@eclosion-tech/syntropy-auth';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
namespace Express {
|
|
7
|
+
interface Request {
|
|
8
|
+
syntropyUser?: SyntropyUserInfo;
|
|
9
|
+
syntropyAccessToken?: string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
interface SyntropyAuthExpressConfig {
|
|
14
|
+
/** Base URL of Syntropy Auth (e.g. https://auth.syntropy.chat) */
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/** OAuth client ID */
|
|
17
|
+
clientId: string;
|
|
18
|
+
/** OAuth client secret */
|
|
19
|
+
clientSecret?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Express middleware that validates Bearer tokens against Syntropy Auth.
|
|
23
|
+
*
|
|
24
|
+
* Reads the `Authorization: Bearer <token>` header, calls the userinfo
|
|
25
|
+
* endpoint, and populates `req.syntropyUser` and `req.syntropyAccessToken`.
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* ```ts
|
|
29
|
+
* import express from "express";
|
|
30
|
+
* import { syntropyAuth } from "@eclosion-tech/syntropy-auth-express";
|
|
31
|
+
*
|
|
32
|
+
* const app = express();
|
|
33
|
+
* app.use(syntropyAuth({
|
|
34
|
+
* baseUrl: "https://auth.syntropy.chat",
|
|
35
|
+
* clientId: "my-api",
|
|
36
|
+
* }));
|
|
37
|
+
*
|
|
38
|
+
* app.get("/api/me", (req, res) => {
|
|
39
|
+
* if (!req.syntropyUser) return res.status(401).json({ error: "Unauthorized" });
|
|
40
|
+
* res.json(req.syntropyUser);
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function syntropyAuth(config: SyntropyAuthExpressConfig): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Express middleware that requires a valid Syntropy Auth token.
|
|
47
|
+
* Returns 401 if no valid token is present.
|
|
48
|
+
*/
|
|
49
|
+
declare function requireSyntropyAuth(config: SyntropyAuthExpressConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
50
|
+
|
|
51
|
+
export { type SyntropyAuthExpressConfig, requireSyntropyAuth, syntropyAuth };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { SyntropyUserInfo } from '@eclosion-tech/syntropy-auth';
|
|
3
|
+
export { SyntropyUserInfo } from '@eclosion-tech/syntropy-auth';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
namespace Express {
|
|
7
|
+
interface Request {
|
|
8
|
+
syntropyUser?: SyntropyUserInfo;
|
|
9
|
+
syntropyAccessToken?: string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
interface SyntropyAuthExpressConfig {
|
|
14
|
+
/** Base URL of Syntropy Auth (e.g. https://auth.syntropy.chat) */
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/** OAuth client ID */
|
|
17
|
+
clientId: string;
|
|
18
|
+
/** OAuth client secret */
|
|
19
|
+
clientSecret?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Express middleware that validates Bearer tokens against Syntropy Auth.
|
|
23
|
+
*
|
|
24
|
+
* Reads the `Authorization: Bearer <token>` header, calls the userinfo
|
|
25
|
+
* endpoint, and populates `req.syntropyUser` and `req.syntropyAccessToken`.
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* ```ts
|
|
29
|
+
* import express from "express";
|
|
30
|
+
* import { syntropyAuth } from "@eclosion-tech/syntropy-auth-express";
|
|
31
|
+
*
|
|
32
|
+
* const app = express();
|
|
33
|
+
* app.use(syntropyAuth({
|
|
34
|
+
* baseUrl: "https://auth.syntropy.chat",
|
|
35
|
+
* clientId: "my-api",
|
|
36
|
+
* }));
|
|
37
|
+
*
|
|
38
|
+
* app.get("/api/me", (req, res) => {
|
|
39
|
+
* if (!req.syntropyUser) return res.status(401).json({ error: "Unauthorized" });
|
|
40
|
+
* res.json(req.syntropyUser);
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function syntropyAuth(config: SyntropyAuthExpressConfig): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Express middleware that requires a valid Syntropy Auth token.
|
|
47
|
+
* Returns 401 if no valid token is present.
|
|
48
|
+
*/
|
|
49
|
+
declare function requireSyntropyAuth(config: SyntropyAuthExpressConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
50
|
+
|
|
51
|
+
export { type SyntropyAuthExpressConfig, requireSyntropyAuth, syntropyAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { SyntropyAuthClient } from "@eclosion-tech/syntropy-auth";
|
|
3
|
+
function syntropyAuth(config) {
|
|
4
|
+
const client = new SyntropyAuthClient({
|
|
5
|
+
baseUrl: config.baseUrl,
|
|
6
|
+
clientId: config.clientId,
|
|
7
|
+
clientSecret: config.clientSecret,
|
|
8
|
+
redirectUri: "http://localhost"
|
|
9
|
+
// unused for token validation
|
|
10
|
+
});
|
|
11
|
+
return async (req, _res, next) => {
|
|
12
|
+
const authHeader = req.headers.authorization;
|
|
13
|
+
if (!authHeader?.startsWith("Bearer ")) {
|
|
14
|
+
return next();
|
|
15
|
+
}
|
|
16
|
+
const token = authHeader.slice(7);
|
|
17
|
+
try {
|
|
18
|
+
const userInfo = await client.getUserInfo(token);
|
|
19
|
+
req.syntropyUser = userInfo;
|
|
20
|
+
req.syntropyAccessToken = token;
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
next();
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function requireSyntropyAuth(config) {
|
|
27
|
+
const authMiddleware = syntropyAuth(config);
|
|
28
|
+
return async (req, res, next) => {
|
|
29
|
+
await authMiddleware(req, res, () => {
|
|
30
|
+
if (!req.syntropyUser) {
|
|
31
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
next();
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
requireSyntropyAuth,
|
|
40
|
+
syntropyAuth
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Request, Response, NextFunction } from \"express\";\nimport { SyntropyAuthClient } from \"@eclosion-tech/syntropy-auth\";\nimport type { SyntropyUserInfo } from \"@eclosion-tech/syntropy-auth\";\n\ndeclare global {\n namespace Express {\n interface Request {\n syntropyUser?: SyntropyUserInfo;\n syntropyAccessToken?: string;\n }\n }\n}\n\nexport interface SyntropyAuthExpressConfig {\n /** Base URL of Syntropy Auth (e.g. https://auth.syntropy.chat) */\n baseUrl: string;\n /** OAuth client ID */\n clientId: string;\n /** OAuth client secret */\n clientSecret?: string;\n}\n\n/**\n * Express middleware that validates Bearer tokens against Syntropy Auth.\n *\n * Reads the `Authorization: Bearer <token>` header, calls the userinfo\n * endpoint, and populates `req.syntropyUser` and `req.syntropyAccessToken`.\n *\n * Usage:\n * ```ts\n * import express from \"express\";\n * import { syntropyAuth } from \"@eclosion-tech/syntropy-auth-express\";\n *\n * const app = express();\n * app.use(syntropyAuth({\n * baseUrl: \"https://auth.syntropy.chat\",\n * clientId: \"my-api\",\n * }));\n *\n * app.get(\"/api/me\", (req, res) => {\n * if (!req.syntropyUser) return res.status(401).json({ error: \"Unauthorized\" });\n * res.json(req.syntropyUser);\n * });\n * ```\n */\nexport function syntropyAuth(config: SyntropyAuthExpressConfig) {\n const client = new SyntropyAuthClient({\n baseUrl: config.baseUrl,\n clientId: config.clientId,\n clientSecret: config.clientSecret,\n redirectUri: \"http://localhost\", // unused for token validation\n });\n\n return async (req: Request, _res: Response, next: NextFunction) => {\n const authHeader = req.headers.authorization;\n if (!authHeader?.startsWith(\"Bearer \")) {\n return next();\n }\n\n const token = authHeader.slice(7);\n\n try {\n const userInfo = await client.getUserInfo(token);\n req.syntropyUser = userInfo;\n req.syntropyAccessToken = token;\n } catch {\n // Invalid token — continue without user\n }\n\n next();\n };\n}\n\n/**\n * Express middleware that requires a valid Syntropy Auth token.\n * Returns 401 if no valid token is present.\n */\nexport function requireSyntropyAuth(config: SyntropyAuthExpressConfig) {\n const authMiddleware = syntropyAuth(config);\n\n return async (req: Request, res: Response, next: NextFunction) => {\n await authMiddleware(req, res, () => {\n if (!req.syntropyUser) {\n res.status(401).json({ error: \"Unauthorized\" });\n return;\n }\n next();\n });\n };\n}\n\nexport type { SyntropyUserInfo };\n"],"mappings":";AACA,SAAS,0BAA0B;AA4C5B,SAAS,aAAa,QAAmC;AAC9D,QAAM,SAAS,IAAI,mBAAmB;AAAA,IACpC,SAAS,OAAO;AAAA,IAChB,UAAU,OAAO;AAAA,IACjB,cAAc,OAAO;AAAA,IACrB,aAAa;AAAA;AAAA,EACf,CAAC;AAED,SAAO,OAAO,KAAc,MAAgB,SAAuB;AACjE,UAAM,aAAa,IAAI,QAAQ;AAC/B,QAAI,CAAC,YAAY,WAAW,SAAS,GAAG;AACtC,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,QAAQ,WAAW,MAAM,CAAC;AAEhC,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,YAAY,KAAK;AAC/C,UAAI,eAAe;AACnB,UAAI,sBAAsB;AAAA,IAC5B,QAAQ;AAAA,IAER;AAEA,SAAK;AAAA,EACP;AACF;AAMO,SAAS,oBAAoB,QAAmC;AACrE,QAAM,iBAAiB,aAAa,MAAM;AAE1C,SAAO,OAAO,KAAc,KAAe,SAAuB;AAChE,UAAM,eAAe,KAAK,KAAK,MAAM;AACnC,UAAI,CAAC,IAAI,cAAc;AACrB,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAC9C;AAAA,MACF;AACA,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eclosion-tech/syntropy-auth-express",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Syntropy Auth Express middleware — session validation and user population",
|
|
5
|
+
"author": "Eclosion Tech",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/EclosionTech/Syntropy.git",
|
|
10
|
+
"directory": "packages/auth-express"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://syntropy.chat",
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.mjs",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.mjs",
|
|
24
|
+
"require": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@eclosion-tech/syntropy-auth": "0.1.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"express": ">=4"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/express": "^5",
|
|
38
|
+
"@types/node": "^20",
|
|
39
|
+
"express": "^5.0.0",
|
|
40
|
+
"tsup": "^8.3.5",
|
|
41
|
+
"typescript": "^5",
|
|
42
|
+
"vitest": "^3.0.4"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"syntropy",
|
|
49
|
+
"auth",
|
|
50
|
+
"express",
|
|
51
|
+
"middleware",
|
|
52
|
+
"oauth"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"dev": "tsup --watch",
|
|
57
|
+
"test": "vitest run --passWithNoTests",
|
|
58
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
59
|
+
"clean": "rm -rf dist node_modules"
|
|
60
|
+
}
|
|
61
|
+
}
|