@angular-devkit/core#join TypeScript Examples
The following examples show how to use
@angular-devkit/core#join.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async writeFile(path: string, content: string | Buffer): Promise<void> {
this.host
.scopedSync()
.write(
normalize(path),
typeof content === 'string' ? Buffer.from(content) : content
);
this.watcherNotifier?.notify([
{ path: getSystemPath(join(this.host.root(), path)), type: 'modified' },
]);
}
Example #2
Source File: output-template-metadata.service.ts From angular-miniprogram with MIT License | 6 votes |
private getLibraryTemplate() {
if (!Object.keys(this.dataGroup.otherMetaCollectionGroup).length) {
return '';
}
const obj: Record<string, ExtraTemplateData> = {};
for (const key in this.dataGroup.otherMetaCollectionGroup) {
if (
Object.prototype.hasOwnProperty.call(
this.dataGroup.otherMetaCollectionGroup,
key
)
) {
const element = this.dataGroup.otherMetaCollectionGroup[key];
const templateStr = element.templateList
.map((item) => item.content)
.join('');
const useComponents = getUseComponents(
Array.from(element.libraryPath),
Array.from(element.localPath),
this.entryPoint
);
const extraTemplateData: ExtraTemplateData = {
template: templateStr,
useComponents: useComponents,
};
obj[key] = extraTemplateData;
}
}
return `let library_${GLOBAL_TEMPLATE_SUFFIX}=${JSON.stringify(obj)}`;
}
Example #3
Source File: output-template-metadata.service.ts From angular-miniprogram with MIT License | 6 votes |
private getSelfTemplate() {
const selfMetaCollection = this.dataGroup.otherMetaCollectionGroup['$self'];
if (!selfMetaCollection) {
return '';
}
this.selfMetaCollection = selfMetaCollection;
const templateStr = selfMetaCollection.templateList
.map((item) => item.content)
.join('');
const extraTemplateData: ExtraTemplateData = {
template: templateStr,
outputPath: resolve(
normalize('/'),
join(normalize(LIBRARY_OUTPUT_ROOTDIR), this.entryPoint, 'self')
),
};
delete this.dataGroup.otherMetaCollectionGroup['$self'];
return `let $self_${GLOBAL_TEMPLATE_SUFFIX}=${JSON.stringify(
extraTemplateData
)}`;
}
Example #4
Source File: merge-using-component-path.ts From angular-miniprogram with MIT License | 6 votes |
export function getUseComponents(
libraryPath: UseComponent[],
localPath: UseComponent[],
moduleId: string
) {
const list = [...libraryPath];
list.push(
...localPath.map((item) => {
item.path = getComponentOutputPath(moduleId, item.className);
return item;
})
);
return list.reduce((pre, cur) => {
pre[cur.selector] = resolve(
normalize('/'),
join(normalize(LIBRARY_OUTPUT_ROOTDIR), cur.path)
);
return pre;
}, {} as Record<string, string>);
}
Example #5
Source File: find-module.ts From router with MIT License | 6 votes |
/**
* Function to find the "closest" module to a generated file's path.
*/
export function findModule(host: Tree, generateDir: string): Path {
let dir: DirEntry | null = host.getDir('/' + generateDir);
const moduleRe = /\.module\.ts$/;
const routingModuleRe = /-routing\.module\.ts/;
while (dir) {
const matches = dir.subfiles.filter(
(p) => moduleRe.test(p) && !routingModuleRe.test(p)
);
if (matches.length === 1) {
return join(dir.path, matches[0]);
} else if (matches.length > 1) {
throw new Error(
'More than one module matches. Use skip-import option to skip importing ' +
'the component into the closest module.'
);
}
dir = dir.parent;
}
throw new Error(
'Could not find an NgModule. Use the skip-import ' +
'option to skip importing in NgModule.'
);
}
Example #6
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async getFileList(dirPath: Path): Promise<string[]> {
const fileList: string[] = [];
const list = await this.list(dirPath).toPromise();
for (let i = 0; i < list.length; i++) {
const element = list[i];
const filePath = join(dirPath, element);
if (await this.isDirectory(filePath).toPromise()) {
fileList.push(...(await this.getFileList(filePath)));
} else {
fileList.push(filePath);
}
}
return fileList;
}
Example #7
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async moveDir(list: string[], from: string, to: string) {
for (let i = 0; i < list.length; i++) {
const item = list[i];
await this.rename(
normalize(join(this.root(), 'src', from, item)),
normalize(join(this.root(), 'src', to, item))
).toPromise();
}
}
Example #8
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async addPageEntry(list: string[]) {
const configPath = join(normalize(this.root()), 'src', 'app.json');
const file = await this.read(configPath).toPromise();
const json = JSON.parse(fileBufferToString(file));
const entryList = list.map((item) => `pages/${item}/${item}-entry`);
json.pages = entryList;
await this.write(
configPath,
stringToFileBuffer(JSON.stringify(json))
).toPromise();
}
Example #9
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async addSpecEntry(list: string[]) {
const configPath = join(normalize(this.root()), 'src', 'app.json');
const file = await this.read(configPath).toPromise();
const json = JSON.parse(fileBufferToString(file));
const entryList = list.map((item) => `spec/${item}/${item}-entry`);
json.pages = entryList;
await this.write(
configPath,
stringToFileBuffer(JSON.stringify(json))
).toPromise();
}
Example #10
Source File: builder.prod.spec.ts From angular-miniprogram with MIT License | 6 votes |
describeBuilder(runBuilder, BROWSER_BUILDER_INFO, (harness) => {
describe('builder-prod', () => {
it('运行', async () => {
const root = harness.host.root();
const list = await harness.host.getFileList(
normalize(join(root, 'src', '__pages'))
);
list.push(
...(await harness.host.getFileList(
normalize(join(root, 'src', '__components'))
))
);
await harness.host.importPathRename(list);
await harness.host.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');
await harness.host.moveDir(
ALL_COMPONENT_NAME_LIST,
'__components',
'components'
);
await harness.host.addPageEntry(ALL_PAGE_NAME_LIST);
harness.useTarget('build', angularConfig);
const result = await harness.executeOnce();
expect(result).toBeTruthy();
expect(result.error).toBeFalsy();
expect(result.logs[0].level !== 'error').toBeTruthy();
expect(result.result?.success).toBeTruthy();
});
});
});
Example #11
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async writeFiles(files: Record<string, string | Buffer>): Promise<void> {
const watchEvents = this.watcherNotifier
? ([] as { path: string; type: 'modified' | 'deleted' }[])
: undefined;
for (const [path, content] of Object.entries(files)) {
this.host
.scopedSync()
.write(
normalize(path),
typeof content === 'string' ? Buffer.from(content) : content
);
watchEvents?.push({
path: getSystemPath(join(this.host.root(), path)),
type: 'modified',
});
}
if (watchEvents) {
this.watcherNotifier?.notify(watchEvents);
}
}
Example #12
Source File: index.ts From angular-miniprogram with MIT License | 6 votes |
async modifyFile(
path: string,
modifier: (content: string) => string | Promise<string>
): Promise<void> {
const content = this.readFile(path);
await this.writeFile(path, await modifier(content));
this.watcherNotifier?.notify([
{ path: getSystemPath(join(this.host.root(), path)), type: 'modified' },
]);
}
Example #13
Source File: get-angular-sub-dir.rule.ts From angular-miniprogram with MIT License | 6 votes |
export function getAngularSubDirRuleFactory(options: HookOptions): Rule {
return async (tree: Tree, context: SchematicContext) => {
const dirs = tree.getDir(
join(normalize(options.sourceInSchematicsPath), options.subDir)
);
if (dirs.subdirs.length && dirs.subfiles.length) {
return;
}
await cloneSpecifiedDir(options);
};
}
Example #14
Source File: const.ts From angular-miniprogram with MIT License | 6 votes |
SCHEMATICS_FORMS_LIBRARY_HOOK_FILE_LIST = [
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/default_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/checkbox_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/number_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/radio_control_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/range_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/select_control_value_accessor.ts'
),
join(
normalize(SCHEMATICS_FORMS_LIBRARY_PATH),
'src/directives/select_multiple_control_value_accessor.ts'
),
join(normalize(SCHEMATICS_FORMS_LIBRARY_PATH), 'src/directives.ts'),
join(normalize(SCHEMATICS_FORMS_LIBRARY_PATH), 'src/forms.ts'),
]
Example #15
Source File: find-module.ts From edit-in-place with MIT License | 6 votes |
/**
* Function to find the "closest" module to a generated file's path.
*/
export function findModule(
host: Tree,
generateDir: string,
moduleExt = MODULE_EXT,
routingModuleExt = ROUTING_MODULE_EXT
): Path {
let dir: DirEntry | null = host.getDir('/' + generateDir);
let foundRoutingModule = false;
while (dir) {
const allMatches = dir.subfiles.filter(p => p.endsWith(moduleExt));
const filteredMatches = allMatches.filter(p => !p.endsWith(routingModuleExt));
foundRoutingModule = foundRoutingModule || allMatches.length !== filteredMatches.length;
if (filteredMatches.length === 1) {
return join(dir.path, filteredMatches[0]);
} else if (filteredMatches.length > 1) {
throw new Error(
'More than one module matches. Use skip-import option to skip importing ' +
'the component into the closest module.'
);
}
dir = dir.parent;
}
const errorMsg = foundRoutingModule
? 'Could not find a non Routing NgModule.' +
`\nModules with suffix '${routingModuleExt}' are strictly reserved for routing.` +
'\nUse the skip-import option to skip importing in NgModule.'
: 'Could not find an NgModule. Use the skip-import option to skip importing in NgModule.';
throw new Error(errorMsg);
}
Example #16
Source File: library.spec.ts From angular-miniprogram with MIT License | 5 votes |
describeBuilder(execute, LIBRARY_BUILDER_INFO, (harness) => {
describe('test-library', () => {
it('运行', async () => {
harness.useTarget('library', DEFAULT_ANGULAR_LIBRARY_CONFIG);
const result = await harness.executeOnce();
expect(result).toBeTruthy();
expect(result.result).toBeTruthy();
expect(result.result.success).toBeTruthy();
if (!result.result.success) {
console.error(result.result.error);
}
const workspaceRoot: string = (result.result as any).workspaceRoot;
const outputPath = normalize(`dist/test-library`);
const output = path.join(workspaceRoot, outputPath);
const entryFile = harness.expectFile(
join(outputPath, 'esm2020', 'test-library.mjs')
);
entryFile.toExist();
entryFile.content.toContain(`$self_Global_Template`);
const globalSelfTemplate = harness.expectFile(
join(
outputPath,
'esm2020',
'global-self-template',
'global-self-template.component.mjs'
)
);
globalSelfTemplate.toExist();
globalSelfTemplate.content.toContain(
`GlobalSelfTemplateComponent_${LIBRARY_COMPONENT_METADATA_SUFFIX}`
);
fs.copySync(
output,
path.resolve(
process.cwd(),
'test',
'hello-world-app',
'node_modules',
'test-library'
)
);
});
});
});
Example #17
Source File: index.ts From angular-miniprogram with MIT License | 5 votes |
async removeFile(path: string): Promise<void> {
this.host.scopedSync().delete(normalize(path));
this.watcherNotifier?.notify([
{ path: getSystemPath(join(this.host.root(), path)), type: 'deleted' },
]);
}
Example #18
Source File: setup-component-data.service.ts From angular-miniprogram with MIT License | 5 votes |
run(
data: string,
originFileName: string,
customStyleSheetProcessor: CustomStyleSheetProcessor
) {
const changedData = changeComponent(data);
if (!changedData) {
return data;
}
const useComponentPath =
this.dataGroup.useComponentPath.get(originFileName)!;
const componentClassName = changedData.componentName;
const componentDirName = strings.dasherize(
strings.camelize(componentClassName)
);
const libraryPath = getComponentOutputPath(
this.entryPoint,
componentClassName
);
const styleUrlList = this.dataGroup.style.get(originFileName);
const styleContentList: string[] = [];
styleUrlList?.forEach((item) => {
styleContentList.push(customStyleSheetProcessor.styleMap.get(item)!);
});
const selfTemplateImportStr = this.dataGroup.otherMetaCollectionGroup[
'$self'
]
? `<import src="${resolve(
normalize('/'),
join(
normalize(LIBRARY_OUTPUT_ROOTDIR),
this.entryPoint,
'self' + this.buildPlatform.fileExtname.contentTemplate
)
)}"/>`
: '';
const insertComponentData: ExportLibraryComponentMeta = {
id:
strings.classify(this.entryPoint) +
strings.classify(strings.camelize(componentDirName)),
className: componentClassName,
content:
selfTemplateImportStr +
this.dataGroup.outputContent.get(originFileName)!,
libraryPath: libraryPath,
useComponents: {
...getUseComponents(
useComponentPath.libraryPath,
useComponentPath.localPath,
this.entryPoint
),
...this.addGlobalTemplateService.getSelfUseComponents(),
},
moduleId: this.entryPoint,
};
if (styleContentList.length) {
insertComponentData.style = styleContentList.join('\n');
}
return `${
changedData.content
}\nlet ${componentClassName}_${LIBRARY_COMPONENT_METADATA_SUFFIX}=${JSON.stringify(
insertComponentData
)}`;
}
Example #19
Source File: index.ts From angular-miniprogram with MIT License | 5 votes |
workspaceRoot = join(normalize(__dirname), `../hello-world-app/`)
Example #20
Source File: get-library-path.ts From angular-miniprogram with MIT License | 5 votes |
export function getComponentOutputPath(entry: string, className: string) {
return join(
normalize(entry),
dasherize(camelize(className)),
dasherize(camelize(className))
);
}
Example #21
Source File: builder.spec.ts From angular-miniprogram with MIT License | 5 votes |
describeBuilder(runBuilder, BROWSER_BUILDER_INFO, (harness) => {
describe('builder-dev', () => {
for (const platform of [
PlatformType.wx,
PlatformType.bdzn,
PlatformType.dd,
PlatformType.jd,
PlatformType.qq,
PlatformType.zfb,
PlatformType.zj,
]) {
it(`运行${PlatformType[platform]}`, async () => {
angularConfig.platform = platform;
const root = harness.host.root();
const list = await harness.host.getFileList(
normalize(join(root, 'src', '__pages'))
);
list.push(
...(await harness.host.getFileList(
normalize(join(root, 'src', '__components'))
))
);
await harness.host.importPathRename(list);
await harness.host.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');
await harness.host.moveDir(
ALL_COMPONENT_NAME_LIST,
'__components',
'components'
);
await harness.host.addPageEntry(ALL_PAGE_NAME_LIST);
harness.useTarget('build', angularConfig);
const result = await harness.executeOnce();
expect(result).toBeTruthy();
expect(result.error).toBeFalsy();
expect(result.logs[0].level !== 'error').toBeTruthy();
expect(result.result?.success).toBeTruthy();
const injectList = getBuildPlatformInjectConfig(angularConfig.platform);
const injector = Injector.create({ providers: injectList });
const buildPlatform = injector.get(BuildPlatform);
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
`app${buildPlatform.fileExtname.style}`
)
)
.toExist();
const libraryPath = join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
LIBRARY_OUTPUT_ROOTDIR,
'test-library'
);
const librarySelfTemplateFile = harness.expectFile(
join(libraryPath, `self${buildPlatform.fileExtname.contentTemplate}`)
);
librarySelfTemplateFile.toExist();
librarySelfTemplateFile.content.toContain(`$$mp$$__self__$$`);
TEST_LIBRARY_COMPONENT_LIST.forEach((item) => {
const componentPath = join(libraryPath, item, item);
harness
.expectFile(componentPath + buildPlatform.fileExtname.logic)
.toExist();
harness
.expectFile(
componentPath + (buildPlatform.fileExtname.config || '.json')
)
.toExist();
harness
.expectFile(componentPath + buildPlatform.fileExtname.content)
.toExist();
});
const realTestPath: string = result.result?.outputPath as string;
const appTestPath = path.resolve(process.cwd(), '__test-app');
fs.copySync(realTestPath, path.resolve(process.cwd(), '__test-app'));
// ('等待断点放开');
fs.removeSync(appTestPath);
});
}
});
});
Example #22
Source File: dynamic-library-entry.plugin.ts From angular-miniprogram with MIT License | 5 votes |
apply(compiler: webpack.Compiler) {
compiler.hooks.thisCompilation.tap(
'DynamicLibraryEntryPlugin',
(thisCompilation) => {
(thisCompilation as any)[LibrarySymbol] = (thisCompilation as any)[
LibrarySymbol
] || { buildPlatform: this.buildPlatform };
const hooks = webpack.NormalModule.getCompilationHooks(thisCompilation);
hooks.readResource
.for(CUSTOM_URI)
.tapAsync(
'DynamicLibraryEntryPlugin',
(loaderContext: any, callback) => {
const resourcePath: string = loaderContext.resourcePath;
const id = resourcePath.match(CUSTOM_URI_REG)![1];
const libraryMeta = this.libraryComponentMap.get(id);
callback(
undefined,
`
import * as amp from 'angular-miniprogram';
import * as library from '${libraryMeta?.contextPath}';
amp.componentRegistry(library.${libraryMeta?.className});
`
);
return;
}
);
compiler.hooks.finishMake.tapAsync(
'DynamicLibraryEntryPlugin',
(compilation, callback) => {
const libraryLoaderContext: LibraryLoaderContext = (
compilation as any
)[LibrarySymbol];
if (compilation !== thisCompilation) {
callback(undefined);
return;
}
if (libraryLoaderContext.libraryMetaList) {
libraryLoaderContext.libraryMetaList.forEach((item) => {
this.libraryComponentMap.set(item.id, item);
});
}
if (this.libraryComponentMap.size === 0) {
callback(undefined);
return;
}
let j = 0;
this.libraryComponentMap.forEach((meta) => {
const entry = join(
normalize(LIBRARY_OUTPUT_ROOTDIR),
meta.libraryPath
);
const dep = webpack.EntryPlugin.createDependency(
`${CUSTOM_URI}://${path.join('__license', meta.id)}.ts`,
entry
);
compilation.addEntry(
compiler.context,
dep,
entry,
(err, result) => {
j++;
if (j === this.libraryComponentMap.size) {
callback(undefined);
}
}
);
});
}
);
}
);
}
Example #23
Source File: find-module.ts From edit-in-place with MIT License | 5 votes |
/**
* Find the module referred by a set of options passed to the schematics.
*/
export function findModuleFromOptions(host: Tree, options: any, projectPath: any): Path | undefined {
if (options.hasOwnProperty('skipImport') && options.skipImport) {
return undefined;
}
const moduleExt = options.moduleExt || MODULE_EXT;
const routingModuleExt = options.routingModuleExt || ROUTING_MODULE_EXT;
if (!options.module) {
const pathToCheck = (projectPath || '') + '/' + options.name;
const module = findModule(host, pathToCheck, moduleExt, routingModuleExt);
return module ? normalize(module) : undefined;
} else {
const modulePath = normalize(`/${projectPath}/${options.module}`);
const componentPath = normalize(`/${projectPath}/${options.name}`);
const moduleBaseName = normalize(modulePath)
.split('/')
.pop();
const candidateSet = new Set<Path>([normalize(projectPath || '/')]);
for (let dir = modulePath; dir !== NormalizedRoot; dir = dirname(dir)) {
candidateSet.add(dir);
}
for (let dir = componentPath; dir !== NormalizedRoot; dir = dirname(dir)) {
candidateSet.add(dir);
}
const candidatesDirs = [...candidateSet].sort((a, b) => b.length - a.length);
for (const c of candidatesDirs) {
const candidateFiles = ['', `${moduleBaseName}.ts`, `${moduleBaseName}${moduleExt}`].map(x => join(c, x));
for (const sc of candidateFiles) {
if (host.exists(sc)) {
return normalize(sc);
}
}
}
throw new Error(
`Specified module '${options.module}' does not exist.\n` +
`Looked in the following directories:\n ${candidatesDirs.join('\n ')}`
);
}
}
Example #24
Source File: compile-source-files.ts From angular-miniprogram with MIT License | 4 votes |
export async function compileSourceFiles(
graph: BuildGraph,
tsConfig: ParsedConfiguration,
moduleResolutionCache: ts.ModuleResolutionCache,
extraOptions?: Partial<CompilerOptions>,
stylesheetProcessor?: StylesheetProcessor,
ngccProcessor?: NgccProcessor,
watch?: boolean
) {
const { NgtscProgram, formatDiagnostics } = await ngCompilerCli();
const tsConfigOptions: CompilerOptions = {
...tsConfig.options,
...extraOptions,
};
const entryPoint: EntryPointNode = graph.find(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isEntryPointInProgress() as any
)!;
const ngPackageNode: PackageNode = graph.find(isPackage)!;
const inlineStyleLanguage = ngPackageNode.data.inlineStyleLanguage;
const tsCompilerHost = ngccTransformCompilerHost(
cacheCompilerHost(
graph,
entryPoint,
tsConfigOptions,
moduleResolutionCache,
stylesheetProcessor,
inlineStyleLanguage
),
tsConfigOptions,
ngccProcessor!,
moduleResolutionCache
);
// inject
augmentLibraryMetadata(tsCompilerHost);
const cache = entryPoint.cache;
const sourceFileCache = cache.sourcesFileCache;
// Create the Angular specific program that contains the Angular compiler
const angularProgram = new NgtscProgram(
tsConfig.rootNames,
tsConfigOptions,
tsCompilerHost,
cache.oldNgtscProgram
);
const angularCompiler = angularProgram.compiler;
const { ignoreForDiagnostics, ignoreForEmit } = angularCompiler;
// SourceFile versions are required for builder programs.
// The wrapped host inside NgtscProgram adds additional files that will not have versions.
const typeScriptProgram = angularProgram.getTsProgram();
augmentProgramWithVersioning(typeScriptProgram);
let builder: ts.BuilderProgram | ts.EmitAndSemanticDiagnosticsBuilderProgram;
if (watch) {
builder = cache.oldBuilder =
ts.createEmitAndSemanticDiagnosticsBuilderProgram(
typeScriptProgram,
tsCompilerHost,
cache.oldBuilder
);
cache.oldNgtscProgram = angularProgram;
} else {
// When not in watch mode, the startup cost of the incremental analysis can be avoided by
// using an abstract builder that only wraps a TypeScript program.
builder = ts.createAbstractBuilder(typeScriptProgram, tsCompilerHost);
}
// Update semantic diagnostics cache
const affectedFiles = new Set<ts.SourceFile>();
// Analyze affected files when in watch mode for incremental type checking
if ('getSemanticDiagnosticsOfNextAffectedFile' in builder) {
// eslint-disable-next-line no-constant-condition
while (true) {
const result = builder.getSemanticDiagnosticsOfNextAffectedFile(
undefined,
(sourceFile) => {
// If the affected file is a TTC shim, add the shim's original source file.
// This ensures that changes that affect TTC are typechecked even when the changes
// are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
// For example, changing @Input property types of a directive used in another component's
// template.
if (
ignoreForDiagnostics.has(sourceFile) &&
sourceFile.fileName.endsWith('.ngtypecheck.ts')
) {
// This file name conversion relies on internal compiler logic and should be converted
// to an official method when available. 15 is length of `.ngtypecheck.ts`
const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
const originalSourceFile = builder.getSourceFile(originalFilename);
if (originalSourceFile) {
affectedFiles.add(originalSourceFile);
}
return true;
}
return false;
}
);
if (!result) {
break;
}
affectedFiles.add(result.affected as ts.SourceFile);
}
}
// Collect program level diagnostics
const allDiagnostics: ts.Diagnostic[] = [
...angularCompiler.getOptionDiagnostics(),
...builder.getOptionsDiagnostics(),
...builder.getGlobalDiagnostics(),
];
// inject
let injector = Injector.create({
providers: [
...getBuildPlatformInjectConfig(PlatformType.library),
{
provide: MiniProgramCompilerService,
useFactory: (injector: Injector, buildPlatform: BuildPlatform) => {
return new MiniProgramCompilerService(
angularProgram,
injector,
buildPlatform
);
},
deps: [Injector, BuildPlatform],
},
{
provide: ENTRY_FILE_TOKEN,
useValue: join(
dirname(normalize(tsConfig.rootNames[0])),
normalize(tsConfigOptions.flatModuleOutFile!)
),
},
{
provide: ENTRY_POINT_TOKEN,
useValue: entryPoint.data.entryPoint.moduleId,
},
],
});
const miniProgramCompilerService = injector.get(MiniProgramCompilerService);
// Required to support asynchronous resource loading
// Must be done before creating transformers or getting template diagnostics
await angularCompiler.analyzeAsync();
// inject
miniProgramCompilerService.init();
const metaMap =
await miniProgramCompilerService.exportComponentBuildMetaMap();
injector = Injector.create({
parent: injector,
providers: [
{ provide: RESOLVED_DATA_GROUP_TOKEN, useValue: metaMap },
{ provide: AddDeclarationMetaDataService },
{ provide: OutputTemplateMetadataService },
{ provide: SetupComponentDataService },
],
});
// Collect source file specific diagnostics
for (const sourceFile of builder.getSourceFiles()) {
if (!ignoreForDiagnostics.has(sourceFile)) {
allDiagnostics.push(
...builder.getSyntacticDiagnostics(sourceFile),
...builder.getSemanticDiagnostics(sourceFile)
);
}
if (sourceFile.isDeclarationFile) {
continue;
}
// Collect sources that are required to be emitted
if (
!ignoreForEmit.has(sourceFile) &&
!angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)
) {
// If required to emit, diagnostics may have also changed
if (!ignoreForDiagnostics.has(sourceFile)) {
affectedFiles.add(sourceFile);
}
} else if (
sourceFileCache &&
!affectedFiles.has(sourceFile) &&
!ignoreForDiagnostics.has(sourceFile)
) {
// Use cached Angular diagnostics for unchanged and unaffected files
const angularDiagnostics =
sourceFileCache.getAngularDiagnostics(sourceFile);
if (angularDiagnostics?.length) {
allDiagnostics.push(...angularDiagnostics);
}
}
}
// Collect new Angular diagnostics for files affected by changes
for (const affectedFile of affectedFiles) {
const angularDiagnostics = angularCompiler.getDiagnosticsForFile(
affectedFile,
/** OptimizeFor.WholeProgram */ 1
);
allDiagnostics.push(...angularDiagnostics);
sourceFileCache.updateAngularDiagnostics(affectedFile, angularDiagnostics);
}
const otherDiagnostics = [];
const errorDiagnostics = [];
for (const diagnostic of allDiagnostics) {
if (diagnostic.category === ts.DiagnosticCategory.Error) {
errorDiagnostics.push(diagnostic);
} else {
otherDiagnostics.push(diagnostic);
}
}
if (otherDiagnostics.length) {
log.msg(formatDiagnostics(errorDiagnostics));
}
if (errorDiagnostics.length) {
throw new Error(formatDiagnostics(errorDiagnostics));
}
const transformers = angularCompiler.prepareEmit().transformers;
for (const sourceFile of builder.getSourceFiles()) {
if (!ignoreForEmit.has(sourceFile)) {
builder.emit(sourceFile, undefined, undefined, undefined, transformers);
}
}
function augmentLibraryMetadata(compilerHost: ts.CompilerHost) {
const oldWriteFile = compilerHost.writeFile;
compilerHost.writeFile = function (
fileName: string,
data: string,
writeByteOrderMark,
onError,
sourceFiles
) {
const entryFileName = injector.get(ENTRY_FILE_TOKEN);
if (fileName.endsWith('.map')) {
return oldWriteFile.call(
this,
fileName,
data,
writeByteOrderMark,
onError,
sourceFiles
);
}
if (fileName.endsWith('.d.ts')) {
const service = injector.get(AddDeclarationMetaDataService);
const result = service.run(fileName, data);
return oldWriteFile.call(
this,
fileName,
result,
writeByteOrderMark,
onError,
sourceFiles
);
}
const sourceFile = sourceFiles && sourceFiles[0];
if (sourceFile) {
if (
entryFileName ===
normalize(sourceFile.fileName.replace(/\.ts$/, '.js'))
) {
const service = injector.get(OutputTemplateMetadataService);
const result = service.run(fileName, data, sourceFiles![0]);
return oldWriteFile.call(
this,
fileName,
result,
writeByteOrderMark,
onError,
sourceFiles
);
}
const originFileName = path.normalize(sourceFile.fileName);
const setupComponentDataService = injector.get(
SetupComponentDataService
);
const result = setupComponentDataService.run(
data,
originFileName,
stylesheetProcessor! as CustomStyleSheetProcessor
);
return oldWriteFile.call(
this,
fileName,
result,
writeByteOrderMark,
onError,
sourceFiles
);
}
return oldWriteFile.call(
this,
fileName,
data,
writeByteOrderMark,
onError,
sourceFiles
);
};
}
}
Example #25
Source File: index.spec.ts From angular-miniprogram with MIT License | 4 votes |
describeBuilder(runBuilder, KARMA_BUILDER_INFO, (harness) => {
// 此测试仅能本地使用,并且只能一个测试用例单独开启
xdescribe('karma', () => {
it('运行', async () => {
const root = harness.host.root();
await harness.host.addSpecEntry([
'empty',
'tag-view-convert-spec',
'style-class-spec',
'life-time-spec',
'ng-if-spec',
'http-spec',
'ng-content-spec',
'ng-for-spec',
'ng-library-import-spec',
'ng-switch-spec',
'ng-template-outlet-spec',
'self-template-spec',
]);
harness.useTarget('build', angularConfig);
let appTestPath: string;
const result = new Promise<BuilderHarnessExecutionResult<BuilderOutput>>(
(res) => {
let result;
harness
.execute({
testContext: {
buildSuccess: async (webpackConfig) => {
const realTestPath: string = webpackConfig.output!
.path as string;
appTestPath = path.resolve(process.cwd(), '__test-app');
fs.removeSync(appTestPath);
fs.copySync(realTestPath, appTestPath);
},
},
})
.subscribe({
next: (value) => (result = value),
complete: () => res(result),
});
}
);
await result;
expect((await result).error).toBe(undefined);
expect((await result).result.success).toBe(true);
fs.removeSync(appTestPath);
});
xit('watch', async () => {
const root = harness.host.root();
const list: string[] = [];
list.push(
...(await harness.host.getFileList(
normalize(join(root, 'src', '__components'))
)),
...(await harness.host.getFileList(
normalize(join(root, 'src', 'spec'))
))
);
await harness.host.importPathRename(list);
await harness.host.moveDir(
['component1', 'component2'],
'__components',
'components'
);
await harness.host.addSpecEntry(['base-component']);
harness.useTarget('build', { ...angularConfig, watch: true });
let appTestPath: string;
const result = new Promise<BuilderHarnessExecutionResult<BuilderOutput>>(
(res) => {
let first = true;
harness
.execute({
testContext: {
buildSuccess: async (webpackConfig) => {
const realTestPath: string = webpackConfig.output!
.path as string;
appTestPath = path.resolve(process.cwd(), '__test-app');
if (!first) {
fs.removeSync(appTestPath);
fs.copySync(realTestPath, appTestPath);
return;
}
first = false;
fs.removeSync(appTestPath);
fs.copySync(realTestPath, appTestPath);
setTimeout(async () => {
await writeFile();
}, 0);
},
},
})
.subscribe({
next: (value) => res(value),
});
}
);
await result;
expect((await result).error).toBe(undefined);
expect((await result).result.success).toBe(true);
fs.removeSync(appTestPath);
});
});
function writeFile() {
const fileContent = harness.readFile(
'src/spec/base-component/base-component.entry.spec.ts'
);
return harness.writeFiles({
'src/spec/base-component/base-component.entry.spec.ts': `${fileContent}
describe('test-add',()=>{it('main',()=>{expect(true).toBe(true)})});`,
});
}
});
Example #26
Source File: index.origin.ts From angular-miniprogram with MIT License | 4 votes |
/**
* @experimental Direct usage of this function is considered experimental.
*/
export function execute(
options: KarmaBuilderOptions,
context: BuilderContext,
transforms: {
webpackConfiguration?: ExecutionTransformer<Configuration>;
// The karma options transform cannot be async without a refactor of the builder implementation
karmaOptions?: (options: KarmaConfigOptions) => KarmaConfigOptions;
} = {}
): Observable<BuilderOutput> {
// Check Angular version.
assertCompatibleAngularVersion(context.workspaceRoot);
let singleRun: boolean | undefined;
if (options.watch !== undefined) {
singleRun = !options.watch;
}
return from(
initialize(options, context, transforms.webpackConfiguration)
).pipe(
switchMap(async ([karma, webpackConfig]) => {
const karmaOptions: KarmaConfigOptions = {
singleRun,
};
// Convert browsers from a string to an array
if (options.browsers) {
karmaOptions.browsers = options.browsers.split(',');
}
if (options.reporters) {
// Split along commas to make it more natural, and remove empty strings.
const reporters = options.reporters
.reduce<string[]>((acc, curr) => acc.concat(curr.split(',')), [])
.filter((x) => !!x);
if (reporters.length > 0) {
karmaOptions.reporters = reporters;
}
}
// prepend special webpack loader that will transform test.ts
if (options.include && options.include.length > 0) {
const mainFilePath = getSystemPath(
join(normalize(context.workspaceRoot), options.main)
);
const files = findTests(
options.include,
dirname(mainFilePath),
context.workspaceRoot
);
// early exit, no reason to start karma
if (!files.length) {
throw new Error(
`Specified patterns: "${options.include.join(
', '
)}" did not match any spec files.`
);
}
// Get the rules and ensure the Webpack configuration is setup properly
const rules = webpackConfig.module?.rules || [];
if (!webpackConfig.module) {
webpackConfig.module = { rules };
} else if (!webpackConfig.module.rules) {
webpackConfig.module.rules = rules;
}
rules.unshift({
test: mainFilePath,
use: {
// cannot be a simple path as it differs between environments
loader: SingleTestTransformLoader,
options: {
files,
logger: context.logger,
},
},
});
}
karmaOptions.buildWebpack = {
options,
webpackConfig,
logger: context.logger,
};
const config = await karma.config.parseConfig(
resolve(context.workspaceRoot, options.karmaConfig),
transforms.karmaOptions
? transforms.karmaOptions(karmaOptions)
: karmaOptions,
{ promiseConfig: true, throwErrors: true }
);
return [karma, config] as [typeof karma, KarmaConfigOptions];
}),
switchMap(
([karma, karmaConfig]) =>
new Observable<BuilderOutput>((subscriber) => {
// Pass onto Karma to emit BuildEvents.
karmaConfig.buildWebpack ??= {};
if (typeof karmaConfig.buildWebpack === 'object') {
(karmaConfig.buildWebpack as any).failureCb ??= () =>
subscriber.next({ success: false });
(karmaConfig.buildWebpack as any).successCb ??= () =>
subscriber.next({ success: true });
(karmaConfig.buildWebpack as any).testContext = (
context as any
).testContext;
}
// Complete the observable once the Karma server returns.
const karmaServer = new karma.Server(
karmaConfig as Config,
(exitCode) => {
subscriber.next({ success: exitCode === 0 });
subscriber.complete();
}
);
const karmaStart = karmaServer.start();
// Cleanup, signal Karma to exit.
return () => karmaStart.then(() => karmaServer.stop());
})
),
defaultIfEmpty({ success: false })
);
}
Example #27
Source File: builder.watch.spec.ts From angular-miniprogram with MIT License | 4 votes |
describeBuilder(
runBuilder,
{ ...BROWSER_BUILDER_INFO, name: 'test-builder:watch' },
(harness) => {
describe('builder-watch-dev', () => {
it('运行', async () => {
const root = harness.host.root();
const list = await harness.host.getFileList(
normalize(join(root, 'src', '__pages'))
);
list.push(
...(await harness.host.getFileList(
normalize(join(root, 'src', '__components'))
))
);
await harness.host.importPathRename(list);
await harness.host.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');
await harness.host.moveDir(
ALL_COMPONENT_NAME_LIST,
'__components',
'components'
);
await harness.host.addPageEntry(ALL_PAGE_NAME_LIST);
let finish: Function;
const waitFinish = new Promise((res) => {
finish = res;
});
harness.useTarget('build', angularConfig);
harness
.execute()
.pipe(
concatMap((result, index) => {
if (index) {
return of(result);
}
harness
.writeFiles({
'src/pages/sub3/sub3.component.html': `<p>{{title}} works!</p>`,
'src/pages/sub3/sub3.component.ts': `import { Component } from '@angular/core';
@Component({
selector: 'app-sub3',
templateUrl: './sub3.component.html',
})
export class Sub3Component {
title = 'sub3组件';
}
`,
'src/pages/sub3/sub3.entry.json': `{
"usingComponents": { }
}
`,
'src/pages/sub3/sub3.entry.ts': `import { pageStartup } from 'angular-miniprogram';
import { Sub3Component } from './sub3.component';
import { Sub3Module } from './sub3.module';
pageStartup(Sub3Module, Sub3Component);
`,
'src/pages/sub3/sub3.module.ts': `import { NgModule } from '@angular/core';
import { Sub3Component } from './sub3.component';
@NgModule({
declarations: [Sub3Component],
})
export class Sub3Module {}
`,
})
.then(
(res) => {},
(rej) => {
throw rej;
}
);
return of(result);
}),
take(2),
skip(1)
)
.subscribe((result) => {
expect(result.logs[0].level !== 'error').toBeTruthy();
expect(result).toBeTruthy();
expect(result.error).toBeFalsy();
expect(result.result?.success).toBeTruthy();
expect(result.logs[0].message).toContain('sub3-entry.js');
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
'pages/sub3/sub3-entry.js'
)
)
.toExist();
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
'pages/sub3/sub3-entry.json'
)
)
.toExist();
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
'pages/sub3/sub3-entry.wxml'
)
)
.toExist();
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
'pages/sub3/sub3-entry.wxss'
)
)
.toExist();
harness
.expectFile(
join(
normalize(DEFAULT_ANGULAR_CONFIG.outputPath),
'library/test-library/lib-comp1-component/lib-comp1-component.js'
)
)
.toExist();
finish();
});
await waitFinish;
});
});
}
);
Example #28
Source File: index.ts From angular-miniprogram with MIT License | 4 votes |
execute(
options: Partial<BuilderHarnessExecutionOptions> = {}
): Observable<BuilderHarnessExecutionResult> {
const {
configuration,
outputLogsOnException = true,
outputLogsOnFailure = true,
useNativeFileWatching = false,
} = options;
const targetOptions = {
...this.options.get(null),
...((configuration && this.options.get(configuration)) ?? {}),
};
if (!useNativeFileWatching) {
if (this.watcherNotifier) {
throw new Error('Only one harness execution at a time is supported.');
}
this.watcherNotifier = new WatcherNotifier();
}
const contextHost: ContextHost = {
findBuilderByTarget: async (project, target) => {
this.validateProjectName(project);
if (target === this.targetName) {
return {
info: this.builderInfo,
handler: this.builderHandler as BuilderHandlerFn<json.JsonObject>,
};
}
const builderTarget = this.builderTargets.get(target);
if (builderTarget) {
return { info: builderTarget.info, handler: builderTarget.handler };
}
throw new Error('Project target does not exist.');
},
async getBuilderName(project, target) {
return (await this.findBuilderByTarget(project, target)).info
.builderName;
},
getMetadata: async (project) => {
this.validateProjectName(project);
return this.projectMetadata as json.JsonObject;
},
getOptions: async (project, target, configuration) => {
this.validateProjectName(project);
if (target === this.targetName) {
return this.options.get(configuration ?? null) ?? {};
} else if (configuration !== undefined) {
// Harness builder targets currently do not support configurations
return {};
} else {
return (
(this.builderTargets.get(target)?.options as json.JsonObject) || {}
);
}
},
hasTarget: async (project, target) => {
this.validateProjectName(project);
return this.targetName === target || this.builderTargets.has(target);
},
getDefaultConfigurationName: async (_project, _target) => {
return undefined;
},
validate: async (options, builderName) => {
let schema;
if (builderName === this.builderInfo.builderName) {
schema = this.builderInfo.optionSchema;
} else {
for (const [, value] of this.builderTargets) {
if (value.info.builderName === builderName) {
schema = value.info.optionSchema;
break;
}
}
}
const validator = await this.schemaRegistry
.compile(schema ?? true)
.toPromise();
const { data } = await validator(options).toPromise();
return data as json.JsonObject;
},
};
const context = new HarnessBuilderContext(
this.builderInfo,
getSystemPath(this.host.root()),
contextHost,
useNativeFileWatching ? undefined : this.watcherNotifier,
options.testContext
);
if (this.targetName !== undefined) {
context.target = {
project: this.projectName,
target: this.targetName,
configuration: configuration as string,
};
}
const logs: logging.LogEntry[] = [];
context.logger.subscribe((e) => logs.push(e));
return this.schemaRegistry.compile(this.builderInfo.optionSchema).pipe(
mergeMap((validator) => validator(targetOptions as any)),
map((validationResult) => validationResult.data),
mergeMap((data) =>
convertBuilderOutputToObservable(
this.builderHandler(data as T & json.JsonObject, context)
)
),
map((buildResult) => ({ result: buildResult, error: undefined })),
catchError((error) => {
if (outputLogsOnException) {
// eslint-disable-next-line no-console
console.error(logs.map((entry) => entry.message).join('\n'));
// eslint-disable-next-line no-console
console.error(error);
}
return of({ result: undefined, error });
}),
map(({ result, error }) => {
if (
outputLogsOnFailure &&
result?.success === false &&
logs.length > 0
) {
// eslint-disable-next-line no-console
console.error(logs.map((entry) => entry.message).join('\n'));
}
// Capture current logs and clear for next
const currentLogs = logs.slice();
logs.length = 0;
return { result, error, logs: currentLogs };
}),
finalize(() => {
this.watcherNotifier = undefined;
for (const teardown of context.teardowns) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
teardown();
}
})
);
}
Example #29
Source File: mini-program-application-analysis.service.ts From angular-miniprogram with MIT License | 4 votes |
async exportComponentBuildMetaMap() {
const injector = Injector.create({
providers: [
{
provide: MiniProgramCompilerService,
useFactory: (injector: Injector, buildPlatform: BuildPlatform) => {
return new MiniProgramCompilerService(
this.ngTscProgram,
injector,
buildPlatform
);
},
deps: [Injector, BuildPlatform],
},
],
parent: this.injector,
});
const miniProgramCompilerService = injector.get(MiniProgramCompilerService);
miniProgramCompilerService.init();
const metaMap =
await miniProgramCompilerService.exportComponentBuildMetaMap();
const selfMetaCollection = metaMap.otherMetaCollectionGroup['$self'];
const selfTemplate: Record<string, string> = {};
if (selfMetaCollection) {
const importSelfTemplatePath = `/self-template/self${this.buildPlatform.fileExtname.contentTemplate}`;
const importSelfTemplate = `<import src="${importSelfTemplatePath}"/>`;
metaMap.outputContent.forEach((value, key) => {
value = `${importSelfTemplate}${value}`;
metaMap.outputContent.set(key, value);
});
metaMap.useComponentPath.forEach((value, key) => {
value.libraryPath.push(...selfMetaCollection.libraryPath);
value.localPath.push(...selfMetaCollection.localPath);
});
selfTemplate[importSelfTemplatePath] = selfMetaCollection.templateList
.map((item) => item.content)
.join('');
delete metaMap.otherMetaCollectionGroup['$self'];
}
metaMap.useComponentPath.forEach((value, key) => {
value.libraryPath = Array.from(new Set(value.libraryPath));
value.localPath = Array.from(new Set(value.localPath));
});
const styleMap = new Map<string, string[]>();
metaMap.style.forEach((value, key) => {
const entryPattern = this.getComponentPagePattern(key);
styleMap.set(entryPattern.outputFiles.style, value);
});
const contentMap = new Map<string, string>();
metaMap.outputContent.forEach((value, key) => {
const entryPattern = this.getComponentPagePattern(key);
contentMap.set(entryPattern.outputFiles.content, value);
});
metaMap.style = styleMap;
const config = new Map<
string,
{
usingComponents: { selector: string; path: string }[];
existConfig: string;
}
>();
metaMap.useComponentPath.forEach((value, key) => {
const entryPattern = this.getComponentPagePattern(key);
const list = [
...value.libraryPath.map((item) => {
item.path = resolve(
normalize('/'),
join(normalize(LIBRARY_OUTPUT_ROOTDIR), item.path)
);
return item;
}),
];
list.push(
...value.localPath.map((item) => ({
selector: item.selector,
path: resolve(
normalize('/'),
normalize(this.getComponentPagePattern(item.path).outputFiles.path)
),
className: item.className,
}))
);
config.set(entryPattern.outputFiles.config, {
usingComponents: list,
existConfig: entryPattern.inputFiles.config,
});
});
for (const key in metaMap.otherMetaCollectionGroup) {
if (
Object.prototype.hasOwnProperty.call(
metaMap.otherMetaCollectionGroup,
key
)
) {
const element = metaMap.otherMetaCollectionGroup[key];
element.libraryPath.forEach((item) => {
item.path = resolve(
normalize('/'),
join(normalize(LIBRARY_OUTPUT_ROOTDIR), item.path)
);
});
element.localPath.forEach((item) => {
item.path = resolve(
normalize('/'),
normalize(this.getComponentPagePattern(item.path).outputFiles.path)
);
});
}
}
return {
style: styleMap,
outputContent: contentMap,
config: config,
otherMetaCollectionGroup: metaMap.otherMetaCollectionGroup,
selfTemplate,
};
}