eslint-plugin-firebase-ai-logic 1.3.0 → 1.4.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.js +1 -1
- package/dist/rules/check-temperature-defaults.d.ts +10 -4
- package/dist/rules/check-temperature-defaults.d.ts.map +1 -1
- package/dist/rules/check-temperature-defaults.js +39 -8
- package/dist/rules/check-temperature-defaults.js.map +1 -1
- package/dist/rules/prefer-count-tokens.d.ts +24 -0
- package/dist/rules/prefer-count-tokens.d.ts.map +1 -1
- package/dist/rules/prefer-count-tokens.js +29 -3
- package/dist/rules/prefer-count-tokens.js.map +1 -1
- package/dist/rules/prefer-optional-properties.d.ts +18 -0
- package/dist/rules/prefer-optional-properties.d.ts.map +1 -1
- package/dist/rules/prefer-optional-properties.js +30 -2
- package/dist/rules/prefer-optional-properties.js.map +1 -1
- package/dist/rules/require-app-check-production.d.ts +4 -0
- package/dist/rules/require-app-check-production.d.ts.map +1 -1
- package/dist/rules/require-app-check-production.js +60 -11
- package/dist/rules/require-app-check-production.js.map +1 -1
- package/dist/rules/require-error-handling.d.ts +3 -0
- package/dist/rules/require-error-handling.d.ts.map +1 -1
- package/dist/rules/require-error-handling.js +35 -2
- package/dist/rules/require-error-handling.js.map +1 -1
- package/dist/rules/validate-schema-structure.d.ts +5 -2
- package/dist/rules/validate-schema-structure.d.ts.map +1 -1
- package/dist/rules/validate-schema-structure.js +30 -6
- package/dist/rules/validate-schema-structure.js.map +1 -1
- package/dist/utils/ast-helpers.d.ts +4 -0
- package/dist/utils/ast-helpers.d.ts.map +1 -1
- package/dist/utils/ast-helpers.js +21 -0
- package/dist/utils/ast-helpers.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,20 +2,26 @@ import type { Rule } from 'eslint';
|
|
|
2
2
|
/**
|
|
3
3
|
* check-temperature-defaults
|
|
4
4
|
*
|
|
5
|
-
* This rule suggests using the default temperature (1.0) for Gemini models,
|
|
5
|
+
* This rule suggests using the default temperature (1.0) for Gemini 3 models,
|
|
6
6
|
* but with important exceptions:
|
|
7
7
|
*
|
|
8
|
+
* ONLY APPLIES TO:
|
|
9
|
+
* - gemini-3-flash-preview
|
|
10
|
+
* - gemini-3-pro-preview
|
|
11
|
+
* (Other models like gemini-2.5-* don't have this recommendation)
|
|
12
|
+
*
|
|
8
13
|
* EXCEPTIONS (low temperature is valid and recommended):
|
|
9
14
|
* 1. Structured output (responseMimeType: 'application/json')
|
|
10
15
|
* - Low temperature (0.1-0.3) prevents hallucinations in extraction tasks
|
|
11
|
-
* 2. Classification tasks
|
|
16
|
+
* 2. Classification tasks (maxOutputTokens <= 20)
|
|
12
17
|
* - Deterministic outputs benefit from low temperature
|
|
13
|
-
* 3. Data extraction
|
|
18
|
+
* 3. Data extraction with responseSchema
|
|
14
19
|
* - Precise extraction needs low temperature
|
|
15
20
|
*
|
|
16
21
|
* The rule only warns when:
|
|
22
|
+
* - Model is Gemini 3 (flash or pro preview)
|
|
17
23
|
* - Temperature is NOT 1.0
|
|
18
|
-
* - AND
|
|
24
|
+
* - AND it's NOT a structured output or classification task
|
|
19
25
|
*/
|
|
20
26
|
declare const rule: Rule.RuleModule;
|
|
21
27
|
export default rule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-temperature-defaults.d.ts","sourceRoot":"","sources":["../../src/rules/check-temperature-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"check-temperature-defaults.d.ts","sourceRoot":"","sources":["../../src/rules/check-temperature-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AASnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA4GhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -4,35 +4,48 @@ const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
|
4
4
|
/**
|
|
5
5
|
* check-temperature-defaults
|
|
6
6
|
*
|
|
7
|
-
* This rule suggests using the default temperature (1.0) for Gemini models,
|
|
7
|
+
* This rule suggests using the default temperature (1.0) for Gemini 3 models,
|
|
8
8
|
* but with important exceptions:
|
|
9
9
|
*
|
|
10
|
+
* ONLY APPLIES TO:
|
|
11
|
+
* - gemini-3-flash-preview
|
|
12
|
+
* - gemini-3-pro-preview
|
|
13
|
+
* (Other models like gemini-2.5-* don't have this recommendation)
|
|
14
|
+
*
|
|
10
15
|
* EXCEPTIONS (low temperature is valid and recommended):
|
|
11
16
|
* 1. Structured output (responseMimeType: 'application/json')
|
|
12
17
|
* - Low temperature (0.1-0.3) prevents hallucinations in extraction tasks
|
|
13
|
-
* 2. Classification tasks
|
|
18
|
+
* 2. Classification tasks (maxOutputTokens <= 20)
|
|
14
19
|
* - Deterministic outputs benefit from low temperature
|
|
15
|
-
* 3. Data extraction
|
|
20
|
+
* 3. Data extraction with responseSchema
|
|
16
21
|
* - Precise extraction needs low temperature
|
|
17
22
|
*
|
|
18
23
|
* The rule only warns when:
|
|
24
|
+
* - Model is Gemini 3 (flash or pro preview)
|
|
19
25
|
* - Temperature is NOT 1.0
|
|
20
|
-
* - AND
|
|
26
|
+
* - AND it's NOT a structured output or classification task
|
|
21
27
|
*/
|
|
22
28
|
const rule = {
|
|
23
29
|
meta: {
|
|
24
30
|
type: 'suggestion',
|
|
25
31
|
docs: {
|
|
26
|
-
description: 'Suggest default temperature (1.0) for Gemini models, except for structured output tasks',
|
|
32
|
+
description: 'Suggest default temperature (1.0) for Gemini 3 models, except for structured output and classification tasks',
|
|
27
33
|
recommended: true,
|
|
28
34
|
url: 'https://github.com/Just-mpm/eslint-plugin-firebase-ai-logic#check-temperature-defaults',
|
|
29
35
|
},
|
|
30
36
|
schema: [],
|
|
31
37
|
messages: {
|
|
32
|
-
nonDefaultTemperature: 'Consider using the default temperature (1.0) for Gemini models. Lower values may cause looping or degraded reasoning. Exception: low temperature
|
|
38
|
+
nonDefaultTemperature: 'Consider using the default temperature (1.0) for Gemini 3 models. Lower values may cause looping or degraded reasoning. Exception: low temperature is appropriate for structured output (JSON) and classification tasks.',
|
|
33
39
|
},
|
|
34
40
|
},
|
|
35
41
|
create(context) {
|
|
42
|
+
// Gemini 3 models that have the temperature=1.0 recommendation
|
|
43
|
+
const GEMINI_3_MODELS = [
|
|
44
|
+
'gemini-3-flash-preview',
|
|
45
|
+
'gemini-3-pro-preview',
|
|
46
|
+
'gemini-3-flash',
|
|
47
|
+
'gemini-3-pro',
|
|
48
|
+
];
|
|
36
49
|
return {
|
|
37
50
|
CallExpression(node) {
|
|
38
51
|
const calleeName = (0, ast_helpers_js_1.getCalleeName)(node);
|
|
@@ -45,9 +58,18 @@ const rule = {
|
|
|
45
58
|
const configArg = node.arguments[1];
|
|
46
59
|
if (!configArg || !(0, ast_helpers_js_1.isObjectExpression)(configArg))
|
|
47
60
|
return;
|
|
61
|
+
// Check model name - only apply to Gemini 3 models
|
|
62
|
+
const modelProp = (0, ast_helpers_js_1.findProperty)(configArg, 'model');
|
|
63
|
+
if (modelProp) {
|
|
64
|
+
const modelName = (0, ast_helpers_js_1.getStringValue)(modelProp.value);
|
|
65
|
+
if (modelName && !GEMINI_3_MODELS.some(m => modelName.includes(m))) {
|
|
66
|
+
// Not a Gemini 3 model - don't apply this rule
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
48
70
|
// Check for generationConfig
|
|
49
|
-
|
|
50
|
-
|
|
71
|
+
const generationConfig = (0, ast_helpers_js_1.findProperty)(configArg, 'generationConfig');
|
|
72
|
+
const configToCheck = generationConfig
|
|
51
73
|
? generationConfig.value
|
|
52
74
|
: configArg;
|
|
53
75
|
if (!(0, ast_helpers_js_1.isObjectExpression)(configToCheck))
|
|
@@ -67,6 +89,15 @@ const rule = {
|
|
|
67
89
|
// Has response schema - structured output, don't warn
|
|
68
90
|
return;
|
|
69
91
|
}
|
|
92
|
+
// Check for maxOutputTokens - if very low (<= 20), it's likely classification
|
|
93
|
+
const maxOutputTokensProp = (0, ast_helpers_js_1.findProperty)(configToCheck, 'maxOutputTokens');
|
|
94
|
+
if (maxOutputTokensProp) {
|
|
95
|
+
const maxTokens = (0, ast_helpers_js_1.getNumberValue)(maxOutputTokensProp.value);
|
|
96
|
+
if (maxTokens !== null && maxTokens <= 20) {
|
|
97
|
+
// Classification task (very short output) - low temperature is appropriate
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
70
101
|
// Check for temperature property
|
|
71
102
|
const temperatureProp = (0, ast_helpers_js_1.findProperty)(configToCheck, 'temperature');
|
|
72
103
|
if (temperatureProp) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-temperature-defaults.js","sourceRoot":"","sources":["../../src/rules/check-temperature-defaults.ts"],"names":[],"mappings":";;AACA,
|
|
1
|
+
{"version":3,"file":"check-temperature-defaults.js","sourceRoot":"","sources":["../../src/rules/check-temperature-defaults.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* prefer-count-tokens
|
|
4
|
+
*
|
|
5
|
+
* This rule suggests using countTokens() before large requests.
|
|
6
|
+
*
|
|
7
|
+
* WHY 2000 CHARACTERS DEFAULT?
|
|
8
|
+
* - 2000 chars ≈ 500 tokens (roughly 4 chars per token)
|
|
9
|
+
* - Cost increases significantly above 200K tokens context
|
|
10
|
+
* - countTokens API is FREE and has 3000 RPM quota
|
|
11
|
+
* - Below 500 tokens, the cost impact is minimal (~$0.0001 for flash)
|
|
12
|
+
*
|
|
13
|
+
* Based on Google's pricing:
|
|
14
|
+
* - Gemini 2.5 Flash-Lite: $0.10/M input tokens
|
|
15
|
+
* - Gemini 2.5 Flash: $0.15/M input tokens
|
|
16
|
+
* - Gemini 3 Pro: $2.00/M input tokens (up to 200K), $4.00/M above
|
|
17
|
+
*
|
|
18
|
+
* The rule is meant to catch large prompts that could:
|
|
19
|
+
* 1. Unexpectedly increase costs
|
|
20
|
+
* 2. Risk exceeding context window limits
|
|
21
|
+
* 3. Benefit from cost estimation before sending
|
|
22
|
+
*
|
|
23
|
+
* @see https://ai.google.dev/gemini-api/docs/tokens
|
|
24
|
+
* @see https://ai.google.dev/gemini-api/docs/pricing
|
|
25
|
+
*/
|
|
2
26
|
declare const rule: Rule.RuleModule;
|
|
3
27
|
export default rule;
|
|
4
28
|
//# sourceMappingURL=prefer-count-tokens.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-count-tokens.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-count-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"prefer-count-tokens.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-count-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA4HhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
4
|
+
/**
|
|
5
|
+
* prefer-count-tokens
|
|
6
|
+
*
|
|
7
|
+
* This rule suggests using countTokens() before large requests.
|
|
8
|
+
*
|
|
9
|
+
* WHY 2000 CHARACTERS DEFAULT?
|
|
10
|
+
* - 2000 chars ≈ 500 tokens (roughly 4 chars per token)
|
|
11
|
+
* - Cost increases significantly above 200K tokens context
|
|
12
|
+
* - countTokens API is FREE and has 3000 RPM quota
|
|
13
|
+
* - Below 500 tokens, the cost impact is minimal (~$0.0001 for flash)
|
|
14
|
+
*
|
|
15
|
+
* Based on Google's pricing:
|
|
16
|
+
* - Gemini 2.5 Flash-Lite: $0.10/M input tokens
|
|
17
|
+
* - Gemini 2.5 Flash: $0.15/M input tokens
|
|
18
|
+
* - Gemini 3 Pro: $2.00/M input tokens (up to 200K), $4.00/M above
|
|
19
|
+
*
|
|
20
|
+
* The rule is meant to catch large prompts that could:
|
|
21
|
+
* 1. Unexpectedly increase costs
|
|
22
|
+
* 2. Risk exceeding context window limits
|
|
23
|
+
* 3. Benefit from cost estimation before sending
|
|
24
|
+
*
|
|
25
|
+
* @see https://ai.google.dev/gemini-api/docs/tokens
|
|
26
|
+
* @see https://ai.google.dev/gemini-api/docs/pricing
|
|
27
|
+
*/
|
|
4
28
|
const rule = {
|
|
5
29
|
meta: {
|
|
6
30
|
type: 'suggestion',
|
|
@@ -15,8 +39,8 @@ const rule = {
|
|
|
15
39
|
properties: {
|
|
16
40
|
promptLengthThreshold: {
|
|
17
41
|
type: 'number',
|
|
18
|
-
default:
|
|
19
|
-
description: 'Character length threshold to suggest token counting',
|
|
42
|
+
default: 2000,
|
|
43
|
+
description: 'Character length threshold to suggest token counting (default: 2000 chars ≈ 500 tokens)',
|
|
20
44
|
},
|
|
21
45
|
},
|
|
22
46
|
additionalProperties: false,
|
|
@@ -29,7 +53,9 @@ const rule = {
|
|
|
29
53
|
},
|
|
30
54
|
create(context) {
|
|
31
55
|
const options = context.options[0] ?? {};
|
|
32
|
-
|
|
56
|
+
// Default threshold: 2000 chars ≈ 500 tokens
|
|
57
|
+
// This is a reasonable threshold where token counting becomes useful
|
|
58
|
+
const promptLengthThreshold = options.promptLengthThreshold ?? 2000;
|
|
33
59
|
// Track if countTokens was called in the same scope
|
|
34
60
|
const scopesWithCountTokens = new Set();
|
|
35
61
|
function getScopeKey(node) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-count-tokens.js","sourceRoot":"","sources":["../../src/rules/prefer-count-tokens.ts"],"names":[],"mappings":";;AACA,4DAAwE;AAExE,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,+FAA+F;YACjG,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,iFAAiF;SACvF;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,qBAAqB,EAAE;wBACrB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prefer-count-tokens.js","sourceRoot":"","sources":["../../src/rules/prefer-count-tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* prefer-optional-properties
|
|
4
|
+
*
|
|
5
|
+
* This rule suggests using 'optionalProperties' array for optional fields,
|
|
6
|
+
* but with important exceptions:
|
|
7
|
+
*
|
|
8
|
+
* EXCEPTIONS (no warning):
|
|
9
|
+
* 1. If the schema has a 'required' array defined
|
|
10
|
+
* - This is the standard way to define required fields in function calling
|
|
11
|
+
* - Fields not in 'required' are implicitly optional
|
|
12
|
+
* 2. If the schema is for function calling parameters
|
|
13
|
+
* - Function calling uses 'required' array pattern
|
|
14
|
+
*
|
|
15
|
+
* The rule only warns when:
|
|
16
|
+
* - Schema has many properties (>5)
|
|
17
|
+
* - AND no 'optionalProperties' array
|
|
18
|
+
* - AND no 'required' array (which would indicate intent)
|
|
19
|
+
*/
|
|
2
20
|
declare const rule: Rule.RuleModule;
|
|
3
21
|
export default rule;
|
|
4
22
|
//# sourceMappingURL=prefer-optional-properties.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-optional-properties.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-optional-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAQnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"prefer-optional-properties.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-optional-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAQnC;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAqHhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
4
|
+
/**
|
|
5
|
+
* prefer-optional-properties
|
|
6
|
+
*
|
|
7
|
+
* This rule suggests using 'optionalProperties' array for optional fields,
|
|
8
|
+
* but with important exceptions:
|
|
9
|
+
*
|
|
10
|
+
* EXCEPTIONS (no warning):
|
|
11
|
+
* 1. If the schema has a 'required' array defined
|
|
12
|
+
* - This is the standard way to define required fields in function calling
|
|
13
|
+
* - Fields not in 'required' are implicitly optional
|
|
14
|
+
* 2. If the schema is for function calling parameters
|
|
15
|
+
* - Function calling uses 'required' array pattern
|
|
16
|
+
*
|
|
17
|
+
* The rule only warns when:
|
|
18
|
+
* - Schema has many properties (>5)
|
|
19
|
+
* - AND no 'optionalProperties' array
|
|
20
|
+
* - AND no 'required' array (which would indicate intent)
|
|
21
|
+
*/
|
|
4
22
|
const rule = {
|
|
5
23
|
meta: {
|
|
6
24
|
type: 'suggestion',
|
|
@@ -13,7 +31,7 @@ const rule = {
|
|
|
13
31
|
messages: {
|
|
14
32
|
useOptionalProperties: "In Firebase AI Logic, all schema fields are required by default. Use 'optionalProperties: [\"fieldName\"]' array to mark fields as optional.",
|
|
15
33
|
nullableNotOptional: "Using 'nullable: true' makes the field accept null but still requires it. Use 'optionalProperties' array to make it truly optional.",
|
|
16
|
-
missingOptionalProperties: "Schema has many properties but no 'optionalProperties' array. Consider which fields should be optional.",
|
|
34
|
+
missingOptionalProperties: "Schema has many properties but no 'optionalProperties' or 'required' array. Consider which fields should be optional.",
|
|
17
35
|
},
|
|
18
36
|
},
|
|
19
37
|
create(context) {
|
|
@@ -22,6 +40,12 @@ const rule = {
|
|
|
22
40
|
return;
|
|
23
41
|
const propertiesProp = (0, ast_helpers_js_1.findProperty)(obj, 'properties');
|
|
24
42
|
const optionalPropertiesProp = (0, ast_helpers_js_1.findProperty)(obj, 'optionalProperties');
|
|
43
|
+
const requiredProp = (0, ast_helpers_js_1.findProperty)(obj, 'required');
|
|
44
|
+
// If 'required' array is defined, the developer has explicitly chosen
|
|
45
|
+
// which fields are required - no need to warn about optionalProperties
|
|
46
|
+
if (requiredProp) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
25
49
|
// Check for nullable fields without optionalProperties
|
|
26
50
|
if (propertiesProp && (0, ast_helpers_js_1.isObjectExpression)(propertiesProp.value)) {
|
|
27
51
|
const propsObj = propertiesProp.value;
|
|
@@ -55,7 +79,11 @@ const rule = {
|
|
|
55
79
|
// Check if schema has many properties but no optionalProperties
|
|
56
80
|
if (propertiesProp && (0, ast_helpers_js_1.isObjectExpression)(propertiesProp.value)) {
|
|
57
81
|
const propertyCount = propertiesProp.value.properties.filter(ast_helpers_js_1.isProperty).length;
|
|
58
|
-
|
|
82
|
+
// Only warn if:
|
|
83
|
+
// - Many properties (>5)
|
|
84
|
+
// - No optionalProperties
|
|
85
|
+
// - No required array (which indicates intentional field selection)
|
|
86
|
+
if (propertyCount > 5 && !optionalPropertiesProp && !requiredProp) {
|
|
59
87
|
context.report({
|
|
60
88
|
node: obj,
|
|
61
89
|
messageId: 'missingOptionalProperties',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-optional-properties.js","sourceRoot":"","sources":["../../src/rules/prefer-optional-properties.ts"],"names":[],"mappings":";;AACA,4DAKiC;AAEjC,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,oGAAoG;YACtG,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,wFAAwF;SAC9F;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,qBAAqB,EACnB,8IAA8I;YAChJ,mBAAmB,EACjB,qIAAqI;YACvI,yBAAyB,EACvB,
|
|
1
|
+
{"version":3,"file":"prefer-optional-properties.js","sourceRoot":"","sources":["../../src/rules/prefer-optional-properties.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,8 +13,12 @@ import type { Rule } from 'eslint';
|
|
|
13
13
|
* 1. Direct import of 'firebase/app-check'
|
|
14
14
|
* 2. Calls to initializeAppCheck()
|
|
15
15
|
* 3. Common patterns: useAppCheck, ensureAppCheckReady, AppCheckProvider
|
|
16
|
+
* 4. Module-level detection: If the file imports from a module that handles AI
|
|
17
|
+
* (like './ai' or '../firebase/ai'), it's likely App Check is handled there
|
|
16
18
|
*
|
|
17
19
|
* If none are found in the same file as getAI(), it suggests (not requires) App Check.
|
|
20
|
+
*
|
|
21
|
+
* CONFIGURABLE: Set 'ignoreFiles' to skip specific files/patterns.
|
|
18
22
|
*/
|
|
19
23
|
declare const rule: Rule.RuleModule;
|
|
20
24
|
export default rule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-app-check-production.d.ts","sourceRoot":"","sources":["../../src/rules/require-app-check-production.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC
|
|
1
|
+
{"version":3,"file":"require-app-check-production.d.ts","sourceRoot":"","sources":["../../src/rules/require-app-check-production.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA0JhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -15,8 +15,12 @@ const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
|
15
15
|
* 1. Direct import of 'firebase/app-check'
|
|
16
16
|
* 2. Calls to initializeAppCheck()
|
|
17
17
|
* 3. Common patterns: useAppCheck, ensureAppCheckReady, AppCheckProvider
|
|
18
|
+
* 4. Module-level detection: If the file imports from a module that handles AI
|
|
19
|
+
* (like './ai' or '../firebase/ai'), it's likely App Check is handled there
|
|
18
20
|
*
|
|
19
21
|
* If none are found in the same file as getAI(), it suggests (not requires) App Check.
|
|
22
|
+
*
|
|
23
|
+
* CONFIGURABLE: Set 'ignoreFiles' to skip specific files/patterns.
|
|
20
24
|
*/
|
|
21
25
|
const rule = {
|
|
22
26
|
meta: {
|
|
@@ -26,7 +30,20 @@ const rule = {
|
|
|
26
30
|
recommended: true,
|
|
27
31
|
url: 'https://github.com/Just-mpm/eslint-plugin-firebase-ai-logic#require-app-check-production',
|
|
28
32
|
},
|
|
29
|
-
schema: [
|
|
33
|
+
schema: [
|
|
34
|
+
{
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
ignoreFiles: {
|
|
38
|
+
type: 'array',
|
|
39
|
+
items: { type: 'string' },
|
|
40
|
+
default: [],
|
|
41
|
+
description: 'File patterns to ignore (e.g., "*.test.ts", "test/**/*")',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
30
47
|
messages: {
|
|
31
48
|
missingAppCheck: 'Consider using App Check to protect your AI endpoints from abuse. If you use lazy loading (useAppCheck, ensureAppCheckReady) in a separate file, you can safely ignore this warning.',
|
|
32
49
|
appCheckSuggestion: "import { initializeAppCheck, ReCaptchaEnterpriseProvider } from 'firebase/app-check'; initializeAppCheck(app, { provider: new ReCaptchaEnterpriseProvider('SITE_KEY') });",
|
|
@@ -38,6 +55,7 @@ const rule = {
|
|
|
38
55
|
let hasAppCheckHelper = false;
|
|
39
56
|
let hasAIInit = false;
|
|
40
57
|
let aiInitNode = null;
|
|
58
|
+
let importsFromAIModule = false;
|
|
41
59
|
// Common App Check helper patterns used in lazy loading
|
|
42
60
|
const appCheckHelperPatterns = [
|
|
43
61
|
'useAppCheck',
|
|
@@ -46,28 +64,52 @@ const rule = {
|
|
|
46
64
|
'getAppCheckInstance',
|
|
47
65
|
'isAppCheckReady',
|
|
48
66
|
'initializeAppCheckLazy',
|
|
67
|
+
'withAppCheck',
|
|
68
|
+
'appCheckReady',
|
|
69
|
+
];
|
|
70
|
+
// Common AI module patterns where App Check might be configured
|
|
71
|
+
const aiModulePatterns = [
|
|
72
|
+
'/ai',
|
|
73
|
+
'/firebase/ai',
|
|
74
|
+
'/lib/ai',
|
|
75
|
+
'/services/ai',
|
|
76
|
+
'getAIInstance',
|
|
77
|
+
'aiService',
|
|
49
78
|
];
|
|
50
79
|
return {
|
|
51
80
|
// Track App Check imports
|
|
52
81
|
ImportDeclaration(node) {
|
|
53
82
|
const source = node.source.value;
|
|
83
|
+
if (typeof source !== 'string')
|
|
84
|
+
return;
|
|
54
85
|
// Direct firebase/app-check import
|
|
55
86
|
if (source === 'firebase/app-check') {
|
|
56
87
|
hasAppCheckImport = true;
|
|
57
88
|
}
|
|
58
89
|
// Check for imports from common App Check helper files/hooks
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
source.includes('appCheck'))) {
|
|
90
|
+
if (source.includes('useAppCheck') ||
|
|
91
|
+
source.includes('AppCheck') ||
|
|
92
|
+
source.includes('appCheck')) {
|
|
63
93
|
hasAppCheckHelper = true;
|
|
64
94
|
}
|
|
95
|
+
// Check if importing from a common AI module pattern
|
|
96
|
+
// These modules typically handle App Check internally
|
|
97
|
+
if (aiModulePatterns.some((pattern) => source.includes(pattern))) {
|
|
98
|
+
importsFromAIModule = true;
|
|
99
|
+
}
|
|
65
100
|
// Check imported specifiers for App Check helpers
|
|
66
101
|
for (const spec of node.specifiers) {
|
|
67
102
|
if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
|
|
68
|
-
|
|
103
|
+
const importedName = spec.imported.name;
|
|
104
|
+
if (appCheckHelperPatterns.includes(importedName)) {
|
|
69
105
|
hasAppCheckHelper = true;
|
|
70
106
|
}
|
|
107
|
+
// Check if importing getAIInstance or similar from another module
|
|
108
|
+
if (importedName === 'getAIInstance' ||
|
|
109
|
+
importedName === 'getAI' ||
|
|
110
|
+
importedName === 'aiInstance') {
|
|
111
|
+
importsFromAIModule = true;
|
|
112
|
+
}
|
|
71
113
|
}
|
|
72
114
|
}
|
|
73
115
|
},
|
|
@@ -84,16 +126,23 @@ const rule = {
|
|
|
84
126
|
if (appCheckHelperPatterns.includes(calleeName)) {
|
|
85
127
|
hasAppCheckHelper = true;
|
|
86
128
|
}
|
|
87
|
-
// Track getAI calls
|
|
129
|
+
// Track getAI calls - but only if it's a DIRECT call, not imported wrapper
|
|
88
130
|
if (calleeName === 'getAI') {
|
|
89
|
-
|
|
90
|
-
|
|
131
|
+
// Check if this is the actual firebase/ai getAI or a wrapper
|
|
132
|
+
// If we already import from an AI module, the App Check is likely handled there
|
|
133
|
+
if (!importsFromAIModule) {
|
|
134
|
+
hasAIInit = true;
|
|
135
|
+
aiInitNode = node;
|
|
136
|
+
}
|
|
91
137
|
}
|
|
92
138
|
},
|
|
93
139
|
// Check at the end of the program
|
|
94
140
|
'Program:exit'() {
|
|
95
|
-
// Only suggest if
|
|
96
|
-
|
|
141
|
+
// Only suggest if:
|
|
142
|
+
// 1. AI is being used directly (not via imported wrapper)
|
|
143
|
+
// 2. No App Check patterns found
|
|
144
|
+
// 3. Not importing from a module that likely handles App Check
|
|
145
|
+
const hasAnyAppCheckPattern = hasAppCheckImport || hasAppCheckInit || hasAppCheckHelper || importsFromAIModule;
|
|
97
146
|
if (hasAIInit && !hasAnyAppCheckPattern && aiInitNode) {
|
|
98
147
|
context.report({
|
|
99
148
|
node: aiInitNode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-app-check-production.js","sourceRoot":"","sources":["../../src/rules/require-app-check-production.ts"],"names":[],"mappings":";;AACA,4DAAwD;AAExD
|
|
1
|
+
{"version":3,"file":"require-app-check-production.js","sourceRoot":"","sources":["../../src/rules/require-app-check-production.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,11 +14,14 @@ import type { Rule } from 'eslint';
|
|
|
14
14
|
* - safeCall
|
|
15
15
|
* - handleApiCall
|
|
16
16
|
* - executeWithRetry
|
|
17
|
+
* 5. Async generators (errors propagate to consumer's try/catch)
|
|
18
|
+
* 6. Class methods that are async generators
|
|
17
19
|
*
|
|
18
20
|
* The rule checks if the API call is:
|
|
19
21
|
* - Inside a try/catch block
|
|
20
22
|
* - Chained with .catch()
|
|
21
23
|
* - Wrapped in a known error-handling function
|
|
24
|
+
* - Inside an async generator (errors propagate to consumer)
|
|
22
25
|
*/
|
|
23
26
|
declare const rule: Rule.RuleModule;
|
|
24
27
|
export default rule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-error-handling.d.ts","sourceRoot":"","sources":["../../src/rules/require-error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC
|
|
1
|
+
{"version":3,"file":"require-error-handling.d.ts","sourceRoot":"","sources":["../../src/rules/require-error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA6MhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -16,11 +16,14 @@ const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
|
16
16
|
* - safeCall
|
|
17
17
|
* - handleApiCall
|
|
18
18
|
* - executeWithRetry
|
|
19
|
+
* 5. Async generators (errors propagate to consumer's try/catch)
|
|
20
|
+
* 6. Class methods that are async generators
|
|
19
21
|
*
|
|
20
22
|
* The rule checks if the API call is:
|
|
21
23
|
* - Inside a try/catch block
|
|
22
24
|
* - Chained with .catch()
|
|
23
25
|
* - Wrapped in a known error-handling function
|
|
26
|
+
* - Inside an async generator (errors propagate to consumer)
|
|
24
27
|
*/
|
|
25
28
|
const rule = {
|
|
26
29
|
meta: {
|
|
@@ -125,6 +128,34 @@ const rule = {
|
|
|
125
128
|
}
|
|
126
129
|
return false;
|
|
127
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if the call is inside an async generator function.
|
|
133
|
+
* Async generators propagate errors to the consumer's for-await-of loop,
|
|
134
|
+
* where they can be caught in a try/catch block. This is a valid error
|
|
135
|
+
* handling pattern.
|
|
136
|
+
*/
|
|
137
|
+
function isInsideAsyncGenerator(node) {
|
|
138
|
+
let current = node.parent;
|
|
139
|
+
while (current) {
|
|
140
|
+
// Check for async generator functions (function* or async function*)
|
|
141
|
+
if (current.type === 'FunctionDeclaration' ||
|
|
142
|
+
current.type === 'FunctionExpression') {
|
|
143
|
+
const funcNode = current;
|
|
144
|
+
if (funcNode.async && funcNode.generator) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Check for async generator method definitions in classes
|
|
149
|
+
if (current.type === 'MethodDefinition') {
|
|
150
|
+
const methodNode = current;
|
|
151
|
+
if (methodNode.value?.async && methodNode.value?.generator) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
current = current.parent || null;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
128
159
|
return {
|
|
129
160
|
CallExpression(node) {
|
|
130
161
|
const calleeName = (0, ast_helpers_js_1.getCalleeName)(node);
|
|
@@ -133,10 +164,12 @@ const rule = {
|
|
|
133
164
|
}
|
|
134
165
|
// Check if this is an awaited call
|
|
135
166
|
const isAwaited = node.parent?.type === 'AwaitExpression';
|
|
136
|
-
// Check if inside try/catch, has .catch(),
|
|
167
|
+
// Check if inside try/catch, has .catch(), inside error handling wrapper,
|
|
168
|
+
// or inside an async generator (which propagates errors to consumer)
|
|
137
169
|
const hasErrorHandling = isInsideTryCatch(node) ||
|
|
138
170
|
isInsideAsyncErrorBoundary(node) ||
|
|
139
|
-
isInsideErrorHandlingWrapper(node)
|
|
171
|
+
isInsideErrorHandlingWrapper(node) ||
|
|
172
|
+
isInsideAsyncGenerator(node);
|
|
140
173
|
if (!hasErrorHandling) {
|
|
141
174
|
context.report({
|
|
142
175
|
node,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-error-handling.js","sourceRoot":"","sources":["../../src/rules/require-error-handling.ts"],"names":[],"mappings":";;AACA,4DAAwD;AAExD
|
|
1
|
+
{"version":3,"file":"require-error-handling.js","sourceRoot":"","sources":["../../src/rules/require-error-handling.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,8 +12,11 @@ import type { Rule } from 'eslint';
|
|
|
12
12
|
* This rule should NOT report errors for using "required" in Schema.object()
|
|
13
13
|
* because it's a valid and common pattern for function calling parameters.
|
|
14
14
|
*
|
|
15
|
-
* The rule now only warns
|
|
16
|
-
* in the same schema
|
|
15
|
+
* The rule now only suggests (not warns) when using BOTH "required" AND
|
|
16
|
+
* "optionalProperties" in the same schema - which while redundant, is
|
|
17
|
+
* technically valid and can improve code clarity.
|
|
18
|
+
*
|
|
19
|
+
* CONFIGURABLE: Set 'allowBothRequiredAndOptional' to true to disable this check.
|
|
17
20
|
*/
|
|
18
21
|
declare const rule: Rule.RuleModule;
|
|
19
22
|
export default rule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-schema-structure.d.ts","sourceRoot":"","sources":["../../src/rules/validate-schema-structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC
|
|
1
|
+
{"version":3,"file":"validate-schema-structure.d.ts","sourceRoot":"","sources":["../../src/rules/validate-schema-structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA6DhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -14,8 +14,11 @@ const ast_helpers_js_1 = require("../utils/ast-helpers.js");
|
|
|
14
14
|
* This rule should NOT report errors for using "required" in Schema.object()
|
|
15
15
|
* because it's a valid and common pattern for function calling parameters.
|
|
16
16
|
*
|
|
17
|
-
* The rule now only warns
|
|
18
|
-
* in the same schema
|
|
17
|
+
* The rule now only suggests (not warns) when using BOTH "required" AND
|
|
18
|
+
* "optionalProperties" in the same schema - which while redundant, is
|
|
19
|
+
* technically valid and can improve code clarity.
|
|
20
|
+
*
|
|
21
|
+
* CONFIGURABLE: Set 'allowBothRequiredAndOptional' to true to disable this check.
|
|
19
22
|
*/
|
|
20
23
|
const rule = {
|
|
21
24
|
meta: {
|
|
@@ -25,23 +28,44 @@ const rule = {
|
|
|
25
28
|
recommended: true,
|
|
26
29
|
url: 'https://github.com/Just-mpm/eslint-plugin-firebase-ai-logic#validate-schema-structure',
|
|
27
30
|
},
|
|
28
|
-
schema: [
|
|
31
|
+
schema: [
|
|
32
|
+
{
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
allowBothRequiredAndOptional: {
|
|
36
|
+
type: 'boolean',
|
|
37
|
+
default: false,
|
|
38
|
+
description: 'Allow using both "required" and "optionalProperties" in the same schema',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
29
44
|
messages: {
|
|
30
|
-
redundantBothRequiredAndOptional: 'Schema has both "required" and "optionalProperties".
|
|
45
|
+
redundantBothRequiredAndOptional: 'Schema has both "required" and "optionalProperties". This is valid but redundant - consider using only one approach for clarity.',
|
|
31
46
|
},
|
|
32
47
|
},
|
|
33
48
|
create(context) {
|
|
49
|
+
const options = context.options[0] ?? {};
|
|
50
|
+
const allowBothRequiredAndOptional = options.allowBothRequiredAndOptional ?? false;
|
|
34
51
|
return {
|
|
35
52
|
// Check for objects that have BOTH required AND optionalProperties
|
|
36
53
|
ObjectExpression(node) {
|
|
54
|
+
// Skip if configured to allow both
|
|
55
|
+
if (allowBothRequiredAndOptional)
|
|
56
|
+
return;
|
|
37
57
|
const hasRequired = (0, ast_helpers_js_1.findProperty)(node, 'required');
|
|
38
58
|
const hasOptionalProperties = (0, ast_helpers_js_1.findProperty)(node, 'optionalProperties');
|
|
39
59
|
const hasProperties = (0, ast_helpers_js_1.findProperty)(node, 'properties');
|
|
40
60
|
// Only check if this looks like a schema definition
|
|
41
61
|
if (!hasProperties)
|
|
42
62
|
return;
|
|
43
|
-
// Only
|
|
44
|
-
|
|
63
|
+
// Only suggest if BOTH are present (redundant but valid)
|
|
64
|
+
// Make sure they're both arrays (not just properties with those names)
|
|
65
|
+
if (hasRequired &&
|
|
66
|
+
hasOptionalProperties &&
|
|
67
|
+
(0, ast_helpers_js_1.isArrayExpression)(hasRequired.value) &&
|
|
68
|
+
(0, ast_helpers_js_1.isArrayExpression)(hasOptionalProperties.value)) {
|
|
45
69
|
context.report({
|
|
46
70
|
node: hasOptionalProperties.key,
|
|
47
71
|
messageId: 'redundantBothRequiredAndOptional',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-schema-structure.js","sourceRoot":"","sources":["../../src/rules/validate-schema-structure.ts"],"names":[],"mappings":";;AACA,
|
|
1
|
+
{"version":3,"file":"validate-schema-structure.js","sourceRoot":"","sources":["../../src/rules/validate-schema-structure.ts"],"names":[],"mappings":";;AACA,4DAA0E;AAE1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,+DAA+D;YACjE,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,uFAAuF;SAC7F;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,4BAA4B,EAAE;wBAC5B,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,KAAK;wBACd,WAAW,EAAE,yEAAyE;qBACvF;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,gCAAgC,EAC9B,kIAAkI;SACrI;KACF;IAED,MAAM,CAAC,OAAO;QACZ,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,MAAM,4BAA4B,GAAG,OAAO,CAAC,4BAA4B,IAAI,KAAK,CAAC;QAEnF,OAAO;YACL,mEAAmE;YACnE,gBAAgB,CAAC,IAAI;gBACnB,mCAAmC;gBACnC,IAAI,4BAA4B;oBAAE,OAAO;gBAEzC,MAAM,WAAW,GAAG,IAAA,6BAAY,EAAC,IAAI,EAAE,UAAU,CAAC,CAAC;gBACnD,MAAM,qBAAqB,GAAG,IAAA,6BAAY,EAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;gBACvE,MAAM,aAAa,GAAG,IAAA,6BAAY,EAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBAEvD,oDAAoD;gBACpD,IAAI,CAAC,aAAa;oBAAE,OAAO;gBAE3B,yDAAyD;gBACzD,uEAAuE;gBACvE,IACE,WAAW;oBACX,qBAAqB;oBACrB,IAAA,kCAAiB,EAAC,WAAW,CAAC,KAAK,CAAC;oBACpC,IAAA,kCAAiB,EAAC,qBAAqB,CAAC,KAAK,CAAC,EAC9C,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,qBAAqB,CAAC,GAAG;wBAC/B,SAAS,EAAE,kCAAkC;qBAC9C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,kBAAe,IAAI,CAAC"}
|
|
@@ -14,6 +14,10 @@ export declare function isTemplateLiteral(node: Node | null | undefined): node i
|
|
|
14
14
|
* Get string value from a literal or template literal
|
|
15
15
|
*/
|
|
16
16
|
export declare function getStringValue(node: Node | null | undefined): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Get number value from a literal node
|
|
19
|
+
*/
|
|
20
|
+
export declare function getNumberValue(node: Node | null | undefined): number | null;
|
|
17
21
|
/**
|
|
18
22
|
* Check if a node is an identifier with a specific name
|
|
19
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ast-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.isStringLiteral = isStringLiteral;
|
|
4
4
|
exports.isTemplateLiteral = isTemplateLiteral;
|
|
5
5
|
exports.getStringValue = getStringValue;
|
|
6
|
+
exports.getNumberValue = getNumberValue;
|
|
6
7
|
exports.isIdentifier = isIdentifier;
|
|
7
8
|
exports.isCallExpression = isCallExpression;
|
|
8
9
|
exports.isNewExpression = isNewExpression;
|
|
@@ -46,6 +47,26 @@ function getStringValue(node) {
|
|
|
46
47
|
}
|
|
47
48
|
return null;
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Get number value from a literal node
|
|
52
|
+
*/
|
|
53
|
+
function getNumberValue(node) {
|
|
54
|
+
if (!node)
|
|
55
|
+
return null;
|
|
56
|
+
if (node.type === 'Literal' && typeof node.value === 'number') {
|
|
57
|
+
return node.value;
|
|
58
|
+
}
|
|
59
|
+
// Handle negative numbers (UnaryExpression with '-' operator)
|
|
60
|
+
if (node.type === 'UnaryExpression' &&
|
|
61
|
+
node.operator === '-' &&
|
|
62
|
+
node.argument.type === 'Literal') {
|
|
63
|
+
const literal = node.argument;
|
|
64
|
+
if (typeof literal.value === 'number') {
|
|
65
|
+
return -literal.value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
49
70
|
/**
|
|
50
71
|
* Check if a node is an identifier with a specific name
|
|
51
72
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-helpers.js","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":";;AAMA,0CAEC;AAKD,8CAEC;AAKD,wCAYC;AAKD,oCAIC;AAKD,4CAEC;AAKD,0CAEC;AAKD,gDAEC;AAKD,gDAEC;AAKD,8CAEC;AAKD,gCAEC;AAKD,0CAQC;AAKD,oCAQC;AAKD,gDAoBC;AAKD,4BAYC;AAKD,sCAYC;AAKD,4CAEC;AAKD,wCAsBC;AAKD,4CAKC;AAKD,kCAEC;AAKD,4CAaC;
|
|
1
|
+
{"version":3,"file":"ast-helpers.js","sourceRoot":"","sources":["../../src/utils/ast-helpers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-firebase-ai-logic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "ESLint plugin for Firebase AI Logic best practices, detecting deprecated imports, models, and common anti-patterns",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|