feat: add @type? optional notation

This commit is contained in:
2026-04-17 11:41:06 +08:00
parent 1f3a812728
commit 075045223f
5 changed files with 96 additions and 20 deletions
+21 -4
View File
@@ -82,7 +82,11 @@ function resolveReferenceId(
}
function parseReferenceIds(schema: ReferenceSchema, valueString: string): unknown {
const valueParser = new ReferenceValueParser(valueString.trim());
const trimmed = valueString.trim();
if (schema.isOptional && trimmed === '') {
return null;
}
const valueParser = new ReferenceValueParser(trimmed);
const ids = valueParser.parseIds(schema.isArray);
if (schema.isArray) {
return ids;
@@ -136,6 +140,7 @@ function parseValueWithReferenceIds(
function extractNestedReferenceIds(value: unknown, schema: Schema): unknown {
switch (schema.type) {
case 'reference':
if (value === null || value === undefined) return value;
if (schema.isArray) {
const ids = Array.isArray(value) ? value : [value];
return ids.map(id => String(id));
@@ -258,6 +263,7 @@ function resolveNestedReferences(
): unknown {
switch (schema.type) {
case 'reference': {
if (value === null || value === undefined) return value;
const { lookup } = loadReferenceTable(schema, refBaseDir, defaultPrimaryKey, currentFilePath);
if (schema.isArray) {
const ids = Array.isArray(value) ? value : [value];
@@ -379,9 +385,14 @@ function parseReferenceValue(
defaultPrimaryKey: string,
currentFilePath: string | undefined
): unknown {
const trimmed = valueString.trim();
if (schema.isOptional && trimmed === '') {
return null;
}
const { lookup } = loadReferenceTable(schema, refBaseDir, defaultPrimaryKey, currentFilePath);
const valueParser = new ReferenceValueParser(valueString.trim());
const valueParser = new ReferenceValueParser(trimmed);
const ids = valueParser.parseIds(schema.isArray);
if (schema.isArray) {
@@ -497,10 +508,10 @@ function schemaToTypeString(schema: Schema, resourceNames?: Map<string, string>)
case 'union':
return schema.members.map(m => schemaToTypeString(m, resourceNames)).join(' | ');
case 'reference': {
// Use the resource name mapping if provided, otherwise capitalize table name
const typeName = resourceNames?.get(schema.tableName) ||
schema.tableName.charAt(0).toUpperCase() + schema.tableName.slice(1);
return schema.isArray ? `readonly ${typeName}[]` : typeName;
const baseType = schema.isArray ? `readonly ${typeName}[]` : typeName;
return schema.isOptional ? `${baseType} | null` : baseType;
}
case 'array':
if (schema.element.type === 'tuple') {
@@ -764,6 +775,12 @@ function generateSchemaResolutionCode(
switch (schema.type) {
case 'reference': {
const lookup = lookupVar(schema.tableName);
if (schema.isOptional) {
if (schema.isArray) {
return `(${valueExpr} === null || ${valueExpr} === undefined ? ${valueExpr} : (Array.isArray(${valueExpr}) ? ${valueExpr}.map(id => ${lookup}.get(String(id))) : ${lookup}.get(String(${valueExpr}))))`;
}
return `(${valueExpr} === null || ${valueExpr} === undefined ? ${valueExpr} : ${lookup}.get(String(${valueExpr})))`;
}
if (schema.isArray) {
return `(Array.isArray(${valueExpr}) ? ${valueExpr}.map(id => ${lookup}.get(String(id))) : ${valueExpr})`;
}