@salesforce/ui-bundle-template-app-angular-template-b2x 11.40.0 → 11.42.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/CHANGELOG.md +16 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/angular.json +1 -1
- package/dist/force-app/main/default/uiBundles/angularextapp/eslint-plugin-angular-graphql.js +148 -0
- package/dist/force-app/main/default/uiBundles/angularextapp/eslint.config.js +9 -1
- package/dist/force-app/main/default/uiBundles/angularextapp/package.json +1 -0
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [11.42.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.41.0...v11.42.0) (2026-07-27)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [11.41.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.40.0...v11.41.0) (2026-07-24)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [11.40.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.39.0...v11.40.0) (2026-07-24)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eslint-plugin-angular-graphql.js
|
|
3
|
+
*
|
|
4
|
+
* Custom ESLint plugin with composite processor that enables BOTH:
|
|
5
|
+
* - Angular inline template linting (processInlineTemplates)
|
|
6
|
+
* - GraphQL tagged template literal linting (@graphql-eslint processor)
|
|
7
|
+
*
|
|
8
|
+
* ESLint only allows one processor per file type. This plugin calls both
|
|
9
|
+
* processors under the hood, returning the source code only once to avoid
|
|
10
|
+
* duplicate TypeScript lint messages.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { createPlugin } from './eslint-plugin-angular-graphql.js';
|
|
14
|
+
* const plugin = createPlugin({ schemaPath: '/absolute/path/to/schema.graphql' });
|
|
15
|
+
*
|
|
16
|
+
* Safety assumptions (verified against source):
|
|
17
|
+
* - Neither processor clones source messages in postprocess (object identity dedup works)
|
|
18
|
+
* - gql tags do not appear inside inline template strings (autofix ranges non-overlapping)
|
|
19
|
+
* - Both processors store internal state keyed by filePath (or derived from it)
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync } from 'node:fs';
|
|
22
|
+
import angular from 'angular-eslint';
|
|
23
|
+
import graphqlPlugin from '@graphql-eslint/eslint-plugin';
|
|
24
|
+
|
|
25
|
+
const angularProcessor = angular.processInlineTemplates;
|
|
26
|
+
const graphqlProcessor = graphqlPlugin.processor;
|
|
27
|
+
|
|
28
|
+
// Track block counts per file for postprocess message routing
|
|
29
|
+
const blockCountsMap = new Map();
|
|
30
|
+
|
|
31
|
+
const compositeProcessor = {
|
|
32
|
+
meta: {
|
|
33
|
+
name: 'angular-graphql/composite',
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
},
|
|
36
|
+
supportsAutofix: true,
|
|
37
|
+
|
|
38
|
+
preprocess(code, filePath) {
|
|
39
|
+
// Call both preprocessors — this populates their internal state maps
|
|
40
|
+
// Angular returns: [source, ...htmlBlocks] (source FIRST)
|
|
41
|
+
const angularResult = angularProcessor.preprocess(code, filePath);
|
|
42
|
+
// GraphQL returns: [...gqlBlocks, source] (source LAST)
|
|
43
|
+
const graphqlResult = graphqlProcessor.preprocess(code, filePath);
|
|
44
|
+
|
|
45
|
+
// Extract blocks (excluding source) from each
|
|
46
|
+
const htmlBlocks = angularResult.length > 1 ? angularResult.slice(1) : [];
|
|
47
|
+
const gqlBlocks = graphqlResult.length > 1 ? graphqlResult.slice(0, -1) : [];
|
|
48
|
+
|
|
49
|
+
// Store counts for postprocess routing
|
|
50
|
+
blockCountsMap.set(filePath, {
|
|
51
|
+
gqlCount: gqlBlocks.length,
|
|
52
|
+
htmlCount: htmlBlocks.length,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Return unified: [gqlBlocks..., htmlBlocks..., source]
|
|
56
|
+
// Source appears exactly ONCE at the end
|
|
57
|
+
return [...gqlBlocks, ...htmlBlocks, code];
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
postprocess(messages, filePath) {
|
|
61
|
+
const { gqlCount, htmlCount } = blockCountsMap.get(filePath) || { gqlCount: 0, htmlCount: 0 };
|
|
62
|
+
blockCountsMap.delete(filePath);
|
|
63
|
+
|
|
64
|
+
const sourceIndex = gqlCount + htmlCount;
|
|
65
|
+
const sourceMessages = messages[sourceIndex] || [];
|
|
66
|
+
|
|
67
|
+
// Short-circuit: neither processor extracted blocks
|
|
68
|
+
if (gqlCount === 0 && htmlCount === 0) {
|
|
69
|
+
return sourceMessages;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Short-circuit: only Angular had blocks
|
|
73
|
+
if (gqlCount === 0) {
|
|
74
|
+
const angularMessages = [sourceMessages, ...messages.slice(0, htmlCount)];
|
|
75
|
+
return angularProcessor.postprocess(angularMessages, filePath);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Short-circuit: only GraphQL had blocks
|
|
79
|
+
if (htmlCount === 0) {
|
|
80
|
+
const gqlMessages = [...messages.slice(0, gqlCount), sourceMessages];
|
|
81
|
+
return graphqlProcessor.postprocess(gqlMessages, filePath);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Both had blocks — route to each postprocess and merge
|
|
85
|
+
// GraphQL expects: [gqlBlock0Msgs, ..., gqlBlockNMsgs, sourceMessages]
|
|
86
|
+
const gqlInput = [...messages.slice(0, gqlCount), sourceMessages];
|
|
87
|
+
const gqlResult = graphqlProcessor.postprocess(gqlInput, filePath);
|
|
88
|
+
|
|
89
|
+
// Angular expects: [sourceMessages, htmlBlock0Msgs, ..., htmlBlockMMsgs]
|
|
90
|
+
const angularInput = [sourceMessages, ...messages.slice(gqlCount, gqlCount + htmlCount)];
|
|
91
|
+
const angularResult = angularProcessor.postprocess(angularInput, filePath);
|
|
92
|
+
|
|
93
|
+
// Deduplicate source messages (both postprocessors pass them through by reference)
|
|
94
|
+
const sourceSet = new Set(sourceMessages);
|
|
95
|
+
const gqlOnly = gqlResult.filter((m) => !sourceSet.has(m));
|
|
96
|
+
|
|
97
|
+
// angularResult = [...sourceMessages, ...adjustedHtmlMessages]
|
|
98
|
+
// gqlOnly = [...adjustedGqlMessages] (source messages filtered out)
|
|
99
|
+
return [...angularResult, ...gqlOnly].sort((a, b) => a.line - b.line || a.column - b.column);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Factory: pass schemaPath, get back a plugin with configs ready to spread.
|
|
105
|
+
* - If schema exists → composite processor (Angular + GraphQL) + GraphQL rules
|
|
106
|
+
* - If no schema → Angular-only inline template processor, no GraphQL rules
|
|
107
|
+
*/
|
|
108
|
+
export function createPlugin({ schemaPath } = {}) {
|
|
109
|
+
const schemaExists = !!(schemaPath && existsSync(schemaPath));
|
|
110
|
+
|
|
111
|
+
const configs = [
|
|
112
|
+
{
|
|
113
|
+
files: ['**/*.ts'],
|
|
114
|
+
processor: schemaExists ? compositeProcessor : angularProcessor,
|
|
115
|
+
},
|
|
116
|
+
...(schemaExists
|
|
117
|
+
? [
|
|
118
|
+
{
|
|
119
|
+
files: ['**/*.graphql'],
|
|
120
|
+
languageOptions: {
|
|
121
|
+
parser: graphqlPlugin.parser,
|
|
122
|
+
parserOptions: {
|
|
123
|
+
graphQLConfig: {
|
|
124
|
+
schema: schemaPath,
|
|
125
|
+
documents: 'src/**/*.ts',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
plugins: {
|
|
130
|
+
'@graphql-eslint': graphqlPlugin,
|
|
131
|
+
},
|
|
132
|
+
rules: {
|
|
133
|
+
'@graphql-eslint/no-anonymous-operations': 'error',
|
|
134
|
+
'@graphql-eslint/no-duplicate-fields': 'error',
|
|
135
|
+
'@graphql-eslint/known-fragment-names': 'error',
|
|
136
|
+
'@graphql-eslint/no-undefined-variables': 'error',
|
|
137
|
+
'@graphql-eslint/no-unused-variables': 'error',
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
: []),
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
meta: { name: 'eslint-plugin-angular-graphql', version: '1.0.0' },
|
|
146
|
+
configs,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
1
3
|
import js from '@eslint/js';
|
|
2
4
|
import angular from 'angular-eslint';
|
|
3
5
|
import tseslint from 'typescript-eslint';
|
|
6
|
+
import { createPlugin } from './eslint-plugin-angular-graphql.js';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const schemaPath = resolve(__dirname, '../../../../../schema.graphql');
|
|
10
|
+
const angularGraphqlPlugin = createPlugin({ schemaPath });
|
|
4
11
|
|
|
5
12
|
export default tseslint.config(
|
|
6
13
|
// Global ignores
|
|
@@ -15,7 +22,6 @@ export default tseslint.config(
|
|
|
15
22
|
...tseslint.configs.recommended,
|
|
16
23
|
...angular.configs.tsRecommended,
|
|
17
24
|
],
|
|
18
|
-
processor: angular.processInlineTemplates,
|
|
19
25
|
rules: {
|
|
20
26
|
'@angular-eslint/directive-selector': [
|
|
21
27
|
'error',
|
|
@@ -57,4 +63,6 @@ export default tseslint.config(
|
|
|
57
63
|
extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility],
|
|
58
64
|
rules: {},
|
|
59
65
|
},
|
|
66
|
+
// Inline template processor + GraphQL rules (plugin handles schema detection)
|
|
67
|
+
...angularGraphqlPlugin.configs,
|
|
60
68
|
);
|
package/dist/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.42.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
|
9
|
-
"version": "11.
|
|
9
|
+
"version": "11.42.0",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"fast-xml-parser": "^5.9.3",
|
package/dist/package.json
CHANGED