@tscircuit/core 0.0.2162 → 0.0.2164

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 (3) hide show
  1. package/dist/index.d.ts +34 -33
  2. package/dist/index.js +731 -644
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -138,6 +138,629 @@ __export(components_exports, {
138
138
  VoltageSource: () => VoltageSource
139
139
  });
140
140
 
141
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialSourcePinSpecificationChecks.ts
142
+ import {
143
+ checkAllPinsInComponentAreUnderspecified,
144
+ checkNoGroundPinDefined,
145
+ checkNoPowerPinDefined
146
+ } from "@tscircuit/checks";
147
+
148
+ // lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
149
+ import { voltage } from "circuit-json";
150
+ var setSupportedCapability = (sourcePortProps, capability) => {
151
+ switch (capability) {
152
+ case "i2c_sda":
153
+ sourcePortProps.supports_i2c_sda = true;
154
+ return;
155
+ case "i2c_scl":
156
+ sourcePortProps.supports_i2c_scl = true;
157
+ return;
158
+ case "spi_cs":
159
+ sourcePortProps.supports_spi_cs = true;
160
+ return;
161
+ case "spi_sck":
162
+ sourcePortProps.supports_spi_sck = true;
163
+ return;
164
+ case "spi_mosi":
165
+ sourcePortProps.supports_spi_mosi = true;
166
+ return;
167
+ case "spi_miso":
168
+ sourcePortProps.supports_spi_miso = true;
169
+ return;
170
+ case "uart_tx":
171
+ sourcePortProps.supports_uart_tx = true;
172
+ return;
173
+ case "uart_rx":
174
+ sourcePortProps.supports_uart_rx = true;
175
+ return;
176
+ default: {
177
+ const unhandledCapability = capability;
178
+ throw new Error(`Unhandled pin capability: ${unhandledCapability}`);
179
+ }
180
+ }
181
+ };
182
+ var setConfiguredCapability = (sourcePortProps, capability) => {
183
+ switch (capability) {
184
+ case "i2c_sda":
185
+ sourcePortProps.is_configured_for_i2c_sda = true;
186
+ return;
187
+ case "i2c_scl":
188
+ sourcePortProps.is_configured_for_i2c_scl = true;
189
+ return;
190
+ case "spi_cs":
191
+ sourcePortProps.is_configured_for_spi_cs = true;
192
+ return;
193
+ case "spi_sck":
194
+ sourcePortProps.is_configured_for_spi_sck = true;
195
+ return;
196
+ case "spi_mosi":
197
+ sourcePortProps.is_configured_for_spi_mosi = true;
198
+ return;
199
+ case "spi_miso":
200
+ sourcePortProps.is_configured_for_spi_miso = true;
201
+ return;
202
+ case "uart_tx":
203
+ sourcePortProps.is_configured_for_uart_tx = true;
204
+ return;
205
+ case "uart_rx":
206
+ sourcePortProps.is_configured_for_uart_rx = true;
207
+ return;
208
+ default: {
209
+ const unhandledCapability = capability;
210
+ throw new Error(
211
+ `Unhandled configured pin capability: ${unhandledCapability}`
212
+ );
213
+ }
214
+ }
215
+ };
216
+ var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
217
+ if (attributes.isInput !== void 0) {
218
+ sourcePortProps.is_input = attributes.isInput;
219
+ }
220
+ if (attributes.isOutput !== void 0) {
221
+ sourcePortProps.is_output = attributes.isOutput;
222
+ }
223
+ if (attributes.isBidirectional !== void 0) {
224
+ sourcePortProps.is_bidirectional = attributes.isBidirectional;
225
+ }
226
+ if (attributes.isPassive !== void 0) {
227
+ sourcePortProps.is_passive = attributes.isPassive;
228
+ }
229
+ if (attributes.canUseTriState !== void 0) {
230
+ sourcePortProps.can_use_tri_state = attributes.canUseTriState;
231
+ }
232
+ if (attributes.isUsingTriState !== void 0) {
233
+ sourcePortProps.is_using_tri_state = attributes.isUsingTriState;
234
+ }
235
+ if (attributes.canUseOpenCollector !== void 0) {
236
+ sourcePortProps.can_use_open_collector = attributes.canUseOpenCollector;
237
+ }
238
+ if (attributes.isUsingOpenCollector !== void 0) {
239
+ sourcePortProps.is_using_open_collector = attributes.isUsingOpenCollector;
240
+ }
241
+ if (attributes.canUseOpenEmitter !== void 0) {
242
+ sourcePortProps.can_use_open_emitter = attributes.canUseOpenEmitter;
243
+ }
244
+ if (attributes.isUsingOpenEmitter !== void 0) {
245
+ sourcePortProps.is_using_open_emitter = attributes.isUsingOpenEmitter;
246
+ }
247
+ if (attributes.isGpio !== void 0) {
248
+ sourcePortProps.is_gpio = attributes.isGpio;
249
+ }
250
+ if (attributes.highlightColor !== void 0) {
251
+ sourcePortProps.highlight_color = attributes.highlightColor;
252
+ }
253
+ for (const capability of attributes.capabilities ?? []) {
254
+ setSupportedCapability(sourcePortProps, capability);
255
+ }
256
+ const configuredCapabilities = /* @__PURE__ */ new Set([
257
+ ...attributes.activeCapabilities ?? [],
258
+ ...attributes.activeCapability ? [attributes.activeCapability] : []
259
+ ]);
260
+ for (const capability of configuredCapabilities) {
261
+ setConfiguredCapability(sourcePortProps, capability);
262
+ }
263
+ if (attributes.mustBeConnected !== void 0) {
264
+ sourcePortProps.must_be_connected = attributes.mustBeConnected;
265
+ }
266
+ if (attributes.providesPower !== void 0) {
267
+ sourcePortProps.provides_power = attributes.providesPower;
268
+ }
269
+ if (attributes.requiresPower !== void 0) {
270
+ sourcePortProps.requires_power = attributes.requiresPower;
271
+ }
272
+ if (attributes.providesGround !== void 0) {
273
+ sourcePortProps.provides_ground = attributes.providesGround;
274
+ }
275
+ if (attributes.requiresGround !== void 0) {
276
+ sourcePortProps.requires_ground = attributes.requiresGround;
277
+ }
278
+ if (attributes.providesVoltage !== void 0) {
279
+ sourcePortProps.provides_voltage = voltage.parse(attributes.providesVoltage);
280
+ }
281
+ if (attributes.requiresVoltage !== void 0) {
282
+ sourcePortProps.requires_voltage = voltage.parse(attributes.requiresVoltage);
283
+ }
284
+ if (attributes.doNotConnect !== void 0) {
285
+ sourcePortProps.do_not_connect = attributes.doNotConnect;
286
+ }
287
+ if (attributes.includeInBoardPinout !== void 0) {
288
+ sourcePortProps.include_in_board_pinout = attributes.includeInBoardPinout;
289
+ }
290
+ if (attributes.canUseInternalPullup !== void 0) {
291
+ sourcePortProps.can_use_internal_pullup = attributes.canUseInternalPullup;
292
+ }
293
+ if (attributes.isUsingInternalPullup !== void 0) {
294
+ sourcePortProps.is_using_internal_pullup = attributes.isUsingInternalPullup;
295
+ }
296
+ if (attributes.needsExternalPullup !== void 0) {
297
+ sourcePortProps.needs_external_pullup = attributes.needsExternalPullup;
298
+ }
299
+ if (attributes.canUseInternalPulldown !== void 0) {
300
+ sourcePortProps.can_use_internal_pulldown = attributes.canUseInternalPulldown;
301
+ }
302
+ if (attributes.isUsingInternalPulldown !== void 0) {
303
+ sourcePortProps.is_using_internal_pulldown = attributes.isUsingInternalPulldown;
304
+ }
305
+ if (attributes.needsExternalPulldown !== void 0) {
306
+ sourcePortProps.needs_external_pulldown = attributes.needsExternalPulldown;
307
+ }
308
+ if (attributes.canUseOpenDrain !== void 0) {
309
+ sourcePortProps.can_use_open_drain = attributes.canUseOpenDrain;
310
+ }
311
+ if (attributes.isUsingOpenDrain !== void 0) {
312
+ sourcePortProps.is_using_open_drain = attributes.isUsingOpenDrain;
313
+ }
314
+ if (attributes.canUsePushPull !== void 0) {
315
+ sourcePortProps.can_use_push_pull = attributes.canUsePushPull;
316
+ }
317
+ if (attributes.isUsingPushPull !== void 0) {
318
+ sourcePortProps.is_using_push_pull = attributes.isUsingPushPull;
319
+ }
320
+ if (attributes.shouldHaveDecouplingCapacitor !== void 0) {
321
+ sourcePortProps.should_have_decoupling_capacitor = attributes.shouldHaveDecouplingCapacitor;
322
+ }
323
+ if (attributes.recommendedDecouplingCapacitorCapacitance !== void 0) {
324
+ sourcePortProps.recommended_decoupling_capacitor_capacitance = attributes.recommendedDecouplingCapacitorCapacitance;
325
+ }
326
+ };
327
+
328
+ // lib/components/primitive-components/Port/get-pin-attribute-mismatches.ts
329
+ var getPinAttributeMismatches = (declared, imported) => {
330
+ const mismatches = [];
331
+ for (const propName of Object.keys(declared)) {
332
+ if (propName === "highlightColor" || propName === "includeInBoardPinout")
333
+ continue;
334
+ const normalized = {};
335
+ applyPinAttributesToSourcePort(normalized, {
336
+ [propName]: declared[propName]
337
+ });
338
+ if (propName === "capabilities") {
339
+ for (const attributeName of Object.keys(
340
+ imported
341
+ )) {
342
+ if (attributeName.startsWith("supports_"))
343
+ Object.assign(normalized, {
344
+ [attributeName]: normalized[attributeName] ?? false
345
+ });
346
+ }
347
+ }
348
+ for (const attributeName of Object.keys(
349
+ normalized
350
+ )) {
351
+ const declaredValue = normalized[attributeName];
352
+ const supportedAttributeName = attributeName.startsWith(
353
+ "is_configured_for_"
354
+ ) ? attributeName.replace("is_configured_for_", "supports_") : attributeName.startsWith("is_using_") ? attributeName.replace("is_using_", "can_use_") : void 0;
355
+ if (supportedAttributeName) {
356
+ if (declaredValue === true && imported[supportedAttributeName] === false)
357
+ mismatches.push(
358
+ `${propName}: ${JSON.stringify(declared[propName])}, fetched ${supportedAttributeName}: false`
359
+ );
360
+ continue;
361
+ }
362
+ const importedValue = imported[attributeName];
363
+ const valuesMatch = typeof importedValue === "number" && typeof declaredValue === "number" ? Math.abs(importedValue - declaredValue) <= Number.EPSILON * 8 * Math.max(1, Math.abs(importedValue), Math.abs(declaredValue)) : importedValue === declaredValue;
364
+ if (importedValue !== void 0 && declaredValue !== void 0 && !valuesMatch)
365
+ mismatches.push(
366
+ `${propName}: ${JSON.stringify(declared[propName])}, fetched ${attributeName}: ${JSON.stringify(importedValue)}`
367
+ );
368
+ }
369
+ }
370
+ return mismatches;
371
+ };
372
+
373
+ // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
374
+ import {
375
+ source_pin_attributes
376
+ } from "circuit-json";
377
+ var getImportedSourcePinAttributes = (port, importedSourcePorts) => {
378
+ if (new Set(
379
+ importedSourcePorts.map((sourcePort) => sourcePort.source_component_id)
380
+ ).size > 1)
381
+ return {};
382
+ const pinNumber = port.props.pinNumber;
383
+ const physicalMatches = pinNumber === void 0 ? [] : importedSourcePorts.filter(
384
+ (sourcePort) => sourcePort.pin_number === pinNumber
385
+ );
386
+ const aliases = port.getNameAndAliases();
387
+ const matches = physicalMatches.length > 0 ? physicalMatches : importedSourcePorts.filter(
388
+ (sourcePort) => [sourcePort.name, ...sourcePort.port_hints ?? []].some(
389
+ (alias) => aliases.includes(alias)
390
+ )
391
+ );
392
+ if (matches.length !== 1) return {};
393
+ const attributes = source_pin_attributes.parse(matches[0]);
394
+ for (const attributeName of Object.keys(
395
+ attributes
396
+ )) {
397
+ if (attributes[attributeName] === void 0)
398
+ delete attributes[attributeName];
399
+ }
400
+ return attributes;
401
+ };
402
+ var resolvePortSourcePinAttributes = (port) => {
403
+ const attributes = getImportedSourcePinAttributes(
404
+ port,
405
+ port.getParentNormalComponent()?._importedSourcePorts ?? []
406
+ );
407
+ for (const pinAttributes of port._getMatchingPinAttributes()) {
408
+ for (const attributeName of Object.keys(
409
+ attributes
410
+ )) {
411
+ if (pinAttributes.capabilities !== void 0 && attributeName.startsWith("supports_") || (pinAttributes.activeCapability !== void 0 || pinAttributes.activeCapabilities !== void 0) && attributeName.startsWith("is_configured_for_"))
412
+ delete attributes[attributeName];
413
+ }
414
+ applyPinAttributesToSourcePort(attributes, pinAttributes);
415
+ }
416
+ return attributes;
417
+ };
418
+
419
+ // lib/utils/get-datasheet-internal-connection-warnings.ts
420
+ var getDatasheetInternalConnectionWarnings = (component) => {
421
+ const reported = component._fetchedInternallyConnectedPinNames ?? component._importedInternallyConnectedPinNames ?? [];
422
+ const ports = component._getAllPortsFromChildren();
423
+ const resolvePort = (identifier) => {
424
+ const name = String(identifier);
425
+ const physical = ports.find(
426
+ (port) => port.physicalPinName === name || port.props.pinNumber !== void 0 && (String(port.props.pinNumber) === name || `pin${port.props.pinNumber}` === name)
427
+ );
428
+ if (physical) return physical;
429
+ const matches = ports.filter((port) => {
430
+ const aliases = port.getNameAndAliases();
431
+ return aliases.includes(name) || name.startsWith("pin") && aliases.includes(name.slice(3));
432
+ });
433
+ return matches.length === 1 ? matches[0] : void 0;
434
+ };
435
+ const declared = component._parsedProps.internallyConnectedPins;
436
+ const declaredGroups = (declared ?? []).map(
437
+ (group) => group.map(resolvePort).filter((port) => port !== void 0)
438
+ );
439
+ return reported.flatMap((group) => {
440
+ const resolved = group.map(resolvePort);
441
+ if (resolved.some((port) => !port)) return [];
442
+ const reportedPorts = [...new Set(resolved)];
443
+ if (reportedPorts.length < 2) return [];
444
+ const connected = /* @__PURE__ */ new Set([reportedPorts[0]]);
445
+ let changed = true;
446
+ while (changed) {
447
+ changed = false;
448
+ for (const group2 of declaredGroups) {
449
+ if (!group2.some((port) => connected.has(port))) continue;
450
+ for (const port of group2) {
451
+ if (!connected.has(port)) {
452
+ connected.add(port);
453
+ changed = true;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ if (reportedPorts.every((port) => connected.has(port))) return [];
459
+ const pinNames = reportedPorts.map((port) => {
460
+ const aliases = port.getNameAndAliases();
461
+ return aliases.find((name) => !/^(?:pin)?\d+$/.test(name)) ?? aliases[0] ?? "unnamed pin";
462
+ });
463
+ const names = pinNames.length === 2 ? pinNames.join(" and ") : `${pinNames.slice(0, -1).join(", ")} and ${pinNames.at(-1)}`;
464
+ return [
465
+ {
466
+ message: `The datasheet reports pins ${names} are internally connected, but ${declared === void 0 ? `the internallyConnectedPins prop isn't set on ${component.getDisplayName()}` : `internallyConnectedPins on ${component.getDisplayName()} does not declare that connection`}.`,
467
+ sourcePortIds: reportedPorts.flatMap(
468
+ (port) => port.source_port_id ? [port.source_port_id] : []
469
+ )
470
+ }
471
+ ];
472
+ });
473
+ };
474
+
475
+ // lib/components/base-components/NormalComponent/NormalComponent_fetchDatasheetForValidation.ts
476
+ import {
477
+ resolveManufacturerPartNumber,
478
+ supplierProps
479
+ } from "@tscircuit/props";
480
+ import { source_pin_attributes as source_pin_attributes2 } from "circuit-json";
481
+
482
+ // lib/utils/fetch-part-circuit-json-with-datasheet.ts
483
+ import { ZodError } from "zod";
484
+ var chipDatasheetPartFetches = /* @__PURE__ */ new WeakMap();
485
+ var fetchDatasheetPart = async (fetchPartCircuitJson, request) => {
486
+ const { supplierPartNumber, manufacturerPartNumber, platformFetch } = request;
487
+ const legacyRequest = {
488
+ supplierPartNumber,
489
+ manufacturerPartNumber,
490
+ platformFetch
491
+ };
492
+ try {
493
+ return { circuitJson: await fetchPartCircuitJson(request) };
494
+ } catch (error) {
495
+ if (!request.includeDatasheetInformation && !(error instanceof ZodError && error.issues.some(
496
+ (issue) => issue.code === "unrecognized_keys" && issue.keys.includes("includeDatasheetInformation")
497
+ )))
498
+ throw error;
499
+ const fallbackRequest = {
500
+ ...request,
501
+ includeDatasheetInformation: false
502
+ };
503
+ let circuitJson;
504
+ let usedLegacyRequest = false;
505
+ try {
506
+ usedLegacyRequest = !request.includeDatasheetInformation;
507
+ circuitJson = await fetchPartCircuitJson(
508
+ usedLegacyRequest ? legacyRequest : fallbackRequest
509
+ );
510
+ } catch {
511
+ if (usedLegacyRequest) throw error;
512
+ circuitJson = await fetchPartCircuitJson(legacyRequest);
513
+ usedLegacyRequest = true;
514
+ }
515
+ if (!circuitJson?.length) throw error;
516
+ const manufacturerPartNumbers = circuitJson.flatMap(
517
+ (element) => element.type === "source_component" && element.manufacturer_part_number ? [element.manufacturer_part_number] : []
518
+ );
519
+ if (manufacturerPartNumber && manufacturerPartNumbers.some(
520
+ (importedManufacturerPartNumber) => importedManufacturerPartNumber.trim().toLowerCase() !== manufacturerPartNumber.trim().toLowerCase()
521
+ ))
522
+ throw error;
523
+ const reason = usedLegacyRequest ? "the parts engine only accepted a request without the datasheet option" : error instanceof Error ? error.message : String(error);
524
+ return { circuitJson, datasheetFailureReason: reason };
525
+ }
526
+ };
527
+ var fetchPartCircuitJsonWithoutDatasheet = async (fetchPartCircuitJson, request) => {
528
+ const { circuitJson } = await fetchDatasheetPart(fetchPartCircuitJson, {
529
+ ...request,
530
+ includeDatasheetInformation: false
531
+ });
532
+ return circuitJson;
533
+ };
534
+ var fetchPartCircuitJsonWithDatasheet = async ({
535
+ fetchPartCircuitJson,
536
+ supplierPartNumber,
537
+ manufacturerPartNumber
538
+ }, sourcePortOwner) => {
539
+ const includeDatasheetInformation = sourcePortOwner.config.componentName === "Chip" || sourcePortOwner.config.componentName === "OpAmp" || sourcePortOwner.config.componentName === "PushButton";
540
+ const request = {
541
+ supplierPartNumber,
542
+ manufacturerPartNumber,
543
+ platformFetch: sourcePortOwner.root?.platform?.platformFetch,
544
+ includeDatasheetInformation
545
+ };
546
+ let partFetch;
547
+ const circuit = sourcePortOwner.root;
548
+ if (sourcePortOwner.config.componentName === "Chip" && circuit) {
549
+ let partFetchesByEngine = chipDatasheetPartFetches.get(circuit);
550
+ if (!partFetchesByEngine) {
551
+ partFetchesByEngine = /* @__PURE__ */ new WeakMap();
552
+ chipDatasheetPartFetches.set(circuit, partFetchesByEngine);
553
+ }
554
+ let partFetches = partFetchesByEngine.get(fetchPartCircuitJson);
555
+ if (!partFetches) {
556
+ partFetches = /* @__PURE__ */ new Map();
557
+ partFetchesByEngine.set(fetchPartCircuitJson, partFetches);
558
+ }
559
+ const partCacheKey = `datasheet_part:${JSON.stringify(
560
+ [supplierPartNumber, manufacturerPartNumber]
561
+ )}`;
562
+ partFetch = partFetches.get(partCacheKey) ?? fetchDatasheetPart(fetchPartCircuitJson, request);
563
+ partFetches.set(partCacheKey, partFetch);
564
+ } else {
565
+ partFetch = fetchDatasheetPart(fetchPartCircuitJson, request);
566
+ }
567
+ const { circuitJson, datasheetFailureReason } = await partFetch;
568
+ if (includeDatasheetInformation && datasheetFailureReason !== void 0) {
569
+ const message = `Datasheet information for ${sourcePortOwner.getDisplayName()} could not be fetched: ${datasheetFailureReason}. Pin attributes may not be populated.`;
570
+ if (sourcePortOwner.source_component_id && sourcePortOwner.root) {
571
+ sourcePortOwner.root.db.source_property_ignored_warning.insert({
572
+ source_component_id: sourcePortOwner.source_component_id,
573
+ property_name: "pinAttributes",
574
+ message,
575
+ error_type: "source_property_ignored_warning"
576
+ });
577
+ } else {
578
+ console.warn(message);
579
+ }
580
+ }
581
+ return circuitJson;
582
+ };
583
+
584
+ // lib/utils/get-imported-internally-connected-pin-names.ts
585
+ var getImportedInternallyConnectedPinNames = (circuitJson) => {
586
+ const ports = circuitJson.filter((element) => element.type === "source_port");
587
+ const components = circuitJson.filter((element) => element.type === "source_component").filter(
588
+ (component) => component.internally_connected_source_port_ids !== void 0
589
+ );
590
+ if (!components.length) return void 0;
591
+ return components.flatMap(
592
+ (component) => (component.internally_connected_source_port_ids ?? []).flatMap((group) => {
593
+ const resolved = group.map(
594
+ (id) => ports.find(
595
+ (port) => port.source_port_id === id && port.source_component_id === component.source_component_id
596
+ )
597
+ );
598
+ if (resolved.some((port) => !port)) return [];
599
+ return [
600
+ resolved.map(
601
+ (port) => port.pin_number !== void 0 ? `pin${port.pin_number}` : port.name
602
+ )
603
+ ];
604
+ })
605
+ );
606
+ };
607
+
608
+ // lib/components/base-components/NormalComponent/NormalComponent_fetchDatasheetForValidation.ts
609
+ var NormalComponent_fetchDatasheetForValidation = (component) => {
610
+ if (!["Chip", "PushButton", "OpAmp"].includes(component.config.componentName))
611
+ return;
612
+ if (component._hasStartedPinAttributesFetch) return;
613
+ if (component.getInheritedProperty("partsEngineDisabled")) return;
614
+ if (component.getInheritedProperty("bomDisabled")) return;
615
+ if (component._importedInternallyConnectedPinNames !== void 0) return;
616
+ if (component._importedSourcePorts.some(
617
+ (port) => Object.values(source_pin_attributes2.parse(port)).some(
618
+ (value) => value !== void 0
619
+ )
620
+ ))
621
+ return;
622
+ const partsEngine = component.getInheritedProperty("partsEngine");
623
+ if (!partsEngine?.fetchPartCircuitJson) return;
624
+ const footprint = component.resolveFootprint();
625
+ const supplierPartNumbers = component._parsedProps.supplierPartNumbers;
626
+ if (supplierProps.shape.supplierPartNumbers.unwrap().keySchema.options.some(
627
+ (supplierName) => typeof component.root?.platform?.footprintLibraryMap?.[supplierName] !== "function" && supplierPartNumbers?.[supplierName]?.some(
628
+ (partNumber) => footprint === `${supplierName}:${partNumber}`
629
+ )
630
+ ))
631
+ return;
632
+ const supplierPartNumber = Object.values(supplierPartNumbers ?? {}).flat()[0];
633
+ const manufacturerPartNumber = resolveManufacturerPartNumber(
634
+ component._parsedProps
635
+ );
636
+ if (!supplierPartNumber && !manufacturerPartNumber) return;
637
+ component._hasStartedPinAttributesFetch = true;
638
+ component._queueAsyncEffect(
639
+ "fetch-datasheet-validation-metadata",
640
+ async () => {
641
+ try {
642
+ const partCircuitJson = await fetchPartCircuitJsonWithDatasheet(
643
+ {
644
+ fetchPartCircuitJson: partsEngine.fetchPartCircuitJson,
645
+ supplierPartNumber,
646
+ manufacturerPartNumber
647
+ },
648
+ component
649
+ );
650
+ component._fetchedSourcePortsForPinAttributes = partCircuitJson?.filter(
651
+ (element) => element.type === "source_port"
652
+ ) ?? [];
653
+ component._fetchedInternallyConnectedPinNames = getImportedInternallyConnectedPinNames(partCircuitJson ?? []);
654
+ component._markDirty("SourceDesignRuleChecks");
655
+ } catch {
656
+ }
657
+ }
658
+ );
659
+ };
660
+
661
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialSourcePinSpecificationChecks.ts
662
+ var NormalComponent_doInitialSourcePinSpecificationChecks = (component) => {
663
+ if (!["Chip", "PushButton", "OpAmp"].includes(component.config.componentName))
664
+ return;
665
+ const isChip = component.config.componentName === "Chip";
666
+ if (!component.source_component_id) return;
667
+ const { db: db2 } = component.root;
668
+ const existingWarning = db2.source_component_pins_underspecified_warning.getWhere({
669
+ source_component_id: component.source_component_id
670
+ });
671
+ const drcChecksDisabled = component.root?.platform?.drcChecksDisabled ?? component.getInheritedProperty("drcChecksDisabled");
672
+ const pinSpecificationDrcChecksDisabled = component.root?.platform?.pinSpecificationDrcChecksDisabled ?? component.getInheritedProperty("pinSpecificationDrcChecksDisabled");
673
+ const checksDisabled = drcChecksDisabled || pinSpecificationDrcChecksDisabled;
674
+ if (!checksDisabled) NormalComponent_fetchDatasheetForValidation(component);
675
+ const sourcePorts = checksDisabled ? [] : component.selectAll("port").flatMap((port) => {
676
+ if (!port.source_port_id) return [];
677
+ const sourcePort = db2.source_port.get(port.source_port_id);
678
+ return sourcePort?.source_component_id === component.source_component_id ? [sourcePort] : [];
679
+ });
680
+ const sourceComponent = checksDisabled ? null : db2.source_component.get(component.source_component_id);
681
+ const chipCircuitJson = sourceComponent ? [sourceComponent, ...sourcePorts] : [];
682
+ const issues = [];
683
+ if (!checksDisabled && isChip) {
684
+ for (const port of component.selectAll("port")) {
685
+ const sourcePort = sourcePorts.find(
686
+ (sourcePort2) => sourcePort2.source_port_id === port.source_port_id
687
+ );
688
+ if (!sourcePort) continue;
689
+ const declared = {};
690
+ for (const alias of port.getNameAndAliases()) {
691
+ Object.assign(declared, component._parsedProps.pinAttributes?.[alias]);
692
+ }
693
+ const imported = getImportedSourcePinAttributes(
694
+ port,
695
+ component._fetchedSourcePortsForPinAttributes.length ? component._fetchedSourcePortsForPinAttributes : component._importedSourcePorts
696
+ );
697
+ const reasons2 = getPinAttributeMismatches(declared, imported);
698
+ if (reasons2.length)
699
+ issues.push({
700
+ pinName: sourcePort.name || "unnamed pin",
701
+ reasons: reasons2,
702
+ sourcePort
703
+ });
704
+ }
705
+ }
706
+ for (const [warningTable, check] of [
707
+ [db2.source_no_power_pin_defined_warning, checkNoPowerPinDefined],
708
+ [db2.source_no_ground_pin_defined_warning, checkNoGroundPinDefined]
709
+ ]) {
710
+ const existing = warningTable.getWhere({
711
+ source_component_id: component.source_component_id
712
+ });
713
+ const existingId = existing?.type === "source_no_power_pin_defined_warning" ? existing.source_no_power_pin_defined_warning_id : existing?.source_no_ground_pin_defined_warning_id;
714
+ const [warning2] = checksDisabled || !isChip || issues.length ? [] : check(chipCircuitJson);
715
+ if (warning2) {
716
+ if (existingId) {
717
+ warningTable.update(existingId, {
718
+ message: warning2.message,
719
+ source_port_ids: warning2.source_port_ids,
720
+ subcircuit_id: warning2.subcircuit_id
721
+ });
722
+ } else {
723
+ db2.insertAll([warning2]);
724
+ }
725
+ } else if (existingId) {
726
+ warningTable.delete(existingId);
727
+ }
728
+ }
729
+ const [underspecifiedWarning] = checksDisabled || !isChip ? [] : checkAllPinsInComponentAreUnderspecified(chipCircuitJson);
730
+ const internalWarnings = checksDisabled ? [] : getDatasheetInternalConnectionWarnings(component);
731
+ if (!issues.length && !underspecifiedWarning && !internalWarnings.length) {
732
+ if (existingWarning) {
733
+ db2.source_component_pins_underspecified_warning.delete(
734
+ existingWarning.source_component_pins_underspecified_warning_id
735
+ );
736
+ }
737
+ return;
738
+ }
739
+ const examples = issues.slice(0, 3).map(({ pinName, reasons: reasons2 }) => `${pinName} (${reasons2.join("; ")})`).join(", ");
740
+ const remaining = issues.length > 3 ? `, and ${issues.length - 3} more` : "";
741
+ const pinMessage = issues.length ? `Chip ${component.name || "unnamed chip"} has pinAttributes that conflict with fetched pin metadata on ${issues.length} pin${issues.length === 1 ? "" : "s"}: ${examples}${remaining}. Check the chip configuration against the part datasheet.` : underspecifiedWarning?.message;
742
+ const warning = {
743
+ source_component_id: component.source_component_id,
744
+ source_port_ids: [
745
+ .../* @__PURE__ */ new Set([
746
+ ...issues.length ? issues.map(({ sourcePort }) => sourcePort.source_port_id) : underspecifiedWarning?.source_port_ids ?? [],
747
+ ...internalWarnings.flatMap((warning2) => warning2.sourcePortIds)
748
+ ])
749
+ ],
750
+ subcircuit_id: component.getSubcircuit().subcircuit_id ?? void 0,
751
+ warning_type: "source_component_pins_underspecified_warning",
752
+ message: [pinMessage, ...internalWarnings.map((warning2) => warning2.message)].filter(Boolean).join(" ")
753
+ };
754
+ if (existingWarning) {
755
+ db2.source_component_pins_underspecified_warning.update(
756
+ existingWarning.source_component_pins_underspecified_warning_id,
757
+ warning
758
+ );
759
+ } else {
760
+ db2.source_component_pins_underspecified_warning.insert(warning);
761
+ }
762
+ };
763
+
141
764
  // lib/utils/schematic/getPinNumberFromPinLabelsKey.ts
142
765
  var PIN_LABELS_KEY_RE = /^(?:pin)?(\d+)$/;
143
766
  var getPinNumberFromPinLabelsKey = (pinKey) => {
@@ -201,7 +824,7 @@ function getNumericPinLabels(pinLabels) {
201
824
  }
202
825
 
203
826
  // lib/components/base-components/NormalComponent/NormalComponent.ts
204
- import { resolveManufacturerPartNumber as resolveManufacturerPartNumber2 } from "@tscircuit/props";
827
+ import { resolveManufacturerPartNumber as resolveManufacturerPartNumber3 } from "@tscircuit/props";
205
828
 
206
829
  // lib/utils/cad/compose-cad-model-rotation.ts
207
830
  import { normalizeDegrees } from "@tscircuit/math-utils";
@@ -3666,53 +4289,6 @@ function fillPolygonWithRects(polygon, options = {}) {
3666
4289
  return rects;
3667
4290
  }
3668
4291
 
3669
- // lib/utils/obstacles/generateApproximatingRects.ts
3670
- function generateApproximatingRects(rotatedRect, numRects = 2) {
3671
- const { center, width, height, rotation: rotation5 } = rotatedRect;
3672
- const rects = [];
3673
- const angleRad = rotation5 * Math.PI / 180;
3674
- const cosAngle = Math.cos(angleRad);
3675
- const sinAngle = Math.sin(angleRad);
3676
- const normalizedRotation = (rotation5 % 360 + 360) % 360;
3677
- const sliceAlongWidth = height <= width ? normalizedRotation >= 45 && normalizedRotation < 135 || normalizedRotation >= 225 && normalizedRotation < 315 : normalizedRotation >= 135 && normalizedRotation < 225 || normalizedRotation >= 315 || normalizedRotation < 45;
3678
- if (sliceAlongWidth) {
3679
- const sliceWidth = width / numRects;
3680
- for (let i2 = 0; i2 < numRects; i2++) {
3681
- const x2 = (i2 - numRects / 2 + 0.5) * sliceWidth;
3682
- const rotatedX = -x2 * cosAngle;
3683
- const rotatedY = -x2 * sinAngle;
3684
- const coverageWidth = sliceWidth * 1.1;
3685
- const coverageHeight = Math.abs(height * cosAngle) + Math.abs(sliceWidth * sinAngle);
3686
- rects.push({
3687
- center: {
3688
- x: center.x + rotatedX,
3689
- y: center.y + rotatedY
3690
- },
3691
- width: coverageWidth,
3692
- height: coverageHeight
3693
- });
3694
- }
3695
- } else {
3696
- const sliceHeight = height / numRects;
3697
- for (let i2 = 0; i2 < numRects; i2++) {
3698
- const y2 = (i2 - numRects / 2 + 0.5) * sliceHeight;
3699
- const rotatedX = -y2 * sinAngle;
3700
- const rotatedY = y2 * cosAngle;
3701
- const coverageWidth = Math.abs(width * cosAngle) + Math.abs(sliceHeight * sinAngle);
3702
- const coverageHeight = sliceHeight * 1.1;
3703
- rects.push({
3704
- center: {
3705
- x: center.x + rotatedX,
3706
- y: center.y + rotatedY
3707
- },
3708
- width: coverageWidth,
3709
- height: coverageHeight
3710
- });
3711
- }
3712
- }
3713
- return rects;
3714
- }
3715
-
3716
4292
  // lib/utils/obstacles/getAxisAlignedRectFromPolygon.ts
3717
4293
  var AXIS_ALIGNED_RECT_TOLERANCE_MM = 1e-3;
3718
4294
  var getAxisAlignedRectFromPolygon = (points) => {
@@ -3822,43 +4398,34 @@ var getObstaclesFromPcbKeepoutOutline = (keepout, componentId) => {
3822
4398
  const deltaY = end.y - start.y;
3823
4399
  const segmentLength = Math.hypot(deltaX, deltaY);
3824
4400
  if (!Number.isFinite(segmentLength) || segmentLength === 0) continue;
3825
- const approximatingRects = generateApproximatingRects({
4401
+ obstacles.push({
4402
+ obstacleId: `${keepout.pcb_keepout_id}_segment_${segmentIndex}`,
4403
+ componentId,
4404
+ type: "rect",
4405
+ layers: keepout.layers,
3826
4406
  center: {
3827
4407
  x: (start.x + end.x) / 2,
3828
4408
  y: (start.y + end.y) / 2
3829
4409
  },
3830
4410
  width: segmentLength,
3831
4411
  height: stroke_width,
3832
- rotation: Math.atan2(deltaY, deltaX) * 180 / Math.PI
4412
+ ccwRotationDegrees: Math.atan2(deltaY, deltaX) * 180 / Math.PI,
4413
+ connectedTo: []
3833
4414
  });
3834
- for (const [approximationIndex, rect] of approximatingRects.entries()) {
3835
- obstacles.push({
3836
- obstacleId: `${keepout.pcb_keepout_id}_segment_${segmentIndex}_rect_${approximationIndex}`,
3837
- componentId,
3838
- type: "rect",
3839
- layers: keepout.layers,
3840
- ...rect,
3841
- connectedTo: []
3842
- });
3843
- }
3844
4415
  }
3845
4416
  const isClosed = outline.length > 1 && outline[0].x === outline.at(-1)?.x && outline[0].y === outline.at(-1)?.y;
3846
4417
  const joinPoints = isClosed ? outline.slice(0, -1) : outline;
3847
4418
  for (const [joinIndex, point6] of joinPoints.entries()) {
3848
- const approximatingRects = fillCircleWithRects(
3849
- { center: point6, radius: stroke_width / 2 },
3850
- { rectHeight: stroke_width / 4 }
3851
- );
3852
- for (const [approximationIndex, rect] of approximatingRects.entries()) {
3853
- obstacles.push({
3854
- obstacleId: `${keepout.pcb_keepout_id}_join_${joinIndex}_rect_${approximationIndex}`,
3855
- componentId,
3856
- type: "rect",
3857
- layers: keepout.layers,
3858
- ...rect,
3859
- connectedTo: []
3860
- });
3861
- }
4419
+ obstacles.push({
4420
+ obstacleId: `${keepout.pcb_keepout_id}_join_${joinIndex}`,
4421
+ componentId,
4422
+ type: "rect",
4423
+ layers: keepout.layers,
4424
+ center: point6,
4425
+ width: stroke_width,
4426
+ height: stroke_width,
4427
+ connectedTo: []
4428
+ });
3862
4429
  }
3863
4430
  return obstacles;
3864
4431
  };
@@ -4670,234 +5237,6 @@ var getCenterOfPcbPrimitives = (pcbPrimitives) => {
4670
5237
  // lib/components/primitive-components/Port/Port.ts
4671
5238
  import { portProps } from "@tscircuit/props";
4672
5239
 
4673
- // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
4674
- import {
4675
- source_pin_attributes
4676
- } from "circuit-json";
4677
-
4678
- // lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
4679
- import { voltage } from "circuit-json";
4680
- var setSupportedCapability = (sourcePortProps, capability) => {
4681
- switch (capability) {
4682
- case "i2c_sda":
4683
- sourcePortProps.supports_i2c_sda = true;
4684
- return;
4685
- case "i2c_scl":
4686
- sourcePortProps.supports_i2c_scl = true;
4687
- return;
4688
- case "spi_cs":
4689
- sourcePortProps.supports_spi_cs = true;
4690
- return;
4691
- case "spi_sck":
4692
- sourcePortProps.supports_spi_sck = true;
4693
- return;
4694
- case "spi_mosi":
4695
- sourcePortProps.supports_spi_mosi = true;
4696
- return;
4697
- case "spi_miso":
4698
- sourcePortProps.supports_spi_miso = true;
4699
- return;
4700
- case "uart_tx":
4701
- sourcePortProps.supports_uart_tx = true;
4702
- return;
4703
- case "uart_rx":
4704
- sourcePortProps.supports_uart_rx = true;
4705
- return;
4706
- default: {
4707
- const unhandledCapability = capability;
4708
- throw new Error(`Unhandled pin capability: ${unhandledCapability}`);
4709
- }
4710
- }
4711
- };
4712
- var setConfiguredCapability = (sourcePortProps, capability) => {
4713
- switch (capability) {
4714
- case "i2c_sda":
4715
- sourcePortProps.is_configured_for_i2c_sda = true;
4716
- return;
4717
- case "i2c_scl":
4718
- sourcePortProps.is_configured_for_i2c_scl = true;
4719
- return;
4720
- case "spi_cs":
4721
- sourcePortProps.is_configured_for_spi_cs = true;
4722
- return;
4723
- case "spi_sck":
4724
- sourcePortProps.is_configured_for_spi_sck = true;
4725
- return;
4726
- case "spi_mosi":
4727
- sourcePortProps.is_configured_for_spi_mosi = true;
4728
- return;
4729
- case "spi_miso":
4730
- sourcePortProps.is_configured_for_spi_miso = true;
4731
- return;
4732
- case "uart_tx":
4733
- sourcePortProps.is_configured_for_uart_tx = true;
4734
- return;
4735
- case "uart_rx":
4736
- sourcePortProps.is_configured_for_uart_rx = true;
4737
- return;
4738
- default: {
4739
- const unhandledCapability = capability;
4740
- throw new Error(
4741
- `Unhandled configured pin capability: ${unhandledCapability}`
4742
- );
4743
- }
4744
- }
4745
- };
4746
- var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
4747
- if (attributes.isInput !== void 0) {
4748
- sourcePortProps.is_input = attributes.isInput;
4749
- }
4750
- if (attributes.isOutput !== void 0) {
4751
- sourcePortProps.is_output = attributes.isOutput;
4752
- }
4753
- if (attributes.isBidirectional !== void 0) {
4754
- sourcePortProps.is_bidirectional = attributes.isBidirectional;
4755
- }
4756
- if (attributes.isPassive !== void 0) {
4757
- sourcePortProps.is_passive = attributes.isPassive;
4758
- }
4759
- if (attributes.canUseTriState !== void 0) {
4760
- sourcePortProps.can_use_tri_state = attributes.canUseTriState;
4761
- }
4762
- if (attributes.isUsingTriState !== void 0) {
4763
- sourcePortProps.is_using_tri_state = attributes.isUsingTriState;
4764
- }
4765
- if (attributes.canUseOpenCollector !== void 0) {
4766
- sourcePortProps.can_use_open_collector = attributes.canUseOpenCollector;
4767
- }
4768
- if (attributes.isUsingOpenCollector !== void 0) {
4769
- sourcePortProps.is_using_open_collector = attributes.isUsingOpenCollector;
4770
- }
4771
- if (attributes.canUseOpenEmitter !== void 0) {
4772
- sourcePortProps.can_use_open_emitter = attributes.canUseOpenEmitter;
4773
- }
4774
- if (attributes.isUsingOpenEmitter !== void 0) {
4775
- sourcePortProps.is_using_open_emitter = attributes.isUsingOpenEmitter;
4776
- }
4777
- if (attributes.isGpio !== void 0) {
4778
- sourcePortProps.is_gpio = attributes.isGpio;
4779
- }
4780
- if (attributes.highlightColor !== void 0) {
4781
- sourcePortProps.highlight_color = attributes.highlightColor;
4782
- }
4783
- for (const capability of attributes.capabilities ?? []) {
4784
- setSupportedCapability(sourcePortProps, capability);
4785
- }
4786
- const configuredCapabilities = /* @__PURE__ */ new Set([
4787
- ...attributes.activeCapabilities ?? [],
4788
- ...attributes.activeCapability ? [attributes.activeCapability] : []
4789
- ]);
4790
- for (const capability of configuredCapabilities) {
4791
- setConfiguredCapability(sourcePortProps, capability);
4792
- }
4793
- if (attributes.mustBeConnected !== void 0) {
4794
- sourcePortProps.must_be_connected = attributes.mustBeConnected;
4795
- }
4796
- if (attributes.providesPower !== void 0) {
4797
- sourcePortProps.provides_power = attributes.providesPower;
4798
- }
4799
- if (attributes.requiresPower !== void 0) {
4800
- sourcePortProps.requires_power = attributes.requiresPower;
4801
- }
4802
- if (attributes.providesGround !== void 0) {
4803
- sourcePortProps.provides_ground = attributes.providesGround;
4804
- }
4805
- if (attributes.requiresGround !== void 0) {
4806
- sourcePortProps.requires_ground = attributes.requiresGround;
4807
- }
4808
- if (attributes.providesVoltage !== void 0) {
4809
- sourcePortProps.provides_voltage = voltage.parse(attributes.providesVoltage);
4810
- }
4811
- if (attributes.requiresVoltage !== void 0) {
4812
- sourcePortProps.requires_voltage = voltage.parse(attributes.requiresVoltage);
4813
- }
4814
- if (attributes.doNotConnect !== void 0) {
4815
- sourcePortProps.do_not_connect = attributes.doNotConnect;
4816
- }
4817
- if (attributes.includeInBoardPinout !== void 0) {
4818
- sourcePortProps.include_in_board_pinout = attributes.includeInBoardPinout;
4819
- }
4820
- if (attributes.canUseInternalPullup !== void 0) {
4821
- sourcePortProps.can_use_internal_pullup = attributes.canUseInternalPullup;
4822
- }
4823
- if (attributes.isUsingInternalPullup !== void 0) {
4824
- sourcePortProps.is_using_internal_pullup = attributes.isUsingInternalPullup;
4825
- }
4826
- if (attributes.needsExternalPullup !== void 0) {
4827
- sourcePortProps.needs_external_pullup = attributes.needsExternalPullup;
4828
- }
4829
- if (attributes.canUseInternalPulldown !== void 0) {
4830
- sourcePortProps.can_use_internal_pulldown = attributes.canUseInternalPulldown;
4831
- }
4832
- if (attributes.isUsingInternalPulldown !== void 0) {
4833
- sourcePortProps.is_using_internal_pulldown = attributes.isUsingInternalPulldown;
4834
- }
4835
- if (attributes.needsExternalPulldown !== void 0) {
4836
- sourcePortProps.needs_external_pulldown = attributes.needsExternalPulldown;
4837
- }
4838
- if (attributes.canUseOpenDrain !== void 0) {
4839
- sourcePortProps.can_use_open_drain = attributes.canUseOpenDrain;
4840
- }
4841
- if (attributes.isUsingOpenDrain !== void 0) {
4842
- sourcePortProps.is_using_open_drain = attributes.isUsingOpenDrain;
4843
- }
4844
- if (attributes.canUsePushPull !== void 0) {
4845
- sourcePortProps.can_use_push_pull = attributes.canUsePushPull;
4846
- }
4847
- if (attributes.isUsingPushPull !== void 0) {
4848
- sourcePortProps.is_using_push_pull = attributes.isUsingPushPull;
4849
- }
4850
- if (attributes.shouldHaveDecouplingCapacitor !== void 0) {
4851
- sourcePortProps.should_have_decoupling_capacitor = attributes.shouldHaveDecouplingCapacitor;
4852
- }
4853
- if (attributes.recommendedDecouplingCapacitorCapacitance !== void 0) {
4854
- sourcePortProps.recommended_decoupling_capacitor_capacitance = attributes.recommendedDecouplingCapacitorCapacitance;
4855
- }
4856
- };
4857
-
4858
- // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
4859
- var getImportedSourcePinAttributes = (port, importedSourcePorts) => {
4860
- if (new Set(
4861
- importedSourcePorts.map((sourcePort) => sourcePort.source_component_id)
4862
- ).size > 1)
4863
- return {};
4864
- const pinNumber = port.props.pinNumber;
4865
- const physicalMatches = pinNumber === void 0 ? [] : importedSourcePorts.filter(
4866
- (sourcePort) => sourcePort.pin_number === pinNumber
4867
- );
4868
- const aliases = port.getNameAndAliases();
4869
- const matches = physicalMatches.length > 0 ? physicalMatches : importedSourcePorts.filter(
4870
- (sourcePort) => [sourcePort.name, ...sourcePort.port_hints ?? []].some(
4871
- (alias) => aliases.includes(alias)
4872
- )
4873
- );
4874
- if (matches.length !== 1) return {};
4875
- const attributes = source_pin_attributes.parse(matches[0]);
4876
- for (const attributeName of Object.keys(
4877
- attributes
4878
- )) {
4879
- if (attributes[attributeName] === void 0)
4880
- delete attributes[attributeName];
4881
- }
4882
- return attributes;
4883
- };
4884
- var resolvePortSourcePinAttributes = (port) => {
4885
- const attributes = getImportedSourcePinAttributes(
4886
- port,
4887
- port.getParentNormalComponent()?._importedSourcePorts ?? []
4888
- );
4889
- for (const pinAttributes of port._getMatchingPinAttributes()) {
4890
- for (const attributeName of Object.keys(
4891
- attributes
4892
- )) {
4893
- if (pinAttributes.capabilities !== void 0 && attributeName.startsWith("supports_") || (pinAttributes.activeCapability !== void 0 || pinAttributes.activeCapabilities !== void 0) && attributeName.startsWith("is_configured_for_"))
4894
- delete attributes[attributeName];
4895
- }
4896
- applyPinAttributesToSourcePort(attributes, pinAttributes);
4897
- }
4898
- return attributes;
4899
- };
4900
-
4901
5240
  // lib/components/primitive-components/Port/Port_doInitialCreateTracesFromProps.ts
4902
5241
  var getConnectionTargets = (target) => {
4903
5242
  if (!target) return [];
@@ -4944,10 +5283,25 @@ function netIsGround(net) {
4944
5283
  return net._parsedProps.isGroundNet ?? GROUND_NET_REGEX.test(net._parsedProps.name);
4945
5284
  }
4946
5285
  function Port_isConnectedToGround(port) {
4947
- for (const connectedTrace of port._getDirectlyConnectedTraces()) {
5286
+ const internallyConnectedPorts = /* @__PURE__ */ new Set([
5287
+ port,
5288
+ ...port._getPortsInternallyConnectedToThisPort()
5289
+ ]);
5290
+ const traces = new Set(
5291
+ [...internallyConnectedPorts].flatMap(
5292
+ (connectedPort) => connectedPort._getDirectlyConnectedTraces()
5293
+ )
5294
+ );
5295
+ for (const connectedTrace of traces) {
4948
5296
  const connectedPorts = connectedTrace._findConnectedPorts().ports ?? [];
4949
- for (const connectedPort of connectedPorts) {
4950
- if (connectedPort === port) continue;
5297
+ const connectedPortGroup = new Set(
5298
+ connectedPorts.flatMap((connectedPort) => [
5299
+ connectedPort,
5300
+ ...connectedPort._getPortsInternallyConnectedToThisPort()
5301
+ ])
5302
+ );
5303
+ for (const connectedPort of connectedPortGroup) {
5304
+ if (internallyConnectedPorts.has(connectedPort)) continue;
4951
5305
  if (portIsGround(connectedPort)) return true;
4952
5306
  }
4953
5307
  for (const connectedNet of connectedTrace._findConnectedNets().nets) {
@@ -4968,16 +5322,35 @@ function portShouldHaveDecouplingCapacitor(port) {
4968
5322
  }
4969
5323
  if (attributes.requires_power !== void 0) return attributes.requires_power;
4970
5324
  if (attributes.provides_power === true) return false;
4971
- for (const portName of port.getNameAndAliases()) {
5325
+ const aliases = port.getNameAndAliases();
5326
+ if (attributes.requires_ground === true || attributes.provides_ground === true || aliases.some((alias) => GROUND_NET_REGEX.test(alias)))
5327
+ return false;
5328
+ for (const portName of aliases) {
5329
+ if (portName === port.physicalPinName) continue;
4972
5330
  if (POWER_NET_REGEX.test(portName)) return true;
4973
5331
  }
4974
5332
  return false;
4975
5333
  }
4976
5334
  function Port_isConnectedToPower(port) {
4977
- for (const connectedTrace of port._getDirectlyConnectedTraces()) {
5335
+ const internallyConnectedPorts = /* @__PURE__ */ new Set([
5336
+ port,
5337
+ ...port._getPortsInternallyConnectedToThisPort()
5338
+ ]);
5339
+ const traces = new Set(
5340
+ [...internallyConnectedPorts].flatMap(
5341
+ (connectedPort) => connectedPort._getDirectlyConnectedTraces()
5342
+ )
5343
+ );
5344
+ for (const connectedTrace of traces) {
4978
5345
  const connectedPorts = connectedTrace._findConnectedPorts().ports ?? [];
4979
- for (const connectedPort of connectedPorts) {
4980
- if (connectedPort === port) continue;
5346
+ const connectedPortGroup = new Set(
5347
+ connectedPorts.flatMap((connectedPort) => [
5348
+ connectedPort,
5349
+ ...connectedPort._getPortsInternallyConnectedToThisPort()
5350
+ ])
5351
+ );
5352
+ for (const connectedPort of connectedPortGroup) {
5353
+ if (internallyConnectedPorts.has(connectedPort)) continue;
4981
5354
  if (portShouldHaveDecouplingCapacitor(connectedPort)) return true;
4982
5355
  }
4983
5356
  }
@@ -5194,12 +5567,21 @@ var Port = class extends PrimitiveComponent2 {
5194
5567
  const parent = this.parent;
5195
5568
  if (!parent || !parent._getInternallyConnectedPins) return [];
5196
5569
  const internallyConnectedPorts = parent._getInternallyConnectedPins();
5197
- for (const ports of internallyConnectedPorts) {
5198
- if (ports.some((port) => port === this)) {
5199
- return ports;
5570
+ const connected = /* @__PURE__ */ new Set([this]);
5571
+ let changed = true;
5572
+ while (changed) {
5573
+ changed = false;
5574
+ for (const ports of internallyConnectedPorts) {
5575
+ if (!ports.some((port) => connected.has(port))) continue;
5576
+ for (const port of ports) {
5577
+ if (!connected.has(port)) {
5578
+ connected.add(port);
5579
+ changed = true;
5580
+ }
5581
+ }
5200
5582
  }
5201
5583
  }
5202
- return [];
5584
+ return connected.size > 1 ? [...connected] : [];
5203
5585
  }
5204
5586
  /**
5205
5587
  * Return true if this port has a schematic representation and can be rendered
@@ -13836,6 +14218,12 @@ var createComponentsFromCircuitJson = ({
13836
14218
  const importedSourcePorts = circuitJson.filter(
13837
14219
  (elm) => elm.type === "source_port"
13838
14220
  );
14221
+ if (sourcePortOwner) {
14222
+ const internalGroups = getImportedInternallyConnectedPinNames(circuitJson);
14223
+ if (internalGroups !== void 0) {
14224
+ sourcePortOwner._importedInternallyConnectedPinNames = internalGroups;
14225
+ }
14226
+ }
13839
14227
  if (sourcePortOwner && importedSourcePorts.length > 0) {
13840
14228
  sourcePortOwner._importedSourcePorts = importedSourcePorts;
13841
14229
  for (const port of sourcePortOwner._getAllPortsFromChildren()) {
@@ -16601,110 +16989,6 @@ import {
16601
16989
  pcb_pin1_location,
16602
16990
  source_component_misconfigured_error
16603
16991
  } from "circuit-json";
16604
-
16605
- // lib/utils/fetch-part-circuit-json-with-datasheet.ts
16606
- import { ZodError } from "zod";
16607
- var chipDatasheetPartFetches = /* @__PURE__ */ new WeakMap();
16608
- var fetchDatasheetPart = async (fetchPartCircuitJson, request) => {
16609
- const { supplierPartNumber, manufacturerPartNumber, platformFetch } = request;
16610
- const legacyRequest = {
16611
- supplierPartNumber,
16612
- manufacturerPartNumber,
16613
- platformFetch
16614
- };
16615
- try {
16616
- return { circuitJson: await fetchPartCircuitJson(request) };
16617
- } catch (error) {
16618
- if (!request.includeDatasheetInformation && !(error instanceof ZodError && error.issues.some(
16619
- (issue) => issue.code === "unrecognized_keys" && issue.keys.includes("includeDatasheetInformation")
16620
- )))
16621
- throw error;
16622
- const fallbackRequest = {
16623
- ...request,
16624
- includeDatasheetInformation: false
16625
- };
16626
- let circuitJson;
16627
- let usedLegacyRequest = false;
16628
- try {
16629
- usedLegacyRequest = !request.includeDatasheetInformation;
16630
- circuitJson = await fetchPartCircuitJson(
16631
- usedLegacyRequest ? legacyRequest : fallbackRequest
16632
- );
16633
- } catch {
16634
- if (usedLegacyRequest) throw error;
16635
- circuitJson = await fetchPartCircuitJson(legacyRequest);
16636
- usedLegacyRequest = true;
16637
- }
16638
- if (!circuitJson?.length) throw error;
16639
- const manufacturerPartNumbers = circuitJson.flatMap(
16640
- (element) => element.type === "source_component" && element.manufacturer_part_number ? [element.manufacturer_part_number] : []
16641
- );
16642
- if (manufacturerPartNumber && manufacturerPartNumbers.some(
16643
- (importedManufacturerPartNumber) => importedManufacturerPartNumber.trim().toLowerCase() !== manufacturerPartNumber.trim().toLowerCase()
16644
- ))
16645
- throw error;
16646
- const reason = usedLegacyRequest ? "the parts engine only accepted a request without the datasheet option" : error instanceof Error ? error.message : String(error);
16647
- return { circuitJson, datasheetFailureReason: reason };
16648
- }
16649
- };
16650
- var fetchPartCircuitJsonWithoutDatasheet = async (fetchPartCircuitJson, request) => {
16651
- const { circuitJson } = await fetchDatasheetPart(fetchPartCircuitJson, {
16652
- ...request,
16653
- includeDatasheetInformation: false
16654
- });
16655
- return circuitJson;
16656
- };
16657
- var fetchPartCircuitJsonWithDatasheet = async ({
16658
- fetchPartCircuitJson,
16659
- supplierPartNumber,
16660
- manufacturerPartNumber
16661
- }, sourcePortOwner) => {
16662
- const includeDatasheetInformation = sourcePortOwner.config.componentName === "Chip" || sourcePortOwner.config.componentName === "OpAmp";
16663
- const request = {
16664
- supplierPartNumber,
16665
- manufacturerPartNumber,
16666
- platformFetch: sourcePortOwner.root?.platform?.platformFetch,
16667
- includeDatasheetInformation
16668
- };
16669
- let partFetch;
16670
- const circuit = sourcePortOwner.root;
16671
- if (sourcePortOwner.config.componentName === "Chip" && circuit) {
16672
- let partFetchesByEngine = chipDatasheetPartFetches.get(circuit);
16673
- if (!partFetchesByEngine) {
16674
- partFetchesByEngine = /* @__PURE__ */ new WeakMap();
16675
- chipDatasheetPartFetches.set(circuit, partFetchesByEngine);
16676
- }
16677
- let partFetches = partFetchesByEngine.get(fetchPartCircuitJson);
16678
- if (!partFetches) {
16679
- partFetches = /* @__PURE__ */ new Map();
16680
- partFetchesByEngine.set(fetchPartCircuitJson, partFetches);
16681
- }
16682
- const partCacheKey = `datasheet_part:${JSON.stringify(
16683
- [supplierPartNumber, manufacturerPartNumber]
16684
- )}`;
16685
- partFetch = partFetches.get(partCacheKey) ?? fetchDatasheetPart(fetchPartCircuitJson, request);
16686
- partFetches.set(partCacheKey, partFetch);
16687
- } else {
16688
- partFetch = fetchDatasheetPart(fetchPartCircuitJson, request);
16689
- }
16690
- const { circuitJson, datasheetFailureReason } = await partFetch;
16691
- if (includeDatasheetInformation && datasheetFailureReason !== void 0) {
16692
- const message = `Datasheet information for ${sourcePortOwner.getDisplayName()} could not be fetched: ${datasheetFailureReason}. Pin attributes may not be populated.`;
16693
- if (sourcePortOwner.source_component_id && sourcePortOwner.root) {
16694
- sourcePortOwner.root.db.source_property_ignored_warning.insert({
16695
- source_component_id: sourcePortOwner.source_component_id,
16696
- property_name: "pinAttributes",
16697
- message,
16698
- error_type: "source_property_ignored_warning"
16699
- });
16700
- } else {
16701
- console.warn(message);
16702
- }
16703
- }
16704
- return circuitJson;
16705
- };
16706
-
16707
- // lib/components/base-components/NormalComponent/NormalComponent_doInitialPartOrientationAnalysis.ts
16708
16992
  var pendingSupplierPartOrientationAnalyses = /* @__PURE__ */ new WeakMap();
16709
16993
  var getPendingSupplierPartOrientationAnalyses = (partsEngine) => {
16710
16994
  const existing = pendingSupplierPartOrientationAnalyses.get(partsEngine);
@@ -17036,8 +17320,8 @@ function NormalComponent_doInitialPcbComponentAnchorAlignment(component) {
17036
17320
 
17037
17321
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialPcbFootprintStringRender.ts
17038
17322
  import {
17039
- supplierProps,
17040
- resolveManufacturerPartNumber
17323
+ supplierProps as supplierProps2,
17324
+ resolveManufacturerPartNumber as resolveManufacturerPartNumber2
17041
17325
  } from "@tscircuit/props";
17042
17326
  import {
17043
17327
  circuit_json_footprint_load_error,
@@ -17123,7 +17407,7 @@ var parseLibraryFootprintRef = (s2) => {
17123
17407
  };
17124
17408
 
17125
17409
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialPcbFootprintStringRender.ts
17126
- var supplierNames = supplierProps.shape.supplierPartNumbers.unwrap().keySchema.options;
17410
+ var supplierNames = supplierProps2.shape.supplierPartNumbers.unwrap().keySchema.options;
17127
17411
  var shouldAddOutsideFootprintWrapper = (component) => component.componentName === "Symbol" || component.isSchematicPrimitive;
17128
17412
  var getSupplierPartCircuitJsonResolver = (component, footprintLibrary, footprintName) => {
17129
17413
  if (component.getInheritedProperty("partsEngineDisabled")) return;
@@ -17142,7 +17426,7 @@ var getSupplierPartCircuitJsonResolver = (component, footprintLibrary, footprint
17142
17426
  {
17143
17427
  fetchPartCircuitJson,
17144
17428
  supplierPartNumber,
17145
- manufacturerPartNumber: resolveManufacturerPartNumber(component.props)
17429
+ manufacturerPartNumber: resolveManufacturerPartNumber2(component.props)
17146
17430
  },
17147
17431
  component
17148
17432
  );
@@ -17718,7 +18002,7 @@ var NormalComponent_doInitialMissingManufacturerPartNumberWarning = (component)
17718
18002
 
17719
18003
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialComponentAvailabilityWarning.ts
17720
18004
  import {
17721
- supplierProps as supplierProps2
18005
+ supplierProps as supplierProps3
17722
18006
  } from "@tscircuit/props";
17723
18007
  import { source_component_availability_warning } from "circuit-json";
17724
18008
 
@@ -17776,7 +18060,7 @@ var checkPartAvailability = (circuit, {
17776
18060
 
17777
18061
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialComponentAvailabilityWarning.ts
17778
18062
  var availabilityChecks = /* @__PURE__ */ new WeakMap();
17779
- var supplierNames2 = supplierProps2.shape.supplierPartNumbers.unwrap().keySchema.options;
18063
+ var supplierNames2 = supplierProps3.shape.supplierPartNumbers.unwrap().keySchema.options;
17780
18064
  function NormalComponent_doInitialComponentAvailabilityWarning(component, { refresh = false } = {}) {
17781
18065
  const root = component.root;
17782
18066
  const sourceComponentId = component.source_component_id;
@@ -17852,14 +18136,14 @@ function NormalComponent_doInitialComponentAvailabilityWarning(component, { refr
17852
18136
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialSupplierFootprintMismatchWarning.ts
17853
18137
  import { getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
17854
18138
  import {
17855
- supplierProps as supplierProps3
18139
+ supplierProps as supplierProps4
17856
18140
  } from "@tscircuit/props";
17857
18141
  import {
17858
18142
  source_part_not_found_warning,
17859
18143
  supplier_footprint_mismatch_warning
17860
18144
  } from "circuit-json";
17861
18145
  var SUPPLIER_FOOTPRINT_IOU_WARNING_THRESHOLD = 0.8;
17862
- var supplierNames3 = supplierProps3.shape.supplierPartNumbers.unwrap().keySchema.options;
18146
+ var supplierNames3 = supplierProps4.shape.supplierPartNumbers.unwrap().keySchema.options;
17863
18147
  var isCopperElement = (elm) => elm.type === "pcb_smtpad" || elm.type === "pcb_plated_hole";
17864
18148
  var isValidBounds = (bounds) => Number.isFinite(bounds.minX) && Number.isFinite(bounds.minY) && Number.isFinite(bounds.maxX) && Number.isFinite(bounds.maxY) && bounds.maxX > bounds.minX && bounds.maxY > bounds.minY;
17865
18149
  var getCopperBounds = (elements) => {
@@ -18183,6 +18467,11 @@ var NormalComponent = class extends PrimitiveComponent2 {
18183
18467
  _asyncFootprintCadModel;
18184
18468
  /** Electrical attributes from imported ports; user props remain authoritative. */
18185
18469
  _importedSourcePorts = [];
18470
+ _importedInternallyConnectedPinNames;
18471
+ /** Optional datasheet facts fetched solely for source-level validation. */
18472
+ _fetchedSourcePortsForPinAttributes = [];
18473
+ _fetchedInternallyConnectedPinNames;
18474
+ _hasStartedPinAttributesFetch = false;
18186
18475
  _isCadModelChild;
18187
18476
  _inferredInternallyConnectedPinNames = [];
18188
18477
  pcb_missing_footprint_error_id;
@@ -18205,7 +18494,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18205
18494
  return [];
18206
18495
  }
18207
18496
  get internallyConnectedPinNames() {
18208
- const rawPins = this._parsedProps.internallyConnectedPins ?? this.defaultInternallyConnectedPinNames;
18497
+ const rawPins = this._parsedProps.internallyConnectedPins ?? this._importedInternallyConnectedPinNames ?? this.defaultInternallyConnectedPinNames;
18209
18498
  return [...rawPins, ...this._inferredInternallyConnectedPinNames].map(
18210
18499
  (pinGroup) => pinGroup.map(
18211
18500
  (pin) => typeof pin === "number" ? `pin${pin}` : pin
@@ -18652,7 +18941,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18652
18941
  const source_component = db2.source_component.insert({
18653
18942
  ftype,
18654
18943
  name: this.name,
18655
- manufacturer_part_number: resolveManufacturerPartNumber2(props),
18944
+ manufacturer_part_number: resolveManufacturerPartNumber3(props),
18656
18945
  supplier_part_numbers: props.supplierPartNumbers,
18657
18946
  display_name: props.displayName
18658
18947
  });
@@ -18719,7 +19008,8 @@ var NormalComponent = class extends PrimitiveComponent2 {
18719
19008
  for (const netPortNames of this.internallyConnectedPinNames) {
18720
19009
  const ports = [];
18721
19010
  for (const portName of netPortNames) {
18722
- ports.push(this.portMap[portName]);
19011
+ const port = this.portMap[portName] ?? this.portMap[`pin${portName}`];
19012
+ if (port) ports.push(port);
18723
19013
  }
18724
19014
  internallyConnectedPorts.push(ports);
18725
19015
  }
@@ -18798,7 +19088,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18798
19088
  const schematic_box_width = dimensions?.getSize().width;
18799
19089
  const schematic_box_height = dimensions?.getSize().height;
18800
19090
  const manufacturer_part_number_schematic_text = db2.schematic_text.insert({
18801
- text: resolveManufacturerPartNumber2(props) ?? "",
19091
+ text: resolveManufacturerPartNumber3(props) ?? "",
18802
19092
  schematic_component_id: schematic_component2.schematic_component_id,
18803
19093
  anchor: "left",
18804
19094
  rotation: 0,
@@ -19820,6 +20110,10 @@ var NormalComponent = class extends PrimitiveComponent2 {
19820
20110
  }
19821
20111
  doInitialSourceDesignRuleChecks() {
19822
20112
  NormalComponent_doInitialSourceDesignRuleChecks(this);
20113
+ NormalComponent_doInitialSourcePinSpecificationChecks(this);
20114
+ }
20115
+ updateSourceDesignRuleChecks() {
20116
+ NormalComponent_doInitialSourcePinSpecificationChecks(this);
19823
20117
  }
19824
20118
  doInitialSourceComponentPropertyValidation() {
19825
20119
  this._insertInvalidFootprintPropErrors();
@@ -20046,7 +20340,7 @@ function inflatePcbBoard(pcbBoard, inflatorContext) {
20046
20340
  }
20047
20341
 
20048
20342
  // lib/components/normal-components/Capacitor.ts
20049
- import { capacitorProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber3 } from "@tscircuit/props";
20343
+ import { capacitorProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber4 } from "@tscircuit/props";
20050
20344
  import { formatSiUnit } from "format-si-unit";
20051
20345
  import { symbols as symbols3 } from "schematic-symbols";
20052
20346
 
@@ -20232,7 +20526,7 @@ var Capacitor = class extends NormalComponent {
20232
20526
  const source_component = db2.source_component.insert({
20233
20527
  ftype: "simple_capacitor",
20234
20528
  name: this.name,
20235
- manufacturer_part_number: resolveManufacturerPartNumber3(props),
20529
+ manufacturer_part_number: resolveManufacturerPartNumber4(props),
20236
20530
  supplier_part_numbers: props.supplierPartNumbers,
20237
20531
  capacitance: props.capacitance,
20238
20532
  max_voltage_rating: props.maxVoltageRating,
@@ -20365,9 +20659,7 @@ function inflateSourceCapacitor(sourceElm, inflatorContext) {
20365
20659
  // lib/components/normal-components/Chip.ts
20366
20660
  import { normalizeDegrees as normalizeDegrees6 } from "@tscircuit/math-utils";
20367
20661
  import { chipProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber5 } from "@tscircuit/props";
20368
- import {
20369
- pcb_component_invalid_layer_error as pcb_component_invalid_layer_error2
20370
- } from "circuit-json";
20662
+ import { pcb_component_invalid_layer_error as pcb_component_invalid_layer_error2 } from "circuit-json";
20371
20663
 
20372
20664
  // lib/components/normal-components/Chip_doInitialPcbPlacementDesignRuleChecks.ts
20373
20665
  import { checkConnectorAccessibleOrientation } from "@tscircuit/checks";
@@ -20431,209 +20723,8 @@ var Chip_doInitialPcbPlacementDesignRuleChecks = (chip) => {
20431
20723
  db2.insertAll([orientationWarning]);
20432
20724
  };
20433
20725
 
20434
- // lib/components/normal-components/Chip_doInitialSourcePinSpecificationChecks.ts
20435
- import {
20436
- checkAllPinsInComponentAreUnderspecified,
20437
- checkNoGroundPinDefined,
20438
- checkNoPowerPinDefined
20439
- } from "@tscircuit/checks";
20440
-
20441
- // lib/components/primitive-components/Port/get-pin-attribute-mismatches.ts
20442
- var getPinAttributeMismatches = (declared, imported) => {
20443
- const mismatches = [];
20444
- for (const propName of Object.keys(declared)) {
20445
- if (propName === "highlightColor" || propName === "includeInBoardPinout")
20446
- continue;
20447
- const normalized = {};
20448
- applyPinAttributesToSourcePort(normalized, {
20449
- [propName]: declared[propName]
20450
- });
20451
- if (propName === "capabilities") {
20452
- for (const attributeName of Object.keys(
20453
- imported
20454
- )) {
20455
- if (attributeName.startsWith("supports_"))
20456
- Object.assign(normalized, {
20457
- [attributeName]: normalized[attributeName] ?? false
20458
- });
20459
- }
20460
- }
20461
- for (const attributeName of Object.keys(
20462
- normalized
20463
- )) {
20464
- const declaredValue = normalized[attributeName];
20465
- const supportedAttributeName = attributeName.startsWith(
20466
- "is_configured_for_"
20467
- ) ? attributeName.replace("is_configured_for_", "supports_") : attributeName.startsWith("is_using_") ? attributeName.replace("is_using_", "can_use_") : void 0;
20468
- if (supportedAttributeName) {
20469
- if (declaredValue === true && imported[supportedAttributeName] === false)
20470
- mismatches.push(
20471
- `${propName}: ${JSON.stringify(declared[propName])}, fetched ${supportedAttributeName}: false`
20472
- );
20473
- continue;
20474
- }
20475
- const importedValue = imported[attributeName];
20476
- const valuesMatch = typeof importedValue === "number" && typeof declaredValue === "number" ? Math.abs(importedValue - declaredValue) <= Number.EPSILON * 8 * Math.max(1, Math.abs(importedValue), Math.abs(declaredValue)) : importedValue === declaredValue;
20477
- if (importedValue !== void 0 && declaredValue !== void 0 && !valuesMatch)
20478
- mismatches.push(
20479
- `${propName}: ${JSON.stringify(declared[propName])}, fetched ${attributeName}: ${JSON.stringify(importedValue)}`
20480
- );
20481
- }
20482
- }
20483
- return mismatches;
20484
- };
20485
-
20486
- // lib/components/normal-components/Chip_fetchPinAttributesForValidation.ts
20487
- import {
20488
- resolveManufacturerPartNumber as resolveManufacturerPartNumber4,
20489
- supplierProps as supplierProps4
20490
- } from "@tscircuit/props";
20491
- import { source_pin_attributes as source_pin_attributes2 } from "circuit-json";
20492
- var Chip_fetchPinAttributesForValidation = (chip) => {
20493
- if (chip.config.componentName !== "Chip") return;
20494
- if (chip._hasStartedPinAttributesFetch) return;
20495
- if (!Object.keys(chip._parsedProps.pinAttributes ?? {}).length) return;
20496
- if (chip.getInheritedProperty("partsEngineDisabled")) return;
20497
- if (chip.getInheritedProperty("bomDisabled")) return;
20498
- if (chip._importedSourcePorts.some(
20499
- (port) => Object.values(source_pin_attributes2.parse(port)).some(
20500
- (value) => value !== void 0
20501
- )
20502
- ))
20503
- return;
20504
- const partsEngine = chip.getInheritedProperty("partsEngine");
20505
- if (!partsEngine?.fetchPartCircuitJson) return;
20506
- const footprint = chip.resolveFootprint();
20507
- if (supplierProps4.shape.supplierPartNumbers.unwrap().keySchema.options.some(
20508
- (supplierName) => typeof chip.root?.platform?.footprintLibraryMap?.[supplierName] !== "function" && chip._parsedProps.supplierPartNumbers?.[supplierName]?.some(
20509
- (partNumber) => footprint === `${supplierName}:${partNumber}`
20510
- )
20511
- ))
20512
- return;
20513
- const supplierPartNumber = Object.values(
20514
- chip._parsedProps.supplierPartNumbers ?? {}
20515
- ).flat()[0];
20516
- const manufacturerPartNumber = resolveManufacturerPartNumber4(
20517
- chip._parsedProps
20518
- );
20519
- if (!supplierPartNumber && !manufacturerPartNumber) return;
20520
- chip._hasStartedPinAttributesFetch = true;
20521
- chip._queueAsyncEffect("fetch-chip-pin-metadata", async () => {
20522
- try {
20523
- const partCircuitJson = await fetchPartCircuitJsonWithDatasheet(
20524
- {
20525
- fetchPartCircuitJson: partsEngine.fetchPartCircuitJson,
20526
- supplierPartNumber,
20527
- manufacturerPartNumber
20528
- },
20529
- chip
20530
- );
20531
- chip._fetchedSourcePortsForPinAttributes = partCircuitJson?.filter((element) => element.type === "source_port") ?? [];
20532
- chip._markDirty("SourceDesignRuleChecks");
20533
- } catch {
20534
- }
20535
- });
20536
- };
20537
-
20538
- // lib/components/normal-components/Chip_doInitialSourcePinSpecificationChecks.ts
20539
- var Chip_doInitialSourcePinSpecificationChecks = (chip) => {
20540
- if (chip.config.componentName !== "Chip") return;
20541
- if (!chip.source_component_id) return;
20542
- const { db: db2 } = chip.root;
20543
- const existingWarning = db2.source_component_pins_underspecified_warning.getWhere({
20544
- source_component_id: chip.source_component_id
20545
- });
20546
- const drcChecksDisabled = chip.root?.platform?.drcChecksDisabled ?? chip.getInheritedProperty("drcChecksDisabled");
20547
- const pinSpecificationDrcChecksDisabled = chip.root?.platform?.pinSpecificationDrcChecksDisabled ?? chip.getInheritedProperty("pinSpecificationDrcChecksDisabled");
20548
- const checksDisabled = drcChecksDisabled || pinSpecificationDrcChecksDisabled;
20549
- if (!checksDisabled) Chip_fetchPinAttributesForValidation(chip);
20550
- const sourcePorts = checksDisabled ? [] : chip.selectAll("port").flatMap((port) => {
20551
- if (!port.source_port_id) return [];
20552
- const sourcePort = db2.source_port.get(port.source_port_id);
20553
- return sourcePort?.source_component_id === chip.source_component_id ? [sourcePort] : [];
20554
- });
20555
- const sourceComponent = checksDisabled ? null : db2.source_component.get(chip.source_component_id);
20556
- const chipCircuitJson = sourceComponent ? [sourceComponent, ...sourcePorts] : [];
20557
- const issues = [];
20558
- if (!checksDisabled) {
20559
- for (const port of chip.selectAll("port")) {
20560
- const sourcePort = sourcePorts.find(
20561
- (sourcePort2) => sourcePort2.source_port_id === port.source_port_id
20562
- );
20563
- if (!sourcePort) continue;
20564
- const declared = {};
20565
- for (const alias of port.getNameAndAliases()) {
20566
- Object.assign(declared, chip._parsedProps.pinAttributes?.[alias]);
20567
- }
20568
- const imported = getImportedSourcePinAttributes(
20569
- port,
20570
- chip._fetchedSourcePortsForPinAttributes.length ? chip._fetchedSourcePortsForPinAttributes : chip._importedSourcePorts
20571
- );
20572
- const reasons2 = getPinAttributeMismatches(declared, imported);
20573
- if (reasons2.length)
20574
- issues.push({
20575
- pinName: sourcePort.name || "unnamed pin",
20576
- reasons: reasons2,
20577
- sourcePort
20578
- });
20579
- }
20580
- }
20581
- for (const [warningTable, check] of [
20582
- [db2.source_no_power_pin_defined_warning, checkNoPowerPinDefined],
20583
- [db2.source_no_ground_pin_defined_warning, checkNoGroundPinDefined]
20584
- ]) {
20585
- const existing = warningTable.getWhere({
20586
- source_component_id: chip.source_component_id
20587
- });
20588
- const existingId = existing?.type === "source_no_power_pin_defined_warning" ? existing.source_no_power_pin_defined_warning_id : existing?.source_no_ground_pin_defined_warning_id;
20589
- const [warning2] = checksDisabled || issues.length ? [] : check(chipCircuitJson);
20590
- if (warning2) {
20591
- if (existingId) {
20592
- warningTable.update(existingId, {
20593
- message: warning2.message,
20594
- source_port_ids: warning2.source_port_ids,
20595
- subcircuit_id: warning2.subcircuit_id
20596
- });
20597
- } else {
20598
- db2.insertAll([warning2]);
20599
- }
20600
- } else if (existingId) {
20601
- warningTable.delete(existingId);
20602
- }
20603
- }
20604
- const [underspecifiedWarning] = checksDisabled ? [] : checkAllPinsInComponentAreUnderspecified(chipCircuitJson);
20605
- if (!issues.length && !underspecifiedWarning) {
20606
- if (existingWarning) {
20607
- db2.source_component_pins_underspecified_warning.delete(
20608
- existingWarning.source_component_pins_underspecified_warning_id
20609
- );
20610
- }
20611
- return;
20612
- }
20613
- const examples = issues.slice(0, 3).map(({ pinName, reasons: reasons2 }) => `${pinName} (${reasons2.join("; ")})`).join(", ");
20614
- const remaining = issues.length > 3 ? `, and ${issues.length - 3} more` : "";
20615
- const warning = {
20616
- source_component_id: chip.source_component_id,
20617
- source_port_ids: issues.length ? issues.map(({ sourcePort }) => sourcePort.source_port_id) : underspecifiedWarning.source_port_ids,
20618
- subcircuit_id: chip.getSubcircuit().subcircuit_id ?? void 0,
20619
- warning_type: "source_component_pins_underspecified_warning",
20620
- message: issues.length ? `Chip ${chip.name || "unnamed chip"} has pinAttributes that conflict with fetched pin metadata on ${issues.length} pin${issues.length === 1 ? "" : "s"}: ${examples}${remaining}. Check the chip configuration against the part datasheet.` : underspecifiedWarning.message
20621
- };
20622
- if (existingWarning) {
20623
- db2.source_component_pins_underspecified_warning.update(
20624
- existingWarning.source_component_pins_underspecified_warning_id,
20625
- warning
20626
- );
20627
- } else {
20628
- db2.source_component_pins_underspecified_warning.insert(warning);
20629
- }
20630
- };
20631
-
20632
20726
  // lib/components/normal-components/Chip.ts
20633
20727
  var Chip = class extends NormalComponent {
20634
- /** Fetched facts used only for comparison when the user supplies a custom footprint. */
20635
- _fetchedSourcePortsForPinAttributes = [];
20636
- _hasStartedPinAttributesFetch = false;
20637
20728
  get config() {
20638
20729
  return {
20639
20730
  componentName: "Chip",
@@ -20688,13 +20779,6 @@ var Chip = class extends NormalComponent {
20688
20779
  });
20689
20780
  this.source_component_id = source_component.source_component_id;
20690
20781
  }
20691
- doInitialSourceDesignRuleChecks() {
20692
- super.doInitialSourceDesignRuleChecks();
20693
- Chip_doInitialSourcePinSpecificationChecks(this);
20694
- }
20695
- updateSourceDesignRuleChecks() {
20696
- Chip_doInitialSourcePinSpecificationChecks(this);
20697
- }
20698
20782
  doInitialPcbComponentRender() {
20699
20783
  if (this.root?.pcbDisabled) return;
20700
20784
  const { db: db2 } = this.root;
@@ -119177,7 +119261,7 @@ var RoutingPhasePreparationError = class extends Error {
119177
119261
  var package_default = {
119178
119262
  name: "@tscircuit/core",
119179
119263
  type: "module",
119180
- version: "0.0.2161",
119264
+ version: "0.0.2163",
119181
119265
  types: "dist/index.d.ts",
119182
119266
  main: "dist/index.js",
119183
119267
  module: "dist/index.js",
@@ -119214,7 +119298,7 @@ var package_default = {
119214
119298
  "@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
119215
119299
  "@tscircuit/bus-lanes-solver": "https://jscdn.tscircuit.com/@tscircuit/bus-lanes-solver/0.0.21.tgz",
119216
119300
  "@tscircuit/cableprinter": "^0.0.6",
119217
- "@tscircuit/capacity-autorouter": "^0.0.982",
119301
+ "@tscircuit/capacity-autorouter": "^0.0.985",
119218
119302
  "@tscircuit/checks": "^0.0.256",
119219
119303
  "@tscircuit/circuit-json-util": "^0.0.122",
119220
119304
  "@tscircuit/common": "^0.0.20",
@@ -121870,6 +121954,9 @@ var Group5 = class extends NormalComponent {
121870
121954
  const debug13 = Debug15("tscircuit:core:updatePcbTraceRender");
121871
121955
  debug13(`[${this.getString()}] updating...`);
121872
121956
  if (!this.isSubcircuit) return;
121957
+ if (this.root?.pcbDisabled) return;
121958
+ if (this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled"))
121959
+ return;
121873
121960
  if (this._isInflatedFromCircuitJson) return;
121874
121961
  if (this._isLegacyAutorouterDisabled()) return;
121875
121962
  if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {