@axintai/compiler 0.3.1 → 0.3.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.
@@ -350,6 +350,6 @@ interface EjectResult {
350
350
  * @param options Eject options (outDir, includeTests, format)
351
351
  * @returns Ejected files
352
352
  */
353
- declare function ejectIntent(source: string, fileName: string, options?: EjectOptions): EjectResult;
353
+ declare function ejectIntent(source: string, fileName: string, options?: EjectOptions): Promise<EjectResult>;
354
354
 
355
355
  export { type CompilerOptions, type CompilerOutput, type Diagnostic, type DiagnosticSeverity, type DisplayRepresentation, type EjectOptions, type EjectResult, type IREntity, type IRIntent, type IRParameter, type IRPrimitiveType, type IRType, LEGACY_PARAM_ALIASES, PARAM_TYPES, ParserError, SWIFT_TYPE_MAP, compileFile, compileFromIR, compileSource, ejectIntent, escapeSwiftString, escapeXml, generateEntitlementsFragment, generateEntity, generateEntityQuery, generateInfoPlistFragment, generateSwift, irFromJSON, irTypeToSwift, parseIntentSource, validateEntity, validateIntent, validateSwiftSource };
@@ -1122,8 +1122,133 @@ function normalizeIRType(type) {
1122
1122
  return { kind: "primitive", value: "string" };
1123
1123
  }
1124
1124
 
1125
+ // src/core/format.ts
1126
+ import { spawn } from "child_process";
1127
+ import { writeFile, unlink } from "fs/promises";
1128
+ import { join } from "path";
1129
+ import { tmpdir } from "os";
1130
+ var SWIFT_FORMAT_CONFIG = {
1131
+ version: 1,
1132
+ lineLength: 100,
1133
+ indentation: { spaces: 4 },
1134
+ tabWidth: 4,
1135
+ maximumBlankLines: 1,
1136
+ respectsExistingLineBreaks: true,
1137
+ lineBreakBeforeControlFlowKeywords: false,
1138
+ lineBreakBeforeEachArgument: false,
1139
+ lineBreakBeforeEachGenericRequirement: false,
1140
+ prioritizeKeepingFunctionOutputTogether: false,
1141
+ indentConditionalCompilationBlocks: true,
1142
+ lineBreakAroundMultilineExpressionChainComponents: false,
1143
+ fileScopedDeclarationPrivacy: { accessLevel: "private" },
1144
+ rules: {
1145
+ AllPublicDeclarationsHaveDocumentation: false,
1146
+ AlwaysUseLowerCamelCase: true,
1147
+ AmbiguousTrailingClosureOverload: true,
1148
+ BeginDocumentationCommentWithOneLineSummary: false,
1149
+ DoNotUseSemicolons: true,
1150
+ DontRepeatTypeInStaticProperties: true,
1151
+ FileScopedDeclarationPrivacy: true,
1152
+ FullyIndirectEnum: true,
1153
+ GroupNumericLiterals: true,
1154
+ IdentifiersMustBeASCII: true,
1155
+ NeverForceUnwrap: false,
1156
+ NeverUseForceTry: false,
1157
+ NeverUseImplicitlyUnwrappedOptionals: false,
1158
+ NoBlockComments: false,
1159
+ NoCasesWithOnlyFallthrough: true,
1160
+ NoEmptyTrailingClosureParentheses: true,
1161
+ NoLabelsInCasePatterns: true,
1162
+ NoLeadingUnderscores: false,
1163
+ NoParensAroundConditions: true,
1164
+ NoVoidReturnOnFunctionSignature: true,
1165
+ OneCasePerLine: true,
1166
+ OneVariableDeclarationPerLine: true,
1167
+ OnlyOneTrailingClosureArgument: true,
1168
+ OrderedImports: true,
1169
+ ReturnVoidInsteadOfEmptyTuple: true,
1170
+ UseEarlyExits: false,
1171
+ UseLetInEveryBoundCaseVariable: true,
1172
+ UseShorthandTypeNames: true,
1173
+ UseSingleLinePropertyGetter: true,
1174
+ UseSynthesizedInitializer: true,
1175
+ UseTripleSlashForDocumentationComments: true,
1176
+ UseWhereClausesInForLoops: false,
1177
+ ValidateDocumentationComments: false
1178
+ }
1179
+ };
1180
+ async function formatSwift(source, options = {}) {
1181
+ const available = await hasSwiftFormat();
1182
+ if (!available) {
1183
+ if (options.strict) {
1184
+ throw new Error(
1185
+ "swift-format not found on $PATH. Install Xcode + Command Line Tools, or drop --format."
1186
+ );
1187
+ }
1188
+ return {
1189
+ formatted: source,
1190
+ ran: false,
1191
+ reason: "swift-format not found on $PATH"
1192
+ };
1193
+ }
1194
+ const configPath = join(
1195
+ tmpdir(),
1196
+ `axint-swift-format-${Date.now()}-${Math.random().toString(36).slice(2)}.json`
1197
+ );
1198
+ await writeFile(configPath, JSON.stringify(SWIFT_FORMAT_CONFIG, null, 2));
1199
+ try {
1200
+ const result = await runSwiftFormat(source, configPath, options.timeoutMs ?? 8e3);
1201
+ if (result.code === 0) {
1202
+ return { formatted: result.stdout, ran: true };
1203
+ }
1204
+ if (options.strict) {
1205
+ throw new Error(`swift-format failed: ${result.stderr}`);
1206
+ }
1207
+ return {
1208
+ formatted: source,
1209
+ ran: false,
1210
+ reason: `swift-format exited ${result.code}: ${result.stderr}`
1211
+ };
1212
+ } finally {
1213
+ await unlink(configPath).catch(() => void 0);
1214
+ }
1215
+ }
1216
+ function hasSwiftFormat() {
1217
+ return new Promise((resolve) => {
1218
+ const child = spawn("swift-format", ["--version"], { stdio: "pipe" });
1219
+ child.on("error", () => resolve(false));
1220
+ child.on("exit", (code) => resolve(code === 0));
1221
+ });
1222
+ }
1223
+ function runSwiftFormat(source, configPath, timeoutMs) {
1224
+ return new Promise((resolve) => {
1225
+ const child = spawn("swift-format", ["format", "--configuration", configPath], {
1226
+ stdio: ["pipe", "pipe", "pipe"]
1227
+ });
1228
+ let stdout = "";
1229
+ let stderr = "";
1230
+ child.stdout?.on("data", (d) => stdout += d.toString());
1231
+ child.stderr?.on("data", (d) => stderr += d.toString());
1232
+ const timer = setTimeout(() => {
1233
+ child.kill("SIGKILL");
1234
+ resolve({
1235
+ stdout,
1236
+ stderr: stderr + `
1237
+ [format] killed after ${timeoutMs}ms`,
1238
+ code: 124
1239
+ });
1240
+ }, timeoutMs);
1241
+ child.on("exit", (code) => {
1242
+ clearTimeout(timer);
1243
+ resolve({ stdout, stderr, code: code ?? 1 });
1244
+ });
1245
+ child.stdin?.write(source);
1246
+ child.stdin?.end();
1247
+ });
1248
+ }
1249
+
1125
1250
  // src/core/eject.ts
1126
- function ejectIntent(source, fileName, options = {}) {
1251
+ async function ejectIntent(source, fileName, options = {}) {
1127
1252
  const compileResult = compileSource(source, fileName, {
1128
1253
  validate: true,
1129
1254
  emitInfoPlist: true,
@@ -1136,7 +1261,11 @@ function ejectIntent(source, fileName, options = {}) {
1136
1261
  }
1137
1262
  const { ir, swiftCode, infoPlistFragment, entitlementsFragment } = compileResult.output;
1138
1263
  const outDir = options.outDir ?? ".";
1139
- const ejectedSwift = transformSwiftForEject(swiftCode, ir);
1264
+ let ejectedSwift = transformSwiftForEject(swiftCode, ir);
1265
+ if (options.format) {
1266
+ const { formatted, ran } = await formatSwift(ejectedSwift);
1267
+ if (ran) ejectedSwift = formatted;
1268
+ }
1140
1269
  const intentFileName = `${ir.name}Intent.swift`;
1141
1270
  const swiftPath = `${outDir}/${intentFileName}`;
1142
1271
  const plistPath = infoPlistFragment ? `${outDir}/${ir.name}Intent.plist.fragment.xml` : null;
@@ -1193,12 +1322,8 @@ function transformSwiftForEject(swiftCode, ir) {
1193
1322
  if (line.includes("// TODO: Implement your intent logic here.")) {
1194
1323
  result.push(` // TODO: Implement your intent logic here.`);
1195
1324
  result.push(` //`);
1196
- result.push(
1197
- ` // For more information about App Intents, see:`
1198
- );
1199
- result.push(
1200
- ` // https://developer.apple.com/documentation/appintents`
1201
- );
1325
+ result.push(` // For more information about App Intents, see:`);
1326
+ result.push(` // https://developer.apple.com/documentation/appintents`);
1202
1327
  } else {
1203
1328
  result.push(line);
1204
1329
  }