Skip to content

Commit

Permalink
Add new way to define decorator implementation with $decorators exp…
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored and sarangan12 committed Sep 16, 2024
1 parent a836699 commit 6c39df6
Show file tree
Hide file tree
Showing 71 changed files with 1,348 additions and 1,069 deletions.
8 changes: 8 additions & 0 deletions .chronus/changes/decorators-export-2024-7-12-2-29-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/bundler"
---

Allow bundling libraries that don't import their `main` file from the TypeSpec
16 changes: 16 additions & 0 deletions .chronus/changes/decorators-export-2024-7-9-21-2-11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: feature
packages:
- "@typespec/compiler"
---

Add new way to define decorator implementation with `$decorators` export.
```ts
export const $decorators = {
"TypeSpec.OpenAPI": {
useRef: $useRef,
oneOf: $oneOf,
},
};
```
15 changes: 15 additions & 0 deletions .chronus/changes/decorators-export-2024-7-9-22-3-58.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: feature
packages:
- "@typespec/http"
- "@typespec/json-schema"
- "@typespec/openapi"
- "@typespec/openapi3"
- "@typespec/protobuf"
- "@typespec/rest"
- "@typespec/versioning"
- "@typespec/xml"
---

Internals: Migrate to new api for declaring decorator implementation
16 changes: 15 additions & 1 deletion docs/extending-typespec/create-decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,21 @@ const tagName: string = "widgets";

## JavaScript decorator implementation

Decorators can be implemented in JavaScript by prefixing the function name with `$`. A decorator function must have the following parameters:
Decorators can be implemented in JavaScript in 2 ways:

1. Prefixing the function name with `$`. e.g `export function $doc(target, name) {...}` **Great to get started/play with decorators**
2. Exporting all decorators for your library using `$decorators` variable. **Recommended**

```ts
export const $decorators = {
// Namespace
"MyOrg.MyLib": {
doc: docDecoratorFn,
},
};
```

A decorator implementation takes the following parameters:

- `1`: `context` of type `DecoratorContext`
- `2`: `target` The TypeSpec type target. (`Namespace`, `Interface`, etc.)
Expand Down
7 changes: 4 additions & 3 deletions packages/bundler/src/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,22 +147,23 @@ async function createRollupConfig(definition: TypeSpecBundleDefinition): Promise
const program = await compile(NodeHost, libraryPath, {
noEmit: true,
});
const jsFiles: string[] = [];
const jsFiles = new Set([resolvePath(libraryPath, definition.packageJson.main)]);
for (const file of program.jsSourceFiles.keys()) {
if (file.startsWith(libraryPath)) {
jsFiles.push(file);
jsFiles.add(file);
}
}
const typespecFiles: Record<string, string> = {
[normalizePath(join(libraryPath, "package.json"))]: JSON.stringify(definition.packageJson),
};

for (const [filename, sourceFile] of program.sourceFiles) {
typespecFiles[filename] = sourceFile.file.text;
}
const content = createBundleEntrypoint({
libraryPath,
mainFile: definition.main,
jsSourceFileNames: jsFiles,
jsSourceFileNames: [...jsFiles],
typespecSourceFiles: typespecFiles,
});

Expand Down
45 changes: 45 additions & 0 deletions packages/compiler/generated-defs/TypeSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,48 @@ export type ReturnTypeVisibilityDecorator = (
target: Operation,
...visibilities: string[]
) => void;

export type TypeSpecDecorators = {
encode: EncodeDecorator;
doc: DocDecorator;
withOptionalProperties: WithOptionalPropertiesDecorator;
withUpdateableProperties: WithUpdateablePropertiesDecorator;
withoutOmittedProperties: WithoutOmittedPropertiesDecorator;
withPickedProperties: WithPickedPropertiesDecorator;
withoutDefaultValues: WithoutDefaultValuesDecorator;
withDefaultKeyVisibility: WithDefaultKeyVisibilityDecorator;
summary: SummaryDecorator;
returnsDoc: ReturnsDocDecorator;
errorsDoc: ErrorsDocDecorator;
deprecated: DeprecatedDecorator;
service: ServiceDecorator;
error: ErrorDecorator;
format: FormatDecorator;
pattern: PatternDecorator;
minLength: MinLengthDecorator;
maxLength: MaxLengthDecorator;
minItems: MinItemsDecorator;
maxItems: MaxItemsDecorator;
minValue: MinValueDecorator;
maxValue: MaxValueDecorator;
minValueExclusive: MinValueExclusiveDecorator;
maxValueExclusive: MaxValueExclusiveDecorator;
secret: SecretDecorator;
list: ListDecorator;
tag: TagDecorator;
friendlyName: FriendlyNameDecorator;
knownValues: KnownValuesDecorator;
key: KeyDecorator;
overload: OverloadDecorator;
projectedName: ProjectedNameDecorator;
encodedName: EncodedNameDecorator;
discriminator: DiscriminatorDecorator;
example: ExampleDecorator;
opExample: OpExampleDecorator;
visibility: VisibilityDecorator;
withVisibility: WithVisibilityDecorator;
inspectType: InspectTypeDecorator;
inspectTypeName: InspectTypeNameDecorator;
parameterVisibility: ParameterVisibilityDecorator;
returnTypeVisibility: ReturnTypeVisibilityDecorator;
};
181 changes: 3 additions & 178 deletions packages/compiler/generated-defs/TypeSpec.ts-test.ts
Original file line number Diff line number Diff line change
@@ -1,180 +1,5 @@
/** An error here would mean that the decorator is not exported or doesn't have the right name. */
import {
$deprecated,
$discriminator,
$doc,
$encode,
$encodedName,
$error,
$errorsDoc,
$example,
$format,
$friendlyName,
$inspectType,
$inspectTypeName,
$key,
$knownValues,
$list,
$maxItems,
$maxLength,
$maxValue,
$maxValueExclusive,
$minItems,
$minLength,
$minValue,
$minValueExclusive,
$opExample,
$overload,
$parameterVisibility,
$pattern,
$projectedName,
$returnTypeVisibility,
$returnsDoc,
$secret,
$service,
$summary,
$tag,
$visibility,
$withDefaultKeyVisibility,
$withOptionalProperties,
$withPickedProperties,
$withUpdateableProperties,
$withVisibility,
$withoutDefaultValues,
$withoutOmittedProperties,
} from "../src/index.js";
import type {
DeprecatedDecorator,
DiscriminatorDecorator,
DocDecorator,
EncodeDecorator,
EncodedNameDecorator,
ErrorDecorator,
ErrorsDocDecorator,
ExampleDecorator,
FormatDecorator,
FriendlyNameDecorator,
InspectTypeDecorator,
InspectTypeNameDecorator,
KeyDecorator,
KnownValuesDecorator,
ListDecorator,
MaxItemsDecorator,
MaxLengthDecorator,
MaxValueDecorator,
MaxValueExclusiveDecorator,
MinItemsDecorator,
MinLengthDecorator,
MinValueDecorator,
MinValueExclusiveDecorator,
OpExampleDecorator,
OverloadDecorator,
ParameterVisibilityDecorator,
PatternDecorator,
ProjectedNameDecorator,
ReturnTypeVisibilityDecorator,
ReturnsDocDecorator,
SecretDecorator,
ServiceDecorator,
SummaryDecorator,
TagDecorator,
VisibilityDecorator,
WithDefaultKeyVisibilityDecorator,
WithOptionalPropertiesDecorator,
WithPickedPropertiesDecorator,
WithUpdateablePropertiesDecorator,
WithVisibilityDecorator,
WithoutDefaultValuesDecorator,
WithoutOmittedPropertiesDecorator,
} from "./TypeSpec.js";

type Decorators = {
$encode: EncodeDecorator;
$doc: DocDecorator;
$withOptionalProperties: WithOptionalPropertiesDecorator;
$withUpdateableProperties: WithUpdateablePropertiesDecorator;
$withoutOmittedProperties: WithoutOmittedPropertiesDecorator;
$withPickedProperties: WithPickedPropertiesDecorator;
$withoutDefaultValues: WithoutDefaultValuesDecorator;
$withDefaultKeyVisibility: WithDefaultKeyVisibilityDecorator;
$summary: SummaryDecorator;
$returnsDoc: ReturnsDocDecorator;
$errorsDoc: ErrorsDocDecorator;
$deprecated: DeprecatedDecorator;
$service: ServiceDecorator;
$error: ErrorDecorator;
$format: FormatDecorator;
$pattern: PatternDecorator;
$minLength: MinLengthDecorator;
$maxLength: MaxLengthDecorator;
$minItems: MinItemsDecorator;
$maxItems: MaxItemsDecorator;
$minValue: MinValueDecorator;
$maxValue: MaxValueDecorator;
$minValueExclusive: MinValueExclusiveDecorator;
$maxValueExclusive: MaxValueExclusiveDecorator;
$secret: SecretDecorator;
$list: ListDecorator;
$tag: TagDecorator;
$friendlyName: FriendlyNameDecorator;
$knownValues: KnownValuesDecorator;
$key: KeyDecorator;
$overload: OverloadDecorator;
$projectedName: ProjectedNameDecorator;
$encodedName: EncodedNameDecorator;
$discriminator: DiscriminatorDecorator;
$example: ExampleDecorator;
$opExample: OpExampleDecorator;
$visibility: VisibilityDecorator;
$withVisibility: WithVisibilityDecorator;
$inspectType: InspectTypeDecorator;
$inspectTypeName: InspectTypeNameDecorator;
$parameterVisibility: ParameterVisibilityDecorator;
$returnTypeVisibility: ReturnTypeVisibilityDecorator;
};

import { $decorators } from "../src/index.js";
import type { TypeSpecDecorators } from "./TypeSpec.js";
/** An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ... */
const _: Decorators = {
$encode,
$doc,
$withOptionalProperties,
$withUpdateableProperties,
$withoutOmittedProperties,
$withPickedProperties,
$withoutDefaultValues,
$withDefaultKeyVisibility,
$summary,
$returnsDoc,
$errorsDoc,
$deprecated,
$service,
$error,
$format,
$pattern,
$minLength,
$maxLength,
$minItems,
$maxItems,
$minValue,
$maxValue,
$minValueExclusive,
$maxValueExclusive,
$secret,
$list,
$tag,
$friendlyName,
$knownValues,
$key,
$overload,
$projectedName,
$encodedName,
$discriminator,
$example,
$opExample,
$visibility,
$withVisibility,
$inspectType,
$inspectTypeName,
$parameterVisibility,
$returnTypeVisibility,
};
const _: TypeSpecDecorators = $decorators["TypeSpec"];
2 changes: 1 addition & 1 deletion packages/compiler/lib/std/decorators.tsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import "../../dist/src/lib/decorators.js";
import "../../dist/src/lib/tsp-index.js";

using TypeSpec.Reflection;

Expand Down
Loading

0 comments on commit 6c39df6

Please sign in to comment.