-
-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(nx-plugin): initial commit page generator/schematic (#577)
- Loading branch information
1 parent
afb9188
commit 4a2de22
Showing
7 changed files
with
405 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
packages/nx-plugin/src/generators/page/__snapshots__/generator.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`analog-page generator > should create analog page correctly > page 1`] = ` | ||
"import { Component } from '@angular/core'; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>home page works!!</p> \`, | ||
}) | ||
export default class HomePage {} | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with metadata correctly > page 1`] = ` | ||
"import { RouteMeta } from '@analogjs/router'; | ||
import { Component } from '@angular/core'; | ||
export const routeMeta: RouteMeta = { | ||
title: 'Home Page', | ||
}; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>home page works!!</p> \`, | ||
}) | ||
export default class HomePage {} | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with redirect correctly > page 1`] = ` | ||
"import { RouteMeta } from '@analogjs/router'; | ||
export const routeMeta: RouteMeta = { | ||
redirectTo: '/home', | ||
pathMatch: 'full', | ||
}; | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with subfolder correctly > page 1`] = ` | ||
"import { Component } from '@angular/core'; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>post page works!!</p> \`, | ||
}) | ||
export default class PostPage {} | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with subfolder correctly > page 2`] = ` | ||
"import { Component } from '@angular/core'; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>products page works!!</p> \`, | ||
}) | ||
export default class ProductsPage {} | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with subfolder correctly > page 3`] = ` | ||
"import { Component } from '@angular/core'; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>productsProductId page works!!</p> \`, | ||
}) | ||
export default class ProductsProductIdPage {} | ||
" | ||
`; | ||
exports[`analog-page generator > should create analog page with subfolder correctly > page 4`] = ` | ||
"import { Component } from '@angular/core'; | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: \` <p>blog page works!!</p> \`, | ||
}) | ||
export default class BlogPage {} | ||
" | ||
`; |
22 changes: 22 additions & 0 deletions
22
packages/nx-plugin/src/generators/page/files/__fileName__.page.ts__template__
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<% if(redirectPage || metadata ) { %>import { RouteMeta } from '@analogjs/router'; <% } %> | ||
<% if(!redirectPage) { %> import { Component } from '@angular/core'; <% } %> | ||
|
||
<% if(!redirectPage) { %> | ||
<% if(metadata) { %> | ||
export const routeMeta: RouteMeta = { | ||
title: '<%= title %>', | ||
}; | ||
<% } %> | ||
@Component({ | ||
standalone: true, | ||
imports: [], | ||
template: ` | ||
<p><%= propertyName %> page works!!</p> | ||
`, | ||
}) | ||
export default class <%= className %>Page { | ||
} <% } else { %> | ||
export const routeMeta: RouteMeta = { | ||
redirectTo: '<%= redirectPath %>', | ||
pathMatch: '<%= pathMatch %>', | ||
};<% } %> |
129 changes: 129 additions & 0 deletions
129
packages/nx-plugin/src/generators/page/generator.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; | ||
import { | ||
Tree, | ||
addProjectConfiguration, | ||
names, | ||
readProjectConfiguration, | ||
} from '@nx/devkit'; | ||
|
||
import { analogPageGenerator } from './generator'; | ||
import { AnalogPageGeneratorSchema } from './schema'; | ||
|
||
describe('analog-page generator', () => { | ||
const setup = async (options: AnalogPageGeneratorSchema) => { | ||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); | ||
addProjectConfiguration(tree, options.pathname, { | ||
projectType: 'application', | ||
sourceRoot: `apps/${names(options.project).fileName}/src`, | ||
root: `apps/${names(options.project).fileName}`, | ||
}); | ||
const config = readProjectConfiguration(tree, options.pathname); | ||
return { | ||
tree, | ||
config, | ||
}; | ||
}; | ||
let tree: Tree; | ||
|
||
beforeEach(() => { | ||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); | ||
}); | ||
|
||
it('should create analog page correctly', async () => { | ||
const options: AnalogPageGeneratorSchema = { | ||
pathname: 'home', | ||
project: 'test', | ||
redirectPage: false, | ||
metadata: false, | ||
}; | ||
|
||
await setup(options); | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/home.page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
}); | ||
|
||
it('should generate an error if the page is a redirect and the path is not provided', async () => { | ||
const options: AnalogPageGeneratorSchema = { | ||
pathname: 'home', | ||
project: 'test', | ||
redirectPage: true, | ||
metadata: false, | ||
}; | ||
|
||
await setup(options); | ||
await expect(analogPageGenerator(tree, options)).rejects.toThrow( | ||
'A redirectPath is required when redirectPage is true.' | ||
); | ||
}); | ||
|
||
it('should create analog page with metadata correctly', async () => { | ||
const options: AnalogPageGeneratorSchema = { | ||
pathname: 'home', | ||
project: 'test', | ||
redirectPage: false, | ||
metadata: true, | ||
title: 'Home Page', | ||
}; | ||
|
||
await setup(options); | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/home.page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
}); | ||
|
||
it('should create analog page with redirect correctly', async () => { | ||
const options: AnalogPageGeneratorSchema = { | ||
pathname: 'home', | ||
project: 'test', | ||
redirectPage: true, | ||
metadata: false, | ||
redirectPath: '/home', | ||
pathMatch: 'full', | ||
}; | ||
|
||
await setup(options); | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/home.page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
}); | ||
|
||
it('should create analog page with subfolder correctly', async () => { | ||
const options: AnalogPageGeneratorSchema = { | ||
pathname: 'blog/post', | ||
project: 'test', | ||
redirectPage: false, | ||
metadata: false, | ||
}; | ||
|
||
await setup(options); | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/blog/post.page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
|
||
options.pathname = 'products/[products]'; | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/products/[products].page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
|
||
options.pathname = 'products/products.[productId]'; | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read( | ||
'apps/test/src/app/pages/products/products.[productId].page.ts', | ||
'utf-8' | ||
) | ||
).toMatchSnapshot('page'); | ||
|
||
options.pathname = '(blog)'; | ||
await analogPageGenerator(tree, options); | ||
expect( | ||
tree.read('apps/test/src/app/pages/(blog).page.ts', 'utf-8') | ||
).toMatchSnapshot('page'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { | ||
convertNxGenerator, | ||
formatFiles, | ||
generateFiles, | ||
getWorkspaceLayout, | ||
names, | ||
offsetFromRoot, | ||
stripIndents, | ||
Tree, | ||
} from '@nx/devkit'; | ||
import * as path from 'path'; | ||
import { AnalogPageGeneratorSchema, NormalizedSchema } from './schema'; | ||
|
||
function normalizeOptions( | ||
tree: Tree, | ||
options: AnalogPageGeneratorSchema | ||
): NormalizedSchema { | ||
const projectRoot = `${getWorkspaceLayout(tree).appsDir}/${options.project}`; | ||
return { | ||
...options, | ||
projectRoot, | ||
}; | ||
} | ||
|
||
function generateFileName(input: string) { | ||
const pattern = /^[a-zA-Z0-9]+\.\[[a-zA-Z0-9-]+\]$/; | ||
if (pattern.test(input)) { | ||
return input.replace(/\[[a-zA-Z0-9-]+\]/, (match) => { | ||
const wordId = match.slice(1, -1); | ||
const camelCaseWordId = wordId.replace(/-([a-zA-Z0-9])/g, (_, letter) => | ||
letter.toUpperCase() | ||
); | ||
return `[${camelCaseWordId}]`; | ||
}); | ||
} else { | ||
return input; | ||
} | ||
} | ||
|
||
function addFiles(tree: Tree, options: NormalizedSchema) { | ||
const splitName = options.pathname.split('/'); | ||
const routeName = splitName[splitName.length - 1]; | ||
const fileName = generateFileName(routeName); | ||
const templateOptions = { | ||
...options, | ||
...names(routeName), | ||
name: names(routeName).fileName, | ||
offsetFromRoot: offsetFromRoot(options.projectRoot), | ||
template: '', | ||
fileName, | ||
}; | ||
|
||
const pageFolders = options.pathname.toLowerCase().split('/'); | ||
|
||
const pageDir = path.join( | ||
options.projectRoot, | ||
`/src/app/pages/${pageFolders.slice(0, -1)}` | ||
); | ||
|
||
generateFiles(tree, path.join(__dirname, 'files'), pageDir, templateOptions); | ||
} | ||
|
||
export async function analogPageGenerator( | ||
tree: Tree, | ||
options: AnalogPageGeneratorSchema | ||
) { | ||
const normalizedOptions = normalizeOptions(tree, options); | ||
if (options.redirectPage && !options.redirectPath) { | ||
throw new Error( | ||
stripIndents`A redirectPath is required when redirectPage is true.` | ||
); | ||
} | ||
addFiles(tree, normalizedOptions); | ||
|
||
await formatFiles(tree); | ||
} | ||
|
||
export const analogPageGeneratorSchematic = | ||
convertNxGenerator(analogPageGenerator); | ||
|
||
export default analogPageGenerator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export interface AnalogPageGeneratorSchema { | ||
pathname: string; | ||
project: string; | ||
metadata?: boolean; | ||
title?: string; | ||
redirectPage?: boolean; | ||
redirectPath?: string; | ||
pathMatch?: string; | ||
} | ||
|
||
export interface NormalizedSchema extends AnalogPageGeneratorSchema { | ||
projectRoot: string; | ||
} |
Oops, something went wrong.