create-sitecore-jss 22.2.0-canary.74 → 22.2.0-canary.75
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/templates/angular/package.json +1 -1
- package/dist/templates/angular/scripts/generate-component-factory/index.ts +45 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/component-factory.ts +147 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/components.ts +19 -0
- package/dist/templates/angular/scripts/generate-component-factory/plugins/packages.ts +29 -0
- package/dist/templates/angular/scripts/generate-component-factory/template.ts +46 -0
- package/dist/templates/angular/scripts/generate-plugins.ts +5 -0
- package/dist/templates/angular/src/app/components/gitignore +1 -1
- package/dist/templates/angular-xmcloud/scripts/generate-component-factory/plugins/packages.ts +34 -0
- package/dist/templates/angular-xmcloud/scripts/generate-component-factory/template.ts +57 -0
- package/package.json +2 -2
- package/dist/templates/angular/scripts/generate-component-factory.ts +0 -174
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"build": "npm-run-all --serial bootstrap build:client build:server",
|
|
23
23
|
"scaffold": "ng generate @sitecore-jss/sitecore-jss-angular-schematics:jss-component --no-manifest",
|
|
24
24
|
"start:angular": "ng serve -o",
|
|
25
|
-
"start:watch-components": "ts-node --project src/tsconfig.webpack-server.json scripts/generate-component-factory.ts --watch",
|
|
25
|
+
"start:watch-components": "ts-node --project src/tsconfig.webpack-server.json scripts/generate-component-factory/index.ts --watch",
|
|
26
26
|
"build:client": "cross-env-shell ng build --configuration=production --base-href $npm_package_config_sitecoreDistPath/browser/ --output-path=$npm_package_config_buildArtifactsPath/browser/",
|
|
27
27
|
"build:server": "cross-env-shell ng run <%- appName %>:server:production --output-path=$npm_package_config_buildArtifactsPath",
|
|
28
28
|
"postbuild:server": "move-cli ./dist/main.js ./dist/server.bundle.js",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const plugins = require('scripts/temp/generate-component-factory-plugins');
|
|
2
|
+
import { PackageDefinition } from '@sitecore-jss/sitecore-jss-dev-tools';
|
|
3
|
+
|
|
4
|
+
export interface ComponentFactoryPluginConfig {
|
|
5
|
+
watch?: boolean;
|
|
6
|
+
packages: PackageDefinition[];
|
|
7
|
+
components: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ComponentFactoryPlugin {
|
|
11
|
+
/**
|
|
12
|
+
* Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins)
|
|
13
|
+
*/
|
|
14
|
+
order: number;
|
|
15
|
+
/**
|
|
16
|
+
* A function which will be called during component factory generation
|
|
17
|
+
* @param {JssConfig} config Current (accumulated) config
|
|
18
|
+
*/
|
|
19
|
+
exec(config: ComponentFactoryPluginConfig): ComponentFactoryPluginConfig;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
COMPONENT FACTORY GENERATION
|
|
24
|
+
Generates the /src/app/components/app-components.module.ts file which maps Angular components
|
|
25
|
+
to JSS components.
|
|
26
|
+
|
|
27
|
+
The component factory module defines a mapping between a string component name and a Angular component instance.
|
|
28
|
+
When the Sitecore Layout service returns a layout definition, it returns named components.
|
|
29
|
+
This mapping is used to construct the component hierarchy for the layout.
|
|
30
|
+
|
|
31
|
+
NOTE: this script can run in two modes. The default mode, the component factory file is written once.
|
|
32
|
+
But if `--watch` is a process argument, the component factory source folder will be watched,
|
|
33
|
+
and the componentFactory.js rewritten on added or deleted files.
|
|
34
|
+
This is used during `jss start` to pick up new or removed components at runtime.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const defaultConfig: ComponentFactoryPluginConfig = {
|
|
38
|
+
watch: process.argv.some(arg => arg === '--watch'),
|
|
39
|
+
packages: [],
|
|
40
|
+
components: [],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
(Object.values(plugins) as ComponentFactoryPlugin[])
|
|
44
|
+
.sort((p1, p2) => p1.order - p2.order)
|
|
45
|
+
.reduce((config, plugin) => plugin.exec(config), defaultConfig);
|
package/dist/templates/angular/scripts/generate-component-factory/plugins/component-factory.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import chokidar from 'chokidar';
|
|
5
|
+
import { componentFactoryTemplate } from '../template';
|
|
6
|
+
import {
|
|
7
|
+
ComponentFactoryPluginConfig,
|
|
8
|
+
ComponentFactoryPlugin as ComponentFactoryPluginType,
|
|
9
|
+
} from '..';
|
|
10
|
+
|
|
11
|
+
export interface PackageDefinition {
|
|
12
|
+
name: string;
|
|
13
|
+
components: {
|
|
14
|
+
moduleName: string;
|
|
15
|
+
componentName: string;
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const componentFactoryPath = path.resolve('src/app/components/app-components.module.ts');
|
|
20
|
+
const componentRootPath = 'src/app/components';
|
|
21
|
+
|
|
22
|
+
function watchComponentFactory(config: ComponentFactoryPluginConfig) {
|
|
23
|
+
console.log(`Watching for changes to component factory sources in ${componentRootPath}...`);
|
|
24
|
+
|
|
25
|
+
chokidar
|
|
26
|
+
.watch(componentRootPath, { ignoreInitial: true, awaitWriteFinish: true })
|
|
27
|
+
.on('add', writeComponentFactory.bind(null, config))
|
|
28
|
+
.on('unlink', writeComponentFactory.bind(null, config));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function writeComponentFactory(config: ComponentFactoryPluginConfig) {
|
|
32
|
+
const componentFactory = generateComponentFactory(config);
|
|
33
|
+
|
|
34
|
+
console.log(`Writing component factory to ${componentFactoryPath}`);
|
|
35
|
+
|
|
36
|
+
fs.writeFileSync(componentFactoryPath, componentFactory, { encoding: 'utf8' });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function generateComponentFactory(config: ComponentFactoryPluginConfig) {
|
|
40
|
+
// By convention, we expect to find Angular components
|
|
41
|
+
// under /src/app/components/component-name/component-name.component.ts
|
|
42
|
+
// If a component-name.module.ts file exists, we will treat it as lazy loaded.
|
|
43
|
+
// If you'd like to use your own convention, encode it below.
|
|
44
|
+
// NOTE: generating the component factory module is also totally optional,
|
|
45
|
+
// and it can be maintained manually if preferred.
|
|
46
|
+
|
|
47
|
+
const imports: string[] = [];
|
|
48
|
+
const registrations: string[] = [];
|
|
49
|
+
const lazyRegistrations: string[] = [];
|
|
50
|
+
const declarations: string[] = [];
|
|
51
|
+
|
|
52
|
+
config.packages.forEach((p) => {
|
|
53
|
+
const variables = p.components
|
|
54
|
+
.map((c) => {
|
|
55
|
+
registrations.push(`{ name: '${c.componentName}', type: ${c.moduleName} },`);
|
|
56
|
+
config.components.push(c.componentName);
|
|
57
|
+
|
|
58
|
+
return c.moduleName;
|
|
59
|
+
})
|
|
60
|
+
.join(', ');
|
|
61
|
+
imports.push(`import { ${variables} } from '${p.name}'`);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
fs.readdirSync(componentRootPath).forEach((componentFolder) => {
|
|
65
|
+
// ignore ts files in component root folder
|
|
66
|
+
if (componentFolder.endsWith('.ts') || componentFolder === '.gitignore') {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const componentFilePath = path.join(
|
|
71
|
+
componentRootPath,
|
|
72
|
+
componentFolder,
|
|
73
|
+
`${componentFolder}.component.ts`
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (!fs.existsSync(componentFilePath)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const componentFileContents = fs.readFileSync(componentFilePath, 'utf8');
|
|
81
|
+
|
|
82
|
+
// ASSUMPTION: your component should export a class directly that follows Angular conventions,
|
|
83
|
+
// i.e. `export class FooComponent` - so we can detect the component's name for auto registration.
|
|
84
|
+
const componentClassMatch = /export class (.+?)Component\b/g.exec(componentFileContents);
|
|
85
|
+
|
|
86
|
+
if (componentClassMatch === null) {
|
|
87
|
+
console.debug(
|
|
88
|
+
`Component ${componentFilePath} did not seem to export a component class. It will be skipped.`
|
|
89
|
+
);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const componentName = componentClassMatch[1];
|
|
94
|
+
const importVarName = `${componentName}Component`;
|
|
95
|
+
|
|
96
|
+
config.components.push(componentName);
|
|
97
|
+
|
|
98
|
+
// check for lazy loading needs
|
|
99
|
+
const moduleFilePath = path.join(
|
|
100
|
+
componentRootPath,
|
|
101
|
+
componentFolder,
|
|
102
|
+
`${componentFolder}.module.ts`
|
|
103
|
+
);
|
|
104
|
+
const isLazyLoaded = fs.existsSync(moduleFilePath);
|
|
105
|
+
|
|
106
|
+
if (isLazyLoaded) {
|
|
107
|
+
console.debug(`Registering JSS component (lazy) ${componentName}`);
|
|
108
|
+
lazyRegistrations.push(
|
|
109
|
+
`{ path: '${componentName}', loadChildren: () => import('./${componentFolder}/${componentFolder}.module').then(m => m.${componentName}Module) },`
|
|
110
|
+
);
|
|
111
|
+
} else {
|
|
112
|
+
console.debug(`Registering JSS component ${componentName}`);
|
|
113
|
+
imports.push(
|
|
114
|
+
`import { ${importVarName} } from './${componentFolder}/${componentFolder}.component';`
|
|
115
|
+
);
|
|
116
|
+
registrations.push(`{ name: '${componentName}', type: ${importVarName} },`);
|
|
117
|
+
declarations.push(`${importVarName},`);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return componentFactoryTemplate({
|
|
122
|
+
imports,
|
|
123
|
+
components: config.components,
|
|
124
|
+
registrations,
|
|
125
|
+
lazyRegistrations,
|
|
126
|
+
declarations,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Generates the component factory file.
|
|
132
|
+
*/
|
|
133
|
+
class ComponentFactoryPlugin implements ComponentFactoryPluginType {
|
|
134
|
+
order = 9999;
|
|
135
|
+
|
|
136
|
+
exec(config: ComponentFactoryPluginConfig) {
|
|
137
|
+
if (config.watch) {
|
|
138
|
+
watchComponentFactory(config);
|
|
139
|
+
} else {
|
|
140
|
+
writeComponentFactory(config);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return config;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const componentFactoryPlugin = new ComponentFactoryPlugin();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ComponentFactoryPlugin, ComponentFactoryPluginConfig } from '..';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provides custom components configuration
|
|
5
|
+
*/
|
|
6
|
+
class ComponentsPlugin implements ComponentFactoryPlugin {
|
|
7
|
+
order = 0;
|
|
8
|
+
|
|
9
|
+
exec(config: ComponentFactoryPluginConfig) {
|
|
10
|
+
/**
|
|
11
|
+
* You can specify components which you want to import using custom path
|
|
12
|
+
*/
|
|
13
|
+
config.components = [];
|
|
14
|
+
|
|
15
|
+
return config;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const componentsPlugin = new ComponentsPlugin();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ComponentFactoryPlugin, ComponentFactoryPluginConfig } from '..';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provides custom packages configuration
|
|
5
|
+
*/
|
|
6
|
+
class PackagesPlugin implements ComponentFactoryPlugin {
|
|
7
|
+
order = 0;
|
|
8
|
+
|
|
9
|
+
exec(config: ComponentFactoryPluginConfig) {
|
|
10
|
+
/**
|
|
11
|
+
* You can specify components which you want to import from external/internal packages
|
|
12
|
+
* in format:
|
|
13
|
+
* {
|
|
14
|
+
* name: 'package name',
|
|
15
|
+
* components: [
|
|
16
|
+
* {
|
|
17
|
+
* componentName: 'component name', // component rendering name,
|
|
18
|
+
* moduleName: 'module name' // component name to import from the package
|
|
19
|
+
* }
|
|
20
|
+
* ]
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
config.packages = [];
|
|
24
|
+
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const packagesPlugin = new PackagesPlugin();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const componentFactoryTemplate = ({
|
|
2
|
+
imports,
|
|
3
|
+
components,
|
|
4
|
+
registrations,
|
|
5
|
+
lazyRegistrations,
|
|
6
|
+
declarations,
|
|
7
|
+
}: {
|
|
8
|
+
imports: string[];
|
|
9
|
+
components: string[];
|
|
10
|
+
registrations: string[];
|
|
11
|
+
lazyRegistrations: string[];
|
|
12
|
+
declarations: string[];
|
|
13
|
+
}) => `// Do not edit this file, it is auto-generated at build time!
|
|
14
|
+
// See scripts/generate-component-factory/index.ts to modify the generation of this file.
|
|
15
|
+
// Use app-components.shared.module.ts to modify the imports, etc of this module.
|
|
16
|
+
// Note: code-generation is optional! See ./.gitignore for directions to remove it,
|
|
17
|
+
// if you do not want it.
|
|
18
|
+
|
|
19
|
+
import { NgModule } from '@angular/core';
|
|
20
|
+
import { JssModule } from '@sitecore-jss/sitecore-jss-angular';
|
|
21
|
+
import { AppComponentsSharedModule } from './app-components.shared.module';
|
|
22
|
+
${imports.join('\n')}
|
|
23
|
+
|
|
24
|
+
export const components = [
|
|
25
|
+
${components.map((c) => `'${c}'`).join(',\n ')}
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
@NgModule({
|
|
29
|
+
imports: [
|
|
30
|
+
AppComponentsSharedModule,
|
|
31
|
+
JssModule.withComponents([
|
|
32
|
+
${registrations.join('\n ')}
|
|
33
|
+
], [
|
|
34
|
+
${lazyRegistrations.join('\n ')}
|
|
35
|
+
]),
|
|
36
|
+
],
|
|
37
|
+
exports: [
|
|
38
|
+
JssModule,
|
|
39
|
+
AppComponentsSharedModule,
|
|
40
|
+
],
|
|
41
|
+
declarations: [
|
|
42
|
+
${declarations.join('\n ')}
|
|
43
|
+
],
|
|
44
|
+
})
|
|
45
|
+
export class AppComponentsModule { }
|
|
46
|
+
`;
|
|
@@ -21,6 +21,11 @@ const pluginDefinitions: PluginDefinition[] = [
|
|
|
21
21
|
rootPath: 'scripts/config/plugins',
|
|
22
22
|
moduleType: ModuleType.ESM,
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
distPath: 'scripts/temp/generate-component-factory-plugins.ts',
|
|
26
|
+
rootPath: 'scripts/generate-component-factory/plugins',
|
|
27
|
+
moduleType: ModuleType.ESM,
|
|
28
|
+
},
|
|
24
29
|
];
|
|
25
30
|
|
|
26
31
|
pluginDefinitions.forEach((definition) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# App component module is auto-generated by default.
|
|
2
2
|
# To manually maintain the module,
|
|
3
3
|
# - Remove this ignore file
|
|
4
|
-
# - Delete /scripts/generate-component-factory.ts
|
|
4
|
+
# - Delete /scripts/generate-component-factory/index.ts
|
|
5
5
|
# - Remove the reference from /scripts/bootstrap.ts
|
|
6
6
|
# - Consider merging app-components.shared and app-components modules
|
|
7
7
|
app-components.module.ts
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ComponentFactoryPlugin, ComponentFactoryPluginConfig } from '..';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Provides custom packages configuration
|
|
5
|
+
*/
|
|
6
|
+
class PackagesPlugin implements ComponentFactoryPlugin {
|
|
7
|
+
order = 0;
|
|
8
|
+
|
|
9
|
+
exec(config: ComponentFactoryPluginConfig) {
|
|
10
|
+
/**
|
|
11
|
+
* You can specify components which you want to import from external/internal packages
|
|
12
|
+
* in format:
|
|
13
|
+
* {
|
|
14
|
+
* name: 'package name',
|
|
15
|
+
* components: [
|
|
16
|
+
* {
|
|
17
|
+
* componentName: 'component name', // component rendering name,
|
|
18
|
+
* moduleName: 'module name' // component name to import from the package
|
|
19
|
+
* }
|
|
20
|
+
* ]
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
config.packages = [
|
|
24
|
+
{
|
|
25
|
+
name: '@sitecore-jss/sitecore-jss-angular',
|
|
26
|
+
components: [{ componentName: 'Form', moduleName: 'FormComponent' }],
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const packagesPlugin = new PackagesPlugin();
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const componentFactoryTemplate = ({
|
|
2
|
+
imports,
|
|
3
|
+
components,
|
|
4
|
+
registrations,
|
|
5
|
+
lazyRegistrations,
|
|
6
|
+
declarations,
|
|
7
|
+
}: {
|
|
8
|
+
imports: string[];
|
|
9
|
+
components: string[];
|
|
10
|
+
registrations: string[];
|
|
11
|
+
lazyRegistrations: string[];
|
|
12
|
+
declarations: string[];
|
|
13
|
+
}) => `// Do not edit this file, it is auto-generated at build time!
|
|
14
|
+
// See scripts/generate-component-factory/index.ts to modify the generation of this file.
|
|
15
|
+
// Use app-components.shared.module.ts to modify the imports, etc of this module.
|
|
16
|
+
// Note: code-generation is optional! See ./.gitignore for directions to remove it,
|
|
17
|
+
// if you do not want it.
|
|
18
|
+
|
|
19
|
+
import { NgModule } from '@angular/core';
|
|
20
|
+
import { EDGE_CONFIG, JssModule } from '@sitecore-jss/sitecore-jss-angular';
|
|
21
|
+
import { AppComponentsSharedModule } from './app-components.shared.module';
|
|
22
|
+
import { environment } from '../../environments/environment';
|
|
23
|
+
${imports.join('\n')}
|
|
24
|
+
|
|
25
|
+
export const components = [
|
|
26
|
+
${components.map((c) => `'${c}'`).join(',\n ')}
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
@NgModule({
|
|
30
|
+
imports: [
|
|
31
|
+
AppComponentsSharedModule,
|
|
32
|
+
JssModule.withComponents([
|
|
33
|
+
${registrations.join('\n ')}
|
|
34
|
+
], [
|
|
35
|
+
${lazyRegistrations.join('\n ')}
|
|
36
|
+
]),
|
|
37
|
+
],
|
|
38
|
+
providers: [
|
|
39
|
+
{
|
|
40
|
+
// This configuration is used to be able to integrate sitecore-jss-angular SDK with Sitecore Edge
|
|
41
|
+
provide: EDGE_CONFIG,
|
|
42
|
+
useValue: {
|
|
43
|
+
sitecoreEdgeUrl: environment.sitecoreEdgeUrl,
|
|
44
|
+
sitecoreEdgeContextId: environment.sitecoreEdgeContextId,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
exports: [
|
|
49
|
+
JssModule,
|
|
50
|
+
AppComponentsSharedModule,
|
|
51
|
+
],
|
|
52
|
+
declarations: [
|
|
53
|
+
${declarations.join('\n ')}
|
|
54
|
+
],
|
|
55
|
+
})
|
|
56
|
+
export class AppComponentsModule { }
|
|
57
|
+
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-sitecore-jss",
|
|
3
|
-
"version": "22.2.0-canary.
|
|
3
|
+
"version": "22.2.0-canary.75",
|
|
4
4
|
"description": "Sitecore JSS initializer",
|
|
5
5
|
"bin": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"ts-node": "^10.9.1",
|
|
64
64
|
"typescript": "~4.9.5"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "cbf3579dc09eaf69b94deff40713e7b682146ffe"
|
|
67
67
|
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const chokidar = require('chokidar');
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
COMPONENT FACTORY GENERATION
|
|
7
|
-
Generates the /src/app/components/app-components.module.ts file which maps Angular components
|
|
8
|
-
to JSS components.
|
|
9
|
-
|
|
10
|
-
The component factory module defines a mapping between a string component name and a Angular component instance.
|
|
11
|
-
When the Sitecore Layout service returns a layout definition, it returns named components.
|
|
12
|
-
This mapping is used to construct the component hierarchy for the layout.
|
|
13
|
-
|
|
14
|
-
NOTE: this script can run in two modes. The default mode, the component factory file is written once.
|
|
15
|
-
But if `--watch` is a process argument, the component factory source folder will be watched,
|
|
16
|
-
and the componentFactory.js rewritten on added or deleted files.
|
|
17
|
-
This is used during `jss start` to pick up new or removed components at runtime.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export interface PackageDefinition {
|
|
21
|
-
name: string;
|
|
22
|
-
components: {
|
|
23
|
-
moduleName: string;
|
|
24
|
-
componentName: string;
|
|
25
|
-
}[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const componentFactoryPath = path.resolve('src/app/components/app-components.module.ts');
|
|
29
|
-
const componentRootPath = 'src/app/components';
|
|
30
|
-
|
|
31
|
-
const isWatch = process.argv.some((arg) => arg === '--watch');
|
|
32
|
-
|
|
33
|
-
if (isWatch) {
|
|
34
|
-
watchComponentFactory();
|
|
35
|
-
} else {
|
|
36
|
-
writeComponentFactory();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function watchComponentFactory() {
|
|
40
|
-
console.log(`Watching for changes to component factory sources in ${componentRootPath}...`);
|
|
41
|
-
|
|
42
|
-
chokidar
|
|
43
|
-
.watch(componentRootPath, { ignoreInitial: true, awaitWriteFinish: true })
|
|
44
|
-
.on('add', writeComponentFactory)
|
|
45
|
-
.on('unlink', writeComponentFactory);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function writeComponentFactory() {
|
|
49
|
-
const componentFactory = generateComponentFactory();
|
|
50
|
-
|
|
51
|
-
console.log(`Writing component factory to ${componentFactoryPath}`);
|
|
52
|
-
|
|
53
|
-
fs.writeFileSync(componentFactoryPath, componentFactory, { encoding: 'utf8' });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function generateComponentFactory() {
|
|
57
|
-
// By convention, we expect to find Angular components
|
|
58
|
-
// under /src/app/components/component-name/component-name.component.ts
|
|
59
|
-
// If a component-name.module.ts file exists, we will treat it as lazy loaded.
|
|
60
|
-
// If you'd like to use your own convention, encode it below.
|
|
61
|
-
// NOTE: generating the component factory module is also totally optional,
|
|
62
|
-
// and it can be maintained manually if preferred.
|
|
63
|
-
|
|
64
|
-
const imports: string[] = [];
|
|
65
|
-
/**
|
|
66
|
-
* You can specify components which you want to import from external/internal packages
|
|
67
|
-
* in format:
|
|
68
|
-
* {
|
|
69
|
-
* name: 'package name',
|
|
70
|
-
* components: [
|
|
71
|
-
* {
|
|
72
|
-
* componentName: 'component name', // component rendering name,
|
|
73
|
-
* moduleName: 'module name' // component name to import from the package
|
|
74
|
-
* }
|
|
75
|
-
* ]
|
|
76
|
-
* }
|
|
77
|
-
*/
|
|
78
|
-
const packages: PackageDefinition[] = [];
|
|
79
|
-
const registrations: string[] = [];
|
|
80
|
-
const lazyRegistrations: string[] = [];
|
|
81
|
-
const declarations: string[] = [];
|
|
82
|
-
const components: string[] = [];
|
|
83
|
-
|
|
84
|
-
packages.forEach((p) => {
|
|
85
|
-
const variables = p.components
|
|
86
|
-
.map((c) => {
|
|
87
|
-
registrations.push(`{ name: '${c.componentName}', type: ${c.moduleName} },`);
|
|
88
|
-
declarations.push(`${c.moduleName},`);
|
|
89
|
-
components.push(c.componentName);
|
|
90
|
-
|
|
91
|
-
return c.moduleName;
|
|
92
|
-
})
|
|
93
|
-
.join(', ');
|
|
94
|
-
imports.push(`import { ${variables} } from '${p.name}'`);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
fs.readdirSync(componentRootPath).forEach((componentFolder) => {
|
|
98
|
-
// ignore ts files in component root folder
|
|
99
|
-
if (componentFolder.endsWith('.ts') || componentFolder === '.gitignore') {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const componentFilePath = path.join(componentRootPath, componentFolder, `${componentFolder}.component.ts`);
|
|
104
|
-
|
|
105
|
-
if (!fs.existsSync(componentFilePath)) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const componentFileContents = fs.readFileSync(componentFilePath, 'utf8');
|
|
110
|
-
|
|
111
|
-
// ASSUMPTION: your component should export a class directly that follows Angular conventions,
|
|
112
|
-
// i.e. `export class FooComponent` - so we can detect the component's name for auto registration.
|
|
113
|
-
const componentClassMatch = /export class (.+?)Component\b/g.exec(componentFileContents);
|
|
114
|
-
|
|
115
|
-
if (componentClassMatch === null) {
|
|
116
|
-
console.debug(`Component ${componentFilePath} did not seem to export a component class. It will be skipped.`);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const componentName = componentClassMatch[1];
|
|
121
|
-
const importVarName = `${componentName}Component`;
|
|
122
|
-
|
|
123
|
-
components.push(componentName);
|
|
124
|
-
|
|
125
|
-
// check for lazy loading needs
|
|
126
|
-
const moduleFilePath = path.join(componentRootPath, componentFolder, `${componentFolder}.module.ts`);
|
|
127
|
-
const isLazyLoaded = fs.existsSync(moduleFilePath);
|
|
128
|
-
|
|
129
|
-
if (isLazyLoaded) {
|
|
130
|
-
console.debug(`Registering JSS component (lazy) ${componentName}`);
|
|
131
|
-
lazyRegistrations.push(`{ path: '${componentName}', loadChildren: () => import('./${componentFolder}/${componentFolder}.module').then(m => m.${componentName}Module) },`);
|
|
132
|
-
} else {
|
|
133
|
-
console.debug(`Registering JSS component ${componentName}`);
|
|
134
|
-
imports.push(`import { ${importVarName} } from './${componentFolder}/${componentFolder}.component';`);
|
|
135
|
-
registrations.push(`{ name: '${componentName}', type: ${importVarName} },`);
|
|
136
|
-
declarations.push(`${importVarName},`);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
return `// Do not edit this file, it is auto-generated at build time!
|
|
141
|
-
// See scripts/generate-component-factory.js to modify the generation of this file.
|
|
142
|
-
// Use app-components.shared.module.ts to modify the imports, etc of this module.
|
|
143
|
-
// Note: code-generation is optional! See ./.gitignore for directions to remove it,
|
|
144
|
-
// if you do not want it.
|
|
145
|
-
|
|
146
|
-
import { NgModule } from '@angular/core';
|
|
147
|
-
import { JssModule } from '@sitecore-jss/sitecore-jss-angular';
|
|
148
|
-
import { AppComponentsSharedModule } from './app-components.shared.module';
|
|
149
|
-
${imports.join('\n')}
|
|
150
|
-
|
|
151
|
-
export const components = [
|
|
152
|
-
${components.map((c) => `'${c}'`).join(',\n ')}
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
@NgModule({
|
|
156
|
-
imports: [
|
|
157
|
-
AppComponentsSharedModule,
|
|
158
|
-
JssModule.withComponents([
|
|
159
|
-
${registrations.join('\n ')}
|
|
160
|
-
], [
|
|
161
|
-
${lazyRegistrations.join('\n ')}
|
|
162
|
-
]),
|
|
163
|
-
],
|
|
164
|
-
exports: [
|
|
165
|
-
JssModule,
|
|
166
|
-
AppComponentsSharedModule,
|
|
167
|
-
],
|
|
168
|
-
declarations: [
|
|
169
|
-
${declarations.join('\n ')}
|
|
170
|
-
],
|
|
171
|
-
})
|
|
172
|
-
export class AppComponentsModule { }
|
|
173
|
-
`;
|
|
174
|
-
}
|