@sitecore-content-sdk/angular 0.1.0-canary.20260609132302

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.
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /* eslint-disable jsdoc/require-jsdoc */
4
+ /* eslint-disable no-unused-vars */
5
+ const vitest_1 = require("vitest");
6
+ const node_tools_1 = require("@sitecore-content-sdk/content/node-tools");
7
+ const tools_1 = require("@sitecore-content-sdk/content/tools");
8
+ const readState = vitest_1.vi.hoisted(() => ({
9
+ readFileImpl: (_filePath) => '@Component({})\nexport class Default {}',
10
+ }));
11
+ const fsMock = vitest_1.vi.hoisted(() => ({
12
+ readFileSync: vitest_1.vi.fn((filePath, _encoding) => readState.readFileImpl(String(filePath))),
13
+ mkdirSync: vitest_1.vi.fn(),
14
+ writeFileSync: vitest_1.vi.fn(),
15
+ }));
16
+ vitest_1.vi.mock('node:fs', () => fsMock);
17
+ vitest_1.vi.mock('@sitecore-content-sdk/content/node-tools', () => ({
18
+ getComponentList: vitest_1.vi.fn(),
19
+ }));
20
+ vitest_1.vi.mock('@sitecore-content-sdk/content/tools', () => ({
21
+ prepareComponentsForMap: vitest_1.vi.fn(),
22
+ buildComponentMapContent: vitest_1.vi.fn(() => '// generated map'),
23
+ }));
24
+ const generate_map_1 = require("../tools/generate-map");
25
+ const mockGetComponentList = vitest_1.vi.mocked(node_tools_1.getComponentList);
26
+ const mockPrepareComponentsForMap = vitest_1.vi.mocked(tools_1.prepareComponentsForMap);
27
+ const mockBuildComponentMapContent = vitest_1.vi.mocked(tools_1.buildComponentMapContent);
28
+ const ANGULAR_BUILTIN_IMPORTS = `import { ScFormComponent } from '@sitecore-content-sdk/angular';`;
29
+ const ANGULAR_BUILTIN_MAP_ENTRIES = [`['Form', ScFormComponent]`];
30
+ const makeComponent = (overrides) => ({
31
+ importPath: './',
32
+ moduleName: 'Mod',
33
+ componentName: 'Comp',
34
+ ...overrides,
35
+ });
36
+ (0, vitest_1.describe)('generateMap', () => {
37
+ const preparedEntries = [
38
+ { key: 'Hero', imports: [], valueExpr: 'HeroMod', annotateClient: false },
39
+ ];
40
+ let cwdSpy;
41
+ (0, vitest_1.beforeEach)(() => {
42
+ cwdSpy = vitest_1.vi.spyOn(process, 'cwd').mockReturnValue('/project/root');
43
+ readState.readFileImpl = () => '@Component({})\nexport class Default {}';
44
+ fsMock.readFileSync.mockClear();
45
+ fsMock.mkdirSync.mockReset();
46
+ fsMock.writeFileSync.mockReset();
47
+ mockPrepareComponentsForMap.mockReset();
48
+ mockPrepareComponentsForMap.mockReturnValue(preparedEntries);
49
+ mockBuildComponentMapContent.mockReset();
50
+ mockBuildComponentMapContent.mockReturnValue('// map file body');
51
+ mockGetComponentList.mockReset();
52
+ mockGetComponentList.mockReturnValue([]);
53
+ });
54
+ (0, vitest_1.afterEach)(() => {
55
+ cwdSpy.mockRestore();
56
+ });
57
+ (0, vitest_1.it)('should pass paths, exclude, includeVariants into getComponentList', () => {
58
+ const paths = ['src/app/a', 'src/app/b'];
59
+ const exclude = ['**/*.spec.ts'];
60
+ (0, generate_map_1.generateMap)({ paths, exclude, includeVariants: false });
61
+ (0, vitest_1.expect)(mockGetComponentList).toHaveBeenCalledWith(paths, exclude, false);
62
+ });
63
+ (0, vitest_1.it)('should default includeVariants to true when omitted', () => {
64
+ (0, generate_map_1.generateMap)({ paths: ['src/components'] });
65
+ (0, vitest_1.expect)(mockGetComponentList).toHaveBeenCalledWith(['src/components'], undefined, true);
66
+ });
67
+ (0, vitest_1.it)('should only add components with @Component directive for component map processing', () => {
68
+ const withDecorator = makeComponent({
69
+ filePath: '/project/root/src/with.component.ts',
70
+ componentName: 'With',
71
+ moduleName: 'With',
72
+ importPath: 'src/with.component',
73
+ });
74
+ const withoutDecorator = makeComponent({
75
+ filePath: '/project/root/src/plain.ts',
76
+ componentName: 'Plain',
77
+ moduleName: 'Plain',
78
+ importPath: 'src/plain',
79
+ });
80
+ mockGetComponentList.mockReturnValue([withDecorator, withoutDecorator]);
81
+ readState.readFileImpl = (filePath) => {
82
+ const p = String(filePath).replace(/\\/g, '/');
83
+ if (p.includes('with.component')) {
84
+ return `import { Component } from '@angular/core';\n@Component({ standalone: true })\nexport class With {}`;
85
+ }
86
+ return `export const x = 1;`;
87
+ };
88
+ (0, generate_map_1.generateMap)({ paths: ['src'] });
89
+ (0, vitest_1.expect)(fsMock.readFileSync).toHaveBeenCalled();
90
+ (0, vitest_1.expect)(mockPrepareComponentsForMap).toHaveBeenCalledTimes(1);
91
+ const [passedComponents] = mockPrepareComponentsForMap.mock.calls[0];
92
+ (0, vitest_1.expect)(passedComponents).toHaveLength(1);
93
+ (0, vitest_1.expect)(passedComponents[0].filePath).toContain('with.component');
94
+ });
95
+ (0, vitest_1.it)('should use default buildAngularComponentMap function when no mapTemplate is provided', () => {
96
+ const comp = makeComponent({
97
+ filePath: '/project/root/src/a.component.ts',
98
+ componentName: 'A',
99
+ moduleName: 'A',
100
+ importPath: 'src/a.component',
101
+ });
102
+ mockGetComponentList.mockReturnValue([comp]);
103
+ (0, generate_map_1.generateMap)({ paths: ['src'] });
104
+ (0, vitest_1.expect)(mockBuildComponentMapContent).toHaveBeenCalledTimes(1);
105
+ });
106
+ (0, vitest_1.it)('should pass angular default imports and builtin entries into component map', () => {
107
+ const comp = makeComponent({
108
+ filePath: '/project/root/src/x.component.ts',
109
+ componentName: 'X',
110
+ moduleName: 'X',
111
+ importPath: 'src/x.component',
112
+ });
113
+ mockGetComponentList.mockReturnValue([comp]);
114
+ const componentImports = [
115
+ { importName: 'Lib', importInfo: { importFrom: '@lib/pkg', namedImports: ['A'] } },
116
+ ];
117
+ (0, generate_map_1.generateMap)({ paths: ['src'], componentImports });
118
+ const [entries, passedImports, options] = mockBuildComponentMapContent.mock.calls[0];
119
+ (0, vitest_1.expect)(entries).toEqual(preparedEntries);
120
+ (0, vitest_1.expect)(passedImports).toEqual(componentImports);
121
+ const opts = options;
122
+ (0, vitest_1.expect)(opts.builtInImports).toBe(ANGULAR_BUILTIN_IMPORTS);
123
+ (0, vitest_1.expect)(opts.builtInMapEntries).toEqual(ANGULAR_BUILTIN_MAP_ENTRIES);
124
+ });
125
+ (0, vitest_1.it)('should pass angular as framework to buildComponentMapContent', () => {
126
+ const comp = makeComponent({
127
+ filePath: '/project/root/src/a.component.ts',
128
+ componentName: 'A',
129
+ moduleName: 'A',
130
+ importPath: 'src/a.component',
131
+ });
132
+ mockGetComponentList.mockReturnValue([comp]);
133
+ (0, generate_map_1.generateMap)({ paths: ['src'] });
134
+ (0, vitest_1.expect)(mockBuildComponentMapContent).toHaveBeenCalledWith(preparedEntries, undefined, vitest_1.expect.objectContaining({ framework: 'angular' }));
135
+ });
136
+ (0, vitest_1.it)('should use mapTemplate override function when provided', () => {
137
+ const comp = makeComponent({
138
+ filePath: '/project/root/src/a.component.ts',
139
+ componentName: 'A',
140
+ moduleName: 'A',
141
+ importPath: 'src/a.component',
142
+ });
143
+ mockGetComponentList.mockReturnValue([comp]);
144
+ const customTemplate = vitest_1.vi.fn().mockReturnValue('CUSTOM_MAP_BODY');
145
+ (0, generate_map_1.generateMap)({ paths: ['src'], mapTemplate: customTemplate });
146
+ (0, vitest_1.expect)(customTemplate).toHaveBeenCalledTimes(1);
147
+ const [comps, imports, ctx] = customTemplate.mock.calls[0];
148
+ (0, vitest_1.expect)(comps).toHaveLength(1);
149
+ (0, vitest_1.expect)(comps[0]).toEqual(comp);
150
+ (0, vitest_1.expect)(imports).toBeUndefined();
151
+ (0, vitest_1.expect)(ctx).toEqual({ entries: preparedEntries, includeVariants: true, isClientMap: false });
152
+ (0, vitest_1.expect)(mockBuildComponentMapContent).not.toHaveBeenCalled();
153
+ (0, vitest_1.expect)(fsMock.writeFileSync).toHaveBeenCalledWith(vitest_1.expect.stringMatching(/[\\/]component-map\.ts$/), 'CUSTOM_MAP_BODY', 'utf8');
154
+ });
155
+ (0, vitest_1.it)('should log to console.error and rethrow when mkdirSync fails', () => {
156
+ const comp = makeComponent({
157
+ filePath: '/project/root/src/a.component.ts',
158
+ componentName: 'A',
159
+ moduleName: 'A',
160
+ importPath: 'src/a.component',
161
+ });
162
+ mockGetComponentList.mockReturnValue([comp]);
163
+ const diskError = new Error('mkdir EACCES');
164
+ fsMock.mkdirSync.mockImplementation(() => {
165
+ throw diskError;
166
+ });
167
+ const consoleErrorSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
168
+ try {
169
+ (0, vitest_1.expect)(() => (0, generate_map_1.generateMap)({ paths: ['src'] })).toThrow(diskError);
170
+ (0, vitest_1.expect)(consoleErrorSpy).toHaveBeenCalledTimes(1);
171
+ const [message, err] = consoleErrorSpy.mock.calls[0];
172
+ (0, vitest_1.expect)(message).toContain('Component Map generation failed');
173
+ (0, vitest_1.expect)(message).toContain('component-map.ts');
174
+ (0, vitest_1.expect)(err).toBe(diskError);
175
+ }
176
+ finally {
177
+ consoleErrorSpy.mockRestore();
178
+ }
179
+ (0, vitest_1.expect)(fsMock.writeFileSync).not.toHaveBeenCalled();
180
+ });
181
+ (0, vitest_1.it)('should log to console.error and rethrow when writeFileSync fails', () => {
182
+ const comp = makeComponent({
183
+ filePath: '/project/root/src/a.component.ts',
184
+ componentName: 'A',
185
+ moduleName: 'A',
186
+ importPath: 'src/a.component',
187
+ });
188
+ mockGetComponentList.mockReturnValue([comp]);
189
+ const writeError = new Error('ENOSPC');
190
+ fsMock.writeFileSync.mockImplementation(() => {
191
+ throw writeError;
192
+ });
193
+ const consoleErrorSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
194
+ try {
195
+ (0, vitest_1.expect)(() => (0, generate_map_1.generateMap)({ paths: ['src'] })).toThrow(writeError);
196
+ (0, vitest_1.expect)(consoleErrorSpy).toHaveBeenCalledTimes(1);
197
+ const [message, err] = consoleErrorSpy.mock.calls[0];
198
+ (0, vitest_1.expect)(message).toContain('Component Map generation failed');
199
+ (0, vitest_1.expect)(message).toContain('component-map.ts');
200
+ (0, vitest_1.expect)(err).toBe(writeError);
201
+ }
202
+ finally {
203
+ consoleErrorSpy.mockRestore();
204
+ }
205
+ (0, vitest_1.expect)(fsMock.mkdirSync).toHaveBeenCalled();
206
+ });
207
+ });
@@ -0,0 +1,2 @@
1
+ export { generateMap } from './generate-map';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateMap = void 0;
4
+ var generate_map_1 = require("./generate-map");
5
+ Object.defineProperty(exports, "generateMap", { enumerable: true, get: function () { return generate_map_1.generateMap; } });
package/dist/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Sitecore Content SDK for Angular
2
+
3
+ This package provides Angular integration for the Sitecore Content SDK. Use it in your Angular application to work with Sitecore XM Cloud content.
4
+
5
+ [Documentation](https://doc.sitecore.com/xmc/en/developers/content-sdk/creating-a-content-sdk-app.html)
6
+
7
+ ## Installation
8
+
9
+ In your Angular app:
10
+
11
+ ```bash
12
+ npm install @sitecore-content-sdk/angular
13
+ # or
14
+ yarn add @sitecore-content-sdk/angular
15
+ ```
16
+
17
+ ## Build (developers)
18
+
19
+ From the monorepo root:
20
+
21
+ ```bash
22
+ yarn install
23
+ yarn build
24
+ ```
25
+
26
+ From this package:
27
+
28
+ ```bash
29
+ yarn install
30
+ yarn build
31
+ ```
32
+
33
+ The library is built with [ng-packagr](https://github.com/ng-packagr/ng-packagr) and outputs to `dist/` in Angular Package Format (APF).