@typespec/emitter-framework 0.6.0-dev.0 → 0.6.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/src/typescript/components/interface-declaration.d.ts +1 -1
  2. package/dist/src/typescript/components/interface-declaration.d.ts.map +1 -1
  3. package/dist/src/typescript/components/interface-declaration.js +39 -27
  4. package/dist/src/typescript/components/interface-declaration.js.map +1 -1
  5. package/dist/src/typescript/components/interface-member.d.ts +2 -1
  6. package/dist/src/typescript/components/interface-member.d.ts.map +1 -1
  7. package/dist/src/typescript/components/interface-member.js +35 -20
  8. package/dist/src/typescript/components/interface-member.js.map +1 -1
  9. package/dist/src/typescript/components/value-expression.d.ts +19 -0
  10. package/dist/src/typescript/components/value-expression.d.ts.map +1 -0
  11. package/dist/src/typescript/components/value-expression.js +72 -0
  12. package/dist/src/typescript/components/value-expression.js.map +1 -0
  13. package/dist/test/typescript/components/value-expression.test.d.ts +2 -0
  14. package/dist/test/typescript/components/value-expression.test.d.ts.map +1 -0
  15. package/dist/test/typescript/test-host.d.ts +5 -0
  16. package/dist/test/typescript/test-host.d.ts.map +1 -1
  17. package/package.json +1 -1
  18. package/src/typescript/components/interface-declaration.tsx +38 -31
  19. package/src/typescript/components/interface-member.tsx +30 -19
  20. package/src/typescript/components/value-expression.tsx +56 -0
  21. package/test/typescript/components/interface-declaration.test.tsx +40 -7
  22. package/test/typescript/components/member-expression.test.tsx +4 -4
  23. package/test/typescript/components/value-expression.test.tsx +236 -0
  24. package/test/typescript/test-host.ts +8 -0
@@ -10,5 +10,5 @@ export declare function InterfaceDeclaration(props: InterfaceDeclarationProps):
10
10
  export interface InterfaceExpressionProps extends ts.InterfaceExpressionProps {
11
11
  type: Model | Interface;
12
12
  }
13
- export declare function InterfaceExpression({ type, children }: InterfaceExpressionProps): ay.Children;
13
+ export declare function InterfaceExpression(props: InterfaceExpressionProps): ay.Children;
14
14
  //# sourceMappingURL=interface-declaration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interface-declaration.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-declaration.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,KAAK,EAA0C,MAAM,oBAAoB,CAAC;AAM9F,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAChG,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,yBAAyB,GACjC,8BAA8B,GAC9B,EAAE,CAAC,yBAAyB,CAAC;AAEjC,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,eAyCpE;AAQD,MAAM,WAAW,wBAAyB,SAAQ,EAAE,CAAC,wBAAwB;IAC3E,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;CACzB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,wBAAwB,eAW/E"}
1
+ {"version":3,"file":"interface-declaration.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-declaration.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,EACL,SAAS,EAET,KAAK,EAIN,MAAM,oBAAoB,CAAC;AAM5B,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAChG,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,yBAAyB,GACjC,8BAA8B,GAC9B,EAAE,CAAC,yBAAyB,CAAC;AAEjC,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,eA+BpE;AAQD,MAAM,WAAW,wBAAyB,SAAQ,EAAE,CAAC,wBAAwB;IAC3E,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;CACzB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,eAMlE"}
@@ -1,7 +1,10 @@
1
+ import { memo as _$memo } from "@alloy-js/core/jsx-runtime";
2
+ import { mergeProps as _$mergeProps } from "@alloy-js/core/jsx-runtime";
1
3
  import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
4
  import * as ay from "@alloy-js/core";
3
5
  import { refkey as getRefkey, mapJoin } from "@alloy-js/core";
4
6
  import * as ts from "@alloy-js/typescript";
7
+ import { isNeverType } from "@typespec/compiler";
5
8
  import { $ } from "@typespec/compiler/experimental/typekit";
6
9
  import { createRekeyableMap } from "@typespec/compiler/utils";
7
10
  import { reportDiagnostic } from "../../lib.js";
@@ -22,13 +25,6 @@ export function InterfaceDeclaration(props) {
22
25
  name = namePolicy.getName(name, "interface");
23
26
  const refkey = props.refkey ?? getRefkey(props.type);
24
27
  const extendsType = props.extends ?? getExtendsType(props.type);
25
- const members = props.type ? [membersFromType(props.type)] : [];
26
- const children = [...members];
27
- if (Array.isArray(props.children)) {
28
- children.push(...props.children);
29
- } else if (props.children) {
30
- children.push(props.children);
31
- }
32
28
  return _$createComponent(ts.InterfaceDeclaration, {
33
29
  get ["default"]() {
34
30
  return props.default;
@@ -42,18 +38,20 @@ export function InterfaceDeclaration(props) {
42
38
  name: name,
43
39
  refkey: refkey,
44
40
  "extends": extendsType,
45
- children: children
41
+ get children() {
42
+ return _$createComponent(InterfaceBody, props);
43
+ }
46
44
  });
47
45
  }
48
46
  function isTypedInterfaceDeclarationProps(props) {
49
47
  return "type" in props;
50
48
  }
51
- export function InterfaceExpression({
52
- type,
53
- children
54
- }) {
55
- const members = type ? membersFromType(type) : [];
56
- return ["{", members, children, "}"];
49
+ export function InterfaceExpression(props) {
50
+ return _$createComponent(ay.Block, {
51
+ get children() {
52
+ return _$createComponent(InterfaceBody, props);
53
+ }
54
+ });
57
55
  }
58
56
  function getExtendsType(type) {
59
57
  if (!$.model.is(type)) {
@@ -95,11 +93,15 @@ function getExtendsType(type) {
95
93
  joiner: ","
96
94
  });
97
95
  }
98
- function membersFromType(type) {
96
+
97
+ /**
98
+ * Renders the members of an interface from its properties, including any additional children.
99
+ */
100
+ function InterfaceBody(props) {
99
101
  let typeMembers;
100
- if ($.model.is(type)) {
101
- typeMembers = $.model.getProperties(type);
102
- const additionalProperties = $.model.getAdditionalPropertiesRecord(type);
102
+ if ($.model.is(props.type)) {
103
+ typeMembers = $.model.getProperties(props.type);
104
+ const additionalProperties = $.model.getAdditionalPropertiesRecord(props.type);
103
105
  if (additionalProperties) {
104
106
  typeMembers.set("additionalProperties", $.modelProperty.create({
105
107
  name: "additionalProperties",
@@ -108,18 +110,28 @@ function membersFromType(type) {
108
110
  }));
109
111
  }
110
112
  } else {
111
- typeMembers = createRekeyableMap(type.operations);
113
+ typeMembers = createRekeyableMap(props.type.operations);
112
114
  }
113
- return _$createComponent(ay.For, {
114
- get each() {
115
- return Array.from(typeMembers.entries());
116
- },
117
- line: true,
118
- children: ([_, prop]) => {
115
+
116
+ // Ensure that we have members to render, otherwise skip rendering the ender property.
117
+ const validTypeMembers = Array.from(typeMembers.values()).filter(member => {
118
+ if ($.modelProperty.is(member) && isNeverType(member.type)) {
119
+ return false;
120
+ }
121
+ return true;
122
+ });
123
+ const enderProp = validTypeMembers.length > 0 ? {
124
+ ender: ";"
125
+ } : {};
126
+ return [_$createComponent(ay.For, _$mergeProps({
127
+ each: validTypeMembers,
128
+ line: true
129
+ }, enderProp, {
130
+ children: typeMember => {
119
131
  return _$createComponent(InterfaceMember, {
120
- type: prop
132
+ type: typeMember
121
133
  });
122
134
  }
123
- });
135
+ })), _$memo(() => props.children)];
124
136
  }
125
137
  //# sourceMappingURL=interface-declaration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interface-declaration.js","names":["ay","refkey","getRefkey","mapJoin","ts","$","createRekeyableMap","reportDiagnostic","InterfaceMember","TypeExpression","InterfaceDeclaration","props","isTypedInterfaceDeclarationProps","_$createComponent","namePolicy","useTSNamePolicy","name","type","program","code","target","getName","extendsType","extends","getExtendsType","members","membersFromType","children","Array","isArray","push","default","export","kind","InterfaceExpression","model","is","undefined","extending","baseModel","array","record","spreadType","getSpreadType","length","ext","joiner","typeMembers","getProperties","additionalProperties","getAdditionalPropertiesRecord","set","modelProperty","create","optional","operations","For","each","from","entries","line","_","prop"],"sources":["../../../../src/typescript/components/interface-declaration.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"interface-declaration.js","names":["ay","refkey","getRefkey","mapJoin","ts","isNeverType","$","createRekeyableMap","reportDiagnostic","InterfaceMember","TypeExpression","InterfaceDeclaration","props","isTypedInterfaceDeclarationProps","_$createComponent","namePolicy","useTSNamePolicy","name","type","program","code","target","getName","extendsType","extends","getExtendsType","default","export","kind","children","InterfaceBody","InterfaceExpression","Block","model","is","undefined","extending","baseModel","array","push","record","spreadType","getSpreadType","length","ext","joiner","typeMembers","getProperties","additionalProperties","getAdditionalPropertiesRecord","set","modelProperty","create","optional","operations","validTypeMembers","Array","from","values","filter","member","enderProp","ender","For","_$mergeProps","each","line","typeMember","_$memo"],"sources":["../../../../src/typescript/components/interface-declaration.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,8 @@
1
+ import * as ay from "@alloy-js/core";
1
2
  import { ModelProperty, Operation } from "@typespec/compiler";
2
3
  export interface InterfaceMemberProps {
3
4
  type: ModelProperty | Operation;
4
5
  optional?: boolean;
5
6
  }
6
- export declare function InterfaceMember({ type, optional }: InterfaceMemberProps): import("@alloy-js/core").Children;
7
+ export declare function InterfaceMember(props: InterfaceMemberProps): ay.Children;
7
8
  //# sourceMappingURL=interface-member.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interface-member.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-member.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAM3E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,oBAAoB,qCAiCvE"}
1
+ {"version":3,"file":"interface-member.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-member.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAe,aAAa,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAM3E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,eA2C1D"}
@@ -1,42 +1,57 @@
1
1
  import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
- import { useTSNamePolicy } from "@alloy-js/typescript";
2
+ import { memo as _$memo } from "@alloy-js/core/jsx-runtime";
3
+ import * as ay from "@alloy-js/core";
4
+ import * as ts from "@alloy-js/typescript";
3
5
  import { isNeverType } from "@typespec/compiler";
4
6
  import { $ } from "@typespec/compiler/experimental/typekit";
5
7
  import { getHttpPart } from "@typespec/http";
6
8
  import { FunctionDeclaration } from "./function-declaration.js";
7
9
  import { TypeExpression } from "./type-expression.js";
8
- export function InterfaceMember({
9
- type,
10
- optional
11
- }) {
12
- const namer = useTSNamePolicy();
13
- const name = namer.getName(type.name, "object-member-getter");
14
- if ($.modelProperty.is(type)) {
15
- const optionality = optional === true || type.optional === true ? "?" : "";
16
- if (isNeverType(type.type)) {
10
+ export function InterfaceMember(props) {
11
+ const namer = ts.useTSNamePolicy();
12
+ const name = namer.getName(props.type.name, "object-member-getter");
13
+ if ($.modelProperty.is(props.type)) {
14
+ if (isNeverType(props.type.type)) {
17
15
  return null;
18
16
  }
19
- let unpackedType = type.type;
20
- const part = getHttpPart($.program, type.type);
17
+ let unpackedType = props.type.type;
18
+ const part = getHttpPart($.program, props.type.type);
21
19
  if (part) {
22
20
  unpackedType = part.type;
23
21
  }
24
- return ["\"", name, "\"", optionality, ": ", _$createComponent(TypeExpression, {
25
- type: unpackedType
26
- }), ";"];
22
+ return _$createComponent(ts.InterfaceMember, {
23
+ name: name,
24
+ get optional() {
25
+ return props.optional ?? props.type.optional;
26
+ },
27
+ get type() {
28
+ return _$createComponent(TypeExpression, {
29
+ type: unpackedType
30
+ });
31
+ }
32
+ });
27
33
  }
28
- if ($.operation.is(type)) {
34
+ if ($.operation.is(props.type)) {
29
35
  const returnType = _$createComponent(TypeExpression, {
30
36
  get type() {
31
- return type.returnType;
37
+ return props.type.returnType;
38
+ }
39
+ });
40
+ const params = _$createComponent(ay.Scope, {
41
+ get children() {
42
+ return _$createComponent(FunctionDeclaration.Parameters, {
43
+ get type() {
44
+ return props.type.parameters;
45
+ }
46
+ });
32
47
  }
33
48
  });
34
- const params = _$createComponent(FunctionDeclaration.Parameters, {
49
+ return _$createComponent(ts.InterfaceMember, {
50
+ name: name,
35
51
  get type() {
36
- return type.parameters;
52
+ return ["(", params, ") => ", returnType];
37
53
  }
38
54
  });
39
- return [name, "(", params, "): ", returnType, ";"];
40
55
  }
41
56
  }
42
57
  //# sourceMappingURL=interface-member.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interface-member.js","names":["useTSNamePolicy","isNeverType","$","getHttpPart","FunctionDeclaration","TypeExpression","InterfaceMember","type","optional","namer","name","getName","modelProperty","is","optionality","unpackedType","part","program","_$createComponent","operation","returnType","params","Parameters","parameters"],"sources":["../../../../src/typescript/components/interface-member.tsx"],"sourcesContent":[null],"mappings":";AAAA,SAASA,eAAe,QAAQ,sBAAsB;AACtD,SAASC,WAAW,QAAkC,oBAAoB;AAC1E,SAASC,CAAC,QAAQ,yCAAyC;AAC3D,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SAASC,cAAc,QAAQ,sBAAsB;AAOrD,OAAO,SAASC,eAAeA,CAAC;EAAEC,IAAI;EAAEC;AAA+B,CAAC,EAAE;EACxE,MAAMC,KAAK,GAAGT,eAAe,CAAC,CAAC;EAC/B,MAAMU,IAAI,GAAGD,KAAK,CAACE,OAAO,CAACJ,IAAI,CAACG,IAAI,EAAE,sBAAsB,CAAC;EAE7D,IAAIR,CAAC,CAACU,aAAa,CAACC,EAAE,CAACN,IAAI,CAAC,EAAE;IAC5B,MAAMO,WAAW,GAAGN,QAAQ,KAAK,IAAI,IAAID,IAAI,CAACC,QAAQ,KAAK,IAAI,GAAG,GAAG,GAAG,EAAE;IAE1E,IAAIP,WAAW,CAACM,IAAI,CAACA,IAAI,CAAC,EAAE;MAC1B,OAAO,IAAI;IACb;IAEA,IAAIQ,YAAY,GAAGR,IAAI,CAACA,IAAI;IAC5B,MAAMS,IAAI,GAAGb,WAAW,CAACD,CAAC,CAACe,OAAO,EAAEV,IAAI,CAACA,IAAI,CAAC;IAC9C,IAAIS,IAAI,EAAE;MACRD,YAAY,GAAGC,IAAI,CAACT,IAAI;IAC1B;IAEA,cAEMG,IAAI,QAAGI,WAAW,QAAAI,iBAAA,CAAIb,cAAc;MAACE,IAAI,EAAEQ;IAAY;EAG/D;EAEA,IAAIb,CAAC,CAACiB,SAAS,CAACN,EAAE,CAACN,IAAI,CAAC,EAAE;IACxB,MAAMa,UAAU,GAAAF,iBAAA,CAAIb,cAAc;MAAA,IAACE,IAAIA,CAAA;QAAA,OAAEA,IAAI,CAACa,UAAU;MAAA;IAAA,EAAI;IAC5D,MAAMC,MAAM,GAAAH,iBAAA,CAAId,mBAAmB,CAACkB,UAAU;MAAA,IAACf,IAAIA,CAAA;QAAA,OAAEA,IAAI,CAACgB,UAAU;MAAA;IAAA,EAAI;IACxE,QAEKb,IAAI,OAAGW,MAAM,SAAKD,UAAU;EAGnC;AACF","ignoreList":[]}
1
+ {"version":3,"file":"interface-member.js","names":["ay","ts","isNeverType","$","getHttpPart","FunctionDeclaration","TypeExpression","InterfaceMember","props","namer","useTSNamePolicy","name","getName","type","modelProperty","is","unpackedType","part","program","_$createComponent","optional","operation","returnType","params","Scope","children","Parameters","parameters"],"sources":["../../../../src/typescript/components/interface-member.tsx"],"sourcesContent":[null],"mappings":";;AAAA,OAAO,KAAKA,EAAE,MAAM,gBAAgB;AACpC,OAAO,KAAKC,EAAE,MAAM,sBAAsB;AAC1C,SAASC,WAAW,QAAkC,oBAAoB;AAC1E,SAASC,CAAC,QAAQ,yCAAyC;AAC3D,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SAASC,cAAc,QAAQ,sBAAsB;AAOrD,OAAO,SAASC,eAAeA,CAACC,KAA2B,EAAE;EAC3D,MAAMC,KAAK,GAAGR,EAAE,CAACS,eAAe,CAAC,CAAC;EAClC,MAAMC,IAAI,GAAGF,KAAK,CAACG,OAAO,CAACJ,KAAK,CAACK,IAAI,CAACF,IAAI,EAAE,sBAAsB,CAAC;EAEnE,IAAIR,CAAC,CAACW,aAAa,CAACC,EAAE,CAACP,KAAK,CAACK,IAAI,CAAC,EAAE;IAClC,IAAIX,WAAW,CAACM,KAAK,CAACK,IAAI,CAACA,IAAI,CAAC,EAAE;MAChC,OAAO,IAAI;IACb;IAEA,IAAIG,YAAY,GAAGR,KAAK,CAACK,IAAI,CAACA,IAAI;IAClC,MAAMI,IAAI,GAAGb,WAAW,CAACD,CAAC,CAACe,OAAO,EAAEV,KAAK,CAACK,IAAI,CAACA,IAAI,CAAC;IACpD,IAAII,IAAI,EAAE;MACRD,YAAY,GAAGC,IAAI,CAACJ,IAAI;IAC1B;IAEA,OAAAM,iBAAA,CACGlB,EAAE,CAACM,eAAe;MACjBI,IAAI,EAAEA,IAAI;MAAA,IACVS,QAAQA,CAAA;QAAA,OAAEZ,KAAK,CAACY,QAAQ,IAAIZ,KAAK,CAACK,IAAI,CAACO,QAAQ;MAAA;MAAA,IAC/CP,IAAIA,CAAA;QAAA,OAAAM,iBAAA,CAAGb,cAAc;UAACO,IAAI,EAAEG;QAAY;MAAA;IAAA;EAG9C;EAEA,IAAIb,CAAC,CAACkB,SAAS,CAACN,EAAE,CAACP,KAAK,CAACK,IAAI,CAAC,EAAE;IAC9B,MAAMS,UAAU,GAAAH,iBAAA,CAAIb,cAAc;MAAA,IAACO,IAAIA,CAAA;QAAA,OAAEL,KAAK,CAACK,IAAI,CAACS,UAAU;MAAA;IAAA,EAAI;IAClE,MAAMC,MAAM,GAAAJ,iBAAA,CACTnB,EAAE,CAACwB,KAAK;MAAA,IAAAC,SAAA;QAAA,OAAAN,iBAAA,CACNd,mBAAmB,CAACqB,UAAU;UAAA,IAACb,IAAIA,CAAA;YAAA,OAAEL,KAAK,CAACK,IAAI,CAACc,UAAU;UAAA;QAAA;MAAA;IAAA,EAE9D;IAED,OAAAR,iBAAA,CACGlB,EAAE,CAACM,eAAe;MACjBI,IAAI,EAAEA,IAAI;MAAA,IACVE,IAAIA,CAAA;QAAA,aAEEU,MAAM,WAASD,UAAU;MAAA;IAAA;EAKrC;AACF","ignoreList":[]}
@@ -0,0 +1,19 @@
1
+ import { Children } from "@alloy-js/core";
2
+ import { Value } from "@typespec/compiler";
3
+ /**
4
+ * Properties for the {@link ValueExpression} component.
5
+ */
6
+ interface ValueExpressionProps {
7
+ /**
8
+ * The TypeSpec value to be converted to a JavaScript expression.
9
+ */
10
+ value: Value;
11
+ }
12
+ /**
13
+ * Generates a JavaScript value expression from a TypeSpec value.
14
+ * @param props properties for the value expression
15
+ * @returns {@link Children} representing the JavaScript value expression
16
+ */
17
+ export declare function ValueExpression(props: Readonly<ValueExpressionProps>): Children;
18
+ export {};
19
+ //# sourceMappingURL=value-expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-expression.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/value-expression.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAkB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;GAEG;AACH,UAAU,oBAAoB;IAC5B;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,QAAQ,CAoC/E"}
@@ -0,0 +1,72 @@
1
+ import { memo as _$memo } from "@alloy-js/core/jsx-runtime";
2
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
3
+ import * as ts from "@alloy-js/typescript";
4
+ import { compilerAssert } from "@typespec/compiler";
5
+
6
+ /**
7
+ * Properties for the {@link ValueExpression} component.
8
+ */
9
+
10
+ /**
11
+ * Generates a JavaScript value expression from a TypeSpec value.
12
+ * @param props properties for the value expression
13
+ * @returns {@link Children} representing the JavaScript value expression
14
+ */
15
+ export function ValueExpression(props) {
16
+ switch (props.value.valueKind) {
17
+ case "StringValue":
18
+ case "BooleanValue":
19
+ case "NullValue":
20
+ return _$createComponent(ts.ValueExpression, {
21
+ get jsValue() {
22
+ return props.value.value;
23
+ }
24
+ });
25
+ case "NumericValue":
26
+ if (props.value.value.asNumber()) {
27
+ return _$createComponent(ts.ValueExpression, {
28
+ get jsValue() {
29
+ return props.value.value.asNumber();
30
+ }
31
+ });
32
+ }
33
+ compilerAssert(props.value.value.isInteger, "BigInt value must be an integer", props.value);
34
+ return _$createComponent(ts.ValueExpression, {
35
+ get jsValue() {
36
+ return props.value.value.asBigInt();
37
+ }
38
+ });
39
+ case "ArrayValue":
40
+ return _$createComponent(ts.ArrayExpression, {
41
+ get jsValue() {
42
+ return props.value.values.map(v => _$createComponent(ValueExpression, {
43
+ value: v
44
+ }));
45
+ }
46
+ });
47
+ case "ScalarValue":
48
+ compilerAssert(props.value.value.name === "fromISO", `Unsupported scalar constructor ${props.value.value.name}`, props.value);
49
+ return _$createComponent(ValueExpression, {
50
+ get value() {
51
+ return props.value.value.args[0];
52
+ }
53
+ });
54
+ case "ObjectValue":
55
+ const jsProperties = {};
56
+ for (const [key, value] of props.value.properties) {
57
+ jsProperties[key] = ValueExpression({
58
+ value: value.value
59
+ });
60
+ }
61
+ return _$createComponent(ts.ObjectExpression, {
62
+ jsValue: jsProperties
63
+ });
64
+ case "EnumValue":
65
+ return _$createComponent(ts.ValueExpression, {
66
+ get jsValue() {
67
+ return props.value.value.value ?? props.value.value.name;
68
+ }
69
+ });
70
+ }
71
+ }
72
+ //# sourceMappingURL=value-expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-expression.js","names":["ts","compilerAssert","ValueExpression","props","value","valueKind","_$createComponent","jsValue","asNumber","isInteger","asBigInt","ArrayExpression","values","map","v","name","args","jsProperties","key","properties","ObjectExpression"],"sources":["../../../../src/typescript/components/value-expression.tsx"],"sourcesContent":[null],"mappings":";;AACA,OAAO,KAAKA,EAAE,MAAM,sBAAsB;AAC1C,SAASC,cAAc,QAAe,oBAAoB;;AAE1D;AACA;AACA;;AAQA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAACC,KAAqC,EAAY;EAC/E,QAAQA,KAAK,CAACC,KAAK,CAACC,SAAS;IAC3B,KAAK,aAAa;IAClB,KAAK,cAAc;IACnB,KAAK,WAAW;MACd,OAAAC,iBAAA,CAAQN,EAAE,CAACE,eAAe;QAAA,IAACK,OAAOA,CAAA;UAAA,OAAEJ,KAAK,CAACC,KAAK,CAACA,KAAK;QAAA;MAAA;IACvD,KAAK,cAAc;MACjB,IAAID,KAAK,CAACC,KAAK,CAACA,KAAK,CAACI,QAAQ,CAAC,CAAC,EAAE;QAChC,OAAAF,iBAAA,CAAQN,EAAE,CAACE,eAAe;UAAA,IAACK,OAAOA,CAAA;YAAA,OAAEJ,KAAK,CAACC,KAAK,CAACA,KAAK,CAACI,QAAQ,CAAC,CAAC;UAAA;QAAA;MAClE;MACAP,cAAc,CAACE,KAAK,CAACC,KAAK,CAACA,KAAK,CAACK,SAAS,EAAE,iCAAiC,EAAEN,KAAK,CAACC,KAAK,CAAC;MAC3F,OAAAE,iBAAA,CAAQN,EAAE,CAACE,eAAe;QAAA,IAACK,OAAOA,CAAA;UAAA,OAAEJ,KAAK,CAACC,KAAK,CAACA,KAAK,CAACM,QAAQ,CAAC,CAAC;QAAA;MAAA;IAClE,KAAK,YAAY;MACf,OAAAJ,iBAAA,CACGN,EAAE,CAACW,eAAe;QAAA,IACjBJ,OAAOA,CAAA;UAAA,OAAEJ,KAAK,CAACC,KAAK,CAACQ,MAAM,CAACC,GAAG,CAAEC,CAAC,IAAAR,iBAAA,CAC/BJ,eAAe;YAACE,KAAK,EAAEU;UAAC,EAC1B,CAAC;QAAA;MAAA;IAGR,KAAK,aAAa;MAChBb,cAAc,CACZE,KAAK,CAACC,KAAK,CAACA,KAAK,CAACW,IAAI,KAAK,SAAS,EACpC,kCAAkCZ,KAAK,CAACC,KAAK,CAACA,KAAK,CAACW,IAAI,EAAE,EAC1DZ,KAAK,CAACC,KACR,CAAC;MACD,OAAAE,iBAAA,CAAQJ,eAAe;QAAA,IAACE,KAAKA,CAAA;UAAA,OAAED,KAAK,CAACC,KAAK,CAACA,KAAK,CAACY,IAAI,CAAC,CAAC,CAAC;QAAA;MAAA;IAC1D,KAAK,aAAa;MAChB,MAAMC,YAAsC,GAAG,CAAC,CAAC;MACjD,KAAK,MAAM,CAACC,GAAG,EAAEd,KAAK,CAAC,IAAID,KAAK,CAACC,KAAK,CAACe,UAAU,EAAE;QACjDF,YAAY,CAACC,GAAG,CAAC,GAAGhB,eAAe,CAAC;UAAEE,KAAK,EAAEA,KAAK,CAACA;QAAM,CAAC,CAAC;MAC7D;MACA,OAAAE,iBAAA,CAAQN,EAAE,CAACoB,gBAAgB;QAACb,OAAO,EAAEU;MAAY;IACnD,KAAK,WAAW;MACd,OAAAX,iBAAA,CAAQN,EAAE,CAACE,eAAe;QAAA,IAACK,OAAOA,CAAA;UAAA,OAAEJ,KAAK,CAACC,KAAK,CAACA,KAAK,CAACA,KAAK,IAAID,KAAK,CAACC,KAAK,CAACA,KAAK,CAACW,IAAI;QAAA;MAAA;EACzF;AACF","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=value-expression.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-expression.test.d.ts","sourceRoot":"","sources":["../../../../test/typescript/components/value-expression.test.tsx"],"names":[],"mappings":""}
@@ -8,4 +8,9 @@ export declare function createEmitterFrameworkTestRunner(options?: {
8
8
  export declare function getProgram(code: string, options?: {
9
9
  libraries: "Http"[];
10
10
  }): Promise<Program>;
11
+ /**
12
+ * Initializes an empty program in the compiler.
13
+ * This is useful when you want to initialize the default TypeKits without any code.
14
+ */
15
+ export declare function initEmptyProgram(): Promise<void>;
11
16
  //# sourceMappingURL=test-host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-host.d.ts","sourceRoot":"","sources":["../../../test/typescript/test-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAQ7C,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAsB,0DASrD;AAED,wBAAsB,gCAAgC,CAAC,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,iEAK7F;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAsB,GACnD,OAAO,CAAC,OAAO,CAAC,CAUlB"}
1
+ {"version":3,"file":"test-host.d.ts","sourceRoot":"","sources":["../../../test/typescript/test-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAQ7C,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAsB,0DASrD;AAED,wBAAsB,gCAAgC,CAAC,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,iEAK7F;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAsB,GACnD,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/emitter-framework",
3
- "version": "0.6.0-dev.0",
3
+ "version": "0.6.0-dev.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -1,7 +1,14 @@
1
1
  import * as ay from "@alloy-js/core";
2
2
  import { Children, refkey as getRefkey, mapJoin } from "@alloy-js/core";
3
3
  import * as ts from "@alloy-js/typescript";
4
- import { Interface, Model, ModelProperty, Operation, RekeyableMap } from "@typespec/compiler";
4
+ import {
5
+ Interface,
6
+ isNeverType,
7
+ Model,
8
+ ModelProperty,
9
+ Operation,
10
+ RekeyableMap,
11
+ } from "@typespec/compiler";
5
12
  import { $ } from "@typespec/compiler/experimental/typekit";
6
13
  import { createRekeyableMap } from "@typespec/compiler/utils";
7
14
  import { reportDiagnostic } from "../../lib.js";
@@ -35,16 +42,6 @@ export function InterfaceDeclaration(props: InterfaceDeclarationProps) {
35
42
 
36
43
  const extendsType = props.extends ?? getExtendsType(props.type);
37
44
 
38
- const members = props.type ? [membersFromType(props.type)] : [];
39
-
40
- const children = [...members];
41
-
42
- if (Array.isArray(props.children)) {
43
- children.push(...props.children);
44
- } else if (props.children) {
45
- children.push(props.children);
46
- }
47
-
48
45
  return (
49
46
  <ts.InterfaceDeclaration
50
47
  default={props.default}
@@ -54,7 +51,7 @@ export function InterfaceDeclaration(props: InterfaceDeclarationProps) {
54
51
  refkey={refkey}
55
52
  extends={extendsType}
56
53
  >
57
- {children}
54
+ <InterfaceBody {...props} />
58
55
  </ts.InterfaceDeclaration>
59
56
  );
60
57
  }
@@ -69,16 +66,11 @@ export interface InterfaceExpressionProps extends ts.InterfaceExpressionProps {
69
66
  type: Model | Interface;
70
67
  }
71
68
 
72
- export function InterfaceExpression({ type, children }: InterfaceExpressionProps) {
73
- const members = type ? membersFromType(type) : [];
74
-
69
+ export function InterfaceExpression(props: InterfaceExpressionProps) {
75
70
  return (
76
- <>
77
- {"{"}
78
- {members}
79
- {children}
80
- {"}"}
81
- </>
71
+ <ay.Block>
72
+ <InterfaceBody {...props} />
73
+ </ay.Block>
82
74
  );
83
75
  }
84
76
 
@@ -124,11 +116,14 @@ function getExtendsType(type: Model | Interface): Children | undefined {
124
116
  );
125
117
  }
126
118
 
127
- function membersFromType(type: Model | Interface): Children {
119
+ /**
120
+ * Renders the members of an interface from its properties, including any additional children.
121
+ */
122
+ function InterfaceBody(props: TypedInterfaceDeclarationProps): Children {
128
123
  let typeMembers: RekeyableMap<string, ModelProperty | Operation> | undefined;
129
- if ($.model.is(type)) {
130
- typeMembers = $.model.getProperties(type);
131
- const additionalProperties = $.model.getAdditionalPropertiesRecord(type);
124
+ if ($.model.is(props.type)) {
125
+ typeMembers = $.model.getProperties(props.type);
126
+ const additionalProperties = $.model.getAdditionalPropertiesRecord(props.type);
132
127
  if (additionalProperties) {
133
128
  typeMembers.set(
134
129
  "additionalProperties",
@@ -140,14 +135,26 @@ function membersFromType(type: Model | Interface): Children {
140
135
  );
141
136
  }
142
137
  } else {
143
- typeMembers = createRekeyableMap(type.operations);
138
+ typeMembers = createRekeyableMap(props.type.operations);
144
139
  }
145
140
 
141
+ // Ensure that we have members to render, otherwise skip rendering the ender property.
142
+ const validTypeMembers = Array.from(typeMembers.values()).filter((member) => {
143
+ if ($.modelProperty.is(member) && isNeverType(member.type)) {
144
+ return false;
145
+ }
146
+ return true;
147
+ });
148
+ const enderProp = validTypeMembers.length > 0 ? { ender: ";" } : {};
149
+
146
150
  return (
147
- <ay.For each={Array.from(typeMembers.entries())} line>
148
- {([_, prop]) => {
149
- return <InterfaceMember type={prop} />;
150
- }}
151
- </ay.For>
151
+ <>
152
+ <ay.For each={validTypeMembers} line {...enderProp}>
153
+ {(typeMember) => {
154
+ return <InterfaceMember type={typeMember} />;
155
+ }}
156
+ </ay.For>
157
+ {props.children}
158
+ </>
152
159
  );
153
160
  }
@@ -1,4 +1,5 @@
1
- import { useTSNamePolicy } from "@alloy-js/typescript";
1
+ import * as ay from "@alloy-js/core";
2
+ import * as ts from "@alloy-js/typescript";
2
3
  import { isNeverType, ModelProperty, Operation } from "@typespec/compiler";
3
4
  import { $ } from "@typespec/compiler/experimental/typekit";
4
5
  import { getHttpPart } from "@typespec/http";
@@ -10,37 +11,47 @@ export interface InterfaceMemberProps {
10
11
  optional?: boolean;
11
12
  }
12
13
 
13
- export function InterfaceMember({ type, optional }: InterfaceMemberProps) {
14
- const namer = useTSNamePolicy();
15
- const name = namer.getName(type.name, "object-member-getter");
14
+ export function InterfaceMember(props: InterfaceMemberProps) {
15
+ const namer = ts.useTSNamePolicy();
16
+ const name = namer.getName(props.type.name, "object-member-getter");
16
17
 
17
- if ($.modelProperty.is(type)) {
18
- const optionality = optional === true || type.optional === true ? "?" : "";
19
-
20
- if (isNeverType(type.type)) {
18
+ if ($.modelProperty.is(props.type)) {
19
+ if (isNeverType(props.type.type)) {
21
20
  return null;
22
21
  }
23
22
 
24
- let unpackedType = type.type;
25
- const part = getHttpPart($.program, type.type);
23
+ let unpackedType = props.type.type;
24
+ const part = getHttpPart($.program, props.type.type);
26
25
  if (part) {
27
26
  unpackedType = part.type;
28
27
  }
29
28
 
30
29
  return (
31
- <>
32
- "{name}"{optionality}: <TypeExpression type={unpackedType} />;
33
- </>
30
+ <ts.InterfaceMember
31
+ name={name}
32
+ optional={props.optional ?? props.type.optional}
33
+ type={<TypeExpression type={unpackedType} />}
34
+ />
34
35
  );
35
36
  }
36
37
 
37
- if ($.operation.is(type)) {
38
- const returnType = <TypeExpression type={type.returnType} />;
39
- const params = <FunctionDeclaration.Parameters type={type.parameters} />;
38
+ if ($.operation.is(props.type)) {
39
+ const returnType = <TypeExpression type={props.type.returnType} />;
40
+ const params = (
41
+ <ay.Scope>
42
+ <FunctionDeclaration.Parameters type={props.type.parameters} />
43
+ </ay.Scope>
44
+ );
45
+
40
46
  return (
41
- <>
42
- {name}({params}): {returnType};
43
- </>
47
+ <ts.InterfaceMember
48
+ name={name}
49
+ type={
50
+ <>
51
+ ({params}) =&gt {returnType}
52
+ </>
53
+ }
54
+ />
44
55
  );
45
56
  }
46
57
  }
@@ -0,0 +1,56 @@
1
+ import { Children } from "@alloy-js/core";
2
+ import * as ts from "@alloy-js/typescript";
3
+ import { compilerAssert, Value } from "@typespec/compiler";
4
+
5
+ /**
6
+ * Properties for the {@link ValueExpression} component.
7
+ */
8
+ interface ValueExpressionProps {
9
+ /**
10
+ * The TypeSpec value to be converted to a JavaScript expression.
11
+ */
12
+ value: Value;
13
+ }
14
+
15
+ /**
16
+ * Generates a JavaScript value expression from a TypeSpec value.
17
+ * @param props properties for the value expression
18
+ * @returns {@link Children} representing the JavaScript value expression
19
+ */
20
+ export function ValueExpression(props: Readonly<ValueExpressionProps>): Children {
21
+ switch (props.value.valueKind) {
22
+ case "StringValue":
23
+ case "BooleanValue":
24
+ case "NullValue":
25
+ return <ts.ValueExpression jsValue={props.value.value} />;
26
+ case "NumericValue":
27
+ if (props.value.value.asNumber()) {
28
+ return <ts.ValueExpression jsValue={props.value.value.asNumber()} />;
29
+ }
30
+ compilerAssert(props.value.value.isInteger, "BigInt value must be an integer", props.value);
31
+ return <ts.ValueExpression jsValue={props.value.value.asBigInt()} />;
32
+ case "ArrayValue":
33
+ return (
34
+ <ts.ArrayExpression
35
+ jsValue={props.value.values.map((v) => (
36
+ <ValueExpression value={v} />
37
+ ))}
38
+ />
39
+ );
40
+ case "ScalarValue":
41
+ compilerAssert(
42
+ props.value.value.name === "fromISO",
43
+ `Unsupported scalar constructor ${props.value.value.name}`,
44
+ props.value,
45
+ );
46
+ return <ValueExpression value={props.value.value.args[0]} />;
47
+ case "ObjectValue":
48
+ const jsProperties: Record<string, Children> = {};
49
+ for (const [key, value] of props.value.properties) {
50
+ jsProperties[key] = ValueExpression({ value: value.value });
51
+ }
52
+ return <ts.ObjectExpression jsValue={jsProperties} />;
53
+ case "EnumValue":
54
+ return <ts.ValueExpression jsValue={props.value.value.value ?? props.value.value.name} />;
55
+ }
56
+ }
@@ -337,6 +337,39 @@ describe("Typescript Interface", () => {
337
337
  expect(actualContent).toBe(expectedContent);
338
338
  });
339
339
 
340
+ it("renders an empty interface with a never-typed member", async () => {
341
+ const program = await getProgram(`
342
+ namespace DemoService;
343
+
344
+ model Widget{
345
+ property: never;
346
+ }
347
+ `);
348
+
349
+ const [namespace] = program.resolveTypeReference("DemoService");
350
+ const models = Array.from((namespace as Namespace).models.values());
351
+
352
+ const res = render(
353
+ <Output>
354
+ <SourceFile path="test.ts">
355
+ <InterfaceDeclaration export type={models[0]} />
356
+ </SourceFile>
357
+ </Output>,
358
+ );
359
+
360
+ const testFile = res.contents.find((file) => file.path === "test.ts");
361
+ assert(testFile, "test.ts file not rendered");
362
+ const actualContent = await format(testFile.contents as string, { parser: "typescript" });
363
+ const expectedContent = await format(
364
+ `export interface Widget {
365
+ }`,
366
+ {
367
+ parser: "typescript",
368
+ },
369
+ );
370
+ expect(actualContent).toBe(expectedContent);
371
+ });
372
+
340
373
  it("can override interface name", async () => {
341
374
  const program = await getProgram(`
342
375
  namespace DemoService;
@@ -505,7 +538,7 @@ describe("Typescript Interface", () => {
505
538
  });
506
539
  });
507
540
 
508
- describe.skip("Bound to Interface", () => {
541
+ describe("Bound to Interface", () => {
509
542
  it("creates an interface", async () => {
510
543
  const program = await getProgram(`
511
544
  namespace DemoService;
@@ -531,7 +564,7 @@ describe("Typescript Interface", () => {
531
564
  const actualContent = await format(testFile.contents as string, { parser: "typescript" });
532
565
  const expectedContent = await format(
533
566
  `export interface WidgetOperations {
534
- getName(id: string): string;
567
+ getName: (id: string) => string;
535
568
  }`,
536
569
  {
537
570
  parser: "typescript",
@@ -572,8 +605,8 @@ describe("Typescript Interface", () => {
572
605
  const actualContent = await format(testFile.contents as string, { parser: "typescript" });
573
606
  const expectedContent = await format(
574
607
  `export interface WidgetOperations {
575
- getName(foo: Foo): string;
576
- getOtherName(name: string): string
608
+ getName: (foo: Foo) => string;
609
+ getOtherName: (name: string) => string
577
610
  }
578
611
  export interface Foo {
579
612
  name: string;
@@ -621,7 +654,7 @@ describe("Typescript Interface", () => {
621
654
  const actualContent = await format(testFile.contents as string, { parser: "typescript" });
622
655
  const expectedContent = await format(
623
656
  `export interface WidgetOperations {
624
- getName(id: string): Widget;
657
+ getName: (id: string) => Widget;
625
658
  }
626
659
  export interface Widget {
627
660
  id: string;
@@ -674,8 +707,8 @@ describe("Typescript Interface", () => {
674
707
  const actualContent = await format(testFile.contents as string, { parser: "typescript" });
675
708
  const expectedContent = await format(
676
709
  `export interface WidgetOperationsExtended {
677
- getName(id: string): Widget;
678
- delete(id: string): void;
710
+ getName: (id: string) => Widget;
711
+ delete: (id: string) => void;
679
712
  }
680
713
  export interface Widget {
681
714
  id: string;
@@ -36,7 +36,7 @@ describe("Typescript Enum Member Expression", () => {
36
36
  three = 3
37
37
  }
38
38
  interface Bar {
39
- "one": Foo.one;
39
+ one: Foo.one;
40
40
  }
41
41
  `);
42
42
  });
@@ -70,7 +70,7 @@ describe("Typescript Enum Member Expression", () => {
70
70
  three = "three"
71
71
  }
72
72
  interface Bar {
73
- "one": Foo.one;
73
+ one: Foo.one;
74
74
  }
75
75
  `);
76
76
  });
@@ -102,7 +102,7 @@ describe("Typescript Union Member Expression", () => {
102
102
  expect(output).toBe(d`
103
103
  type Foo = 1 | 2 | 3;
104
104
  interface Bar {
105
- "one": 1;
105
+ one: 1;
106
106
  }
107
107
  `);
108
108
  });
@@ -132,7 +132,7 @@ describe("Typescript Union Member Expression", () => {
132
132
  expect(output).toBe(d`
133
133
  type Foo = "one" | "two" | "three";
134
134
  interface Bar {
135
- "one": "one";
135
+ one: "one";
136
136
  }
137
137
  `);
138
138
  });
@@ -0,0 +1,236 @@
1
+ import { Output, render } from "@alloy-js/core";
2
+ import { dedent } from "@alloy-js/core/testing";
3
+ import { SourceFile } from "@alloy-js/typescript";
4
+ import { EnumValue, Model, Namespace, Numeric, NumericValue, Value } from "@typespec/compiler";
5
+ import { $ } from "@typespec/compiler/experimental/typekit";
6
+ import { assert, beforeAll, describe, expect, it } from "vitest";
7
+ import { ValueExpression } from "../../../src/typescript/components/value-expression.js";
8
+ import { getProgram, initEmptyProgram } from "../test-host.js";
9
+
10
+ beforeAll(async () => {
11
+ await initEmptyProgram();
12
+ });
13
+
14
+ it("renders strings", async () => {
15
+ const value = $.value.createString("test");
16
+
17
+ await testValueExpression(value, `"test"`);
18
+ });
19
+
20
+ describe("numeric values", () => {
21
+ it("renders integers", async () => {
22
+ const value = $.value.createNumeric(42);
23
+
24
+ await testValueExpression(value, `42`);
25
+ });
26
+
27
+ it("renders decimals", async () => {
28
+ const value = $.value.createNumeric(42.5);
29
+
30
+ await testValueExpression(value, `42.5`);
31
+ });
32
+
33
+ it("renders bigints", async () => {
34
+ const digits = "1234567890123456789012345678901234567890";
35
+ const value: NumericValue = {
36
+ entityKind: "Value",
37
+ valueKind: "NumericValue",
38
+ value: Numeric(digits),
39
+ } as NumericValue;
40
+
41
+ await testValueExpression(value, `${digits}n`);
42
+ });
43
+
44
+ it("throws on invalid numbers", async () => {
45
+ const digits = "123456789123456789.112233445566778899";
46
+ const value: NumericValue = {
47
+ entityKind: "Value",
48
+ valueKind: "NumericValue",
49
+ value: Numeric(digits),
50
+ } as NumericValue;
51
+
52
+ await expect(testValueExpression(value, ``)).rejects.toThrow("BigInt value must be an integer");
53
+ });
54
+ });
55
+
56
+ it("renders booleans", async () => {
57
+ const value = $.value.createBoolean(true);
58
+ await testValueExpression(value, `true`);
59
+ });
60
+
61
+ it("renders nulls", async () => {
62
+ const value = {
63
+ entityKind: "Value",
64
+ valueKind: "NullValue",
65
+ value: null,
66
+ } as Value;
67
+ await testValueExpression(value, `null`);
68
+ });
69
+
70
+ it("renders empty arrays", async () => {
71
+ // Can be replaced with with TypeKit once #6976 is implemented
72
+ const value = {
73
+ entityKind: "Value",
74
+ valueKind: "ArrayValue",
75
+ values: [],
76
+ } as unknown as Value;
77
+ await testValueExpression(value, `[]`);
78
+ });
79
+
80
+ it("renders arrays with mixed values", async () => {
81
+ // Can be replaced with with TypeKit once #6976 is implemented
82
+ const value = {
83
+ entityKind: "Value",
84
+ valueKind: "ArrayValue",
85
+ values: [$.value.createString("foo"), $.value.createNumeric(42), $.value.createBoolean(true)],
86
+ } as Value;
87
+ await testValueExpression(value, `["foo", 42, true]`);
88
+ });
89
+
90
+ it("renders scalars", async () => {
91
+ const program = await getProgram(`
92
+ namespace DemoService;
93
+ model DateRange {
94
+ @encode("rfc7231")
95
+ minDate: utcDateTime = utcDateTime.fromISO("2024-02-15T18:36:03Z");
96
+ }
97
+ `);
98
+ const [namespace] = program.resolveTypeReference("DemoService");
99
+ const dateRange = (namespace as Namespace).models.get("DateRange");
100
+ const minDate = dateRange?.properties.get("minDate")?.defaultValue;
101
+ assert.exists(minDate, "unable to find minDate property");
102
+ await testValueExpression(minDate, `"2024-02-15T18:36:03Z"`);
103
+ });
104
+
105
+ it("throws on unsupported scalar", async () => {
106
+ const program = await getProgram(`
107
+ namespace DemoService;
108
+
109
+ scalar ipv4 extends string {
110
+ init fromInt(value: uint32);
111
+ }
112
+
113
+ @example (#{ip: ipv4.fromInt(2130706433)})
114
+ model IpAddress {
115
+ ip: ipv4;
116
+ }
117
+ `);
118
+ const [namespace] = program.resolveTypeReference("DemoService");
119
+ const model = (namespace as Namespace).models.get("IpAddress");
120
+ assert.exists(model, "unable to find IpAddress model");
121
+
122
+ const value = getExampleValue(model);
123
+ await expect(testValueExpression(value, ``)).rejects.toThrow(
124
+ /Unsupported scalar constructor fromInt/,
125
+ );
126
+ });
127
+
128
+ it("renders empty objects", async () => {
129
+ // Can be replaced with with TypeKit once #6976 is implemented
130
+ const program = await getProgram(`
131
+ namespace DemoService;
132
+ @example(#{})
133
+ model ObjectValue {};
134
+ `);
135
+ const [namespace] = program.resolveTypeReference("DemoService");
136
+ const model = (namespace as Namespace).models.get("ObjectValue");
137
+ assert.exists(model, "unable to find ObjectValue model");
138
+
139
+ const value = getExampleValue(model);
140
+ await testValueExpression(value, `{}`);
141
+ });
142
+
143
+ it("renders objects with properties", async () => {
144
+ // Can be replaced with with TypeKit once #6976 is implemented
145
+ const program = await getProgram(`
146
+ namespace DemoService;
147
+ @example(#{a: 5, b: "foo", c: true})
148
+ model ObjectValue {
149
+ a: int32;
150
+ b: string;
151
+ c: boolean;
152
+ };
153
+ `);
154
+ const [namespace] = program.resolveTypeReference("DemoService");
155
+ const model = (namespace as Namespace).models.get("ObjectValue");
156
+ assert.exists(model, "unable to find ObjectValue model");
157
+
158
+ const value = getExampleValue(model);
159
+ await testValueExpression(
160
+ value,
161
+ dedent(`
162
+ {
163
+ a: 5,
164
+ b: "foo",
165
+ c: true,
166
+ }`),
167
+ );
168
+ });
169
+
170
+ it("renders enums", async () => {
171
+ // Can be replaced with with TypeKit once #6976 is implemented
172
+ const program = await getProgram(`
173
+ namespace DemoService;
174
+ enum Color {
175
+ Red,
176
+ Green: 3,
177
+ Blue
178
+ }
179
+ `);
180
+ const [namespace] = program.resolveTypeReference("DemoService");
181
+ const colors = (namespace as Namespace).enums.get("Color");
182
+ assert.exists(colors, "unable to find Color enum");
183
+
184
+ const red = colors?.members.get("Red");
185
+ assert.exists(red, "unable to find Red enum member");
186
+ await testValueExpression(
187
+ {
188
+ valueKind: "EnumValue",
189
+ value: red,
190
+ } as EnumValue,
191
+ `"Red"`,
192
+ );
193
+
194
+ const green = colors?.members.get("Green");
195
+ assert.exists(green, "unable to find Green enum member");
196
+ await testValueExpression(
197
+ {
198
+ valueKind: "EnumValue",
199
+ value: green,
200
+ } as EnumValue,
201
+ `3`,
202
+ );
203
+ });
204
+
205
+ /**
206
+ * Helper that renders a value expression and checks the output against the expected value.
207
+ */
208
+ async function testValueExpression(value: Value, expected: string) {
209
+ const prefix = "const val = ";
210
+ const res = render(
211
+ <Output>
212
+ <SourceFile path="test.ts">
213
+ {prefix}
214
+ <ValueExpression value={value} />
215
+ </SourceFile>
216
+ </Output>,
217
+ );
218
+ const testFile = res.contents.find((file) => file.path === "test.ts");
219
+
220
+ assert.exists(testFile, "test.ts file not rendered");
221
+
222
+ assert.equal(
223
+ testFile.contents,
224
+ `${prefix}${expected}`,
225
+ "test.ts file contents do not match expected",
226
+ );
227
+ }
228
+
229
+ /**
230
+ * Extracts the value marked with the @example decorator from a model.
231
+ */
232
+ function getExampleValue(model: Model): Value {
233
+ const decorator = model?.decorators.find((d) => d.definition?.name === "@example");
234
+ assert.exists(decorator?.args[0]?.value, "unable to find example decorator");
235
+ return decorator.args[0].value as Value;
236
+ }
@@ -39,3 +39,11 @@ export async function getProgram(
39
39
  expectDiagnosticEmpty(diagnostics);
40
40
  return wrapper.program;
41
41
  }
42
+
43
+ /**
44
+ * Initializes an empty program in the compiler.
45
+ * This is useful when you want to initialize the default TypeKits without any code.
46
+ */
47
+ export async function initEmptyProgram(): Promise<void> {
48
+ await getProgram("");
49
+ }