@typespec/http-server-js 0.58.0-alpha.12-dev.0 → 0.58.0-alpha.12-dev.1
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.
- package/dist/generated-defs/helpers/datetime.d.ts +4 -0
- package/dist/generated-defs/helpers/datetime.d.ts.map +1 -0
- package/dist/generated-defs/helpers/datetime.js +256 -0
- package/dist/generated-defs/helpers/datetime.js.map +1 -0
- package/dist/generated-defs/helpers/index.d.ts.map +1 -1
- package/dist/generated-defs/helpers/index.js +1 -0
- package/dist/generated-defs/helpers/index.js.map +1 -1
- package/dist/src/common/declaration.js +1 -1
- package/dist/src/common/declaration.js.map +1 -1
- package/dist/src/common/reference.js +1 -1
- package/dist/src/common/reference.js.map +1 -1
- package/dist/src/common/scalar.d.ts +175 -22
- package/dist/src/common/scalar.d.ts.map +1 -1
- package/dist/src/common/scalar.js +420 -93
- package/dist/src/common/scalar.js.map +1 -1
- package/dist/src/common/serialization/index.d.ts +2 -2
- package/dist/src/common/serialization/index.d.ts.map +1 -1
- package/dist/src/common/serialization/index.js +9 -3
- package/dist/src/common/serialization/index.js.map +1 -1
- package/dist/src/common/serialization/json.d.ts +2 -2
- package/dist/src/common/serialization/json.d.ts.map +1 -1
- package/dist/src/common/serialization/json.js +144 -42
- package/dist/src/common/serialization/json.js.map +1 -1
- package/dist/src/helpers/datetime.d.ts +92 -0
- package/dist/src/helpers/datetime.d.ts.map +1 -0
- package/dist/src/helpers/datetime.js +151 -0
- package/dist/src/helpers/datetime.js.map +1 -0
- package/dist/src/http/server/index.d.ts.map +1 -1
- package/dist/src/http/server/index.js +17 -12
- package/dist/src/http/server/index.js.map +1 -1
- package/dist/src/http/server/multipart.js +1 -1
- package/dist/src/http/server/multipart.js.map +1 -1
- package/dist/src/lib.d.ts +10 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +6 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/util/case.d.ts +9 -0
- package/dist/src/util/case.d.ts.map +1 -1
- package/dist/src/util/case.js +18 -0
- package/dist/src/util/case.js.map +1 -1
- package/dist/src/util/differentiate.d.ts +4 -4
- package/dist/src/util/differentiate.d.ts.map +1 -1
- package/dist/src/util/differentiate.js +10 -10
- package/dist/src/util/differentiate.js.map +1 -1
- package/generated-defs/helpers/datetime.ts +263 -0
- package/generated-defs/helpers/index.ts +1 -0
- package/package.json +7 -7
- package/src/common/declaration.ts +1 -1
- package/src/common/reference.ts +1 -1
- package/src/common/scalar.ts +709 -103
- package/src/common/serialization/index.ts +11 -4
- package/src/common/serialization/json.ts +174 -52
- package/src/helpers/datetime.ts +235 -0
- package/src/http/server/index.ts +29 -15
- package/src/http/server/multipart.ts +1 -1
- package/src/lib.ts +6 -0
- package/src/util/case.ts +19 -0
- package/src/util/differentiate.ts +15 -8
- package/temp/tsconfig.tsbuildinfo +1 -1
- package/test/datetime.test.ts +226 -0
- package/test/scalar.test.ts +345 -0
package/src/http/server/index.ts
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from "@typespec/http";
|
|
13
13
|
import { createOrGetModuleForNamespace } from "../../common/namespace.js";
|
|
14
14
|
import { emitTypeReference, isValueLiteralType } from "../../common/reference.js";
|
|
15
|
-
import { parseTemplateForScalar } from "../../common/scalar.js";
|
|
16
15
|
import {
|
|
17
16
|
SerializableType,
|
|
18
17
|
isSerializationRequired,
|
|
@@ -33,6 +32,7 @@ import { emitMultipart, emitMultipartLegacy } from "./multipart.js";
|
|
|
33
32
|
|
|
34
33
|
import { module as headerHelpers } from "../../../generated-defs/helpers/header.js";
|
|
35
34
|
import { module as httpHelpers } from "../../../generated-defs/helpers/http.js";
|
|
35
|
+
import { getJsScalar } from "../../common/scalar.js";
|
|
36
36
|
import { requiresJsonSerialization } from "../../common/serialization/json.js";
|
|
37
37
|
|
|
38
38
|
const DEFAULT_CONTENT_TYPE = "application/json";
|
|
@@ -127,7 +127,7 @@ function* emitRawServerOperation(
|
|
|
127
127
|
|
|
128
128
|
const queryParams: Extract<HttpOperationParameter, { type: "query" }>[] = [];
|
|
129
129
|
|
|
130
|
-
const parsedParams = new
|
|
130
|
+
const parsedParams = new Map<ModelProperty, HttpOperationParameter>();
|
|
131
131
|
|
|
132
132
|
for (const parameter of operation.parameters.parameters) {
|
|
133
133
|
const resolvedParameter =
|
|
@@ -140,11 +140,11 @@ function* emitRawServerOperation(
|
|
|
140
140
|
throw new UnimplementedError("cookie parameters");
|
|
141
141
|
case "query":
|
|
142
142
|
queryParams.push(parameter);
|
|
143
|
-
parsedParams.
|
|
143
|
+
parsedParams.set(resolvedParameter, parameter);
|
|
144
144
|
break;
|
|
145
145
|
case "path":
|
|
146
146
|
// Already handled above.
|
|
147
|
-
parsedParams.
|
|
147
|
+
parsedParams.set(resolvedParameter, parameter);
|
|
148
148
|
break;
|
|
149
149
|
default:
|
|
150
150
|
throw new Error(
|
|
@@ -228,7 +228,7 @@ function* emitRawServerOperation(
|
|
|
228
228
|
|
|
229
229
|
let value: string;
|
|
230
230
|
|
|
231
|
-
if (requiresJsonSerialization(ctx, body.type)) {
|
|
231
|
+
if (requiresJsonSerialization(ctx, module, body.type)) {
|
|
232
232
|
value = `${bodyTypeName}.fromJsonObject(JSON.parse(body))`;
|
|
233
233
|
} else {
|
|
234
234
|
value = `JSON.parse(body)`;
|
|
@@ -283,13 +283,17 @@ function* emitRawServerOperation(
|
|
|
283
283
|
} else {
|
|
284
284
|
const resolvedParameter = param.type.kind === "ModelProperty" ? param.type : param;
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
const httpOperationParam = parsedParams.get(resolvedParameter);
|
|
287
|
+
|
|
288
|
+
if (resolvedParameter.type.kind === "Scalar" && httpOperationParam) {
|
|
289
|
+
const jsScalar = getJsScalar(ctx, module, resolvedParameter.type, resolvedParameter);
|
|
290
|
+
|
|
291
|
+
const encoder = jsScalar.http[httpOperationParam.type];
|
|
292
|
+
|
|
293
|
+
paramBaseExpression = encoder.decode(paramNameCase.camelCase);
|
|
294
|
+
} else {
|
|
295
|
+
paramBaseExpression = paramNameCase.camelCase;
|
|
296
|
+
}
|
|
293
297
|
}
|
|
294
298
|
|
|
295
299
|
if (param.optional) {
|
|
@@ -360,7 +364,7 @@ function* emitResultProcessing(
|
|
|
360
364
|
// Single target type
|
|
361
365
|
yield* emitResultProcessingForType(ctx, names, t, module);
|
|
362
366
|
} else {
|
|
363
|
-
const codeTree = differentiateUnion(ctx, t);
|
|
367
|
+
const codeTree = differentiateUnion(ctx, module, t);
|
|
364
368
|
|
|
365
369
|
yield* writeCodeTree(ctx, codeTree, {
|
|
366
370
|
subject: names.result,
|
|
@@ -452,7 +456,12 @@ function* emitResultProcessingForType(
|
|
|
452
456
|
|
|
453
457
|
if (body) {
|
|
454
458
|
const bodyCase = parseCase(body.name);
|
|
455
|
-
const serializationRequired = isSerializationRequired(
|
|
459
|
+
const serializationRequired = isSerializationRequired(
|
|
460
|
+
ctx,
|
|
461
|
+
module,
|
|
462
|
+
body.type,
|
|
463
|
+
"application/json",
|
|
464
|
+
);
|
|
456
465
|
requireSerialization(ctx, body.type, "application/json");
|
|
457
466
|
|
|
458
467
|
yield `${names.ctx}.response.setHeader("content-type", "application/json");`;
|
|
@@ -469,7 +478,12 @@ function* emitResultProcessingForType(
|
|
|
469
478
|
if (allMetadataIsRemoved) {
|
|
470
479
|
yield `${names.ctx}.response.end();`;
|
|
471
480
|
} else {
|
|
472
|
-
const serializationRequired = isSerializationRequired(
|
|
481
|
+
const serializationRequired = isSerializationRequired(
|
|
482
|
+
ctx,
|
|
483
|
+
module,
|
|
484
|
+
target,
|
|
485
|
+
"application/json",
|
|
486
|
+
);
|
|
473
487
|
requireSerialization(ctx, target, "application/json");
|
|
474
488
|
|
|
475
489
|
yield `${names.ctx}.response.setHeader("content-type", "application/json");`;
|
|
@@ -167,7 +167,7 @@ export function* emitMultipart(
|
|
|
167
167
|
yield ` const __object = JSON.parse(Buffer.concat(__chunks).toString("utf-8"));`;
|
|
168
168
|
yield "";
|
|
169
169
|
|
|
170
|
-
if (requiresJsonSerialization(ctx, namedPart.body.type)) {
|
|
170
|
+
if (requiresJsonSerialization(ctx, module, namedPart.body.type)) {
|
|
171
171
|
const bodyTypeReference = emitTypeReference(
|
|
172
172
|
ctx,
|
|
173
173
|
namedPart.body.type,
|
package/src/lib.ts
CHANGED
|
@@ -125,6 +125,12 @@ export const $lib = createTypeSpecLibrary({
|
|
|
125
125
|
"An OpenAPI3 document could not be generated for this service because versioned services are not yet supported by the HTTP server emitter for JavaScript.",
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
|
+
"unknown-encoding": {
|
|
129
|
+
severity: "error",
|
|
130
|
+
messages: {
|
|
131
|
+
default: paramMessage`Unknown encoding '${"encoding"}' to type '${"target"}' for type '${"type"}'.`,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
128
134
|
},
|
|
129
135
|
});
|
|
130
136
|
|
package/src/util/case.ts
CHANGED
|
@@ -28,6 +28,25 @@ export function isUnspeakable(name: string): boolean {
|
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns an access expression for a given subject and key.
|
|
35
|
+
*
|
|
36
|
+
* If the access can be performed using dot notation, it will. Otherwise, bracket notation will be used.
|
|
37
|
+
*
|
|
38
|
+
* @param subject - the expression to access
|
|
39
|
+
* @param key - the key to access within the subject, must be an index value literal, not an expression
|
|
40
|
+
*/
|
|
41
|
+
export function access(subject: string, key: string | number): string {
|
|
42
|
+
subject = JS_IDENTIFIER.test(subject) ? subject : `(${subject})`;
|
|
43
|
+
if (typeof key === "string" && JS_IDENTIFIER.test(key)) {
|
|
44
|
+
return `${subject}.${key}`;
|
|
45
|
+
} else {
|
|
46
|
+
return `${subject}[${JSON.stringify(key)}]`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
31
50
|
/**
|
|
32
51
|
* Destructures a name into its components.
|
|
33
52
|
*
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
isUnknownType,
|
|
22
22
|
} from "@typespec/compiler";
|
|
23
23
|
import { getJsScalar } from "../common/scalar.js";
|
|
24
|
-
import { JsContext } from "../ctx.js";
|
|
24
|
+
import { JsContext, Module } from "../ctx.js";
|
|
25
25
|
import { reportDiagnostic } from "../lib.js";
|
|
26
26
|
import { isUnspeakable, parseCase } from "./case.js";
|
|
27
27
|
import { UnimplementedError, UnreachableError } from "./error.js";
|
|
@@ -287,6 +287,7 @@ const PROPERTY_ID = (prop: ModelProperty) => parseCase(prop.name).camelCase;
|
|
|
287
287
|
*/
|
|
288
288
|
export function differentiateUnion(
|
|
289
289
|
ctx: JsContext,
|
|
290
|
+
module: Module,
|
|
290
291
|
union: Union,
|
|
291
292
|
renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID,
|
|
292
293
|
): CodeTree {
|
|
@@ -313,7 +314,7 @@ export function differentiateUnion(
|
|
|
313
314
|
}
|
|
314
315
|
}
|
|
315
316
|
|
|
316
|
-
return differentiateTypes(ctx, cases, renderPropertyName);
|
|
317
|
+
return differentiateTypes(ctx, module, cases, renderPropertyName);
|
|
317
318
|
} else {
|
|
318
319
|
const property = (variants[0].type as Model).properties.get(discriminator)!;
|
|
319
320
|
|
|
@@ -353,6 +354,7 @@ export function differentiateUnion(
|
|
|
353
354
|
*/
|
|
354
355
|
export function differentiateTypes(
|
|
355
356
|
ctx: JsContext,
|
|
357
|
+
module: Module,
|
|
356
358
|
cases: Set<PreciseType>,
|
|
357
359
|
renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID,
|
|
358
360
|
): CodeTree {
|
|
@@ -378,7 +380,7 @@ export function differentiateTypes(
|
|
|
378
380
|
const intrinsics = (categories.Intrinsic as (VoidType | NullType)[]) ?? [];
|
|
379
381
|
|
|
380
382
|
if (literals.length + scalars.length + intrinsics.length === 0) {
|
|
381
|
-
return differentiateModelTypes(ctx, select(models, cases), renderPropertyName);
|
|
383
|
+
return differentiateModelTypes(ctx, module, select(models, cases), renderPropertyName);
|
|
382
384
|
} else {
|
|
383
385
|
const branches: IfBranch[] = [];
|
|
384
386
|
|
|
@@ -419,7 +421,7 @@ export function differentiateTypes(
|
|
|
419
421
|
const scalarRepresentations = new Map<string, Scalar>();
|
|
420
422
|
|
|
421
423
|
for (const scalar of scalars) {
|
|
422
|
-
const jsScalar = getJsScalar(ctx
|
|
424
|
+
const jsScalar = getJsScalar(ctx, module, scalar, scalar).type;
|
|
423
425
|
|
|
424
426
|
if (scalarRepresentations.has(jsScalar)) {
|
|
425
427
|
reportDiagnostic(ctx.program, {
|
|
@@ -503,7 +505,7 @@ export function differentiateTypes(
|
|
|
503
505
|
branches,
|
|
504
506
|
else:
|
|
505
507
|
models.length > 0
|
|
506
|
-
? differentiateModelTypes(ctx, select(models, cases), renderPropertyName)
|
|
508
|
+
? differentiateModelTypes(ctx, module, select(models, cases), renderPropertyName)
|
|
507
509
|
: undefined,
|
|
508
510
|
};
|
|
509
511
|
}
|
|
@@ -563,10 +565,14 @@ function getJsValue(ctx: JsContext, literal: JsLiteralType | EnumMember): Litera
|
|
|
563
565
|
*/
|
|
564
566
|
type IntegerRange = [number, number];
|
|
565
567
|
|
|
566
|
-
function getIntegerRange(
|
|
568
|
+
function getIntegerRange(
|
|
569
|
+
ctx: JsContext,
|
|
570
|
+
module: Module,
|
|
571
|
+
property: ModelProperty,
|
|
572
|
+
): IntegerRange | false {
|
|
567
573
|
if (
|
|
568
574
|
property.type.kind === "Scalar" &&
|
|
569
|
-
getJsScalar(ctx
|
|
575
|
+
getJsScalar(ctx, module, property.type, property).type === "number"
|
|
570
576
|
) {
|
|
571
577
|
const minValue = getMinValue(ctx.program, property);
|
|
572
578
|
const maxValue = getMaxValue(ctx.program, property);
|
|
@@ -594,6 +600,7 @@ function overlaps(range: IntegerRange, other: IntegerRange): boolean {
|
|
|
594
600
|
*/
|
|
595
601
|
export function differentiateModelTypes(
|
|
596
602
|
ctx: JsContext,
|
|
603
|
+
module: Module,
|
|
597
604
|
models: Set<Model>,
|
|
598
605
|
renderPropertyName: (prop: ModelProperty) => string = PROPERTY_ID,
|
|
599
606
|
): CodeTree {
|
|
@@ -656,7 +663,7 @@ export function differentiateModelTypes(
|
|
|
656
663
|
|
|
657
664
|
// CASE - unique range
|
|
658
665
|
|
|
659
|
-
const range = getIntegerRange(ctx, prop);
|
|
666
|
+
const range = getIntegerRange(ctx, module, prop);
|
|
660
667
|
if (range) {
|
|
661
668
|
let ranges = propertyRanges.get(renderedPropName);
|
|
662
669
|
if (!ranges) {
|