Browse Source

Merge pull request #19917 from abpframework/auto-merge/rel-8-2/2748

Merge branch dev with rel-8.2
pull/19922/head
maliming 2 years ago
committed by GitHub
parent
commit
4d023632a6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      Directory.Packages.props
  2. 37
      docs/en/API/API-Versioning.md
  3. 37
      docs/zh-Hans/API/API-Versioning.md
  4. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/Extensions/DependencyInjection/AbpApiVersioningExtensions.cs
  5. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  6. 28
      npm/ng-packs/packages/schematics/src/commands/api/index.ts
  7. 34
      npm/ng-packs/packages/schematics/src/utils/model.ts
  8. 29
      npm/ng-packs/packages/schematics/src/utils/type.ts

3
Directory.Packages.props

@ -11,7 +11,8 @@
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" /> <PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" /> <PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" />
<PackageVersion Include="AutoMapper" Version="13.0.1" /> <PackageVersion Include="AutoMapper" Version="13.0.1" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="7.1.0" /> <PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.300.2" /> <PackageVersion Include="AWSSDK.S3" Version="3.7.300.2" />
<PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.300.2" /> <PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.300.2" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.17.0" /> <PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.17.0" />

37
docs/en/API/API-Versioning.md

@ -8,11 +8,10 @@ ABP Framework integrates the [ASPNET-API-Versioning](https://github.com/dotnet/a
```cs ```cs
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}); });
@ -239,11 +238,10 @@ public override void ConfigureServices(ServiceConfigurationContext context)
preActions.Configure(options); preActions.Configure(options);
}); });
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
@ -263,27 +261,22 @@ public override void ConfigureServices(ServiceConfigurationContext context)
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}).AddApiExplorer(options => {
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
}); });
context.Services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
context.Services.AddAbpSwaggerGen( context.Services.AddAbpSwaggerGen(
@ -322,7 +315,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
app.UseAbpRequestLocalization(); app.UseAbpRequestLocalization();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI( app.UseAbpSwaggerUI(
options => options =>
{ {
var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>(); var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();

37
docs/zh-Hans/API/API-Versioning.md

@ -7,11 +7,10 @@ ABP框架集成了[ASPNET-API-版本控制](https://github.com/dotnet/aspnet-api
```cs ```cs
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}); });
@ -238,11 +237,10 @@ public override void ConfigureServices(ServiceConfigurationContext context)
preActions.Configure(options); preActions.Configure(options);
}); });
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
@ -262,27 +260,22 @@ public override void ConfigureServices(ServiceConfigurationContext context)
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}).AddApiExplorer(options => {
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
}); });
context.Services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
context.Services.AddAbpSwaggerGen( context.Services.AddAbpSwaggerGen(
@ -321,7 +314,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
app.UseAbpRequestLocalization(); app.UseAbpRequestLocalization();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI( app.UseAbpSwaggerUI(
options => options =>
{ {
var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>(); var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();

6
framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/Extensions/DependencyInjection/AbpApiVersioningExtensions.cs

@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection;
public static class AbpApiVersioningExtensions public static class AbpApiVersioningExtensions
{ {
public static IServiceCollection AddAbpApiVersioning( public static IApiVersioningBuilder AddAbpApiVersioning(
this IServiceCollection services, this IServiceCollection services,
Action<ApiVersioningOptions>? apiVersioningOptionsSetupAction = null, Action<ApiVersioningOptions>? apiVersioningOptionsSetupAction = null,
Action<MvcApiVersioningOptions>? mvcApiVersioningOptionsSetupAction = null) Action<MvcApiVersioningOptions>? mvcApiVersioningOptionsSetupAction = null)
@ -21,9 +21,7 @@ public static class AbpApiVersioningExtensions
apiVersioningOptionsSetupAction ??= _ => { }; apiVersioningOptionsSetupAction ??= _ => { };
mvcApiVersioningOptionsSetupAction ??= _ => { }; mvcApiVersioningOptionsSetupAction ??= _ => { };
services.AddApiVersioning(apiVersioningOptionsSetupAction).AddMvc(mvcApiVersioningOptionsSetupAction); return services.AddApiVersioning(apiVersioningOptionsSetupAction).AddMvc(mvcApiVersioningOptionsSetupAction);
return services;
} }
public static void ConfigureAbp(this MvcApiVersioningOptions options, AbpAspNetCoreMvcOptions mvcOptions) public static void ConfigureAbp(this MvcApiVersioningOptions options, AbpAspNetCoreMvcOptions mvcOptions)

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj

@ -32,6 +32,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" />
<PackageReference Include="Asp.Versioning.Mvc" /> <PackageReference Include="Asp.Versioning.Mvc" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" />
</ItemGroup> </ItemGroup>
</Project> </Project>

28
npm/ng-packs/packages/schematics/src/commands/api/index.ts

@ -48,21 +48,28 @@ export default function (schema: GenerateProxySchema) {
const createProxyConfigWriter = createProxyConfigWriterCreator(targetPath); const createProxyConfigWriter = createProxyConfigWriterCreator(targetPath);
const data = readProxyConfig(tree); const data = readProxyConfig(tree);
data.types = sanitizeTypeNames(data.types); data.types = sanitizeTypeNames(data.types);
const types = data.types; const types = data.types;
const modules = data.modules; const modules = data.modules;
const serviceType = schema.serviceType || defaultEServiceType; const serviceType = schema.serviceType || defaultEServiceType;
if (!types || !modules) throw new SchematicsException(Exception.InvalidApiDefinition);
if (!types || !modules) {
throw new SchematicsException(Exception.InvalidApiDefinition);
}
const definition = data.modules[moduleName]; const definition = data.modules[moduleName];
if (!definition) if (!definition) {
throw new SchematicsException(interpolate(Exception.InvalidModule, moduleName)); throw new SchematicsException(interpolate(Exception.InvalidModule, moduleName));
}
const apiName = definition.remoteServiceName; const apiName = definition.remoteServiceName;
data.modules[moduleName].controllers = sanitizeControllerTypeNames(definition.controllers); data.modules[moduleName].controllers = sanitizeControllerTypeNames(definition.controllers);
const controllers = filterControllersByServiceType( const controllers = filterControllersByServiceType(
serviceType, serviceType,
data.modules[moduleName].controllers, data.modules[moduleName].controllers,
); );
const serviceImports: Record<string, string[]> = {}; const serviceImports: Record<string, string[]> = {};
const generateServices = createServiceGenerator({ const generateServices = createServiceGenerator({
targetPath, targetPath,
@ -90,8 +97,12 @@ export default function (schema: GenerateProxySchema) {
modelImports, modelImports,
}); });
if (!data.generated.includes(moduleName)) data.generated.push(moduleName); if (!data.generated.includes(moduleName)) {
data.generated.push(moduleName);
}
data.generated.sort(); data.generated.sort();
const json = generateProxyConfigJson(data); const json = generateProxyConfigJson(data);
const overwriteProxyConfig = createProxyConfigWriter('overwrite', json); const overwriteProxyConfig = createProxyConfigWriter('overwrite', json);
@ -129,11 +140,18 @@ function createModelGenerator(params: ModelGeneratorParams) {
const { targetPath, serviceImports, modelImports } = params; const { targetPath, serviceImports, modelImports } = params;
const reduceImportRefsToModels = createImportRefsToModelReducer(params); const reduceImportRefsToModels = createImportRefsToModelReducer(params);
const models = Object.values(serviceImports).reduce(reduceImportRefsToModels, []); const models = Object.values(serviceImports).reduce(reduceImportRefsToModels, []);
models.forEach(({ imports }) => models.forEach(({ imports }) =>
imports.forEach(({ refs, path }) => imports.forEach(({ refs, path }) =>
refs.forEach(ref => { refs.forEach(ref => {
if (path === '@abp/ng.core') return; if (path === '@abp/ng.core') {
if (!modelImports[path]) return (modelImports[path] = [ref]); return;
}
if (!modelImports[path]) {
return (modelImports[path] = [ref]);
}
modelImports[path] = [...new Set([...modelImports[path], ref])]; modelImports[path] = [...new Set([...modelImports[path], ref])];
}), }),
), ),

34
npm/ng-packs/packages/schematics/src/utils/model.ts

@ -71,23 +71,30 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) {
model.interfaces.forEach(_interface => { model.interfaces.forEach(_interface => {
const { baseType } = types[_interface.ref]; const { baseType } = types[_interface.ref];
if (baseType && parseNamespace(solution, baseType) !== model.namespace){ if (baseType && parseNamespace(solution, baseType) !== model.namespace) {
const baseTypeWithGenericParams = parseBaseTypeWithGenericTypes(baseType); const baseTypeWithGenericParams = parseBaseTypeWithGenericTypes(baseType);
baseTypeWithGenericParams.forEach(t => { baseTypeWithGenericParams.forEach(t => {
toBeImported.push({ toBeImported.push({
type: t, type: t,
isEnum: false, isEnum: false,
}); });
}) });
}
}
[..._interface.properties, ..._interface.generics].forEach(prop => { [..._interface.properties, ..._interface.generics].forEach(prop => {
prop.refs.forEach(ref => { prop.refs.forEach(ref => {
const propType = types[ref]; const propType = types[ref];
if (!propType) return; if (!propType) {
if (propType.isEnum) toBeImported.push({ type: ref, isEnum: true }); return;
else if (parseNamespace(solution, ref) !== model.namespace) }
if (propType.isEnum) {
toBeImported.push({ type: ref, isEnum: true });
}
if (parseNamespace(solution, ref) !== model.namespace) {
toBeImported.push({ type: ref, isEnum: false }); toBeImported.push({ type: ref, isEnum: false });
}
}); });
}); });
}); });
@ -176,20 +183,21 @@ export function createRefToImportReducerCreator(params: ModelGeneratorParams) {
} }
function isOptionalProperty(prop: PropertyDef) { function isOptionalProperty(prop: PropertyDef) {
return (prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && !prop.isRequired)); return prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && !prop.isRequired);
} }
export function parseBaseTypeWithGenericTypes(type: string): string[] { export function parseBaseTypeWithGenericTypes(type: string): string[] {
const parsedTypeNode = parseGenerics(type); const parsedTypeNode = parseGenerics(type);
const nodeToText = (node: TypeNode,acc:string[] = []): string[] => {
const nodeToText = (node: TypeNode, acc: string[] = []): string[] => {
acc.push(node.data); acc.push(node.data);
if(node.children && node.children.length > 0){ if (node.children && node.children.length > 0) {
node.children.forEach(child => { node.children.forEach(child => {
nodeToText(child,acc); nodeToText(child, acc);
}) });
} }
return acc; return acc;
} };
return nodeToText(parsedTypeNode); return nodeToText(parsedTypeNode);
} }

29
npm/ng-packs/packages/schematics/src/utils/type.ts

@ -14,7 +14,7 @@ export function createTypeSimplifier() {
); );
type = /any</.test(type) ? 'any' : type; type = /any</.test(type) ? 'any' : type;
const { identifier, generics, array} = extractSimpleGenerics(type); const { identifier, generics, array } = extractSimpleGenerics(type);
return generics.length ? `${identifier}<${generics.join(', ')}>${array}` : identifier; return generics.length ? `${identifier}<${generics.join(', ')}>${array}` : identifier;
}); });
@ -64,12 +64,21 @@ export function createTypesToImportsReducer(solution: string, namespace: string)
return (imports: Import[], types: TypeWithEnum[]) => { return (imports: Import[], types: TypeWithEnum[]) => {
types.forEach(({ type, isEnum }) => { types.forEach(({ type, isEnum }) => {
const newImport = mapTypeToImport(type, isEnum); const newImport = mapTypeToImport(type, isEnum);
if (!newImport) return; if (!newImport) {
return;
}
if(newImport.specifiers.some(f => f.toLocaleLowerCase() === type.toLocaleLowerCase())){
return;
}
const existingImport = imports.find( const existingImport = imports.find(
({ keyword, path }) => keyword === newImport.keyword && path === newImport.path, ({ keyword, path }) => keyword === newImport.keyword && path === newImport.path,
); );
if (!existingImport) return imports.push(newImport);
if (!existingImport){
return imports.push(newImport);
}
existingImport.refs = [...new Set([...existingImport.refs, ...newImport.refs])]; existingImport.refs = [...new Set([...existingImport.refs, ...newImport.refs])];
existingImport.specifiers = [ existingImport.specifiers = [
@ -91,11 +100,15 @@ export function createTypeToImportMapper(solution: string, namespace: string) {
const modelNamespace = parseNamespace(solution, type); const modelNamespace = parseNamespace(solution, type);
const refs = [removeTypeModifiers(type)]; const refs = [removeTypeModifiers(type)];
const specifiers = [adaptType(simplifyType(refs[0]).split('<')[0])]; const specifiers = [adaptType(simplifyType(refs[0]).split('<')[0])];
const path = VOLO_REGEX.test(type) let path = relativePathToModel(namespace, modelNamespace);
? '@abp/ng.core'
: isEnum if (VOLO_REGEX.test(type)) {
? relativePathToEnum(namespace, modelNamespace, specifiers[0]) path = '@abp/ng.core';
: relativePathToModel(namespace, modelNamespace); }
if (isEnum) {
path = relativePathToEnum(namespace, modelNamespace, specifiers[0]);
}
return new Import({ keyword: eImportKeyword.Type, path, refs, specifiers }); return new Import({ keyword: eImportKeyword.Type, path, refs, specifiers });
}; };

Loading…
Cancel
Save