@effect/tsgo 0.19.0 → 0.21.0

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/README.md CHANGED
@@ -104,6 +104,7 @@ Some diagnostics are off by default or have a default severity of suggestion, bu
104
104
  <tr><td><code>flatMapToMap</code></td><td>💡</td><td>🔧</td><td>Suggests using Effect.map instead of Effect.flatMap when the callback only wraps its result with Effect.succeed</td><td>✓</td><td>✓</td></tr>
105
105
  <tr><td><code>missedPipeableOpportunity</code></td><td>➖</td><td>🔧</td><td>Suggests using .pipe() for nested function calls</td><td>✓</td><td>✓</td></tr>
106
106
  <tr><td><code>missingEffectServiceDependency</code></td><td>➖</td><td></td><td>Checks that Effect.Service dependencies satisfy all required layer inputs</td><td>✓</td><td></td></tr>
107
+ <tr><td><code>missingPipeableSignature</code></td><td>➖</td><td></td><td>Reports exported fixed-arity functions whose call signatures have no corresponding pipeable overload</td><td>✓</td><td>✓</td></tr>
107
108
  <tr><td><code>multipleCatchTag</code></td><td>💡</td><td></td><td>Suggests collapsing consecutive Effect.catchTag transformations into a single Effect.catchTags call when semantics stay equivalent</td><td></td><td>✓</td></tr>
108
109
  <tr><td><code>nestedEffectGenYield</code></td><td>➖</td><td></td><td>Warns when yielding a nested bare Effect.gen inside an existing Effect generator context</td><td>✓</td><td>✓</td></tr>
109
110
  <tr><td><code>newSchemaClass</code></td><td>➖</td><td>🔧</td><td>Suggests using Schema make instead of new for Schema classes</td><td></td><td>✓</td></tr>
@@ -4158,6 +4158,73 @@ const liftThrowable = (f) => (...a) => {
4158
4158
  }
4159
4159
  };
4160
4160
  /**
4161
+ * Extracts the value from a `Some`, or throws a custom error for `None`.
4162
+ *
4163
+ * **When to use**
4164
+ *
4165
+ * Use when you need fail-fast unwrapping of an `Option` for unexpected absence
4166
+ * and want to provide a descriptive debugging error.
4167
+ *
4168
+ * **Details**
4169
+ *
4170
+ * - `Some` → returns the inner value
4171
+ * - `None` → throws the value returned by `onNone()`
4172
+ *
4173
+ * **Example** (Throwing a custom error)
4174
+ *
4175
+ * ```ts
4176
+ * import { Option } from "effect"
4177
+ *
4178
+ * console.log(Option.getOrThrowWith(Option.some(1), () => new Error("missing")))
4179
+ * // Output: 1
4180
+ *
4181
+ * Option.getOrThrowWith(Option.none(), () => new Error("missing"))
4182
+ * // throws Error: missing
4183
+ * ```
4184
+ *
4185
+ * @see {@link getOrThrow} for a version with a default error
4186
+ * @see {@link getOrElse} for a non-throwing alternative
4187
+ *
4188
+ * @category converting
4189
+ * @since 2.0.0
4190
+ */
4191
+ const getOrThrowWith = /* @__PURE__ */ dual(2, (self, onNone) => {
4192
+ if (isSome(self)) return self.value;
4193
+ throw onNone();
4194
+ });
4195
+ /**
4196
+ * Extracts the value from a `Some`, or throws a default `Error` for `None`.
4197
+ *
4198
+ * **When to use**
4199
+ *
4200
+ * Use when you need quick fail-fast unwrapping of an `Option` and a generic
4201
+ * error is acceptable.
4202
+ *
4203
+ * **Details**
4204
+ *
4205
+ * - `Some` → returns the inner value
4206
+ * - `None` → throws `new Error("getOrThrow called on a None")`
4207
+ *
4208
+ * **Example** (Throwing a default error)
4209
+ *
4210
+ * ```ts
4211
+ * import { Option } from "effect"
4212
+ *
4213
+ * console.log(Option.getOrThrow(Option.some(1)))
4214
+ * // Output: 1
4215
+ *
4216
+ * Option.getOrThrow(Option.none())
4217
+ * // throws Error: getOrThrow called on a None
4218
+ * ```
4219
+ *
4220
+ * @see {@link getOrThrowWith} for a custom error
4221
+ * @see {@link getOrElse} for a non-throwing alternative
4222
+ *
4223
+ * @category converting
4224
+ * @since 2.0.0
4225
+ */
4226
+ const getOrThrow = /* @__PURE__ */ getOrThrowWith(() => /* @__PURE__ */ new Error("getOrThrow called on a None"));
4227
+ /**
4161
4228
  * Transforms the value inside a `Some` using the provided function, leaving
4162
4229
  * `None` unchanged.
4163
4230
  *
@@ -53904,6 +53971,49 @@ const choice$2 = (choices) => {
53904
53971
  return Object.assign(primitive, { choiceKeys: choices.map(([key]) => key) });
53905
53972
  };
53906
53973
  /**
53974
+ * Creates a primitive that validates and resolves file system paths.
53975
+ *
53976
+ * **Example** (Parsing file system paths)
53977
+ *
53978
+ * ```ts
53979
+ * import { Effect } from "effect"
53980
+ * import { Primitive } from "effect/unstable/cli"
53981
+ *
53982
+ * const program = Effect.gen(function*() {
53983
+ * // Parse a file path that must exist
53984
+ * const filePrimitive = Primitive.path("file", true)
53985
+ * const filePath = yield* filePrimitive.parse("./package.json")
53986
+ * console.log(filePath) // Absolute path to package.json
53987
+ *
53988
+ * // Parse a directory path
53989
+ * const dirPrimitive = Primitive.path("directory", false)
53990
+ * const dirPath = yield* dirPrimitive.parse("./src")
53991
+ * console.log(dirPath) // Absolute path to src directory
53992
+ *
53993
+ * // Parse any path type
53994
+ * const anyPrimitive = Primitive.path("either", false)
53995
+ * const anyPath = yield* anyPrimitive.parse("./some/path")
53996
+ * console.log(anyPath) // Absolute path
53997
+ * })
53998
+ * ```
53999
+ *
54000
+ * @category constructors
54001
+ * @since 4.0.0
54002
+ */
54003
+ const path$1 = (pathType, mustExist) => makePrimitive("Path", fnUntraced(function* (value) {
54004
+ const fs = yield* FileSystem;
54005
+ const path = yield* Path;
54006
+ const absolutePath = path.isAbsolute(value) ? value : path.resolve(value);
54007
+ const exists = yield* mapError(fs.exists(absolutePath), (error) => `Failed to check path existence: ${error.message}`);
54008
+ if (mustExist === true && !exists) return yield* fail(`Path does not exist: ${absolutePath}`);
54009
+ if (exists && pathType !== "either") {
54010
+ const stat = yield* mapError(fs.stat(absolutePath), (error) => `Failed to stat path: ${error.message}`);
54011
+ if (pathType === "file" && stat.type !== "File") return yield* fail(`Path is not a file: ${absolutePath}`);
54012
+ if (pathType === "directory" && stat.type !== "Directory") return yield* fail(`Path is not a directory: ${absolutePath}`);
54013
+ }
54014
+ return absolutePath;
54015
+ }));
54016
+ /**
53907
54017
  * Creates a sentinel primitive that always fails to parse a value.
53908
54018
  *
53909
54019
  * **When to use**
@@ -54207,7 +54317,7 @@ const custom = (initialState, ...args) => {
54207
54317
  * @category constructors
54208
54318
  * @since 4.0.0
54209
54319
  */
54210
- const file = (options = {}) => {
54320
+ const file$2 = (options = {}) => {
54211
54321
  const opts = {
54212
54322
  type: options.type ?? "file",
54213
54323
  message: options.message ?? `Choose a file`,
@@ -55124,6 +55234,71 @@ const choice$1 = (kind, name, choices) => {
55124
55234
  return choiceWithValue$1(kind, name, choices.map((value) => [value, value]));
55125
55235
  };
55126
55236
  /**
55237
+ * Creates a path parameter that accepts file or directory paths.
55238
+ *
55239
+ * **Example** (Creating path parameters)
55240
+ *
55241
+ * ```ts
55242
+ * import { Param } from "effect/unstable/cli"
55243
+ *
55244
+ * // @internal - this module is not exported publicly
55245
+ *
55246
+ * // Basic path parameter
55247
+ * const outputPath = Param.path(Param.flagKind, "output")
55248
+ *
55249
+ * // Path that must exist
55250
+ * const inputPath = Param.path(Param.flagKind, "input", { mustExist: true })
55251
+ *
55252
+ * // File-only path
55253
+ * const configFile = Param.path(Param.flagKind, "config", {
55254
+ * pathType: "file",
55255
+ * mustExist: true,
55256
+ * typeName: "config-file"
55257
+ * })
55258
+ * ```
55259
+ *
55260
+ * @category constructors
55261
+ * @since 4.0.0
55262
+ */
55263
+ const path = (kind, name, options) => makeSingle({
55264
+ name,
55265
+ kind,
55266
+ primitiveType: path$1(options?.pathType ?? "either", options?.mustExist),
55267
+ typeName: options?.typeName
55268
+ });
55269
+ /**
55270
+ * Creates a file path parameter.
55271
+ *
55272
+ * **Details**
55273
+ *
55274
+ * This is a convenience function that creates a path parameter with a
55275
+ * `pathType` set to `"file"` and a default type name of `"file"`.
55276
+ *
55277
+ * **Example** (Creating file parameters)
55278
+ *
55279
+ * ```ts
55280
+ * import { Param } from "effect/unstable/cli"
55281
+ *
55282
+ * // @internal - this module is not exported publicly
55283
+ *
55284
+ * // Basic file parameter
55285
+ * const outputFile = Param.file(Param.flagKind, "output")
55286
+ *
55287
+ * // File that must exist
55288
+ * const inputFile = Param.file(Param.flagKind, "input", { mustExist: true })
55289
+ *
55290
+ * // Usage: --output result.txt --input existing-file.txt
55291
+ * ```
55292
+ *
55293
+ * @category constructors
55294
+ * @since 4.0.0
55295
+ */
55296
+ const file$1 = (kind, name, options) => path(kind, name, {
55297
+ pathType: "file",
55298
+ typeName: "file",
55299
+ mustExist: options?.mustExist
55300
+ });
55301
+ /**
55127
55302
  * Creates an empty sentinel parameter that always fails to parse.
55128
55303
  *
55129
55304
  * **When to use**
@@ -55683,6 +55858,27 @@ const choiceWithValue = (name, choices) => choiceWithValue$1(flagKind, name, cho
55683
55858
  */
55684
55859
  const choice = (name, choices) => choice$1(flagKind, name, choices);
55685
55860
  /**
55861
+ * Creates a file path flag that accepts file paths with optional existence validation.
55862
+ *
55863
+ * **Example** (Creating file flags)
55864
+ *
55865
+ * ```ts
55866
+ * import { Flag } from "effect/unstable/cli"
55867
+ *
55868
+ * // Basic file flag
55869
+ * const inputFlag = Flag.file("input")
55870
+ * // Usage: --input ./data.json
55871
+ *
55872
+ * // File that must exist
55873
+ * const configFlag = Flag.file("config", { mustExist: true })
55874
+ * // Usage: --config ./config.yaml (file must exist)
55875
+ * ```
55876
+ *
55877
+ * @category constructors
55878
+ * @since 4.0.0
55879
+ */
55880
+ const file = (name, options) => file$1(flagKind, name, options);
55881
+ /**
55686
55882
  * Creates an empty sentinel flag that always fails to parse.
55687
55883
  * This is useful for creating placeholder flags or for combinators.
55688
55884
  *
@@ -204655,7 +204851,7 @@ var FileReadError = class extends TaggedError("FileReadError") {
204655
204851
  //#endregion
204656
204852
  //#region package.json
204657
204853
  var name = "@effect/tsgo";
204658
- var version = "0.19.0";
204854
+ var version = "0.21.0";
204659
204855
 
204660
204856
  //#endregion
204661
204857
  //#region src/setup/consts.ts
@@ -204663,7 +204859,6 @@ const LSP_PACKAGE_NAME = name;
204663
204859
  const LSP_PLUGIN_NAME = "@effect/language-service";
204664
204860
  const defaultTypescriptPackageNames = ["typescript", "@typescript/native"];
204665
204861
  const PATCH_COMMAND = "effect-tsgo patch";
204666
- const TSCONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/Effect-TS/tsgo/refs/heads/main/schema.json";
204667
204862
  /**
204668
204863
  * `typescript` package versions >= 7 ship the native Go-ported binary that this
204669
204864
  * tool patches. Older `typescript` releases (<= 6) are the JS compiler and must
@@ -204673,10 +204868,6 @@ const isNativeTypescriptVersion = (version) => {
204673
204868
  const match = /\d+/.exec(version.trim());
204674
204869
  return match !== null && Number(match[0]) >= 7;
204675
204870
  };
204676
- /**
204677
- * Resolve the VS Code TypeScript 7 tsdk folder.
204678
- */
204679
- const nativeBackendTsdkPath = (packageName) => "node_modules/" + packageName;
204680
204871
 
204681
204872
  //#endregion
204682
204873
  //#region src/setup/assessment.ts
@@ -204766,6 +204957,7 @@ const assessTsConfig = (input) => {
204766
204957
  const hasPlugins = parsed.compilerOptions?.plugins !== void 0;
204767
204958
  const plugins = parsed.compilerOptions?.plugins ?? [];
204768
204959
  const hasLspPlugin = plugins.some((plugin) => plugin.name === LSP_PLUGIN_NAME);
204960
+ const currentSchemaPath = typeof parsed.$schema === "string" ? some(parsed.$schema) : none$3();
204769
204961
  const currentDiagnosticSeverities = getCurrentDiagnosticSeverities(plugins);
204770
204962
  return {
204771
204963
  path: input.fileName,
@@ -204774,6 +204966,7 @@ const assessTsConfig = (input) => {
204774
204966
  text: input.text,
204775
204967
  hasPlugins,
204776
204968
  hasLspPlugin,
204969
+ currentSchemaPath,
204777
204970
  currentDiagnosticSeverities
204778
204971
  };
204779
204972
  };
@@ -205223,18 +205416,18 @@ const computeTsConfigChanges = (current, target, lspVersion) => {
205223
205416
  const ctx = createTrackerContext();
205224
205417
  const fileChange = tsInternal.textChanges.ChangeTracker.with(ctx, (tracker) => {
205225
205418
  const schemaProperty = findPropertyInObject(rootObj, "$schema");
205226
- const shouldAddSchema = !schemaProperty;
205227
- const shouldUpdateSchema = !!schemaProperty && (!import_typescript.isStringLiteral(schemaProperty.initializer) || schemaProperty.initializer.text !== TSCONFIG_SCHEMA_URL);
205419
+ const shouldAddSchema = isSome(target.schemaPath) && !schemaProperty;
205420
+ const shouldUpdateSchema = isSome(target.schemaPath) && !!schemaProperty && (!import_typescript.isStringLiteral(schemaProperty.initializer) || schemaProperty.initializer.text !== target.schemaPath.value);
205228
205421
  if (shouldAddSchema) descriptions.push("Add $schema to tsconfig");
205229
205422
  else if (shouldUpdateSchema) descriptions.push("Update $schema in tsconfig");
205230
205423
  descriptions.push(`Add compilerOptions with ${LSP_PLUGIN_NAME} plugin`);
205231
- const schemaPropertyAssignment = import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("$schema"), import_typescript.factory.createStringLiteral(TSCONFIG_SCHEMA_URL));
205424
+ const schemaPropertyAssignment = map$10(target.schemaPath, (schemaPath) => import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("$schema"), import_typescript.factory.createStringLiteral(schemaPath)));
205232
205425
  const compilerOptionsAssignment = import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("compilerOptions"), import_typescript.factory.createObjectLiteralExpression([import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("plugins"), import_typescript.factory.createArrayLiteralExpression([createLspPluginObject(target)], true))], true));
205233
205426
  const nextProperties = rootObj.properties.map((property) => {
205234
- if (schemaProperty && property === schemaProperty) return schemaPropertyAssignment;
205427
+ if (schemaProperty && property === schemaProperty && isSome(schemaPropertyAssignment)) return schemaPropertyAssignment.value;
205235
205428
  return property;
205236
205429
  });
205237
- if (shouldAddSchema) nextProperties.push(schemaPropertyAssignment);
205430
+ if (shouldAddSchema && isSome(schemaPropertyAssignment)) nextProperties.push(schemaPropertyAssignment.value);
205238
205431
  nextProperties.push(compilerOptionsAssignment);
205239
205432
  tracker.replaceNode(current.sourceFile, rootObj, import_typescript.factory.createObjectLiteralExpression(nextProperties, true));
205240
205433
  }).find((fc) => fc.fileName === current.sourceFile.fileName);
@@ -205260,7 +205453,7 @@ const computeTsConfigChanges = (current, target, lspVersion) => {
205260
205453
  const fileChange = tsInternal.textChanges.ChangeTracker.with(ctx, (tracker) => {
205261
205454
  const schemaProperty = findPropertyInObject(rootObj, "$schema");
205262
205455
  const pluginsProperty = findPropertyInObject(compilerOptions, "plugins");
205263
- const schemaPropertyAssignment = import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("$schema"), import_typescript.factory.createStringLiteral(TSCONFIG_SCHEMA_URL));
205456
+ const schemaPropertyAssignment = map$10(target.schemaPath, (schemaPath) => import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral("$schema"), import_typescript.factory.createStringLiteral(schemaPath)));
205264
205457
  if (isNone(lspVersion)) {
205265
205458
  if (schemaProperty) {
205266
205459
  descriptions.push("Remove $schema from tsconfig");
@@ -205281,12 +205474,12 @@ const computeTsConfigChanges = (current, target, lspVersion) => {
205281
205474
  }
205282
205475
  }
205283
205476
  } else {
205284
- if (!schemaProperty) {
205477
+ if (!schemaProperty && isSome(schemaPropertyAssignment)) {
205285
205478
  descriptions.push("Add $schema to tsconfig");
205286
- insertNodeAtEndOfList(tracker, current.sourceFile, rootObj.properties, schemaPropertyAssignment);
205287
- } else if (!import_typescript.isStringLiteral(schemaProperty.initializer) || schemaProperty.initializer.text !== TSCONFIG_SCHEMA_URL) {
205479
+ insertNodeAtEndOfList(tracker, current.sourceFile, rootObj.properties, schemaPropertyAssignment.value);
205480
+ } else if (schemaProperty && isSome(target.schemaPath) && (!import_typescript.isStringLiteral(schemaProperty.initializer) || schemaProperty.initializer.text !== target.schemaPath.value)) {
205288
205481
  descriptions.push("Update $schema in tsconfig");
205289
- tracker.replaceNode(current.sourceFile, schemaProperty.initializer, schemaPropertyAssignment.initializer);
205482
+ tracker.replaceNode(current.sourceFile, schemaProperty.initializer, getOrThrow(schemaPropertyAssignment).initializer);
205290
205483
  }
205291
205484
  const pluginObject = createLspPluginObject(target);
205292
205485
  if (!pluginsProperty) {
@@ -205350,18 +205543,19 @@ const computeVSCodeSettingsChanges = (current, target) => {
205350
205543
  const rootObj = getRootObject(current.sourceFile);
205351
205544
  if (!rootObj) return emptyFileChangesResult();
205352
205545
  const ctx = createTrackerContext();
205546
+ const createSettingValue = (value) => typeof value === "string" ? import_typescript.factory.createStringLiteral(value) : typeof value === "boolean" ? value ? import_typescript.factory.createTrue() : import_typescript.factory.createFalse() : Array.isArray(value) && value.every((item) => typeof item === "string") ? import_typescript.factory.createArrayLiteralExpression(value.map((item) => import_typescript.factory.createStringLiteral(item))) : import_typescript.factory.createNull();
205353
205547
  const fileChange = tsInternal.textChanges.ChangeTracker.with(ctx, (tracker) => {
205354
205548
  if (rootObj.properties.length === 0) {
205355
205549
  const newProperties = [];
205356
205550
  for (const [key, value] of Object.entries(target.settings)) {
205357
205551
  descriptions.push(`Add ${key} setting`);
205358
- newProperties.push(import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral(key), typeof value === "string" ? import_typescript.factory.createStringLiteral(value) : typeof value === "boolean" ? value ? import_typescript.factory.createTrue() : import_typescript.factory.createFalse() : import_typescript.factory.createNull()));
205552
+ newProperties.push(import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral(key), createSettingValue(value)));
205359
205553
  }
205360
205554
  const newRootObj = import_typescript.factory.createObjectLiteralExpression(newProperties, true);
205361
205555
  tracker.replaceNode(current.sourceFile, rootObj, newRootObj);
205362
205556
  } else for (const [key, value] of Object.entries(target.settings)) if (!findPropertyInObject(rootObj, key)) {
205363
205557
  descriptions.push(`Add ${key} setting`);
205364
- const newProp = import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral(key), typeof value === "string" ? import_typescript.factory.createStringLiteral(value) : typeof value === "boolean" ? value ? import_typescript.factory.createTrue() : import_typescript.factory.createFalse() : import_typescript.factory.createNull());
205558
+ const newProp = import_typescript.factory.createPropertyAssignment(import_typescript.factory.createStringLiteral(key), createSettingValue(value));
205365
205559
  insertNodeAtEndOfList(tracker, current.sourceFile, rootObj.properties, newProp);
205366
205560
  }
205367
205561
  }).find((fc) => fc.fileName === current.path);
@@ -206673,6 +206867,23 @@ var rules = [
206673
206867
  }]
206674
206868
  }
206675
206869
  },
206870
+ {
206871
+ "name": "missingPipeableSignature",
206872
+ "group": "style",
206873
+ "description": "Reports exported fixed-arity functions whose call signatures have no corresponding pipeable overload",
206874
+ "defaultSeverity": "off",
206875
+ "fixable": false,
206876
+ "supportedEffect": ["v3", "v4"],
206877
+ "codes": [377101],
206878
+ "preview": {
206879
+ "sourceText": "\nexport const getAt = (self: ReadonlyArray<string>, index: number): string => self[index]\n",
206880
+ "diagnostics": [{
206881
+ "start": 14,
206882
+ "end": 19,
206883
+ "text": "Exported function `getAt` has no pipeable overload corresponding to its signature `(self: ReadonlyArray<string>, index: number) => string`. effect(missingPipeableSignature)"
206884
+ }]
206885
+ }
206886
+ },
206676
206887
  {
206677
206888
  "name": "multipleCatchTag",
206678
206889
  "group": "style",
@@ -207378,7 +207589,10 @@ const fromAssessment = (inputState) => ({
207378
207589
  typescriptVersion: inputState.packageJson.typescriptVersion,
207379
207590
  prepareScript: map$10(inputState.packageJson.prepareScript, (_) => _.hasPatch).pipe(getOrElse$1(() => false))
207380
207591
  },
207381
- tsconfig: { diagnosticSeverities: inputState.tsconfig.currentDiagnosticSeverities },
207592
+ tsconfig: {
207593
+ schemaPath: inputState.tsconfig.currentSchemaPath,
207594
+ diagnosticSeverities: inputState.tsconfig.currentDiagnosticSeverities
207595
+ },
207382
207596
  vscodeSettings: map$10(inputState.vscodeSettings, (settings) => ({ settings: settings.parsed })),
207383
207597
  editors: []
207384
207598
  });
@@ -207402,7 +207616,7 @@ const findTsConfigFiles = (currentDir) => gen(function* () {
207402
207616
  const files = yield* fs.readDirectory(currentDir);
207403
207617
  return filter$2(files, isTsConfigFile).map((file) => path.join(currentDir, file));
207404
207618
  });
207405
- const promptForTsConfigPath = (currentDir) => file({
207619
+ const promptForTsConfigPath = (currentDir) => file$2({
207406
207620
  type: "file",
207407
207621
  message: "Select tsconfig to configure",
207408
207622
  startingPath: currentDir,
@@ -207460,6 +207674,21 @@ const configCommand = make("config").pipe(withDescription("Configure diagnostic
207460
207674
  });
207461
207675
  })));
207462
207676
 
207677
+ //#endregion
207678
+ //#region src/diagnostics.ts
207679
+ const runDiagnosticsBinary = (binaryPath, request, spawn = node_child_process.spawnSync) => {
207680
+ const result = spawn(binaryPath, ["--effect-cli-diagnostics", JSON.stringify(request)], { stdio: "inherit" });
207681
+ if (result.error !== void 0) throw result.error;
207682
+ return result;
207683
+ };
207684
+ const propagateDiagnosticsExit = (result, parent = process) => {
207685
+ if (result.signal !== null) {
207686
+ parent.kill(parent.pid, result.signal);
207687
+ return;
207688
+ }
207689
+ parent.exitCode = result.status ?? 1;
207690
+ };
207691
+
207463
207692
  //#endregion
207464
207693
  //#region src/presets.ts
207465
207694
  const metadata = metadata_default;
@@ -207518,6 +207747,7 @@ function isPresetEnabled(presetName, severities) {
207518
207747
  * Gather target state from user based on current assessment
207519
207748
  */
207520
207749
  const gatherTargetState = (assessment, context) => gen(function* () {
207750
+ const path = yield* Path;
207521
207751
  const currentLspState = match$8(assessment.packageJson.lspVersion, {
207522
207752
  onNone: () => "no",
207523
207753
  onSome: (lsp) => lsp.dependencyType
@@ -207550,7 +207780,10 @@ const gatherTargetState = (assessment, context) => gen(function* () {
207550
207780
  typescriptVersion: assessment.packageJson.typescriptVersion,
207551
207781
  prepareScript: false
207552
207782
  },
207553
- tsconfig: { diagnosticSeverities: none$3() },
207783
+ tsconfig: {
207784
+ schemaPath: none$3(),
207785
+ diagnosticSeverities: none$3()
207786
+ },
207554
207787
  vscodeSettings: none$3(),
207555
207788
  editors: []
207556
207789
  };
@@ -207595,10 +207828,12 @@ const gatherTargetState = (assessment, context) => gen(function* () {
207595
207828
  ]
207596
207829
  });
207597
207830
  const defaultTypescriptPackageName = defaultTypescriptPackageNames[0];
207831
+ const relativeSchemaPath = path.relative(path.dirname(assessment.tsconfig.path), context.defaultSchemaPath).replaceAll("\\", "/");
207598
207832
  const vscodeSettings = editors.includes("vscode") ? some({ settings: {
207599
- "typescript.native-preview.tsdk": nativeBackendTsdkPath(defaultTypescriptPackageName),
207600
- "typescript.experimental.useTsgo": true,
207601
- "js/ts.experimental.useTsgo": true
207833
+ "js/ts.experimental.useTsgo": true,
207834
+ "js/ts.tsdk.path": "./node_modules/typescript/bin",
207835
+ "js/ts.tsdk.promptToUseWorkspaceVersion": true,
207836
+ "js/ts.tsdk.additionalLocations": ["./node_modules/typescript/bin"]
207602
207837
  } }) : none$3();
207603
207838
  return {
207604
207839
  packageJson: {
@@ -207613,7 +207848,10 @@ const gatherTargetState = (assessment, context) => gen(function* () {
207613
207848
  })),
207614
207849
  prepareScript: true
207615
207850
  },
207616
- tsconfig: { diagnosticSeverities },
207851
+ tsconfig: {
207852
+ schemaPath: some(relativeSchemaPath.startsWith(".") ? relativeSchemaPath : `./${relativeSchemaPath}`),
207853
+ diagnosticSeverities
207854
+ },
207617
207855
  vscodeSettings,
207618
207856
  editors
207619
207857
  };
@@ -207621,18 +207859,20 @@ const gatherTargetState = (assessment, context) => gen(function* () {
207621
207859
 
207622
207860
  //#endregion
207623
207861
  //#region upstream.json
207624
- var tsVersion = "7.1.0-dev.20260708.3";
207862
+ var tsVersion = "7.1.0-dev.20260713.1";
207625
207863
 
207626
207864
  //#endregion
207627
207865
  //#region src/setup/index.ts
207628
207866
  const setupCommand = make("setup").pipe(withDescription("Setup @effect/tsgo for the given project using an interactive CLI."), withHandler(() => gen(function* () {
207629
- const currentDir = (yield* Path).resolve(process.cwd());
207867
+ const path = yield* Path;
207868
+ const currentDir = path.resolve(process.cwd());
207630
207869
  const tsconfigInput = yield* selectTsConfigFile(currentDir);
207631
207870
  const assessmentInput = yield* createAssessmentInput(currentDir, tsconfigInput);
207632
207871
  const assessmentState = assess(assessmentInput);
207633
207872
  const targetState = yield* gatherTargetState(assessmentState, {
207634
207873
  defaultLspVersion: version,
207635
- defaultTypescriptVersion: tsVersion
207874
+ defaultTypescriptVersion: tsVersion,
207875
+ defaultSchemaPath: path.resolve(currentDir, "node_modules", name, "schema.json")
207636
207876
  });
207637
207877
  const result = computeChanges(assessmentState, targetState);
207638
207878
  yield* reviewAndApplyChanges(result, assessmentState, { cancelMessage: "Setup cancelled. No changes were made." });
@@ -207938,10 +208178,36 @@ const patchCommand = make("patch", {
207938
208178
  }).pipe(withDescription("Patch the Effect Language Service binary"), withHandler(({ force, typescriptPackage }) => patch(force, packageNamesWithPreferred(typescriptPackage))));
207939
208179
  const unpatchCommand = make("unpatch").pipe(withDescription("Unpatch and restore the original TypeScript-Go binary"), withHandler(() => unpatch));
207940
208180
  const getExePathCommand = make("get-exe-path").pipe(withDescription("Print the Effect Language Service executable path"), withHandler(() => resolveInstalledTypeScriptBinary(defaultTypescriptPackageNames).pipe(flatMap((installedTypeScript) => getPackagedBinaryPath(installedTypeScript, false)), flatMap((exePath) => log(exePath)))));
208181
+ const diagnosticsCommand = make("diagnostics", {
208182
+ file: file("file").pipe(optional, withDescription$1("The full path of the file to check for diagnostics")),
208183
+ project: file("project").pipe(optional, withDescription$1("The full path of the project tsconfig.json file to check for diagnostics")),
208184
+ format: choice("format", [
208185
+ "json",
208186
+ "pretty",
208187
+ "text",
208188
+ "github-actions"
208189
+ ]).pipe(withDefault("pretty"), withDescription$1("Output format: json (machine-readable), pretty (colored with context), text (plain text), github-actions (workflow commands)")),
208190
+ strict: boolean("strict").pipe(withDefault(false), withDescription$1("Treat warnings as errors (affects exit code)")),
208191
+ severity: string("severity").pipe(optional, withDescription$1("Filter by severity levels (comma-separated: error,warning,message)")),
208192
+ progress: boolean("progress").pipe(withDefault(false), withDescription$1("Show progress as files are checked (outputs to stderr)")),
208193
+ lspconfig: string("lspconfig").pipe(optional, withDescription$1("An optional inline JSON lsp config that replaces the current project lsp config"))
208194
+ }).pipe(withDescription("Gets the Effect language service diagnostics on the given files or project"), withHandler(({ file, format, lspconfig, progress, project, severity, strict }) => gen(function* () {
208195
+ propagateDiagnosticsExit(runDiagnosticsBinary(yield* getPackagedBinaryPath(yield* resolveInstalledTypeScriptBinary(defaultTypescriptPackageNames), false), {
208196
+ cwd: process.cwd(),
208197
+ file: getOrUndefined(file),
208198
+ project: getOrUndefined(project),
208199
+ format,
208200
+ strict,
208201
+ severity: getOrUndefined(severity),
208202
+ progress,
208203
+ lspconfig: getOrUndefined(lspconfig)
208204
+ }));
208205
+ })));
207941
208206
  make("tsgo").pipe(withSubcommands([
207942
208207
  patchCommand,
207943
208208
  unpatchCommand,
207944
208209
  getExePathCommand,
208210
+ diagnosticsCommand,
207945
208211
  setupCommand,
207946
208212
  configCommand
207947
208213
  ])).pipe(run({ version }), provide(layer), runMain());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/tsgo",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "description": "Effect Language Service for TypeScript-Go — Effect-specific diagnostics and hover features.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -19,16 +19,17 @@
19
19
  },
20
20
  "files": [
21
21
  "dist/",
22
- "README.md"
22
+ "README.md",
23
+ "schema.json"
23
24
  ],
24
25
  "optionalDependencies": {
25
- "@effect/tsgo-win32-x64": "0.19.0",
26
- "@effect/tsgo-win32-arm64": "0.19.0",
27
- "@effect/tsgo-linux-x64": "0.19.0",
28
- "@effect/tsgo-linux-arm64": "0.19.0",
29
- "@effect/tsgo-linux-arm": "0.19.0",
30
- "@effect/tsgo-darwin-x64": "0.19.0",
31
- "@effect/tsgo-darwin-arm64": "0.19.0"
26
+ "@effect/tsgo-win32-x64": "0.21.0",
27
+ "@effect/tsgo-win32-arm64": "0.21.0",
28
+ "@effect/tsgo-linux-x64": "0.21.0",
29
+ "@effect/tsgo-linux-arm64": "0.21.0",
30
+ "@effect/tsgo-linux-arm": "0.21.0",
31
+ "@effect/tsgo-darwin-x64": "0.21.0",
32
+ "@effect/tsgo-darwin-arm64": "0.21.0"
32
33
  },
33
34
  "devDependencies": {
34
35
  "@effect/platform-node": "^4.0.0-beta.83",