Skip to content

Commit

Permalink
feat: add ng-add option to provide metadata modules (#978)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlj95 authored Oct 21, 2024
1 parent f487862 commit b86627b
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 10 deletions.
56 changes: 55 additions & 1 deletion projects/ngx-meta/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SchematicTestRunner } from '@angular-devkit/schematics/testing'
import { Tree } from '@angular-devkit/schematics'
import { beforeEach, describe } from '@jest/globals'
import { join } from 'path'
import { Schema as NgAddSchema } from './schema'
import { MetadataModules, Schema as NgAddSchema } from './schema'
import { ProviderTestCase } from './testing/provider-test-case'
import { createTestApp } from '../testing/create-test-app'
import { shouldAddRootProvider } from './testing/should-add-root-provider'
Expand Down Expand Up @@ -35,6 +35,36 @@ describe('ng-add schematic', () => {
name: 'routing',
symbol: 'provideNgxMetaRouting',
})
const PROVIDERS_BY_MODULE_NAME: {
// 👇 With this type we ensure that all possible types are tested
// If we miss one, the type will be incomplete
[K in MetadataModules]: ProviderTestCase
} = {
'json-ld': new ProviderTestCase({
name: 'JSON-LD',
symbol: 'provideNgxMetaJsonLd',
entrypoint: 'json-ld',
}),
'open-graph': new ProviderTestCase({
name: 'Open Graph',
symbol: 'provideNgxMetaOpenGraph',
entrypoint: 'open-graph',
}),
'open-graph-profile': new ProviderTestCase({
name: 'Open Graph (profile)',
symbol: 'provideNgxMetaOpenGraphProfile',
entrypoint: 'open-graph',
}),
standard: new ProviderTestCase({
name: 'standard',
symbol: 'provideNgxMetaStandard',
}),
'twitter-card': new ProviderTestCase({
name: 'Twitter Card',
symbol: 'provideNgxMetaTwitterCard',
entrypoint: 'twitter-card',
}),
}

;([true, false] as const).forEach((standalone) => {
const appKind = standalone ? 'standalone' : 'module-based'
Expand All @@ -59,6 +89,9 @@ describe('ng-add schematic', () => {

shouldAddRootProvider(CORE_PROVIDER, () => tree, standalone)
shouldNotAddRootProvider(ROUTING_PROVIDER, () => tree, standalone)
Object.values(PROVIDERS_BY_MODULE_NAME).forEach((provider) => {
shouldNotAddRootProvider(provider, () => tree, standalone)
})
})
;[true, false].forEach((routing) => {
describe(`when routing option is ${routing}`, () => {
Expand All @@ -77,6 +110,27 @@ describe('ng-add schematic', () => {
: shouldNotAddRootProvider(ROUTING_PROVIDER, () => tree, standalone)
})
})
Object.keys(PROVIDERS_BY_MODULE_NAME).forEach(
(metadataModule: MetadataModules) => {
describe(`when metadata module option contains '${metadataModule}'`, () => {
let tree: Tree

beforeEach(async () => {
tree = await runner.runSchematic<Partial<NgAddSchema>>(
SCHEMATIC_NAME,
{ ...defaultOptions, metadataModules: [metadataModule] },
appTree,
)
})

shouldAddRootProvider(
PROVIDERS_BY_MODULE_NAME[metadataModule],
() => tree,
standalone,
)
})
},
)
})
})
})
24 changes: 16 additions & 8 deletions projects/ngx-meta/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { chain, noop, Rule } from '@angular-devkit/schematics'
import { addRootProvider } from '@schematics/angular/utility'
import { Schema } from './schema'
import { MetadataModules, Schema } from './schema'
import { classify } from '@angular-devkit/core/src/utils/strings'

const ENTRYPOINTS = new Set<MetadataModules>([
'json-ld',
'open-graph',
'standard',
'twitter-card',
])
// noinspection JSUnusedGlobalSymbols (actually used in `collection.json`)
export function ngAdd(options: Schema): Rule {
const maybeAddNgxMetaRootProvider = (name?: string): Rule => {
if (!name) {
return noop()
}
const addNgxMetaRootProvider = (name: string): Rule => {
const entrypoint =
[...ENTRYPOINTS].find((entrypoint) => name.startsWith(entrypoint)) ?? name
return addRootProvider(
options.project,
({ code, external }) =>
code`${external(`provideNgxMeta${classify(name)}`, `@davidlj95/ngx-meta/${name}`)}()`,
code`${external(`provideNgxMeta${classify(name)}`, `@davidlj95/ngx-meta/${entrypoint}`)}()`,
)
}

return chain([
maybeAddNgxMetaRootProvider('core'),
maybeAddNgxMetaRootProvider(options.routing ? 'routing' : undefined),
addNgxMetaRootProvider('core'),
options.routing ? addNgxMetaRootProvider('routing') : noop(),
...options.metadataModules.map((metadataModule) =>
addNgxMetaRootProvider(metadataModule),
),
])
}
32 changes: 32 additions & 0 deletions projects/ngx-meta/schematics/ng-add/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,38 @@
"default": false,
"//todo": "Enable x-prompts for this and metadata modules to include when both are ready",
"//x-prompt": "Would you like to provide metadata in Angular routes' data?"
},
"metadataModules": {
"type": "array",
"description": "Built-in metadata modules to use",
"default": [],
"//todo": "Enable x-prompts for this and metadata modules to include when both are ready",
"//x-prompt": {
"type": "list",
"message": "What metadata would you like to set?",
"items": [
{
"label": "JSON-LD [ https://ngx-meta.dev/built-in-modules/json-ld/ ]",
"value": "json-ld"
},
{
"label": "Open Graph [ https://ngx-meta.dev/built-in-modules/open-graph/ ]",
"value": "open-graph"
},
{
"label": "Open Graph's profile [ https://ngx-meta.dev/built-in-modules/open-graph/#profile ]",
"value": "open-graph-profile"
},
{
"label": "Standard [ https://ngx-meta.dev/built-in-modules/standard/ ]",
"value": "standard"
},
{
"label": "Twitter Card [ https://ngx-meta.dev/built-in-modules/twitter-cards/ ]",
"value": "twitter-card"
}
]
}
}
},
"required": []
Expand Down
8 changes: 8 additions & 0 deletions projects/ngx-meta/schematics/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
export interface Schema {
project: string
routing: boolean
metadataModules: ReadonlyArray<MetadataModules>
}

export type MetadataModules =
| 'json-ld'
| 'open-graph'
| 'open-graph-profile'
| 'standard'
| 'twitter-card'
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const shouldAddRootProvider = (
standalone,
)
expect(appConfigOrAppModuleContents).toContain(
`import { ${providerTestCase.symbol} } from '${LIB_NAME}/${providerTestCase.entrypoint}`,
`import { ${providerTestCase.symbol} } from '${LIB_NAME}/${providerTestCase.entrypoint}'`,
)
expect(stripWhitespace(appConfigOrAppModuleContents)).toMatch(
new RegExp(`providers:\\[.*${regexpEscape(providerTestCase.code)}.*]`),
Expand Down

0 comments on commit b86627b

Please sign in to comment.