@elaraai/tsserver-plugin-east 1.0.36 → 1.0.38
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 +104 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -919,6 +919,16 @@ function resolvesToFsImport(id, ctx) {
|
|
|
919
919
|
const imp = importOfSymbol(ctx.checker.getSymbolAtLocation(id), t);
|
|
920
920
|
return imp !== void 0 && t.isStringLiteral(imp.moduleSpecifier) && FS_MODULES.has(imp.moduleSpecifier.text);
|
|
921
921
|
}
|
|
922
|
+
function insidePlatformImplement(node, t) {
|
|
923
|
+
let cur = node.parent;
|
|
924
|
+
while (cur !== void 0) {
|
|
925
|
+
if (t.isCallExpression(cur) && t.isPropertyAccessExpression(cur.expression) && cur.expression.name.text === "implement") {
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
cur = cur.parent;
|
|
929
|
+
}
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
922
932
|
function isProcessEnv(node, t) {
|
|
923
933
|
return t.isPropertyAccessExpression(node) && t.isIdentifier(node.expression) && node.expression.text === "process" && node.name.text === "env";
|
|
924
934
|
}
|
|
@@ -941,6 +951,8 @@ var noCompileTimeDataInjection = {
|
|
|
941
951
|
}
|
|
942
952
|
if (insideBlockScope(node, ctx))
|
|
943
953
|
return;
|
|
954
|
+
if (insidePlatformImplement(node, t))
|
|
955
|
+
return;
|
|
944
956
|
if (isProcessEnv(node, t)) {
|
|
945
957
|
fire(ctx, node, "Reading `process.env` at module scope couples the deployed program to its build environment. Make it an `e3.input` / dataset parameter.");
|
|
946
958
|
return;
|
|
@@ -2083,6 +2095,95 @@ var noDuplicateDefinitionName = {
|
|
|
2083
2095
|
}
|
|
2084
2096
|
};
|
|
2085
2097
|
|
|
2098
|
+
// ../east-diagnostics/dist/src/rules/no-inline-credentials.js
|
|
2099
|
+
var NAME27 = "no-inline-credentials";
|
|
2100
|
+
var CODE27 = 990032;
|
|
2101
|
+
var CREDENTIAL_FIELDS = /* @__PURE__ */ new Set([
|
|
2102
|
+
"password",
|
|
2103
|
+
"passphrase",
|
|
2104
|
+
"privateKey",
|
|
2105
|
+
"secretAccessKey",
|
|
2106
|
+
"accessKeyId",
|
|
2107
|
+
"apiKey",
|
|
2108
|
+
"token",
|
|
2109
|
+
"accessToken",
|
|
2110
|
+
"refreshToken",
|
|
2111
|
+
"sessionToken",
|
|
2112
|
+
"secretKey",
|
|
2113
|
+
"clientSecret"
|
|
2114
|
+
]);
|
|
2115
|
+
var HOST_FIELDS = /* @__PURE__ */ new Set(["host", "hostname", "endpoint", "url", "server", "address"]);
|
|
2116
|
+
var LOCAL_HOSTS = ["localhost", "127.0.0.1", "::1"];
|
|
2117
|
+
function isStringy(node, t) {
|
|
2118
|
+
return t.isStringLiteral(node) || t.isNoSubstitutionTemplateLiteral(node);
|
|
2119
|
+
}
|
|
2120
|
+
function literalCredential(init2, t) {
|
|
2121
|
+
if (isStringy(init2, t) && init2.text.length > 0)
|
|
2122
|
+
return init2;
|
|
2123
|
+
if (!t.isCallExpression(init2))
|
|
2124
|
+
return void 0;
|
|
2125
|
+
const callee = init2.expression;
|
|
2126
|
+
const calleeName = t.isIdentifier(callee) ? callee.text : t.isPropertyAccessExpression(callee) ? callee.name.text : void 0;
|
|
2127
|
+
if (calleeName !== "some" && calleeName !== "variant")
|
|
2128
|
+
return void 0;
|
|
2129
|
+
const args = calleeName === "variant" ? init2.arguments.slice(1) : init2.arguments;
|
|
2130
|
+
for (const arg of args) {
|
|
2131
|
+
if (isStringy(arg, t) && arg.text.length > 0)
|
|
2132
|
+
return arg;
|
|
2133
|
+
}
|
|
2134
|
+
return void 0;
|
|
2135
|
+
}
|
|
2136
|
+
function mentionsLocalHost(node, t) {
|
|
2137
|
+
if (isStringy(node, t) && LOCAL_HOSTS.some((h) => node.text.includes(h)))
|
|
2138
|
+
return true;
|
|
2139
|
+
let found = false;
|
|
2140
|
+
t.forEachChild(node, (child) => {
|
|
2141
|
+
if (!found && mentionsLocalHost(child, t))
|
|
2142
|
+
found = true;
|
|
2143
|
+
});
|
|
2144
|
+
return found;
|
|
2145
|
+
}
|
|
2146
|
+
function targetsLocalHost(obj, t) {
|
|
2147
|
+
for (const prop of obj.properties) {
|
|
2148
|
+
if (!t.isPropertyAssignment(prop))
|
|
2149
|
+
continue;
|
|
2150
|
+
const name = t.isIdentifier(prop.name) || t.isStringLiteral(prop.name) ? prop.name.text : void 0;
|
|
2151
|
+
if (name !== void 0 && HOST_FIELDS.has(name) && mentionsLocalHost(prop.initializer, t))
|
|
2152
|
+
return true;
|
|
2153
|
+
}
|
|
2154
|
+
return false;
|
|
2155
|
+
}
|
|
2156
|
+
var noInlineCredentials = {
|
|
2157
|
+
name: NAME27,
|
|
2158
|
+
code: CODE27,
|
|
2159
|
+
description: "Flag literal string credentials (password, secretAccessKey, token, \u2026) in East/e3 source \u2014 use Env.get so the IR carries the variable name, not the secret.",
|
|
2160
|
+
check(node, ctx) {
|
|
2161
|
+
const t = ctx.ts;
|
|
2162
|
+
if (!t.isPropertyAssignment(node))
|
|
2163
|
+
return;
|
|
2164
|
+
const name = t.isIdentifier(node.name) || t.isStringLiteral(node.name) ? node.name.text : void 0;
|
|
2165
|
+
if (name === void 0 || !CREDENTIAL_FIELDS.has(name))
|
|
2166
|
+
return;
|
|
2167
|
+
if (!importsEastPackage(ctx.sourceFile, t))
|
|
2168
|
+
return;
|
|
2169
|
+
const literal = literalCredential(node.initializer, t);
|
|
2170
|
+
if (literal === void 0)
|
|
2171
|
+
return;
|
|
2172
|
+
if (t.isObjectLiteralExpression(node.parent) && targetsLocalHost(node.parent, t))
|
|
2173
|
+
return;
|
|
2174
|
+
const sf = ctx.sourceFile;
|
|
2175
|
+
const start = literal.getStart(sf);
|
|
2176
|
+
ctx.report({
|
|
2177
|
+
ruleName: NAME27,
|
|
2178
|
+
code: CODE27,
|
|
2179
|
+
start,
|
|
2180
|
+
length: literal.getEnd() - start,
|
|
2181
|
+
messageText: `Literal credential in \`${name}\` \u2014 East source compiles to content-addressed IR that is stored, exported, and replicated, so a secret here is effectively unredactable. Use \`Env.get("YOUR_VAR")\` (east-node-std) and supply the value per environment: your shell locally, the deployment's secret store in hosted runtimes.`,
|
|
2182
|
+
category: "warning"
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
};
|
|
2186
|
+
|
|
2086
2187
|
// ../east-diagnostics/dist/src/rules/index.js
|
|
2087
2188
|
var allRules = [
|
|
2088
2189
|
// East-side idiom hygiene (original set)
|
|
@@ -2115,7 +2216,9 @@ var allRules = [
|
|
|
2115
2216
|
noHandrolledValueTypeMirror,
|
|
2116
2217
|
noHostComparisonOnEastValues,
|
|
2117
2218
|
requireExampleReturns,
|
|
2118
|
-
noDuplicateDefinitionName
|
|
2219
|
+
noDuplicateDefinitionName,
|
|
2220
|
+
// secrets hygiene: IR is content-addressed and replicated — no literal creds
|
|
2221
|
+
noInlineCredentials
|
|
2119
2222
|
];
|
|
2120
2223
|
|
|
2121
2224
|
// ../east-diagnostics/dist/src/run.js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elaraai/tsserver-plugin-east",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.38",
|
|
4
4
|
"license": "AGPL-3.0-or-later",
|
|
5
5
|
"description": "TypeScript language service plugin for East — East idiom diagnostics and localized East type-diff error messages as native editor squiggles.",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"esbuild": "^0.27.3",
|
|
34
34
|
"typescript": "~5.9.2",
|
|
35
|
-
"@elaraai/east": "1.0.
|
|
36
|
-
"@elaraai/east-diagnostics": "1.0.
|
|
35
|
+
"@elaraai/east": "1.0.38",
|
|
36
|
+
"@elaraai/east-diagnostics": "1.0.38"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "node scripts/build.mjs",
|