Compare commits
99
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c27210f4f4 | ||
|
|
0a4cca2b41 | ||
|
|
233ff2bf64 | ||
|
|
86d7ae49fb | ||
|
|
6768ef5fff | ||
|
|
499dd49ec2 | ||
|
|
445f674367 | ||
|
|
b69be9f419 | ||
|
|
a27680d893 | ||
|
|
682132e7ac | ||
|
|
b06a605f38 | ||
|
|
69c8d2c4db | ||
|
|
7cf013a783 | ||
|
|
1df9549a0e | ||
|
|
7b2176b31b | ||
|
|
07c7e7d328 | ||
|
|
a34faa3b29 | ||
|
|
c6504b3d1b | ||
|
|
5aba461451 | ||
|
|
bbc35ab4e3 | ||
|
|
3c685eece7 | ||
|
|
1c30dc070d | ||
|
|
82a54e7905 | ||
|
|
8d33346993 | ||
|
|
3307bd90e4 | ||
|
|
f46f598baf | ||
|
|
6251f2490b | ||
|
|
ab8783a1f7 | ||
|
|
271f4a44bc | ||
|
|
11a11d664f | ||
|
|
c9ebbb6406 | ||
|
|
c6af133e76 | ||
|
|
16be4e8cfc | ||
|
|
ef84b1e563 | ||
|
|
a2d0cf11a9 | ||
|
|
0d67b5ea0f | ||
|
|
a8b66070c3 | ||
|
|
ff3658352a | ||
|
|
f63d40ff48 | ||
|
|
66e1845fc6 | ||
|
|
23513d3f2e | ||
|
|
4cbb5624af | ||
|
|
c102bef2a6 | ||
|
|
543b639ffc | ||
|
|
c0ac9d57df | ||
|
|
d1cd3c2004 | ||
|
|
8e5515afc0 | ||
|
|
7f6b63d05b | ||
|
|
9609cb31c1 | ||
|
|
bcd33b3fa5 | ||
|
|
b6123a0043 | ||
|
|
1ca16eb69a | ||
|
|
ecd6561831 | ||
|
|
abd8c59e60 | ||
|
|
73e9a3efe2 | ||
|
|
55c4254b25 | ||
|
|
b3366e05db | ||
|
|
b796dd933b | ||
|
|
d6d39937ed | ||
|
|
4306211981 | ||
|
|
ebd0bd1e29 | ||
|
|
0891230b39 | ||
|
|
312efaa771 | ||
|
|
33ec9f7f14 | ||
|
|
c389d91da2 | ||
|
|
d0d7ff257e | ||
|
|
c1bfb36de5 | ||
|
|
d96fc225cf | ||
|
|
08a73d5171 | ||
|
|
40386134a8 | ||
|
|
b3cc8b7463 | ||
|
|
3635999f47 | ||
|
|
2d5d48949a | ||
|
|
283fa76162 | ||
|
|
d441aea02c | ||
|
|
e1a9b4037e | ||
|
|
5cf34634d2 | ||
|
|
f5433c4e48 | ||
|
|
e6c8943530 | ||
|
|
ca0b6fba23 | ||
|
|
c3fb3e6fad | ||
|
|
c511256f32 | ||
|
|
9cd4a3c443 | ||
|
|
939522d98c | ||
|
|
4e24e2daa4 | ||
|
|
8db8b30ed8 | ||
|
|
5db95d7212 | ||
|
|
3f3c7cb0ba | ||
|
|
9562afddf0 | ||
|
|
6e9e7b780d | ||
|
|
a189d21af9 | ||
|
|
788c3373d8 | ||
|
|
37043f316e | ||
|
|
ff40ddd1a9 | ||
|
|
fb1430ad1a | ||
|
|
d479d3c07b | ||
|
|
9c5c0b5a91 | ||
|
|
e177b1d1ea | ||
|
|
b1bce0c166 |
@@ -254,3 +254,5 @@ releases/
|
||||
# README.md
|
||||
# LICENSE
|
||||
|
||||
/build/
|
||||
/test-results/
|
||||
|
||||
Generated
+31
-1
@@ -1,7 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="EMPTY_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/EagerLinkingTBDs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/PrecompiledHeaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/XCBuildData/120e9a8ae12faa2f3ba3b63c6df49ba3.xcbuilddata" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/XCBuildData/7f733ee9c557a22c77228b85d3bb3f5e.xcbuilddata" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/XCBuildData/a06f417aacd1b83f24bd3cc2cf22ad87.xcbuilddata" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Build/Intermediates.noindex/XCBuildData/db88895332a02f341932219e1765f45d.xcbuilddata" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/0H" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/2G" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/8A" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/8U" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/AI" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/BZ" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/D2" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/L6" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/QF" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/SA" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Index.noindex/DataStore/v5/records/XW" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Logs/Launch" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Logs/Localization" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Logs/Package" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/Logs/Test" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/releases" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results/DBSyn-20261019-094628.xcresult" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results/DBSyn-20261019-094908.xcresult" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results/DBSyn-20261019-095109.xcresult" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results/DBSyn-20261019-095434-45691.xcresult" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test-results/DBSyn-20261019-095659-45920.xcresult" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
F0737000000000000000000D /* DBSyn target proxy */ = { isa = PBXContainerItemProxy; containerPortal = 000000000000000000000001; proxyType = 1; remoteGlobalIDString = 000000000000000000000005; remoteInfo = DBSyn; };
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
F0737000000000000000000E /* DBSyn dependency */ = { isa = PBXTargetDependency; target = 000000000000000000000005; targetProxy = F0737000000000000000000D; };
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
B74000000000000000000001 /* LaravelMigrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B74000000000000000000002 /* LaravelMigrationView.swift */; };
|
||||
B73200000000000000000001 /* SchemaDiagramPrintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73200000000000000000002 /* SchemaDiagramPrintView.swift */; };
|
||||
B73000000000000000000001 /* SchemaDiagramView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73000000000000000000002 /* SchemaDiagramView.swift */; };
|
||||
000000000000000000000013 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000010 /* App.swift */; };
|
||||
000000000000000000000014 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000011 /* MainView.swift */; };
|
||||
000000000000000000000015 /* DatabaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000012 /* DatabaseModel.swift */; };
|
||||
000000000000000000000017 /* MySQLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000016 /* MySQLProtocol.swift */; };
|
||||
|
||||
A10000000000000000000003 /* DBSyn.icns in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000001 /* DBSyn.icns */; };
|
||||
A10000000000000000000004 /* DBSynBrand.png in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000002 /* DBSynBrand.png */; };
|
||||
F07370000000000000000002 /* DiagramLogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07370000000000000000001 /* DiagramLogic.swift */; };
|
||||
F07370000000000000000006 /* DBSynTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F07370000000000000000005 /* DBSynTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
B74000000000000000000002 /* LaravelMigrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaravelMigrationView.swift; sourceTree = "<group>"; };
|
||||
B73200000000000000000002 /* SchemaDiagramPrintView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemaDiagramPrintView.swift; sourceTree = "<group>"; };
|
||||
B73000000000000000000002 /* SchemaDiagramView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemaDiagramView.swift; sourceTree = "<group>"; };
|
||||
00000000000000000000000F /* DBSyn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DBSyn.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
000000000000000000000010 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000011 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000012 /* DatabaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseModel.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000016 /* MySQLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySQLProtocol.swift; sourceTree = "<group>"; };
|
||||
|
||||
A10000000000000000000001 /* DBSyn.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = DBSyn.icns; sourceTree = "<group>"; };
|
||||
A10000000000000000000002 /* DBSynBrand.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DBSynBrand.png; sourceTree = "<group>"; };
|
||||
F07370000000000000000001 /* DiagramLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagramLogic.swift; sourceTree = "<group>"; };
|
||||
F07370000000000000000005 /* DBSynTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBSynTests.swift; sourceTree = "<group>"; };
|
||||
F07370000000000000000007 /* DBSynTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DBSynTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
000000000000000000000008 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F07370000000000000000009 /* Tests Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = (); runOnlyForDeploymentPostprocessing = 0; };
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
000000000000000000000002 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
000000000000000000000003 /* DBSyn */,
|
||||
F07370000000000000000003 /* DBSynTests */,
|
||||
000000000000000000000004 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
000000000000000000000003 /* DBSyn */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
000000000000000000000010 /* App.swift */,
|
||||
000000000000000000000011 /* MainView.swift */,
|
||||
000000000000000000000012 /* DatabaseModel.swift */,
|
||||
F07370000000000000000001 /* DiagramLogic.swift */,
|
||||
B73000000000000000000002 /* SchemaDiagramView.swift */,
|
||||
B74000000000000000000002 /* LaravelMigrationView.swift */,
|
||||
B73200000000000000000002 /* SchemaDiagramPrintView.swift */,
|
||||
000000000000000000000016 /* MySQLProtocol.swift */,
|
||||
|
||||
A10000000000000000000005 /* Resources */,);
|
||||
path = DBSyn;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
000000000000000000000004 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00000000000000000000000F /* DBSyn.app */,
|
||||
F07370000000000000000007 /* DBSynTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
||||
A10000000000000000000005 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A10000000000000000000001 /* DBSyn.icns */,
|
||||
A10000000000000000000002 /* DBSynBrand.png */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07370000000000000000003 /* DBSynTests */ = { isa = PBXGroup; children = (F07370000000000000000005 /* DBSynTests.swift */,); path = DBSynTests; sourceTree = "<group>"; };
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
000000000000000000000005 /* DBSyn */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00000000000000000000000A /* Build configuration list for PBXNativeTarget "DBSyn" */;
|
||||
buildPhases = (
|
||||
000000000000000000000006 /* Sources */,
|
||||
000000000000000000000008 /* Frameworks */,
|
||||
000000000000000000000007 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = DBSyn;
|
||||
productName = DBSyn;
|
||||
productReference = 00000000000000000000000F /* DBSyn.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
F07370000000000000000004 /* DBSynTests */ = { isa = PBXNativeTarget; buildConfigurationList = F0737000000000000000000A /* Test Configurations */; buildPhases = (F07370000000000000000008 /* Test Sources */, F07370000000000000000009 /* Tests Frameworks */,); buildRules = (); dependencies = (F0737000000000000000000E /* DBSyn dependency */,); name = DBSynTests; productName = DBSynTests; productReference = F07370000000000000000007 /* DBSynTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; };
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
000000000000000000000001 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1600;
|
||||
TargetAttributes = {
|
||||
000000000000000000000005 = {
|
||||
CreatedOnToolsVersion = 16.0;
|
||||
};
|
||||
F07370000000000000000004 = { CreatedOnToolsVersion = 16.0; TestTargetID = 000000000000000000000005; };
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 000000000000000000000009 /* Build configuration list for PBXProject "DBSyn" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 000000000000000000000002;
|
||||
productRefGroup = 000000000000000000000004 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
000000000000000000000005 /* DBSyn */,
|
||||
F07370000000000000000004 /* DBSynTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
000000000000000000000007 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
||||
A10000000000000000000003 /* DBSyn.icns in Resources */,
|
||||
A10000000000000000000004 /* DBSynBrand.png in Resources */,);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
000000000000000000000006 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
000000000000000000000013 /* App.swift in Sources */,
|
||||
000000000000000000000014 /* MainView.swift in Sources */,
|
||||
000000000000000000000015 /* DatabaseModel.swift in Sources */,
|
||||
F07370000000000000000002 /* DiagramLogic.swift in Sources */,
|
||||
B73000000000000000000001 /* SchemaDiagramView.swift in Sources */,
|
||||
B74000000000000000000001 /* LaravelMigrationView.swift in Sources */,
|
||||
B73200000000000000000001 /* SchemaDiagramPrintView.swift in Sources */,
|
||||
000000000000000000000017 /* MySQLProtocol.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F07370000000000000000008 /* Test Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = (F07370000000000000000006 /* DBSynTests.swift in Sources */,); runOnlyForDeploymentPostprocessing = 0; };
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00000000000000000000000B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00000000000000000000000C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
00000000000000000000000D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 39R6U3437D;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "DBSyn";
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 ABSDEV. All rights reserved.";
|
||||
INFOPLIST_KEY_CFBundleIconFile = "DBSyn.icns";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSyn;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00000000000000000000000E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 39R6U3437D;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "DBSyn";
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
CURRENT_PROJECT_VERSION = 82;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 ABSDEV. All rights reserved.";
|
||||
INFOPLIST_KEY_CFBundleIconFile = "DBSyn.icns";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSyn;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F0737000000000000000000B /* Tests Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGNING_ALLOWED = NO; ONLY_ACTIVE_ARCH = YES; SWIFT_ENABLE_EXPLICIT_MODULES = NO; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 15.0; PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSynTests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DBSyn.app/Contents/MacOS/DBSyn"; }; name = Debug; };
|
||||
F0737000000000000000000C /* Tests Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGNING_ALLOWED = NO; ONLY_ACTIVE_ARCH = YES; SWIFT_ENABLE_EXPLICIT_MODULES = NO; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 15.0; PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSynTests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DBSyn.app/Contents/MacOS/DBSyn"; }; name = Release; };
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
000000000000000000000009 /* Build configuration list for PBXProject "DBSyn" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00000000000000000000000B /* Debug */,
|
||||
00000000000000000000000C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
00000000000000000000000A /* Build configuration list for PBXNativeTarget "DBSyn" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00000000000000000000000D /* Debug */,
|
||||
00000000000000000000000E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F0737000000000000000000A /* Test Configurations */ = { isa = XCConfigurationList; buildConfigurations = (F0737000000000000000000B /* Tests Debug */, F0737000000000000000000C /* Tests Release */,); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; };
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 000000000000000000000001 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme LastUpgradeVersion="1600" version="1.7">
|
||||
<BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES"><BuildActionEntries><BuildActionEntry buildForTesting="YES" buildForRunning="YES" buildForProfiling="YES" buildForArchiving="YES" buildForAnalyzing="YES"><BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="000000000000000000000005" BuildableName="DBSyn.app" BlueprintName="DBSyn" ReferencedContainer="container:DBSyn.xcodeproj"/></BuildActionEntry></BuildActionEntries></BuildAction>
|
||||
<TestAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.IDEFoundation.Launcher.Posix" shouldUseLaunchSchemeArgsEnv="YES"><Testables><TestableReference skipped="NO"><BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="F07370000000000000000004" BuildableName="DBSynTests.xctest" BlueprintName="DBSynTests" ReferencedContainer="container:DBSyn.xcodeproj"/></TestableReference></Testables></TestAction>
|
||||
<LaunchAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.IDEFoundation.Launcher.Posix" launchStyle="0" useCustomWorkingDirectory="NO" ignoresPersistentStateOnLaunch="NO" debugDocumentVersioning="YES" debugServiceExtension="internal" allowLocationSimulation="YES"><BuildableProductRunnable runnableDebuggingMode="0"><BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="000000000000000000000005" BuildableName="DBSyn.app" BlueprintName="DBSyn" ReferencedContainer="container:DBSyn.xcodeproj"/></BuildableProductRunnable></LaunchAction>
|
||||
<ProfileAction buildConfiguration="Release" shouldUseLaunchSchemeArgsEnv="YES" savedToolIdentifier="" useCustomWorkingDirectory="NO" debugDocumentVersioning="YES"><BuildableProductRunnable runnableDebuggingMode="0"><BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="000000000000000000000005" BuildableName="DBSyn.app" BlueprintName="DBSyn" ReferencedContainer="container:DBSyn.xcodeproj"/></BuildableProductRunnable></ProfileAction>
|
||||
<AnalyzeAction buildConfiguration="Debug"/><ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"/>
|
||||
</Scheme>
|
||||
+664
@@ -0,0 +1,664 @@
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
extension Notification.Name {
|
||||
static let dbsynOpenConnectionManager = Notification.Name("DBSyn.OpenConnectionManager")
|
||||
static let workbenchRevealSQLEditor = Notification.Name("DBSyn.RevealSQLEditor")
|
||||
}
|
||||
|
||||
@main
|
||||
struct DBSynApp: App {
|
||||
@StateObject private var model = DatabaseModel()
|
||||
@AppStorage("preferences.appearance") private var appearance = "system"
|
||||
@State private var showingMigrationGenerator = false
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup("DBSyn") {
|
||||
WorkbenchLaunchView()
|
||||
.preferredColorScheme(appearance == "dark" ? .dark : appearance == "light" ? .light : nil)
|
||||
.onAppear {
|
||||
if let iconURL = Bundle.main.url(forResource: "DBSyn", withExtension: "icns"),
|
||||
let icon = NSImage(contentsOf: iconURL) {
|
||||
NSApplication.shared.applicationIconImage = icon
|
||||
}
|
||||
}
|
||||
.environmentObject(model)
|
||||
.sheet(isPresented: $showingMigrationGenerator) { LaravelMigrationView(model: model, onClose: { showingMigrationGenerator = false }) }
|
||||
.frame(minWidth: 800, minHeight: 520)
|
||||
}
|
||||
.defaultSize(width: 1200, height: 800)
|
||||
.windowResizability(.contentSize)
|
||||
.commands {
|
||||
CommandGroup(replacing: .appInfo) {
|
||||
Button("About DBSyn") {
|
||||
let icon = NSImage(contentsOfFile: Bundle.main.path(forResource: "DBSynBrand", ofType: "png") ?? "")
|
||||
NSApplication.shared.orderFrontStandardAboutPanel(options: [
|
||||
.applicationName: "DBSyn",
|
||||
.applicationIcon: icon ?? NSApplication.shared.applicationIconImage ?? NSImage(),
|
||||
.version: Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "1.0",
|
||||
.credits: NSAttributedString(string: "Native MySQL client for macOS")
|
||||
])
|
||||
}
|
||||
}
|
||||
WorkbenchFileCommands(model: model)
|
||||
CommandMenu("Tools") {
|
||||
Button("Generate Laravel Migration…") { showingMigrationGenerator = true }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Settings {
|
||||
WorkbenchSettingsView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Application Preferences
|
||||
|
||||
@MainActor
|
||||
final class WorkbenchPreferences: ObservableObject {
|
||||
static let shared = WorkbenchPreferences()
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.appearance")
|
||||
var appearance = "system"
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
var autoExpandTables = true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Settings
|
||||
|
||||
struct WorkbenchSettingsView: View {
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
private var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
private var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
private var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
private var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.defaultRowLimit")
|
||||
private var defaultRowLimit = 500
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
private var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
private var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
private var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
private var autoExpandTables = true
|
||||
|
||||
@AppStorage("preferences.appearance")
|
||||
private var appearance = "system"
|
||||
|
||||
@AppStorage("preferences.migrationFilenamePrefix")
|
||||
private var migrationFilenamePrefix = "create"
|
||||
|
||||
@State private var selectedSection: SettingsSection? = .general
|
||||
|
||||
private enum SettingsSection: String, CaseIterable, Identifiable {
|
||||
case general = "General"
|
||||
case connections = "Connections"
|
||||
case security = "Security"
|
||||
case editor = "SQL Editor"
|
||||
case execution = "Query Execution"
|
||||
case results = "Result Grid"
|
||||
case database = "Database"
|
||||
case diagrams = "Schema Designer"
|
||||
case laravel = "Laravel"
|
||||
case administration = "Administration"
|
||||
case exports = "Export & Backup"
|
||||
case advanced = "Advanced"
|
||||
var id: String { rawValue }
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .general: return "gearshape"
|
||||
case .connections: return "server.rack"
|
||||
case .security: return "lock.shield"
|
||||
case .editor: return "chevron.left.forwardslash.chevron.right"
|
||||
case .execution: return "bolt"
|
||||
case .results: return "tablecells"
|
||||
case .database: return "externaldrive"
|
||||
case .diagrams: return "point.3.connected.trianglepath.dotted"
|
||||
case .laravel: return "curlybraces"
|
||||
case .administration: return "gauge.with.dots.needle.67percent"
|
||||
case .exports: return "square.and.arrow.up"
|
||||
case .advanced: return "wrench.and.screwdriver"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AppStorage("preferences.diagramPalette") private var diagramPalette = "Ocean"
|
||||
@AppStorage("preferences.diagramShowAllColumns") private var diagramShowAllColumns = false
|
||||
@AppStorage("preferences.migrationOutputDirectory") private var migrationOutputDirectory = ""
|
||||
@AppStorage("preferences.migrationUseTimestamps") private var migrationUseTimestamps = true
|
||||
@AppStorage("preferences.confirmDestructiveSQL") private var confirmDestructiveSQL = true
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 0) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("DBSyn Settings")
|
||||
.font(.headline)
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.top, 18)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
ForEach(SettingsSection.allCases) { section in
|
||||
Button {
|
||||
selectedSection = section
|
||||
} label: {
|
||||
Label(section.rawValue, systemImage: section.icon)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 9)
|
||||
.background(
|
||||
(selectedSection ?? .general) == section
|
||||
? Color.accentColor.opacity(0.22)
|
||||
: Color.clear,
|
||||
in: RoundedRectangle(cornerRadius: 7)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.accessibilityIdentifier("settings.section.\(section.id)")
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 10)
|
||||
}
|
||||
}
|
||||
.frame(width: 230)
|
||||
.frame(maxHeight: .infinity, alignment: .top)
|
||||
.background(Color(nsColor: .controlBackgroundColor))
|
||||
|
||||
Divider()
|
||||
|
||||
ScrollView {
|
||||
Group {
|
||||
switch selectedSection ?? .general {
|
||||
case .general: generalSettings
|
||||
case .connections: connectionsSettings
|
||||
case .security: securitySettings
|
||||
case .editor: editorSettings
|
||||
case .execution: executionSettings
|
||||
case .results: resultSettings
|
||||
case .database: databaseSettings
|
||||
case .diagrams: diagramSettings
|
||||
case .laravel: migrationSettings
|
||||
case .administration: administrationSettings
|
||||
case .exports: exportSettings
|
||||
case .advanced: advancedSettings
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
.frame(minWidth: 850, idealWidth: 1050, minHeight: 570, idealHeight: 710)
|
||||
.preferredColorScheme(appearance == "dark" ? .dark : appearance == "light" ? .light : nil)
|
||||
}
|
||||
|
||||
private func information(_ message: String) -> some View {
|
||||
Text(message).font(.callout).foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
|
||||
private var connectionsSettings: some View {
|
||||
settingsPage("Connections") {
|
||||
information("Manage and switch saved connections from the main window's Connections menu. Select a profile to connect, or edit its MySQL host, port and default schema.")
|
||||
information("Connection profiles and credentials are stored separately. Passwords are held in macOS Keychain.")
|
||||
Button("Open Connection Manager") {
|
||||
NotificationCenter.default.post(name: .dbsynOpenConnectionManager, object: nil)
|
||||
// Leave window management to the Settings scene.
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
}
|
||||
|
||||
private var securitySettings: some View {
|
||||
settingsPage("Security & Transport") {
|
||||
information("Each connection has independent TLS and SSH transport options. Edit a connection to configure certificate-verified TLS, or an SSH tunnel using macOS OpenSSH.")
|
||||
information("Do not disable certificate verification to work around connection failures. Native TLS handshake compatibility must be validated against your server before relying on it.")
|
||||
information("Passwords use the DBSyn.MySQL Keychain service. Legacy WorkbenchReplacement.MySQL credentials are read for compatibility.")
|
||||
}
|
||||
}
|
||||
|
||||
private var databaseSettings: some View {
|
||||
settingsPage("Database Navigator") {
|
||||
settingsRow("Expand tables") {
|
||||
Toggle("Automatically expand table folders", isOn: $autoExpandTables)
|
||||
}
|
||||
information("Select the active database in the schema navigator. Refresh schema metadata from the main window after switching connections.")
|
||||
}
|
||||
}
|
||||
|
||||
private var diagramSettings: some View {
|
||||
settingsPage("Schema Designer") {
|
||||
settingsRow("Default palette") {
|
||||
Picker("Palette", selection: $diagramPalette) {
|
||||
ForEach(["Ocean", "Slate", "Forest", "Plum"], id: \.self) { Text($0) }
|
||||
}.labelsHidden().frame(width: 200)
|
||||
}
|
||||
settingsRow("Columns") {
|
||||
Toggle("Show all columns by default", isOn: $diagramShowAllColumns)
|
||||
}
|
||||
information("Diagram-specific layouts and table selections are saved from the Schema Designer. You can override the palette and column visibility there.")
|
||||
}
|
||||
}
|
||||
|
||||
private var administrationSettings: some View {
|
||||
settingsPage("Administration") {
|
||||
information("Server status, connections, users, variables, performance and logs are available in the Administration navigator.")
|
||||
information("Server start/stop and configuration-file editing require server-level operating-system privileges and are not available through ordinary MySQL credentials.")
|
||||
}
|
||||
}
|
||||
|
||||
private var exportSettings: some View {
|
||||
settingsPage("Export & Backup") {
|
||||
information("SQL and CSV export, backup and restore actions are available from the main window. Choose a destination when exporting.")
|
||||
information("Backups and restores can be destructive. Review the target server and schema before starting a restore.")
|
||||
}
|
||||
}
|
||||
|
||||
private var advancedSettings: some View {
|
||||
settingsPage("Advanced") {
|
||||
settingsRow("Safety") {
|
||||
Toggle("Confirm destructive SQL operations", isOn: $confirmDestructiveSQL)
|
||||
}
|
||||
information("The safety preference is reserved for a future SQL confirmation integration; it does not yet intercept SQL execution.")
|
||||
information("For troubleshooting, use the macOS Console and the DBSyn test runner. TLS negotiation must be tested on a macOS host.")
|
||||
}
|
||||
}
|
||||
|
||||
private var migrationSettings: some View {
|
||||
settingsPage("Laravel & Developer Tools") {
|
||||
Text("Generate Laravel migrations from a connected MySQL table or an imported CREATE TABLE SQL file.")
|
||||
.foregroundStyle(.secondary)
|
||||
settingsRow("Filename prefix") {
|
||||
TextField("create", text: $migrationFilenamePrefix)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
}
|
||||
settingsRow("Output folder") {
|
||||
TextField("Choose folder when saving", text: $migrationOutputDirectory)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
}
|
||||
settingsRow("Filename") {
|
||||
Toggle("Use timestamp prefix", isOn: $migrationUseTimestamps)
|
||||
}
|
||||
Text("Open Tools → Generate Laravel Migration to preview, edit and save the generated PHP file.")
|
||||
.font(.callout).foregroundStyle(.secondary)
|
||||
Text("Generated migrations must be reviewed before execution. DBSyn never executes generated PHP.")
|
||||
.font(.caption).foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
private var editorSettings: some View {
|
||||
settingsPage("SQL Editor") {
|
||||
|
||||
settingsRow("Font Size") {
|
||||
Stepper(
|
||||
"\(Int(editorFontSize)) pt",
|
||||
value: $editorFontSize,
|
||||
in: 10...24,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Tab Width") {
|
||||
Picker("", selection: $tabWidth) {
|
||||
Text("2 spaces").tag(2)
|
||||
Text("4 spaces").tag(4)
|
||||
Text("8 spaces").tag(8)
|
||||
}
|
||||
.labelsHidden()
|
||||
.frame(width: 150)
|
||||
}
|
||||
|
||||
settingsRow("SQL Formatting") {
|
||||
Toggle(
|
||||
"Automatically uppercase SQL keywords",
|
||||
isOn: $uppercaseKeywords
|
||||
)
|
||||
}
|
||||
|
||||
settingsRow("Editor Display") {
|
||||
Toggle(
|
||||
"Show line numbers",
|
||||
isOn: $showLineNumbers
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var executionSettings: some View {
|
||||
settingsPage("Query Execution") {
|
||||
|
||||
settingsRow("Default Row Limit") {
|
||||
HStack(spacing: 12) {
|
||||
TextField(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
format: .number
|
||||
)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 110)
|
||||
|
||||
Stepper(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
in: 50...100000,
|
||||
step: 50
|
||||
)
|
||||
.labelsHidden()
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
"Controls the number of rows retrieved when opening a table from the schema navigator."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.leading, 186)
|
||||
|
||||
Divider()
|
||||
.padding(.vertical, 12)
|
||||
|
||||
Text("Examples")
|
||||
.font(.headline)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Text(
|
||||
"500 rows: Faster browsing and lower memory usage.\n" +
|
||||
"5,000 rows: Useful for larger datasets.\n" +
|
||||
"50,000 rows: May take longer to retrieve."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
|
||||
private var resultSettings: some View {
|
||||
settingsPage("Result Grid") {
|
||||
|
||||
settingsRow("Row Height") {
|
||||
Stepper(
|
||||
"\(Int(resultRowHeight)) px",
|
||||
value: $resultRowHeight,
|
||||
in: 18...40,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Column Width") {
|
||||
Stepper(
|
||||
"\(Int(resultColumnWidth)) px",
|
||||
value: $resultColumnWidth,
|
||||
in: 80...400,
|
||||
step: 10
|
||||
)
|
||||
.frame(width: 140)
|
||||
}
|
||||
|
||||
settingsRow("Appearance") {
|
||||
Toggle(
|
||||
"Alternating row colours",
|
||||
isOn: $alternatingRows
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var generalSettings: some View {
|
||||
settingsPage("General") {
|
||||
|
||||
settingsRow("Appearance") {
|
||||
Picker("Appearance", selection: $appearance) {
|
||||
Text("System").tag("system")
|
||||
Text("Light").tag("light")
|
||||
Text("Dark").tag("dark")
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
.labelsHidden()
|
||||
.accessibilityLabel("Application appearance")
|
||||
.frame(width: 260, alignment: .leading)
|
||||
}
|
||||
|
||||
Text(appearance == "system"
|
||||
? "DBSyn follows your Mac’s appearance setting."
|
||||
: appearance == "light"
|
||||
? "DBSyn always uses Light appearance."
|
||||
: "DBSyn always uses Dark appearance.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.leading, 186)
|
||||
|
||||
settingsRow("Navigator") {
|
||||
Toggle(
|
||||
"Automatically expand table folders",
|
||||
isOn: $autoExpandTables
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func settingsPage<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
|
||||
Divider()
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(26)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color(nsColor: .windowBackgroundColor))
|
||||
}
|
||||
|
||||
private func settingsRow<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
HStack(alignment: .center, spacing: 16) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 13))
|
||||
.frame(width: 170, alignment: .leading)
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.frame(height: 30)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Splash Screen
|
||||
|
||||
struct WorkbenchLaunchView: View {
|
||||
@State private var showingSplash = true
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
MainView()
|
||||
|
||||
if showingSplash {
|
||||
WorkbenchSplashView()
|
||||
.transition(.opacity)
|
||||
.zIndex(10)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? await Task.sleep(for: .seconds(3))
|
||||
|
||||
withAnimation(.easeOut(duration: 0.4)) {
|
||||
showingSplash = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkbenchSplashView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Spacer()
|
||||
|
||||
if let path = Bundle.main.path(
|
||||
forResource: "DBSynBrand",
|
||||
ofType: "png"
|
||||
), let image = NSImage(contentsOfFile: path) {
|
||||
Image(nsImage: image)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 160, height: 160)
|
||||
}
|
||||
|
||||
Text("DBSyn")
|
||||
.font(.system(size: 30, weight: .bold))
|
||||
|
||||
Text("Modern MySQL Client for macOS")
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
HStack(spacing: 30) {
|
||||
feature("cylinder.split.1x2", "Schemas")
|
||||
feature("chevron.left.forwardslash.chevron.right", "SQL Editor")
|
||||
feature("tablecells", "Result Grid")
|
||||
feature("server.rack", "Connections")
|
||||
}
|
||||
.padding(.top, 20)
|
||||
|
||||
Spacer()
|
||||
|
||||
ProgressView()
|
||||
.frame(width: 260)
|
||||
|
||||
Text("Starting DBSyn…")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.bottom, 30)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color(nsColor: .windowBackgroundColor),
|
||||
Color(nsColor: .controlBackgroundColor)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private func feature(_ symbol: String, _ title: String) -> some View {
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: symbol)
|
||||
.font(.system(size: 24))
|
||||
.foregroundStyle(.blue)
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 12))
|
||||
}
|
||||
.frame(width: 90)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench File Menu
|
||||
|
||||
struct WorkbenchFileCommands: Commands {
|
||||
@ObservedObject var model: DatabaseModel
|
||||
|
||||
var body: some Commands {
|
||||
CommandGroup(replacing: .newItem) {
|
||||
Button("New Query Tab") {
|
||||
model.newQueryTab()
|
||||
NotificationCenter.default.post(name: .workbenchRevealSQLEditor, object: nil)
|
||||
}
|
||||
.keyboardShortcut("t", modifiers: .command)
|
||||
}
|
||||
|
||||
CommandGroup(after: .newItem) {
|
||||
Button("Open SQL Script…") {
|
||||
model.openSQLScript()
|
||||
}
|
||||
.keyboardShortcut("o", modifiers: .command)
|
||||
|
||||
Menu("Open Recent SQL Script") {
|
||||
if model.recentSQLScripts.isEmpty {
|
||||
Text("No Recent Scripts")
|
||||
} else {
|
||||
ForEach(model.recentSQLScripts, id: \.self) { path in
|
||||
Button(URL(fileURLWithPath: path).lastPathComponent) {
|
||||
model.openRecentSQLScript(at: path)
|
||||
}
|
||||
.help(path)
|
||||
}
|
||||
Divider()
|
||||
Button("Clear Recent Scripts") { model.clearRecentSQLScripts() }
|
||||
}
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Button("Save SQL Script") {
|
||||
model.saveSQLScript()
|
||||
}
|
||||
.keyboardShortcut("s", modifiers: .command)
|
||||
|
||||
Button("Save SQL Script As…") {
|
||||
model.saveSQLScript(asNewFile: true)
|
||||
}
|
||||
.keyboardShortcut("s", modifiers: [.command, .shift])
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
import Foundation
|
||||
import CoreGraphics
|
||||
|
||||
/// Pure schema-diagram operations shared by the UI and XCTest suite.
|
||||
enum DiagramLogic {
|
||||
static func selectedObjects(_ requested: Set<String>, available: [String]) -> Set<String> {
|
||||
requested.intersection(Set(available))
|
||||
}
|
||||
|
||||
static func arrangedPositions(_ names: [String]) -> [String: CGPoint] {
|
||||
let countPerRow = max(1, Int(ceil(sqrt(Double(max(1, names.count))))))
|
||||
var positions: [String: CGPoint] = [:]
|
||||
for (index, name) in names.enumerated() {
|
||||
positions[name] = CGPoint(x: CGFloat(index % countPerRow) * 290 + 30,
|
||||
y: CGFloat(index / countPerRow) * 300 + 30)
|
||||
}
|
||||
return positions
|
||||
}
|
||||
|
||||
static func translatedPosition(_ origin: CGPoint, translation: CGSize, zoom: CGFloat) -> CGPoint {
|
||||
let scale = max(zoom, 0.1)
|
||||
return CGPoint(x: origin.x + translation.width / scale,
|
||||
y: origin.y + translation.height / scale)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
// Pure conversion engine; can be exercised independently of the UI.
|
||||
enum LaravelMigrationGenerator {
|
||||
static func generate(_ ddl: String) throws -> String {
|
||||
guard let match = ddl.range(of: #"(?is)CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?`?([\w]+)`?\s*\("#, options: .regularExpression) else {
|
||||
throw NSError(domain: "DBSyn.Migration", code: 1, userInfo: [NSLocalizedDescriptionKey: "No CREATE TABLE definition found. Supply MySQL CREATE TABLE SQL."])
|
||||
}
|
||||
let prefix = String(ddl[match]); let name = prefix.replacingOccurrences(of: #"(?is)^.*?CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?"#, with: "", options: .regularExpression).replacingOccurrences(of: "(", with: "").replacingOccurrences(of: "`", with: "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let start = match.upperBound
|
||||
var depth = 1; var end = start; var quote: Character? = nil
|
||||
for index in ddl[start...].indices {
|
||||
let c = ddl[index]
|
||||
if let q = quote { if c == q { quote = nil }; continue }
|
||||
if c == "'" || c == "\"" || c == "`" { quote = c; continue }
|
||||
if c == "(" { depth += 1 }; if c == ")" { depth -= 1; if depth == 0 { end = index; break } }
|
||||
}
|
||||
guard depth == 0 else { throw NSError(domain: "DBSyn.Migration", code: 2, userInfo: [NSLocalizedDescriptionKey: "Unbalanced CREATE TABLE parentheses."]) }
|
||||
let body = String(ddl[start..<end]); var lines: [String] = []
|
||||
let definitions = splitColumns(body)
|
||||
let primaryKeys = definitions.filter { $0.trimmingCharacters(in: .whitespacesAndNewlines).uppercased().hasPrefix("PRIMARY KEY") }
|
||||
.flatMap { backtickNames($0) }
|
||||
let autoPrimary = definitions.contains { $0.uppercased().contains("AUTO_INCREMENT") } && primaryKeys.count == 1
|
||||
for definition in definitions {
|
||||
let item = definition.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let upper = item.uppercased()
|
||||
if upper.hasPrefix("PRIMARY KEY") {
|
||||
if autoPrimary { continue }
|
||||
let columns = backtickNames(item)
|
||||
if columns.count == 1 {
|
||||
lines.append(" $table->primary('\(columns[0])');")
|
||||
} else if !columns.isEmpty {
|
||||
let quotedColumns = columns.map { "'\($0)'" }.joined(separator: ", ")
|
||||
lines.append(" $table->primary([\(quotedColumns)]);")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if upper.hasPrefix("UNIQUE KEY") || upper.hasPrefix("UNIQUE INDEX") || upper.hasPrefix("KEY ") || upper.hasPrefix("INDEX ") {
|
||||
let columns = backtickNames(item)
|
||||
if columns.count > 1 {
|
||||
let columnNames = Array(columns.dropFirst())
|
||||
let quotedColumns = columnNames.map { "'\($0)'" }.joined(separator: ", ")
|
||||
let indexMethod = upper.hasPrefix("UNIQUE") ? "unique" : "index"
|
||||
lines.append(" $table->\(indexMethod)([\(quotedColumns)]);")
|
||||
}
|
||||
continue
|
||||
}
|
||||
if upper.hasPrefix("CONSTRAINT") || upper.hasPrefix("FOREIGN KEY") || upper.hasPrefix("CHECK") { lines.append(" // Review manually: " + item.replacingOccurrences(of: "\n", with: " ")); continue }
|
||||
guard let column = item.range(of: #"^`?([A-Za-z_][\w]*)`?\s+"#, options: .regularExpression) else { continue }
|
||||
let col = String(item[column]).trimmingCharacters(in: .whitespaces).replacingOccurrences(of: "`", with: "")
|
||||
let spec = String(item[column.upperBound...]); let type = spec.lowercased()
|
||||
let method: String
|
||||
if type.hasPrefix("bigint") { method = "bigInteger" }
|
||||
else if type.hasPrefix("tinyint(1)") || type.hasPrefix("boolean") { method = "boolean" }
|
||||
else if type.hasPrefix("tinyint") { method = "tinyInteger" }
|
||||
else if type.hasPrefix("smallint") { method = "smallInteger" }
|
||||
else if type.hasPrefix("mediumint") { method = "mediumInteger" }
|
||||
else if type.hasPrefix("int") || type.hasPrefix("integer") { method = "integer" }
|
||||
else if type.hasPrefix("varchar") { method = "string" }
|
||||
else if type.hasPrefix("char") { method = "char" }
|
||||
else if type.hasPrefix("longtext") { method = "longText" }
|
||||
else if type.hasPrefix("mediumtext") { method = "mediumText" }
|
||||
else if type.hasPrefix("text") { method = "text" }
|
||||
else if type.hasPrefix("datetime") { method = "dateTime" }
|
||||
else if type.hasPrefix("timestamp") { method = "timestamp" }
|
||||
else if type.hasPrefix("date") { method = "date" }
|
||||
else if type.hasPrefix("time") { method = "time" }
|
||||
else if type.hasPrefix("json") { method = "json" }
|
||||
else if type.hasPrefix("double") { method = "double" }
|
||||
else if type.hasPrefix("float") { method = "float" }
|
||||
else if type.hasPrefix("decimal") { method = "decimal" }
|
||||
else if type.hasPrefix("blob") { method = "binary" }
|
||||
else { method = "string" }
|
||||
var args = "'\(col)'"
|
||||
if method == "string" || method == "char", let range = type.range(of: #"\(\s*\d+\s*\)"#, options: .regularExpression) { args += ", " + type[range].filter(\.isNumber) }
|
||||
if method == "decimal", let range = type.range(of: #"\(\s*\d+\s*,\s*\d+\s*\)"#, options: .regularExpression) { args += ", " + type[range].dropFirst().dropLast() }
|
||||
if upper.contains("AUTO_INCREMENT") && primaryKeys == [col] && method == "bigInteger" {
|
||||
lines.append(" $table->id('\(col)');")
|
||||
continue
|
||||
}
|
||||
var expr = " $table->\(method)(\(args))"
|
||||
if upper.contains("UNSIGNED") { expr += "->unsigned()" }
|
||||
if !upper.contains("NOT NULL") { expr += "->nullable()" }
|
||||
if upper.contains("AUTO_INCREMENT") { expr += "->autoIncrement()" }
|
||||
lines.append(expr + ";")
|
||||
}
|
||||
let safeName = name.replacingOccurrences(of: "'", with: "\\'")
|
||||
return """
|
||||
<?php
|
||||
|
||||
use Illuminate\\Database\\Migrations\\Migration;
|
||||
use Illuminate\\Database\\Schema\\Blueprint;
|
||||
use Illuminate\\Support\\Facades\\Schema;
|
||||
|
||||
return new class extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('\(safeName)', function (Blueprint $table) {
|
||||
\(lines.joined(separator: "\n"))
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('\(safeName)');
|
||||
}
|
||||
};
|
||||
"""
|
||||
}
|
||||
private static func backtickNames(_ text: String) -> [String] {
|
||||
guard let regex = try? NSRegularExpression(pattern: "`([^`]+)`") else { return [] }
|
||||
let ns = text as NSString
|
||||
return regex.matches(in: text, range: NSRange(location: 0, length: ns.length)).map { ns.substring(with: $0.range(at: 1)) }
|
||||
}
|
||||
private static func splitColumns(_ text: String) -> [String] {
|
||||
var parts: [String] = []; var current = ""; var depth = 0; var quote: Character? = nil
|
||||
for c in text {
|
||||
if let q = quote { current.append(c); if c == q { quote = nil }; continue }
|
||||
if c == "'" || c == "\"" || c == "`" { quote = c; current.append(c); continue }
|
||||
if c == "(" { depth += 1 }; if c == ")" { depth -= 1 }
|
||||
if c == "," && depth == 0 { parts.append(current); current = "" } else { current.append(c) }
|
||||
}
|
||||
if !current.isEmpty { parts.append(current) }; return parts
|
||||
}
|
||||
}
|
||||
|
||||
struct LaravelMigrationView: View {
|
||||
@ObservedObject var model: DatabaseModel
|
||||
@AppStorage("preferences.migrationFilenamePrefix") private var prefix = "create"
|
||||
@State private var sourceSQL = ""
|
||||
@State private var generated = ""
|
||||
@State private var errorText = ""
|
||||
@State private var tableName = ""
|
||||
@State private var chosenDatabase = ""
|
||||
@State private var isLoading = false
|
||||
@State private var tableSearch = ""
|
||||
@State private var statusText = ""
|
||||
var onClose: () -> Void = {}
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
HStack {
|
||||
Image(systemName: "curlybraces.square").font(.title2).foregroundStyle(.tint)
|
||||
VStack(alignment: .leading) {
|
||||
Text("Laravel Migration Generator").font(.title2.bold())
|
||||
Text("Convert a MySQL table or CREATE TABLE SQL into a Laravel migration.").foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
Button(action: onClose) { Image(systemName: "xmark.circle.fill").font(.title2).foregroundStyle(.secondary) }
|
||||
.buttonStyle(.plain).help("Close Migration Generator")
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack(spacing: 12) {
|
||||
Text("Database").frame(width: 80, alignment: .leading)
|
||||
Picker("Database", selection: $chosenDatabase) {
|
||||
Text("Select database…").tag("")
|
||||
ForEach(databaseOptions, id: \.self) { name in
|
||||
Text(name).tag(name)
|
||||
}
|
||||
}
|
||||
.labelsHidden()
|
||||
.frame(maxWidth: 330)
|
||||
Button("Use Current Database") {
|
||||
chosenDatabase = model.completionDatabase
|
||||
}
|
||||
.disabled(model.completionDatabase.isEmpty)
|
||||
Spacer()
|
||||
}
|
||||
HStack(spacing: 12) {
|
||||
Text("Table").frame(width: 80, alignment: .leading)
|
||||
TextField("Enter a table name", text: $tableName)
|
||||
.frame(maxWidth: 330)
|
||||
if !availableTables.isEmpty {
|
||||
Menu {
|
||||
TextField("Search tables", text: $tableSearch)
|
||||
Divider()
|
||||
ForEach(filteredTables.prefix(100), id: \.self) { name in
|
||||
Button(name) { tableName = name }
|
||||
}
|
||||
if filteredTables.isEmpty { Text("No matching tables") }
|
||||
} label: {
|
||||
Label("Browse Tables (\(availableTables.count))", systemImage: "magnifyingglass")
|
||||
}
|
||||
.frame(maxWidth: 230)
|
||||
}
|
||||
Button(isLoading ? "Loading…" : "Load Table") { loadTable() }
|
||||
.disabled(tableName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || chosenDatabase.isEmpty || model.selected == nil || isLoading)
|
||||
Button("Open SQL File…") { openFile() }
|
||||
Spacer()
|
||||
}
|
||||
if chosenDatabase.isEmpty {
|
||||
Text("Choose a database before loading a table. SQL files can be opened without a connection.")
|
||||
.font(.caption).foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
HSplitView {
|
||||
VStack(alignment: .leading) {
|
||||
Text("MySQL CREATE TABLE").font(.headline)
|
||||
TextEditor(text: $sourceSQL).font(.system(.body, design: .monospaced)).frame(minWidth: 330)
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text("Laravel Migration · PHP").font(.headline)
|
||||
TextEditor(text: $generated).font(.system(.body, design: .monospaced)).frame(minWidth: 330)
|
||||
}
|
||||
}
|
||||
if !errorText.isEmpty { Text(errorText).foregroundStyle(.red).font(.callout) }
|
||||
if !statusText.isEmpty { Text(statusText).foregroundStyle(.green).font(.callout) }
|
||||
HStack {
|
||||
Text("Review indexes, foreign keys, defaults and unsupported MySQL types before running a migration.").font(.caption).foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Generate / Refresh") { generate() }.buttonStyle(.borderedProminent)
|
||||
.disabled(sourceSQL.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
||||
Button("Copy PHP") { NSPasteboard.general.clearContents(); NSPasteboard.general.setString(generated, forType: .string) }.disabled(generated.isEmpty)
|
||||
Button("Save Migration…") { save() }.disabled(generated.isEmpty)
|
||||
}
|
||||
}
|
||||
.padding(22)
|
||||
.frame(minWidth: 980, minHeight: 650)
|
||||
.onAppear {
|
||||
if chosenDatabase.isEmpty {
|
||||
chosenDatabase = model.completionDatabase
|
||||
}
|
||||
}
|
||||
.onChange(of: chosenDatabase) { _, _ in tableName = ""; tableSearch = "" }
|
||||
.onChange(of: sourceSQL) { _, _ in statusText = "Source changed — select Generate / Refresh to update PHP." }
|
||||
}
|
||||
private var databaseOptions: [String] {
|
||||
Array(Set(model.databases + model.schemaTables.keys + [model.completionDatabase].filter { !$0.isEmpty })).sorted()
|
||||
}
|
||||
private var availableTables: [String] {
|
||||
model.schemaTables[chosenDatabase] ?? []
|
||||
}
|
||||
private var filteredTables: [String] {
|
||||
let query = tableSearch.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return query.isEmpty ? availableTables : availableTables.filter { $0.localizedCaseInsensitiveContains(query) }
|
||||
}
|
||||
private func generate() {
|
||||
do {
|
||||
generated = try LaravelMigrationGenerator.generate(sourceSQL)
|
||||
errorText = ""
|
||||
statusText = "Migration generated — review the PHP, then Copy or Save."
|
||||
} catch {
|
||||
errorText = error.localizedDescription
|
||||
statusText = ""
|
||||
}
|
||||
}
|
||||
private func openFile() {
|
||||
let panel = NSOpenPanel(); panel.allowedContentTypes = [UTType(filenameExtension: "sql") ?? .plainText, .plainText]; panel.allowsMultipleSelection = false
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
do { sourceSQL = try String(contentsOf: url, encoding: .utf8); generate() }
|
||||
catch { errorText = error.localizedDescription }
|
||||
}
|
||||
}
|
||||
private func loadTable() {
|
||||
guard let profile = model.selected else { return }
|
||||
isLoading = true
|
||||
let db = chosenDatabase.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !db.isEmpty else {
|
||||
errorText = "Select a database before loading a table."
|
||||
isLoading = false
|
||||
return
|
||||
}
|
||||
let escaped = tableName.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "`", with: "``")
|
||||
let escapedDB = db.replacingOccurrences(of: "`", with: "``")
|
||||
errorText = ""
|
||||
Task {
|
||||
do {
|
||||
let result = try await NativeMySQLRunner.run(profile: profile, database: db, password: PasswordStore.read(profile.id), sql: "SHOW CREATE TABLE `\(escapedDB)`.`\(escaped)`")
|
||||
guard let ddl = result.rows.first?.last, !ddl.isEmpty else { throw NSError(domain: "DBSyn.Migration", code: 3, userInfo: [NSLocalizedDescriptionKey: "No table definition returned."]) }
|
||||
sourceSQL = ddl; generate()
|
||||
} catch { errorText = "Could not load \(db).\(tableName): \(error.localizedDescription)" }
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
private func save() {
|
||||
let panel = NSSavePanel(); panel.allowedContentTypes = [UTType(filenameExtension: "php") ?? .plainText]
|
||||
let name = tableName.isEmpty ? "table" : tableName.lowercased()
|
||||
let timestamp = DateFormatter()
|
||||
timestamp.dateFormat = "yyyy_MM_dd_HHmmss"
|
||||
let useTimestamps = UserDefaults.standard.object(forKey: "preferences.migrationUseTimestamps") as? Bool ?? true
|
||||
let datePrefix = useTimestamps ? timestamp.string(from: Date()) + "_" : ""
|
||||
panel.nameFieldStringValue = "\(datePrefix)\(prefix)_\(name)_table.php"
|
||||
let folder = UserDefaults.standard.string(forKey: "preferences.migrationOutputDirectory") ?? ""
|
||||
if !folder.isEmpty { panel.directoryURL = URL(fileURLWithPath: (folder as NSString).expandingTildeInPath, isDirectory: true) }
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
do { try generated.write(to: url, atomically: true, encoding: .utf8); errorText = ""; statusText = "Saved: \(url.lastPathComponent)" }
|
||||
catch { errorText = error.localizedDescription }
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import CommonCrypto
|
||||
import CoreFoundation
|
||||
import CFNetwork
|
||||
import Security
|
||||
|
||||
// Native MySQL wire protocol client. No external mysql executable is used.
|
||||
@@ -10,6 +11,69 @@ struct MySQLWireError: LocalizedError {
|
||||
var errorDescription: String? { message }
|
||||
}
|
||||
|
||||
// SSH transport uses the system OpenSSH client and key-based authentication.
|
||||
// No remote MySQL password is passed to ssh. SSH host-key verification remains enabled.
|
||||
private final class DBSynSSHTunnels {
|
||||
static let shared = DBSynSSHTunnels()
|
||||
private let lock = NSLock()
|
||||
private var running: [UUID: (Process, ConnectionProfile, Int)] = [:]
|
||||
|
||||
func endpoint(for profile: ConnectionProfile) throws -> (String, Int) {
|
||||
guard profile.useSSHTunnel else { return (profile.host, profile.port) }
|
||||
lock.lock(); defer { lock.unlock() }
|
||||
if let current = running[profile.id] {
|
||||
if current.0.isRunning && current.1 == profile { return ("127.0.0.1", current.2) }
|
||||
if current.0.isRunning { current.0.terminate() }
|
||||
running.removeValue(forKey: profile.id)
|
||||
}
|
||||
guard !profile.sshHost.isEmpty, !profile.sshUser.isEmpty else {
|
||||
throw MySQLWireError(message: "Configure SSH hostname and SSH username in Connection Settings")
|
||||
}
|
||||
// A stable local port per connection; ExitOnForwardFailure rejects conflicts.
|
||||
let bytes = Array(profile.id.uuidString.utf8)
|
||||
let checksum = bytes.reduce(0) { ($0 &* 31 &+ Int($1)) % 10000 }
|
||||
let localPort = 45000 + checksum
|
||||
let process = Process()
|
||||
process.executableURL = URL(fileURLWithPath: "/usr/bin/ssh")
|
||||
var args = ["-N", "-T", "-o", "BatchMode=yes", "-o", "ExitOnForwardFailure=yes", "-o", "ConnectTimeout=8", "-o", "StrictHostKeyChecking=yes", "-p", String(profile.sshPort)]
|
||||
if !profile.sshIdentityFile.isEmpty { args += ["-i", (profile.sshIdentityFile as NSString).expandingTildeInPath] }
|
||||
args += ["-L", "127.0.0.1:\(localPort):\(profile.host):\(profile.port)", "\(profile.sshUser)@\(profile.sshHost)"]
|
||||
process.arguments = args
|
||||
process.standardInput = FileHandle.nullDevice
|
||||
process.standardOutput = FileHandle.nullDevice
|
||||
process.standardError = FileHandle.nullDevice
|
||||
do { try process.run() } catch { throw MySQLWireError(message: "Cannot launch SSH: \(error.localizedDescription)") }
|
||||
// SSH may take several seconds to authenticate. A running process does
|
||||
// not mean its local listener is ready. Probe the forwarded endpoint
|
||||
// before handing it to the MySQL handshake.
|
||||
let deadline = Date().addingTimeInterval(10)
|
||||
var ready = false
|
||||
while Date() < deadline && process.isRunning {
|
||||
let probe = Process()
|
||||
probe.executableURL = URL(fileURLWithPath: "/usr/bin/nc")
|
||||
probe.arguments = ["-z", "-G", "1", "127.0.0.1", String(localPort)]
|
||||
probe.standardInput = FileHandle.nullDevice
|
||||
probe.standardOutput = FileHandle.nullDevice
|
||||
probe.standardError = FileHandle.nullDevice
|
||||
if (try? probe.run()) != nil {
|
||||
probe.waitUntilExit()
|
||||
if probe.terminationStatus == 0 { ready = true; break }
|
||||
}
|
||||
Thread.sleep(forTimeInterval: 0.15)
|
||||
}
|
||||
guard ready else {
|
||||
if process.isRunning { process.terminate() }
|
||||
throw MySQLWireError(message: "SSH forwarding did not become ready within 10 seconds (local port \(localPort)). Check SSH credentials, host key and target address.")
|
||||
}
|
||||
running[profile.id] = (process, profile, localPort)
|
||||
return ("127.0.0.1", localPort)
|
||||
}
|
||||
func stop(_ id: UUID) {
|
||||
lock.lock(); defer { lock.unlock() }
|
||||
if let existing = running.removeValue(forKey: id), existing.0.isRunning { existing.0.terminate() }
|
||||
}
|
||||
}
|
||||
|
||||
private struct ByteCursor {
|
||||
let bytes: [UInt8]
|
||||
var offset = 0
|
||||
@@ -139,8 +203,15 @@ final class MySQLWireConnection {
|
||||
private let output: OutputStream
|
||||
private var sequence: UInt8 = 0
|
||||
private let maxPacket = 16_777_215
|
||||
private let serverHost: String
|
||||
private let requireTLS: Bool
|
||||
private let verifyTLS: Bool
|
||||
private var tlsActive = false
|
||||
|
||||
init(host: String, port: Int) throws {
|
||||
init(host: String, port: Int, requireTLS: Bool = false, verifyTLS: Bool = true) throws {
|
||||
self.serverHost = host
|
||||
self.requireTLS = requireTLS
|
||||
self.verifyTLS = verifyTLS
|
||||
guard (1...65535).contains(port) else { throw MySQLWireError(message: "Invalid port") }
|
||||
var read: Unmanaged<CFReadStream>?
|
||||
var write: Unmanaged<CFWriteStream>?
|
||||
@@ -176,6 +247,9 @@ final class MySQLWireConnection {
|
||||
let header = try readExact(4)
|
||||
let count = Int(header[0]) | Int(header[1]) << 8 | Int(header[2]) << 16
|
||||
sequence = header[3] &+ 1
|
||||
guard count <= maxPacket else {
|
||||
throw MySQLWireError(message: "MySQL packet exceeds protocol limit")
|
||||
}
|
||||
return try readExact(count)
|
||||
}
|
||||
private func send(_ payload: [UInt8]) throws {
|
||||
@@ -193,6 +267,25 @@ final class MySQLWireConnection {
|
||||
written += n
|
||||
}
|
||||
}
|
||||
// MySQL TLS is negotiated AFTER the server greeting: first send CLIENT_SSL,
|
||||
// then upgrade the existing TCP streams, then send the authentication packet.
|
||||
// Never send credentials if TLS negotiation or certificate verification fails.
|
||||
private func upgradeToTLS() throws {
|
||||
let settings: [String: Any] = [
|
||||
kCFStreamSSLLevel as String: kCFStreamSocketSecurityLevelNegotiatedSSL,
|
||||
kCFStreamSSLValidatesCertificateChain as String: verifyTLS,
|
||||
kCFStreamSSLPeerName as String: verifyTLS ? serverHost : kCFNull as Any
|
||||
]
|
||||
let key = Stream.PropertyKey(rawValue: kCFStreamPropertySSLSettings as String)
|
||||
guard input.setProperty(settings, forKey: key),
|
||||
output.setProperty(settings, forKey: key) else {
|
||||
throw MySQLWireError(message: "TLS stream upgrade unavailable; no credentials sent. Use SSH tunnelling for this server.")
|
||||
}
|
||||
// CFStream performs the TLS handshake before delivering encrypted data.
|
||||
// Writing authentication triggers the handshake; any failure aborts it.
|
||||
tlsActive = true
|
||||
}
|
||||
|
||||
private func checkError(_ p: [UInt8]) throws {
|
||||
guard p.first == 0xff else { return }
|
||||
let details = String(decoding: p.dropFirst(3), as: UTF8.self)
|
||||
@@ -217,11 +310,21 @@ final class MySQLWireConnection {
|
||||
let salt2 = try c.take(max(13, authLen - 8))
|
||||
let salt = salt1 + salt2.prefix(max(0, authLen - 9))
|
||||
let plugin = (try? c.nulString()) ?? "mysql_native_password"
|
||||
// This initial implementation deliberately refuses cleartext remote credentials.
|
||||
guard hostIsLoopback else { throw MySQLWireError(message: "Direct remote connections require TLS, which is not yet implemented. Use a local SSH tunnel.") }
|
||||
if requireTLS {
|
||||
let clientSSL = 0x00000800
|
||||
guard capabilities & clientSSL != 0 else {
|
||||
throw MySQLWireError(message: "MySQL server does not advertise TLS; refusing to send credentials")
|
||||
}
|
||||
let sslFlags = 0x00000001 | 0x00000004 | 0x00000200 | 0x00000800 | 0x00002000 | 0x00008000 | 0x00080000
|
||||
let request = le32(sslFlags & capabilities) + le32(16_777_216) + [UInt8(45)] + [UInt8](repeating: 0, count: 23)
|
||||
try send(request)
|
||||
try upgradeToTLS()
|
||||
} else if !hostIsLoopback {
|
||||
throw MySQLWireError(message: "Remote connections require verified TLS or an SSH tunnel")
|
||||
}
|
||||
// CLIENT_LONG_PASSWORD, LONG_FLAG, PROTOCOL_41, TRANSACTIONS,
|
||||
// SECURE_CONNECTION and PLUGIN_AUTH. Do not set DEPRECATE_EOF.
|
||||
let clientFlags = 0x00000001 | 0x00000004 | 0x00000200 | 0x00002000 | 0x00008000 | 0x00080000
|
||||
let clientFlags = 0x00000001 | 0x00000004 | 0x00000200 | (requireTLS ? 0x00000800 : 0) | 0x00002000 | 0x00008000 | 0x00080000
|
||||
let response = try authResponse(password: password, salt: Array(salt), plugin: plugin)
|
||||
var body = le32(clientFlags & capabilities) + le32(16_777_216) + [UInt8(45)] + [UInt8](repeating: 0, count: 23)
|
||||
body += Array(user.utf8) + [0, UInt8(response.count)] + response
|
||||
@@ -250,14 +353,15 @@ final class MySQLWireConnection {
|
||||
case 0x03: // Fast authentication accepted; wait for OK.
|
||||
reply = try readPacket()
|
||||
case 0x04: // Full authentication required.
|
||||
guard hostIsLoopback else {
|
||||
throw MySQLWireError(message: "Remote full authentication requires TLS (not implemented). Use a trusted local SSH tunnel.")
|
||||
guard hostIsLoopback || tlsActive else {
|
||||
throw MySQLWireError(message: "Full authentication requires encrypted transport")
|
||||
}
|
||||
if password.isEmpty {
|
||||
if tlsActive {
|
||||
try send(Array(password.utf8) + [0])
|
||||
} else if password.isEmpty {
|
||||
try send([0])
|
||||
} else {
|
||||
// Request the server's RSA public key (0x02). This is
|
||||
// intended ONLY for a trusted local loopback connection.
|
||||
// RSA fallback is restricted to trusted loopback transport.
|
||||
try send([0x02])
|
||||
let keyPacket = try readPacket()
|
||||
try checkError(keyPacket)
|
||||
@@ -358,39 +462,79 @@ private final class PersistentMySQLSessions {
|
||||
let connection: MySQLWireConnection
|
||||
}
|
||||
|
||||
private let queue = DispatchQueue(label: "WorkbenchReplacement.MySQLSessions")
|
||||
private var connections: [UUID: Entry] = [:]
|
||||
// Each profile has its own serial executor. An unreachable server cannot
|
||||
// block requests to any other saved connection.
|
||||
private final class SessionSlot {
|
||||
let queue: DispatchQueue
|
||||
var entry: Entry?
|
||||
// Only accessed on queue except generation, which is lock protected.
|
||||
private let generationLock = NSLock()
|
||||
private var currentGeneration: UInt64 = 0
|
||||
|
||||
init(id: UUID) {
|
||||
queue = DispatchQueue(label: "DBSyn.MySQLSession.\(id.uuidString)")
|
||||
}
|
||||
func generation() -> UInt64 {
|
||||
generationLock.lock(); defer { generationLock.unlock() }
|
||||
return currentGeneration
|
||||
}
|
||||
func invalidate() {
|
||||
generationLock.lock(); currentGeneration &+= 1; generationLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
private let slotsLock = NSLock()
|
||||
private var slots: [UUID: SessionSlot] = [:]
|
||||
|
||||
private func slot(for id: UUID) -> SessionSlot {
|
||||
slotsLock.lock(); defer { slotsLock.unlock() }
|
||||
if let existing = slots[id] { return existing }
|
||||
let created = SessionSlot(id: id)
|
||||
slots[id] = created
|
||||
return created
|
||||
}
|
||||
|
||||
func execute(profile: ConnectionProfile, database: String,
|
||||
password: String, sql: String) throws -> QueryResult {
|
||||
try queue.sync {
|
||||
// A changed connection profile or password requires a new session.
|
||||
if let previous = connections[profile.id],
|
||||
(previous.profile != profile || previous.password != password) {
|
||||
connections.removeValue(forKey: profile.id)
|
||||
let session = slot(for: profile.id)
|
||||
let expectedGeneration = session.generation()
|
||||
return try session.queue.sync {
|
||||
guard session.generation() == expectedGeneration else {
|
||||
throw MySQLWireError(message: "Connection request superseded")
|
||||
}
|
||||
|
||||
if connections[profile.id] == nil {
|
||||
let connection = try MySQLWireConnection(host: profile.host, port: profile.port)
|
||||
connection.markHost(profile.host)
|
||||
if let previous = session.entry,
|
||||
(previous.profile != profile || previous.password != password) {
|
||||
session.entry = nil
|
||||
DBSynSSHTunnels.shared.stop(profile.id)
|
||||
}
|
||||
if session.entry == nil {
|
||||
let endpoint = try DBSynSSHTunnels.shared.endpoint(for: profile)
|
||||
let connection = try MySQLWireConnection(
|
||||
host: endpoint.0, port: endpoint.1,
|
||||
requireTLS: !profile.useSSHTunnel &&
|
||||
!["127.0.0.1", "localhost", "::1"].contains(endpoint.0.lowercased()),
|
||||
verifyTLS: profile.verifyTLS
|
||||
)
|
||||
connection.markHost(endpoint.0)
|
||||
try connection.authenticate(user: profile.username,
|
||||
password: password, database: database)
|
||||
connections[profile.id] = Entry(profile: profile,
|
||||
password: password,
|
||||
guard session.generation() == expectedGeneration else {
|
||||
throw MySQLWireError(message: "Connection request superseded")
|
||||
}
|
||||
session.entry = Entry(profile: profile, password: password,
|
||||
connection: connection)
|
||||
}
|
||||
|
||||
guard let entry = connections[profile.id] else {
|
||||
guard let entry = session.entry else {
|
||||
throw MySQLWireError(message: "MySQL session was not created")
|
||||
}
|
||||
do {
|
||||
// Crucially, no new authentication takes place here. USE,
|
||||
// session variables and transactions survive between queries.
|
||||
return try entry.connection.query(sql)
|
||||
let result = try entry.connection.query(sql)
|
||||
guard session.generation() == expectedGeneration else {
|
||||
throw MySQLWireError(message: "Connection request superseded")
|
||||
}
|
||||
return result
|
||||
} catch {
|
||||
// The wire protocol can be out of sync after a failed query.
|
||||
// Discard it rather than silently issuing commands on a bad socket.
|
||||
connections.removeValue(forKey: profile.id)
|
||||
session.entry = nil
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -399,22 +543,36 @@ private final class PersistentMySQLSessions {
|
||||
func stream(profile: ConnectionProfile, database: String,
|
||||
password: String, sql: String,
|
||||
onRow: (String) throws -> Void) throws -> Int64 {
|
||||
try queue.sync {
|
||||
guard let entry = connections[profile.id],
|
||||
let session = slot(for: profile.id)
|
||||
let expectedGeneration = session.generation()
|
||||
return try session.queue.sync {
|
||||
guard session.generation() == expectedGeneration,
|
||||
let entry = session.entry,
|
||||
entry.profile == profile, entry.password == password else {
|
||||
throw MySQLWireError(message: "Export session is no longer connected")
|
||||
}
|
||||
do {
|
||||
return try entry.connection.streamFirstColumn(sql, onRow: onRow)
|
||||
return try entry.connection.streamFirstColumn(sql, onRow: { row in
|
||||
guard session.generation() == expectedGeneration else {
|
||||
throw MySQLWireError(message: "Export cancelled: connection switched")
|
||||
}
|
||||
try onRow(row)
|
||||
})
|
||||
} catch {
|
||||
connections.removeValue(forKey: profile.id)
|
||||
session.entry = nil
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(profileID: UUID) {
|
||||
queue.sync { _ = connections.removeValue(forKey: profileID) }
|
||||
let session = slot(for: profileID)
|
||||
// Invalidate immediately without waiting for a blocked network read.
|
||||
session.invalidate()
|
||||
session.queue.async {
|
||||
session.entry = nil
|
||||
DBSynSSHTunnels.shared.stop(profileID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +600,8 @@ enum NativeMySQLRunner {
|
||||
}.value
|
||||
}
|
||||
|
||||
// Connection shutdown may wait behind a slow network operation on the
|
||||
// session's serial queue. Never make the SwiftUI main thread wait for it.
|
||||
static func disconnect(profileID: UUID) {
|
||||
PersistentMySQLSessions.shared.disconnect(profileID: profileID)
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 460 KiB |
@@ -0,0 +1,149 @@
|
||||
import AppKit
|
||||
|
||||
/// Resolution-independent diagram renderer shared by PDF, PNG, SVG and macOS printing.
|
||||
/// The exported palette is intentionally independent of the user's macOS appearance.
|
||||
final class SchemaDiagramPrintView: NSView {
|
||||
struct Column { let name: String; let type: String; let primary: Bool }
|
||||
struct Entry { let name: String; let isView: Bool; let columns: [Column]; let origin: CGPoint }
|
||||
struct Link { let from: String; let to: String; let column: String; let target: String }
|
||||
|
||||
let database: String
|
||||
let diagram: String
|
||||
let entries: [Entry]
|
||||
let links: [Link]
|
||||
let theme: String
|
||||
private let cardWidth: CGFloat = 260
|
||||
private let headerHeight: CGFloat = 34
|
||||
private let rowHeight: CGFloat = 19
|
||||
private let margin: CGFloat = 55
|
||||
private let titleHeight: CGFloat = 76
|
||||
private let navy = NSColor(calibratedRed: 0.12, green: 0.20, blue: 0.34, alpha: 1)
|
||||
private var blue: NSColor {
|
||||
switch theme {
|
||||
case "Slate": return NSColor(calibratedRed: 0.30, green: 0.38, blue: 0.49, alpha: 1)
|
||||
case "Forest": return NSColor(calibratedRed: 0.16, green: 0.43, blue: 0.36, alpha: 1)
|
||||
case "Plum": return NSColor(calibratedRed: 0.42, green: 0.32, blue: 0.55, alpha: 1)
|
||||
default: return NSColor(calibratedRed: 0.12, green: 0.38, blue: 0.66, alpha: 1)
|
||||
}
|
||||
}
|
||||
private var violet: NSColor { blue.blended(withFraction: 0.25, of: .systemPurple) ?? blue }
|
||||
private let ink = NSColor(calibratedRed: 0.16, green: 0.23, blue: 0.32, alpha: 1)
|
||||
private let muted = NSColor(calibratedRed: 0.43, green: 0.49, blue: 0.57, alpha: 1)
|
||||
private let border = NSColor(calibratedRed: 0.79, green: 0.83, blue: 0.88, alpha: 1)
|
||||
|
||||
init(database: String, diagram: String, entries: [Entry], links: [Link], theme: String = "Ocean") {
|
||||
self.database = database
|
||||
self.diagram = diagram
|
||||
self.entries = entries
|
||||
self.links = links
|
||||
self.theme = theme
|
||||
let width = max(900, (entries.map { $0.origin.x + 260 }.max() ?? 750) + 110)
|
||||
let height = max(650, (entries.map { $0.origin.y + CGFloat($0.columns.count) * 19 + 46 }.max() ?? 500) + 130)
|
||||
super.init(frame: CGRect(x: 0, y: 0, width: width, height: height))
|
||||
}
|
||||
required init?(coder: NSCoder) { nil }
|
||||
override var isFlipped: Bool { true }
|
||||
private func cardHeight(_ entry: Entry) -> CGFloat { headerHeight + CGFloat(entry.columns.count) * rowHeight + 12 }
|
||||
private func cardRect(_ entry: Entry) -> CGRect {
|
||||
CGRect(x: entry.origin.x + margin, y: entry.origin.y + titleHeight,
|
||||
width: cardWidth, height: cardHeight(entry))
|
||||
}
|
||||
private func text(_ string: String, at point: CGPoint, font: NSFont, color: NSColor) {
|
||||
(string as NSString).draw(at: point, withAttributes: [.font: font, .foregroundColor: color])
|
||||
}
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
NSColor.white.setFill()
|
||||
NSBezierPath(rect: bounds).fill()
|
||||
navy.setFill()
|
||||
NSBezierPath(rect: CGRect(x: 0, y: 0, width: bounds.width, height: 8)).fill()
|
||||
text(database, at: CGPoint(x: margin, y: 25), font: .systemFont(ofSize: 22, weight: .bold), color: navy)
|
||||
text("SCHEMA DIAGRAM / \(diagram)", at: CGPoint(x: margin, y: 54), font: .systemFont(ofSize: 10, weight: .medium), color: muted)
|
||||
text("\(entries.count) objects • \(links.count) relationships", at: CGPoint(x: margin, y: bounds.height - 27), font: .systemFont(ofSize: 10), color: muted)
|
||||
let byName = Dictionary(uniqueKeysWithValues: entries.map { ($0.name, $0) })
|
||||
for link in links {
|
||||
guard let source = byName[link.from], let target = byName[link.to] else { continue }
|
||||
let a = cardRect(source), b = cardRect(target)
|
||||
let toRight = a.midX <= b.midX
|
||||
let start = CGPoint(x: toRight ? a.maxX : a.minX, y: a.midY)
|
||||
let end = CGPoint(x: toRight ? b.minX : b.maxX, y: b.midY)
|
||||
let curve = NSBezierPath()
|
||||
curve.move(to: start)
|
||||
curve.curve(to: end,
|
||||
controlPoint1: CGPoint(x: start.x + (toRight ? 55 : -55), y: start.y),
|
||||
controlPoint2: CGPoint(x: end.x + (toRight ? -55 : 55), y: end.y))
|
||||
NSColor(calibratedRed: 0.39, green: 0.53, blue: 0.69, alpha: 1).setStroke()
|
||||
curve.lineWidth = 1.7
|
||||
curve.stroke()
|
||||
}
|
||||
for entry in entries {
|
||||
let rect = cardRect(entry)
|
||||
NSColor.white.setFill()
|
||||
NSBezierPath(roundedRect: rect, xRadius: 7, yRadius: 7).fill()
|
||||
border.setStroke()
|
||||
NSBezierPath(roundedRect: rect, xRadius: 7, yRadius: 7).stroke()
|
||||
let header = CGRect(x: rect.minX, y: rect.minY, width: rect.width, height: headerHeight)
|
||||
(entry.isView ? violet : blue).setFill()
|
||||
NSBezierPath(rect: header).fill()
|
||||
text(entry.name, at: CGPoint(x: rect.minX + 12, y: rect.minY + 9),
|
||||
font: .systemFont(ofSize: 12, weight: .semibold), color: .white)
|
||||
for (i, column) in entry.columns.enumerated() {
|
||||
let y = rect.minY + headerHeight + CGFloat(i) * rowHeight
|
||||
if i.isMultiple(of: 2) {
|
||||
NSColor(calibratedRed: 0.96, green: 0.97, blue: 0.99, alpha: 1).setFill()
|
||||
NSBezierPath(rect: CGRect(x: rect.minX + 1, y: y, width: rect.width - 2, height: rowHeight)).fill()
|
||||
}
|
||||
let label = (column.primary ? "◆ " : " ") + column.name
|
||||
text(String(label.prefix(29)), at: CGPoint(x: rect.minX + 9, y: y + 3),
|
||||
font: .systemFont(ofSize: 10, weight: column.primary ? .semibold : .regular), color: ink)
|
||||
let type = String(column.type.prefix(22)) as NSString
|
||||
let attrs: [NSAttributedString.Key: Any] = [.font: NSFont.systemFont(ofSize: 9), .foregroundColor: muted]
|
||||
let typeWidth = type.size(withAttributes: attrs).width
|
||||
type.draw(at: CGPoint(x: rect.maxX - typeWidth - 10, y: y + 4), withAttributes: attrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func escape(_ text: String) -> String {
|
||||
text.replacingOccurrences(of: "&", with: "&")
|
||||
.replacingOccurrences(of: "<", with: "<")
|
||||
.replacingOccurrences(of: ">", with: ">")
|
||||
.replacingOccurrences(of: "\"", with: """)
|
||||
}
|
||||
func svgDocument() -> String {
|
||||
var svg = """
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="\(Int(bounds.width))" height="\(Int(bounds.height))" viewBox="0 0 \(Int(bounds.width)) \(Int(bounds.height))">
|
||||
<rect width="100%" height="100%" fill="#ffffff"/>
|
||||
<rect width="100%" height="8" fill="#1f3457"/>
|
||||
<text x="55" y="44" font-family="-apple-system,Arial,sans-serif" font-size="22" font-weight="700" fill="#1f3457">\(escape(database))</text>
|
||||
<text x="55" y="66" font-family="Arial,sans-serif" font-size="10" fill="#6e7d91">SCHEMA DIAGRAM / \(escape(diagram))</text>
|
||||
"""
|
||||
let byName = Dictionary(uniqueKeysWithValues: entries.map { ($0.name, $0) })
|
||||
for link in links {
|
||||
guard let source = byName[link.from], let target = byName[link.to] else { continue }
|
||||
let a = cardRect(source), b = cardRect(target), right = a.midX <= b.midX
|
||||
let sx = right ? a.maxX : a.minX, ex = right ? b.minX : b.maxX
|
||||
let delta: CGFloat = right ? 55 : -55
|
||||
svg += "<path d=\"M \(sx) \(a.midY) C \(sx + delta) \(a.midY), \(ex - delta) \(b.midY), \(ex) \(b.midY)\" fill=\"none\" stroke=\"#6488af\" stroke-width=\"1.7\"/>\n"
|
||||
}
|
||||
let svgBlue = blue.usingColorSpace(.deviceRGB) ?? blue
|
||||
let svgViolet = violet.usingColorSpace(.deviceRGB) ?? violet
|
||||
func hex(_ color: NSColor) -> String {
|
||||
String(format: "#%02X%02X%02X", Int(color.redComponent * 255), Int(color.greenComponent * 255), Int(color.blueComponent * 255))
|
||||
}
|
||||
for entry in entries {
|
||||
let r = cardRect(entry)
|
||||
svg += "<rect x=\"\(r.minX)\" y=\"\(r.minY)\" width=\"\(r.width)\" height=\"\(r.height)\" rx=\"7\" fill=\"white\" stroke=\"#cbd4e0\"/>\n"
|
||||
svg += "<rect x=\"\(r.minX)\" y=\"\(r.minY)\" width=\"\(r.width)\" height=\"34\" fill=\"\(entry.isView ? hex(svgViolet) : hex(svgBlue))\"/>\n"
|
||||
svg += "<text x=\"\(r.minX + 12)\" y=\"\(r.minY + 23)\" font-family=\"Arial,sans-serif\" font-size=\"12\" font-weight=\"600\" fill=\"white\">\(escape(entry.name))</text>\n"
|
||||
for (index, column) in entry.columns.enumerated() {
|
||||
let y = r.minY + 34 + CGFloat(index) * 19
|
||||
if index.isMultiple(of: 2) { svg += "<rect x=\"\(r.minX + 1)\" y=\"\(y)\" width=\"\(r.width - 2)\" height=\"19\" fill=\"#f5f8fc\"/>\n" }
|
||||
svg += "<text x=\"\(r.minX + 9)\" y=\"\(y + 13)\" font-family=\"Arial,sans-serif\" font-size=\"10\" fill=\"#293b52\">\(escape((column.primary ? "◆ " : " ") + column.name))</text>\n"
|
||||
svg += "<text x=\"\(r.maxX - 9)\" y=\"\(y + 13)\" text-anchor=\"end\" font-family=\"Arial,sans-serif\" font-size=\"9\" fill=\"#6e7d91\">\(escape(column.type))</text>\n"
|
||||
}
|
||||
}
|
||||
svg += "<text x=\"55\" y=\"\(bounds.height - 20)\" font-family=\"Arial,sans-serif\" font-size=\"10\" fill=\"#6e7d91\">\(entries.count) objects / \(links.count) relationships</text>\n</svg>"
|
||||
return svg
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
private struct DiagramRelation: Identifiable {
|
||||
var id: String { "\(from).\(column).\(to).\(targetColumn)" }
|
||||
let from: String
|
||||
let column: String
|
||||
let to: String
|
||||
let targetColumn: String
|
||||
}
|
||||
|
||||
private struct DiagramPoint: Codable {
|
||||
var x: Double
|
||||
var y: Double
|
||||
}
|
||||
|
||||
// Keep the drag translation local to the node. Updating the entire diagram's
|
||||
// positions dictionary on every mouse event caused layout churn and jerky drags.
|
||||
private struct DiagramDraggableNode<Content: View>: View {
|
||||
let zoom: CGFloat
|
||||
let onDrop: (CGSize) -> Void
|
||||
@ViewBuilder let content: () -> Content
|
||||
@GestureState private var translation: CGSize = .zero
|
||||
|
||||
var body: some View {
|
||||
content()
|
||||
.offset(x: translation.width / max(zoom, 0.1),
|
||||
y: translation.height / max(zoom, 0.1))
|
||||
.highPriorityGesture(
|
||||
DragGesture(minimumDistance: 3, coordinateSpace: .global)
|
||||
.updating($translation) { value, state, _ in
|
||||
state = value.translation
|
||||
}
|
||||
.onEnded { value in
|
||||
onDrop(value.translation)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct DBSynSchemaDiagramView: View {
|
||||
@ObservedObject var model: DatabaseModel
|
||||
let database: String
|
||||
var onClose: () -> Void = {}
|
||||
@State private var positions: [String: CGPoint] = [:]
|
||||
@State private var relations: [DiagramRelation] = []
|
||||
@State private var zoom: CGFloat = 1
|
||||
@State private var search = ""
|
||||
@State private var selectedObject: String?
|
||||
@State private var loadingRelationships = false
|
||||
@State private var errorMessage: String?
|
||||
@State private var showViews = true
|
||||
@State private var showingObjects = true
|
||||
@State private var includedObjects: Set<String> = []
|
||||
@State private var selectionRevision = 0
|
||||
@State private var theme = "Ocean"
|
||||
@State private var showAllColumns = false
|
||||
@State private var relatedOnly = false
|
||||
@State private var diagramName = "Main"
|
||||
@State private var diagrams: [String] = ["Main"]
|
||||
@State private var newDiagramName = ""
|
||||
@State private var showingNewDiagram = false
|
||||
@State private var showingDeleteConfirmation = false
|
||||
@State private var exportError: String?
|
||||
@State private var showingExportError = false
|
||||
|
||||
private let nodeWidth: CGFloat = 245
|
||||
private let headerHeight: CGFloat = 36
|
||||
private let rowHeight: CGFloat = 21
|
||||
private var maxColumns: Int { showAllColumns ? 200 : 10 }
|
||||
private var snapshot: DatabaseModel.SchemaIntrospection? { model.introspection(for: database) }
|
||||
private var objects: [String] {
|
||||
guard let snapshot else { return [] }
|
||||
let all = snapshot.tables + (showViews ? snapshot.views : [])
|
||||
return all.filter { name in
|
||||
includedObjects.contains(name) && (search.isEmpty || name.localizedCaseInsensitiveContains(search)) &&
|
||||
(!relatedOnly || selectedObject == nil || name == selectedObject || relations.contains { ($0.from == selectedObject && $0.to == name) || ($0.to == selectedObject && $0.from == name) })
|
||||
}
|
||||
}
|
||||
private var diagramNamespace: String {
|
||||
"DBSyn.diagram.v2.\(model.selected?.id.uuidString ?? "unknown").\(database)"
|
||||
}
|
||||
private var storageKey: String { "\(diagramNamespace).layout.\(diagramName)" }
|
||||
private var catalogKey: String { "\(diagramNamespace).catalog" }
|
||||
private var selectionKey: String { "\(diagramNamespace).objects.\(diagramName)" }
|
||||
private var themeKey: String { "\(diagramNamespace).theme.\(diagramName)" }
|
||||
private var allObjects: [String] { (snapshot?.tables ?? []) + (snapshot?.views ?? []) }
|
||||
private var nodeColor: Color {
|
||||
switch theme {
|
||||
case "Slate": return Color(red: 0.30, green: 0.38, blue: 0.49)
|
||||
case "Forest": return Color(red: 0.16, green: 0.43, blue: 0.36)
|
||||
case "Plum": return Color(red: 0.42, green: 0.32, blue: 0.55)
|
||||
default: return Color(red: 0.12, green: 0.38, blue: 0.66)
|
||||
}
|
||||
}
|
||||
private func restoreOptions() {
|
||||
if let stored = UserDefaults.standard.stringArray(forKey: selectionKey) {
|
||||
includedObjects = Set(stored)
|
||||
} else { includedObjects = Set(allObjects) }
|
||||
theme = UserDefaults.standard.string(forKey: themeKey) ?? UserDefaults.standard.string(forKey: "preferences.diagramPalette") ?? "Ocean"
|
||||
showAllColumns = UserDefaults.standard.bool(forKey: "preferences.diagramShowAllColumns")
|
||||
}
|
||||
private func saveOptions() {
|
||||
UserDefaults.standard.set(Array(includedObjects).sorted(), forKey: selectionKey)
|
||||
UserDefaults.standard.set(theme, forKey: themeKey)
|
||||
}
|
||||
private func columns(_ name: String) -> [DatabaseModel.IntrospectedColumn] {
|
||||
snapshot?.columnsByTable[name] ?? []
|
||||
}
|
||||
private func height(_ name: String) -> CGFloat {
|
||||
headerHeight + CGFloat(min(columns(name).count, maxColumns)) * rowHeight + 12
|
||||
}
|
||||
private func position(_ name: String) -> CGPoint {
|
||||
positions[name] ?? CGPoint(x: 30, y: 30)
|
||||
}
|
||||
private func center(_ name: String, right: Bool) -> CGPoint {
|
||||
let p = position(name)
|
||||
return CGPoint(x: p.x + (right ? nodeWidth : 0), y: p.y + min(height(name), 260) / 2)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
// Two compact toolbar rows avoid the truncated controls shown in the original sheet.
|
||||
HStack(spacing: 10) {
|
||||
Label(database, systemImage: "point.3.connected.trianglepath.dotted")
|
||||
.font(.headline).lineLimit(1)
|
||||
Text("SCHEMA DESIGNER").font(.caption2.weight(.semibold)).foregroundStyle(.secondary)
|
||||
Spacer(minLength: 12)
|
||||
Button("Close", systemImage: "xmark") { savePositions(); saveOptions(); onClose() }
|
||||
.labelStyle(.iconOnly).help("Close diagram")
|
||||
.keyboardShortcut(.cancelAction)
|
||||
}
|
||||
.padding(.horizontal, 16).padding(.top, 12).padding(.bottom, 8)
|
||||
HStack(spacing: 10) {
|
||||
Picker("Diagram", selection: $diagramName) {
|
||||
ForEach(diagrams, id: \.self) { Text($0).tag($0) }
|
||||
}
|
||||
.frame(width: 175)
|
||||
.onChange(of: diagramName) { oldValue, _ in
|
||||
savePositions(named: oldValue)
|
||||
positions = [:]
|
||||
restorePositions()
|
||||
restoreOptions()
|
||||
if positions.isEmpty { arrange() }
|
||||
}
|
||||
Button { showingNewDiagram = true } label: { Image(systemName: "plus") }
|
||||
.help("New diagram")
|
||||
Button { showingDeleteConfirmation = true } label: { Image(systemName: "trash") }
|
||||
.disabled(diagrams.count <= 1).help("Delete diagram")
|
||||
Divider().frame(height: 18)
|
||||
Button { showingObjects.toggle() } label: {
|
||||
Label("Tables", systemImage: "sidebar.left")
|
||||
}.help("Show or hide the table selection sidebar")
|
||||
TextField("Find table or view", text: $search)
|
||||
.textFieldStyle(.roundedBorder).frame(minWidth: 130, idealWidth: 220, maxWidth: 260)
|
||||
Toggle("Views", isOn: $showViews).toggleStyle(.checkbox)
|
||||
Toggle("Related", isOn: $relatedOnly).toggleStyle(.checkbox)
|
||||
Spacer(minLength: 8)
|
||||
Menu {
|
||||
ForEach(["Ocean", "Slate", "Forest", "Plum"], id: \.self) { option in
|
||||
Button { theme = option; saveOptions() } label: {
|
||||
if theme == option { Label(option, systemImage: "checkmark") }
|
||||
else { Text(option) }
|
||||
}
|
||||
}
|
||||
} label: { Label("Colours", systemImage: "paintpalette") }
|
||||
Menu {
|
||||
Toggle("Show all columns", isOn: $showAllColumns)
|
||||
Button("Auto Layout") { arrange(); savePositions() }
|
||||
Button("Refresh Metadata") { model.introspect(database: database); loadRelationships() }
|
||||
} label: { Label("Layout", systemImage: "slider.horizontal.3") }
|
||||
Button { zoom = max(0.4, zoom - 0.15) } label: { Image(systemName: "minus.magnifyingglass") }
|
||||
Text("\(Int(zoom * 100))%").monospacedDigit().frame(width: 45)
|
||||
Button { zoom = min(2, zoom + 0.15) } label: { Image(systemName: "plus.magnifyingglass") }
|
||||
Menu {
|
||||
Button("Export PDF…") { exportDiagram(.pdf) }
|
||||
Button("Export PNG…") { exportDiagram(.png) }
|
||||
Button("Export SVG…") { exportDiagram(.svg) }
|
||||
Divider()
|
||||
Button("Print…") { printDiagram() }
|
||||
} label: { Label("Export / Print", systemImage: "square.and.arrow.up") }
|
||||
}
|
||||
.controlSize(.small)
|
||||
.padding(.horizontal, 16).padding(.bottom, 12)
|
||||
Divider()
|
||||
HStack(spacing: 0) {
|
||||
if showingObjects {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack {
|
||||
Text("OBJECTS").font(.caption.weight(.semibold)).foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Text("\(includedObjects.count)/\(allObjects.count)")
|
||||
.font(.caption.monospacedDigit()).foregroundStyle(.secondary)
|
||||
}
|
||||
HStack {
|
||||
Button("All") { updateIncludedObjects(Set(allObjects)) }
|
||||
Button("None") { updateIncludedObjects([]) }
|
||||
Spacer()
|
||||
}.buttonStyle(.link)
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .leading, spacing: 5) {
|
||||
ForEach(allObjects.filter { search.isEmpty || $0.localizedCaseInsensitiveContains(search) }, id: \.self) { name in
|
||||
Toggle(isOn: Binding(
|
||||
get: { includedObjects.contains(name) },
|
||||
set: { enabled in
|
||||
var updated = includedObjects
|
||||
if enabled { updated.insert(name) }
|
||||
else { updated.remove(name) }
|
||||
updateIncludedObjects(updated)
|
||||
})) {
|
||||
Label(name, systemImage: snapshot?.views.contains(name) == true ? "eye" : "tablecells")
|
||||
.lineLimit(1).font(.system(size: 12))
|
||||
}.toggleStyle(.checkbox)
|
||||
}
|
||||
}.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
.padding(12).frame(width: 235)
|
||||
.background(Color(nsColor: .controlBackgroundColor))
|
||||
Divider()
|
||||
}
|
||||
VStack(spacing: 0) {
|
||||
if snapshot == nil {
|
||||
ContentUnavailableView("No Introspection Data", systemImage: "externaldrive.badge.questionmark", description: Text("Run Introspection on this database to load tables and views."))
|
||||
Button("Introspect Now") { model.introspect(database: database); loadRelationships() }.padding()
|
||||
} else {
|
||||
ScrollView([.horizontal, .vertical]) {
|
||||
ZStack(alignment: .topLeading) {
|
||||
Canvas { context, _ in
|
||||
for relation in relations where objects.contains(relation.from) && objects.contains(relation.to) {
|
||||
let a = position(relation.from)
|
||||
let b = position(relation.to)
|
||||
let right = a.x <= b.x
|
||||
let start = center(relation.from, right: right)
|
||||
let end = center(relation.to, right: !right)
|
||||
let bend: CGFloat = right ? 65 : -65
|
||||
var path = Path()
|
||||
path.move(to: start)
|
||||
path.addCurve(to: end,
|
||||
control1: CGPoint(x: start.x + bend, y: start.y),
|
||||
control2: CGPoint(x: end.x - bend, y: end.y))
|
||||
context.stroke(path, with: .color(.accentColor.opacity(0.7)), lineWidth: 1.7)
|
||||
}
|
||||
}
|
||||
ForEach(objects, id: \.self) { name in
|
||||
DiagramDraggableNode(zoom: zoom, onDrop: { translation in
|
||||
let start = position(name)
|
||||
positions[name] = CGPoint(
|
||||
x: max(10, start.x + translation.width / max(zoom, 0.1)),
|
||||
y: max(10, start.y + translation.height / max(zoom, 0.1)))
|
||||
savePositions()
|
||||
}) {
|
||||
diagramNode(name)
|
||||
}
|
||||
.position(x: position(name).x + nodeWidth / 2,
|
||||
y: position(name).y + height(name) / 2)
|
||||
}
|
||||
}
|
||||
.frame(width: canvasWidth, height: canvasHeight, alignment: .topLeading)
|
||||
.scaleEffect(zoom, anchor: .topLeading)
|
||||
.frame(width: canvasWidth * zoom, height: canvasHeight * zoom, alignment: .topLeading)
|
||||
}
|
||||
.background(Color(nsColor: .textBackgroundColor))
|
||||
.id(selectionRevision)
|
||||
.onChange(of: snapshot?.loadedAt) { _, _ in
|
||||
if UserDefaults.standard.stringArray(forKey: selectionKey) == nil {
|
||||
includedObjects = Set(allObjects)
|
||||
}
|
||||
if positions.isEmpty { arrange() }
|
||||
loadRelationships()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
HStack {
|
||||
Text("\(snapshot?.tables.count ?? 0) tables · \(snapshot?.views.count ?? 0) views · \(relations.count) foreign-key relationships")
|
||||
if loadingRelationships { ProgressView().controlSize(.small) }
|
||||
if let errorMessage { Text(errorMessage).foregroundStyle(.secondary).lineLimit(1) }
|
||||
Spacer()
|
||||
Text("Drag tables to arrange · Select to highlight relationships")
|
||||
}
|
||||
.font(.caption)
|
||||
.padding(9)
|
||||
}
|
||||
.frame(minWidth: 850, idealWidth: 1320, minHeight: 570, idealHeight: 850)
|
||||
.background(DiagramResizableWindow())
|
||||
.onAppear { loadCatalog(); restorePositions(); restoreOptions(); if positions.isEmpty { arrange() }; loadRelationships() }
|
||||
.onDisappear { savePositions(); saveOptions() }
|
||||
.alert("New Schema Diagram", isPresented: $showingNewDiagram) {
|
||||
TextField("Diagram name", text: $newDiagramName)
|
||||
Button("Create") { createDiagram() }
|
||||
Button("Cancel", role: .cancel) { }
|
||||
} message: { Text("Create a separate saved layout for this database.") }
|
||||
.confirmationDialog("Delete \(diagramName)?", isPresented: $showingDeleteConfirmation) {
|
||||
Button("Delete Diagram", role: .destructive) { deleteDiagram() }
|
||||
} message: { Text("Only the saved diagram layout is removed. Database objects are not changed.") }
|
||||
.alert("Diagram Export", isPresented: $showingExportError) {
|
||||
Button("OK", role: .cancel) { }
|
||||
} message: { Text(exportError ?? "Unable to export diagram") }
|
||||
}
|
||||
|
||||
private var canvasWidth: CGFloat {
|
||||
max(1200, objects.map { position($0).x + nodeWidth + 80 }.max() ?? 1200)
|
||||
}
|
||||
private var canvasHeight: CGFloat {
|
||||
max(800, objects.map { position($0).y + height($0) + 80 }.max() ?? 800)
|
||||
}
|
||||
|
||||
private func diagramNode(_ name: String) -> some View {
|
||||
let isView = snapshot?.views.contains(name) == true
|
||||
let related = selectedObject == nil || selectedObject == name || relations.contains { ($0.from == selectedObject && $0.to == name) || ($0.to == selectedObject && $0.from == name) }
|
||||
return VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(spacing: 7) {
|
||||
Image(systemName: isView ? "eye" : "tablecells")
|
||||
Text(name).fontWeight(.semibold).lineLimit(1)
|
||||
Spacer()
|
||||
if isView { Text("VIEW").font(.system(size: 9, weight: .bold)) }
|
||||
}
|
||||
.font(.system(size: 12))
|
||||
.padding(.horizontal, 10)
|
||||
.frame(height: headerHeight)
|
||||
.foregroundStyle(.white)
|
||||
.background(isView ? nodeColor.opacity(0.76) : nodeColor)
|
||||
ForEach(Array(columns(name).prefix(maxColumns)), id: \.id) { column in
|
||||
HStack(spacing: 5) {
|
||||
Image(systemName: column.key == "PRI" ? "key.fill" : "circle.fill")
|
||||
.font(.system(size: column.key == "PRI" ? 10 : 4))
|
||||
.foregroundStyle(column.key == "PRI" ? Color.orange : Color.secondary)
|
||||
.frame(width: 13)
|
||||
Text(column.name).lineLimit(1)
|
||||
Spacer(minLength: 4)
|
||||
Text(column.dataType).foregroundStyle(.secondary).lineLimit(1)
|
||||
}
|
||||
.font(.system(size: 10))
|
||||
.padding(.horizontal, 9)
|
||||
.frame(height: rowHeight)
|
||||
}
|
||||
if columns(name).count > maxColumns {
|
||||
Text("+ \(columns(name).count - maxColumns) more columns")
|
||||
.font(.caption2).foregroundStyle(.secondary).padding(.horizontal, 10)
|
||||
}
|
||||
Spacer(minLength: 5)
|
||||
}
|
||||
.frame(width: nodeWidth, height: height(name))
|
||||
.background(Color(nsColor: .controlBackgroundColor))
|
||||
.clipShape(RoundedRectangle(cornerRadius: 7))
|
||||
.overlay(RoundedRectangle(cornerRadius: 7).stroke(selectedObject == name ? Color.accentColor : Color(nsColor: .separatorColor), lineWidth: selectedObject == name ? 2.5 : 1))
|
||||
.shadow(color: .black.opacity(0.13), radius: 3, y: 2)
|
||||
.opacity(related ? 1 : 0.4)
|
||||
.onTapGesture { selectedObject = selectedObject == name ? nil : name }
|
||||
}
|
||||
|
||||
// Rebuild the visible canvas whenever the selected objects change. The
|
||||
// previous implementation only saved the checkboxes, leaving the diagram
|
||||
// scrolled to stale positions after None / All / individual selections.
|
||||
private func updateIncludedObjects(_ updated: Set<String>) {
|
||||
let valid = DiagramLogic.selectedObjects(updated, available: allObjects)
|
||||
guard valid != includedObjects else { return }
|
||||
includedObjects = valid
|
||||
if let selectedObject, !valid.contains(selectedObject) {
|
||||
self.selectedObject = nil
|
||||
}
|
||||
// Keep the selected subset compact, rather than retaining the old
|
||||
// coordinates of objects from a much larger diagram.
|
||||
arrange()
|
||||
savePositions()
|
||||
saveOptions()
|
||||
selectionRevision += 1
|
||||
}
|
||||
|
||||
private func arrange() {
|
||||
let names = allObjects.filter { includedObjects.contains($0) }
|
||||
positions.merge(DiagramLogic.arrangedPositions(names)) { _, latest in latest }
|
||||
}
|
||||
private func loadCatalog() {
|
||||
let stored = UserDefaults.standard.stringArray(forKey: catalogKey) ?? ["Main"]
|
||||
diagrams = stored.isEmpty ? ["Main"] : stored
|
||||
if !diagrams.contains(diagramName) { diagramName = diagrams[0] }
|
||||
}
|
||||
private func createDiagram() {
|
||||
let name = newDiagramName.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !name.isEmpty, !diagrams.contains(name) else { return }
|
||||
savePositions()
|
||||
diagrams.append(name)
|
||||
UserDefaults.standard.set(diagrams, forKey: catalogKey)
|
||||
diagramName = name
|
||||
newDiagramName = ""
|
||||
}
|
||||
private func deleteDiagram() {
|
||||
guard diagrams.count > 1 else { return }
|
||||
UserDefaults.standard.removeObject(forKey: storageKey)
|
||||
diagrams.removeAll { $0 == diagramName }
|
||||
UserDefaults.standard.set(diagrams, forKey: catalogKey)
|
||||
diagramName = diagrams[0]
|
||||
}
|
||||
private func savePositions(named name: String) {
|
||||
let points = positions.mapValues { DiagramPoint(x: Double($0.x), y: Double($0.y)) }
|
||||
if let data = try? JSONEncoder().encode(points) {
|
||||
UserDefaults.standard.set(data, forKey: "\(diagramNamespace).layout.\(name)")
|
||||
}
|
||||
}
|
||||
private func savePositions() { savePositions(named: diagramName) }
|
||||
private func restorePositions() {
|
||||
guard let data = UserDefaults.standard.data(forKey: storageKey),
|
||||
let saved = try? JSONDecoder().decode([String: DiagramPoint].self, from: data) else { return }
|
||||
positions = saved.mapValues { CGPoint(x: $0.x, y: $0.y) }
|
||||
}
|
||||
private func loadRelationships() {
|
||||
guard let profile = model.selected else { return }
|
||||
loadingRelationships = true
|
||||
errorMessage = nil
|
||||
let password = PasswordStore.read(profile.id)
|
||||
let escaped = database.replacingOccurrences(of: "'", with: "''")
|
||||
Task {
|
||||
do {
|
||||
let result = try await NativeMySQLRunner.run(profile: profile, database: database, password: password,
|
||||
sql: "SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '\(escaped)' AND REFERENCED_TABLE_NAME IS NOT NULL ORDER BY TABLE_NAME, ORDINAL_POSITION")
|
||||
guard model.selected?.id == profile.id else { loadingRelationships = false; return }
|
||||
relations = result.rows.compactMap { row in
|
||||
guard row.count >= 4 else { return nil }
|
||||
return DiagramRelation(from: row[0], column: row[1], to: row[2], targetColumn: row[3])
|
||||
}
|
||||
} catch {
|
||||
errorMessage = "Foreign keys unavailable: \(error.localizedDescription)"
|
||||
}
|
||||
loadingRelationships = false
|
||||
}
|
||||
}
|
||||
private enum DiagramFormat: Equatable { case pdf, png, svg }
|
||||
|
||||
private func printLayout() -> SchemaDiagramPrintView {
|
||||
let entries = objects.map { name in
|
||||
SchemaDiagramPrintView.Entry(name: name,
|
||||
isView: snapshot?.views.contains(name) == true,
|
||||
columns: columns(name).map { .init(name: $0.name, type: $0.dataType, primary: $0.key == "PRI") },
|
||||
origin: position(name))
|
||||
}
|
||||
let links = relations.filter { objects.contains($0.from) && objects.contains($0.to) }
|
||||
.map { SchemaDiagramPrintView.Link(from: $0.from, to: $0.to, column: $0.column, target: $0.targetColumn) }
|
||||
return SchemaDiagramPrintView(database: database, diagram: diagramName, entries: entries, links: links, theme: theme)
|
||||
}
|
||||
|
||||
private func exportDiagram(_ format: DiagramFormat) {
|
||||
let panel = NSSavePanel()
|
||||
panel.title = "Export Schema Diagram"
|
||||
panel.nameFieldStringValue = "\(database)-\(diagramName).\(format == .pdf ? "pdf" : format == .png ? "png" : "svg")"
|
||||
panel.canCreateDirectories = true
|
||||
guard panel.runModal() == .OK, let url = panel.url else { return }
|
||||
do {
|
||||
let view = printLayout()
|
||||
let data: Data
|
||||
switch format {
|
||||
case .pdf: data = view.dataWithPDF(inside: view.bounds)
|
||||
case .png:
|
||||
guard let bitmap = view.bitmapImageRepForCachingDisplay(in: view.bounds) else {
|
||||
throw NSError(domain: "DBSynDiagram", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unable to create bitmap"])
|
||||
}
|
||||
view.cacheDisplay(in: view.bounds, to: bitmap)
|
||||
guard let png = bitmap.representation(using: .png, properties: [:]) else {
|
||||
throw NSError(domain: "DBSynDiagram", code: 2, userInfo: [NSLocalizedDescriptionKey: "Unable to encode PNG"])
|
||||
}
|
||||
data = png
|
||||
case .svg: data = Data(view.svgDocument().utf8)
|
||||
}
|
||||
try data.write(to: url, options: .atomic)
|
||||
} catch {
|
||||
exportError = error.localizedDescription
|
||||
showingExportError = true
|
||||
}
|
||||
}
|
||||
|
||||
private func printDiagram() {
|
||||
let view = printLayout()
|
||||
guard let info = NSPrintInfo.shared.copy() as? NSPrintInfo else { return }
|
||||
info.horizontalPagination = .fit
|
||||
info.verticalPagination = .fit
|
||||
info.isHorizontallyCentered = true
|
||||
info.isVerticallyCentered = true
|
||||
info.orientation = view.bounds.width > view.bounds.height ? .landscape : .portrait
|
||||
NSPrintOperation(view: view, printInfo: info).run()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Allows the schema designer sheet to be resized rather than locking its initial dimensions.
|
||||
private struct DiagramResizableWindow: NSViewRepresentable {
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
let view = NSView(frame: .zero)
|
||||
DispatchQueue.main.async { [weak view] in
|
||||
guard let window = view?.window else { return }
|
||||
window.styleMask.insert(.resizable)
|
||||
window.minSize = NSSize(width: 850, height: 570)
|
||||
}
|
||||
return view
|
||||
}
|
||||
func updateNSView(_ nsView: NSView, context: Context) { }
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import XCTest
|
||||
@testable import DBSyn
|
||||
|
||||
final class DBSynTests: XCTestCase {
|
||||
func testSQLSplitsMultipleStatements() {
|
||||
XCTAssertEqual(SQLStatementSplitter.split("USE AAMEDIUK; SELECT * FROM ADCUSERS;"),
|
||||
["USE AAMEDIUK", "SELECT * FROM ADCUSERS"])
|
||||
}
|
||||
|
||||
func testSQLSplitterPreservesQuotedSemicolons() {
|
||||
XCTAssertEqual(SQLStatementSplitter.split("SELECT 'a;b'; SELECT `a;b` FROM t;"),
|
||||
["SELECT 'a;b'", "SELECT `a;b` FROM t"])
|
||||
}
|
||||
|
||||
func testSQLSplitterIgnoresComments() {
|
||||
XCTAssertEqual(SQLStatementSplitter.split("# comment;\nUSE db; /* comment; */ SELECT 1;"),
|
||||
["USE db", "SELECT 1"])
|
||||
}
|
||||
|
||||
func testSQLSplitterIgnoresEmptyStatements() {
|
||||
XCTAssertEqual(SQLStatementSplitter.split(";; SELECT 1;;;"), ["SELECT 1"])
|
||||
}
|
||||
|
||||
func testUSEDatabaseUnquoted() {
|
||||
XCTAssertEqual(SQLStatementSplitter.usedDatabase("USE AAMEDIUK"), "AAMEDIUK")
|
||||
}
|
||||
|
||||
func testUSEDatabaseQuoted() {
|
||||
XCTAssertEqual(SQLStatementSplitter.usedDatabase("USE `my``db`"), "my`db")
|
||||
}
|
||||
|
||||
func testUSEDatabaseRejectsOtherStatements() {
|
||||
XCTAssertNil(SQLStatementSplitter.usedDatabase("SELECT * FROM ADCUSERS"))
|
||||
}
|
||||
|
||||
func testSQLFormatterUppercasesKeywords() {
|
||||
XCTAssertEqual(SQLFormatter.uppercaseKeywords("select * from ADCUSERS where id = 1"),
|
||||
"SELECT * FROM ADCUSERS WHERE id = 1")
|
||||
}
|
||||
|
||||
func testSQLFormatterPreservesStringLiteralsAndComments() {
|
||||
let input = "select 'select from' # select stays lower\nfrom users"
|
||||
XCTAssertEqual(SQLFormatter.uppercaseKeywords(input),
|
||||
"SELECT 'select from' # select stays lower\nFROM users")
|
||||
}
|
||||
|
||||
func testConnectionProfileCodableRoundTrip() throws {
|
||||
var profile = ConnectionProfile()
|
||||
profile.name = "Development"
|
||||
profile.database = "AAMEDIUK"
|
||||
let decoded = try JSONDecoder().decode(ConnectionProfile.self, from: JSONEncoder().encode(profile))
|
||||
XCTAssertEqual(decoded, profile)
|
||||
}
|
||||
|
||||
func testIntrospectionCacheCodableRoundTrip() throws {
|
||||
let connectionID = UUID()
|
||||
let column = DatabaseModel.IntrospectedColumn(table: "ADCUSERS", name: "id", dataType: "bigint", nullable: false, key: "PRI", defaultValue: nil, extra: "auto_increment")
|
||||
let snapshot = DatabaseModel.SchemaIntrospection(connectionID: connectionID, database: "AAMEDIUK", loadedAt: Date(timeIntervalSince1970: 1000), tables: ["ADCUSERS"], views: ["ACTIVE_USERS"], columnsByTable: ["ADCUSERS": [column]])
|
||||
let decoded = try JSONDecoder().decode(DatabaseModel.SchemaIntrospection.self, from: JSONEncoder().encode(snapshot))
|
||||
XCTAssertEqual(decoded.connectionID, connectionID)
|
||||
XCTAssertEqual(decoded.database, "AAMEDIUK")
|
||||
XCTAssertEqual(decoded.tables, ["ADCUSERS"])
|
||||
XCTAssertEqual(decoded.views, ["ACTIVE_USERS"])
|
||||
XCTAssertEqual(decoded.columnsByTable["ADCUSERS"]?.first?.name, "id")
|
||||
}
|
||||
|
||||
func testDiagramSelectNone() {
|
||||
XCTAssertEqual(DiagramLogic.selectedObjects([], available: ["A", "B"]), [])
|
||||
}
|
||||
|
||||
func testDiagramSelectSubsetAndIgnoreRemovedObjects() {
|
||||
XCTAssertEqual(DiagramLogic.selectedObjects(["A", "MISSING"], available: ["A", "B"]), ["A"])
|
||||
}
|
||||
|
||||
func testDiagramSelectAll() {
|
||||
let available = ["A", "B", "VIEW_C"]
|
||||
XCTAssertEqual(DiagramLogic.selectedObjects(Set(available), available: available), Set(available))
|
||||
}
|
||||
|
||||
func testDiagramLayoutContainsEverySelectedTable() {
|
||||
let names = (0..<25).map { "table_\($0)" }
|
||||
let positions = DiagramLogic.arrangedPositions(names)
|
||||
XCTAssertEqual(positions.count, names.count)
|
||||
XCTAssertEqual(positions["table_0"], CGPoint(x: 30, y: 30))
|
||||
XCTAssertEqual(Set(positions.values.map { "\($0.x),\($0.y)" }).count, names.count)
|
||||
}
|
||||
|
||||
func testDiagramDragRespectsZoom() {
|
||||
let origin = CGPoint(x: 100, y: 200)
|
||||
XCTAssertEqual(DiagramLogic.translatedPosition(origin, translation: CGSize(width: 60, height: -40), zoom: 2),
|
||||
CGPoint(x: 130, y: 180))
|
||||
}
|
||||
|
||||
func testDiagramDragHandlesZeroZoom() {
|
||||
let point = DiagramLogic.translatedPosition(.zero, translation: CGSize(width: 10, height: 5), zoom: 0)
|
||||
XCTAssertTrue(point.x.isFinite && point.y.isFinite)
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 56;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
000000000000000000000013 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000010 /* App.swift */; };
|
||||
000000000000000000000014 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000011 /* MainView.swift */; };
|
||||
000000000000000000000015 /* DatabaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000012 /* DatabaseModel.swift */; };
|
||||
000000000000000000000017 /* MySQLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000016 /* MySQLProtocol.swift */; };
|
||||
|
||||
A10000000000000000000003 /* WorkbenchReplacement.icns in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000001 /* WorkbenchReplacement.icns */; };
|
||||
A10000000000000000000004 /* WorkbenchBrand.png in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000002 /* WorkbenchBrand.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00000000000000000000000F /* WorkbenchReplacement.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WorkbenchReplacement.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
000000000000000000000010 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000011 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000012 /* DatabaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseModel.swift; sourceTree = "<group>"; };
|
||||
000000000000000000000016 /* MySQLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySQLProtocol.swift; sourceTree = "<group>"; };
|
||||
|
||||
A10000000000000000000001 /* WorkbenchReplacement.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = WorkbenchReplacement.icns; sourceTree = "<group>"; };
|
||||
A10000000000000000000002 /* WorkbenchBrand.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = WorkbenchBrand.png; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
000000000000000000000008 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
000000000000000000000002 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
000000000000000000000003 /* WorkbenchReplacement */,
|
||||
000000000000000000000004 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
000000000000000000000003 /* WorkbenchReplacement */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
000000000000000000000010 /* App.swift */,
|
||||
000000000000000000000011 /* MainView.swift */,
|
||||
000000000000000000000012 /* DatabaseModel.swift */,
|
||||
000000000000000000000016 /* MySQLProtocol.swift */,
|
||||
|
||||
A10000000000000000000005 /* Resources */,);
|
||||
path = WorkbenchReplacement;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
000000000000000000000004 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00000000000000000000000F /* WorkbenchReplacement.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
||||
A10000000000000000000005 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A10000000000000000000001 /* WorkbenchReplacement.icns */,
|
||||
A10000000000000000000002 /* WorkbenchBrand.png */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
000000000000000000000005 /* WorkbenchReplacement */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00000000000000000000000A /* Build configuration list for PBXNativeTarget "WorkbenchReplacement" */;
|
||||
buildPhases = (
|
||||
000000000000000000000006 /* Sources */,
|
||||
000000000000000000000008 /* Frameworks */,
|
||||
000000000000000000000007 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = WorkbenchReplacement;
|
||||
productName = WorkbenchReplacement;
|
||||
productReference = 00000000000000000000000F /* WorkbenchReplacement.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
000000000000000000000001 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1600;
|
||||
TargetAttributes = {
|
||||
000000000000000000000005 = {
|
||||
CreatedOnToolsVersion = 16.0;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 000000000000000000000009 /* Build configuration list for PBXProject "WorkbenchReplacement" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 000000000000000000000002;
|
||||
productRefGroup = 000000000000000000000004 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
000000000000000000000005 /* WorkbenchReplacement */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
000000000000000000000007 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
||||
A10000000000000000000003 /* WorkbenchReplacement.icns in Resources */,
|
||||
A10000000000000000000004 /* WorkbenchBrand.png in Resources */,);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
000000000000000000000006 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
000000000000000000000013 /* App.swift in Sources */,
|
||||
000000000000000000000014 /* MainView.swift in Sources */,
|
||||
000000000000000000000015 /* DatabaseModel.swift in Sources */,
|
||||
000000000000000000000017 /* MySQLProtocol.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00000000000000000000000B /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00000000000000000000000C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 15.0;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
00000000000000000000000D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 39R6U3437D;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Workbench Replacement";
|
||||
INFOPLIST_KEY_CFBundleIconFile = WorkbenchReplacement;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.absdev.WorkbenchReplacement;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00000000000000000000000E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 39R6U3437D;
|
||||
ENABLE_APP_SANDBOX = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Workbench Replacement";
|
||||
INFOPLIST_KEY_CFBundleIconFile = WorkbenchReplacement;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.absdev.WorkbenchReplacement;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
000000000000000000000009 /* Build configuration list for PBXProject "WorkbenchReplacement" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00000000000000000000000B /* Debug */,
|
||||
00000000000000000000000C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
00000000000000000000000A /* Build configuration list for PBXNativeTarget "WorkbenchReplacement" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00000000000000000000000D /* Debug */,
|
||||
00000000000000000000000E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 000000000000000000000001 /* Project object */;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,429 +0,0 @@
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct WorkbenchReplacementApp: App {
|
||||
@StateObject private var model = DatabaseModel()
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup("Workbench Replacement") {
|
||||
WorkbenchLaunchView()
|
||||
.environmentObject(model)
|
||||
.frame(minWidth: 800, minHeight: 520)
|
||||
}
|
||||
.defaultSize(width: 1200, height: 800)
|
||||
.windowResizability(.contentSize)
|
||||
.commands {
|
||||
WorkbenchFileCommands(model: model)
|
||||
}
|
||||
|
||||
|
||||
Settings {
|
||||
WorkbenchSettingsView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Application Preferences
|
||||
|
||||
@MainActor
|
||||
final class WorkbenchPreferences: ObservableObject {
|
||||
static let shared = WorkbenchPreferences()
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.appearance")
|
||||
var appearance = "light"
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
var autoExpandTables = true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Settings
|
||||
|
||||
struct WorkbenchSettingsView: View {
|
||||
|
||||
@AppStorage("preferences.editorFontSize")
|
||||
private var editorFontSize = 13.0
|
||||
|
||||
@AppStorage("preferences.uppercaseKeywords")
|
||||
private var uppercaseKeywords = true
|
||||
|
||||
@AppStorage("preferences.showLineNumbers")
|
||||
private var showLineNumbers = true
|
||||
|
||||
@AppStorage("preferences.tabWidth")
|
||||
private var tabWidth = 4
|
||||
|
||||
@AppStorage("preferences.defaultRowLimit")
|
||||
private var defaultRowLimit = 500
|
||||
|
||||
@AppStorage("preferences.resultRowHeight")
|
||||
private var resultRowHeight = 24.0
|
||||
|
||||
@AppStorage("preferences.resultColumnWidth")
|
||||
private var resultColumnWidth = 170.0
|
||||
|
||||
@AppStorage("preferences.alternatingRows")
|
||||
private var alternatingRows = true
|
||||
|
||||
@AppStorage("preferences.autoExpandTables")
|
||||
private var autoExpandTables = true
|
||||
|
||||
var body: some View {
|
||||
TabView {
|
||||
|
||||
editorSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"SQL Editor",
|
||||
systemImage: "chevron.left.forwardslash.chevron.right"
|
||||
)
|
||||
}
|
||||
|
||||
executionSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"Query Execution",
|
||||
systemImage: "bolt"
|
||||
)
|
||||
}
|
||||
|
||||
resultSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"Result Grid",
|
||||
systemImage: "tablecells"
|
||||
)
|
||||
}
|
||||
|
||||
generalSettings
|
||||
.tabItem {
|
||||
Label(
|
||||
"General",
|
||||
systemImage: "gearshape"
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(width: 620, height: 390)
|
||||
.preferredColorScheme(.light)
|
||||
}
|
||||
|
||||
private var editorSettings: some View {
|
||||
settingsPage("SQL Editor") {
|
||||
|
||||
settingsRow("Font Size") {
|
||||
Stepper(
|
||||
"\(Int(editorFontSize)) pt",
|
||||
value: $editorFontSize,
|
||||
in: 10...24,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Tab Width") {
|
||||
Picker("", selection: $tabWidth) {
|
||||
Text("2 spaces").tag(2)
|
||||
Text("4 spaces").tag(4)
|
||||
Text("8 spaces").tag(8)
|
||||
}
|
||||
.labelsHidden()
|
||||
.frame(width: 150)
|
||||
}
|
||||
|
||||
settingsRow("SQL Formatting") {
|
||||
Toggle(
|
||||
"Automatically uppercase SQL keywords",
|
||||
isOn: $uppercaseKeywords
|
||||
)
|
||||
}
|
||||
|
||||
settingsRow("Editor Display") {
|
||||
Toggle(
|
||||
"Show line numbers",
|
||||
isOn: $showLineNumbers
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var executionSettings: some View {
|
||||
settingsPage("Query Execution") {
|
||||
|
||||
settingsRow("Default Row Limit") {
|
||||
HStack(spacing: 12) {
|
||||
TextField(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
format: .number
|
||||
)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.frame(width: 110)
|
||||
|
||||
Stepper(
|
||||
"",
|
||||
value: $defaultRowLimit,
|
||||
in: 50...100000,
|
||||
step: 50
|
||||
)
|
||||
.labelsHidden()
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
"Controls the number of rows retrieved when opening a table from the schema navigator."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.leading, 190)
|
||||
|
||||
Divider()
|
||||
.padding(.vertical, 12)
|
||||
|
||||
Text("Examples")
|
||||
.font(.headline)
|
||||
|
||||
Text(
|
||||
"500 rows: Faster browsing and lower memory usage.\n" +
|
||||
"5,000 rows: Useful for larger datasets.\n" +
|
||||
"50,000 rows: May take longer to retrieve."
|
||||
)
|
||||
.font(.system(size: 12))
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
}
|
||||
|
||||
private var resultSettings: some View {
|
||||
settingsPage("Result Grid") {
|
||||
|
||||
settingsRow("Row Height") {
|
||||
Stepper(
|
||||
"\(Int(resultRowHeight)) px",
|
||||
value: $resultRowHeight,
|
||||
in: 18...40,
|
||||
step: 1
|
||||
)
|
||||
.frame(width: 130)
|
||||
}
|
||||
|
||||
settingsRow("Column Width") {
|
||||
Stepper(
|
||||
"\(Int(resultColumnWidth)) px",
|
||||
value: $resultColumnWidth,
|
||||
in: 80...400,
|
||||
step: 10
|
||||
)
|
||||
.frame(width: 140)
|
||||
}
|
||||
|
||||
settingsRow("Appearance") {
|
||||
Toggle(
|
||||
"Alternating row colours",
|
||||
isOn: $alternatingRows
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var generalSettings: some View {
|
||||
settingsPage("General") {
|
||||
|
||||
settingsRow("Navigator") {
|
||||
Toggle(
|
||||
"Automatically expand table folders",
|
||||
isOn: $autoExpandTables
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func settingsPage<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 20, weight: .semibold))
|
||||
|
||||
Divider()
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding(26)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color(nsColor: .windowBackgroundColor))
|
||||
}
|
||||
|
||||
private func settingsRow<Content: View>(
|
||||
_ title: String,
|
||||
@ViewBuilder content: () -> Content
|
||||
) -> some View {
|
||||
|
||||
HStack(alignment: .center, spacing: 16) {
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 13))
|
||||
.frame(width: 170, alignment: .trailing)
|
||||
|
||||
content()
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.frame(height: 30)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench Splash Screen
|
||||
|
||||
struct WorkbenchLaunchView: View {
|
||||
@State private var showingSplash = true
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
MainView()
|
||||
|
||||
if showingSplash {
|
||||
WorkbenchSplashView()
|
||||
.transition(.opacity)
|
||||
.zIndex(10)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
try? await Task.sleep(for: .seconds(3))
|
||||
|
||||
withAnimation(.easeOut(duration: 0.4)) {
|
||||
showingSplash = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkbenchSplashView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 20) {
|
||||
Spacer()
|
||||
|
||||
if let path = Bundle.main.path(
|
||||
forResource: "WorkbenchBrand",
|
||||
ofType: "png"
|
||||
), let image = NSImage(contentsOfFile: path) {
|
||||
Image(nsImage: image)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 160, height: 160)
|
||||
}
|
||||
|
||||
Text("Workbench Replacement")
|
||||
.font(.system(size: 30, weight: .bold))
|
||||
|
||||
Text("Modern MySQL Client for macOS")
|
||||
.font(.system(size: 15))
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
HStack(spacing: 30) {
|
||||
feature("cylinder.split.1x2", "Schemas")
|
||||
feature("chevron.left.forwardslash.chevron.right", "SQL Editor")
|
||||
feature("tablecells", "Result Grid")
|
||||
feature("server.rack", "Connections")
|
||||
}
|
||||
.padding(.top, 20)
|
||||
|
||||
Spacer()
|
||||
|
||||
ProgressView()
|
||||
.frame(width: 260)
|
||||
|
||||
Text("Starting Workbench Replacement…")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.bottom, 30)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(
|
||||
LinearGradient(
|
||||
colors: [
|
||||
Color(red: 0.96, green: 0.98, blue: 1),
|
||||
Color(red: 0.88, green: 0.93, blue: 1)
|
||||
],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
.preferredColorScheme(.light)
|
||||
}
|
||||
|
||||
private func feature(_ symbol: String, _ title: String) -> some View {
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: symbol)
|
||||
.font(.system(size: 24))
|
||||
.foregroundStyle(.blue)
|
||||
|
||||
Text(title)
|
||||
.font(.system(size: 12))
|
||||
}
|
||||
.frame(width: 90)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Workbench File Menu
|
||||
|
||||
struct WorkbenchFileCommands: Commands {
|
||||
@ObservedObject var model: DatabaseModel
|
||||
|
||||
var body: some Commands {
|
||||
CommandGroup(replacing: .newItem) {
|
||||
Button("New Query Tab") {
|
||||
model.newQueryTab()
|
||||
}
|
||||
.keyboardShortcut("t", modifiers: .command)
|
||||
}
|
||||
|
||||
CommandGroup(after: .newItem) {
|
||||
Button("Open SQL Script…") {
|
||||
model.openSQLScript()
|
||||
}
|
||||
.keyboardShortcut("o", modifiers: .command)
|
||||
|
||||
Divider()
|
||||
|
||||
Button("Save SQL Script") {
|
||||
model.saveSQLScript()
|
||||
}
|
||||
.keyboardShortcut("s", modifiers: .command)
|
||||
|
||||
Button("Save SQL Script As…") {
|
||||
model.saveSQLScript(asNewFile: true)
|
||||
}
|
||||
.keyboardShortcut("s", modifiers: [.command, .shift])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,485 +0,0 @@
|
||||
import Foundation
|
||||
import AppKit
|
||||
import Security
|
||||
|
||||
struct ConnectionProfile: Identifiable, Codable, Hashable {
|
||||
var id = UUID()
|
||||
var name = "Local MySQL"
|
||||
var host = "127.0.0.1"
|
||||
var port = 3306
|
||||
var username = "root"
|
||||
var database = ""
|
||||
}
|
||||
struct QueryResult {
|
||||
var columns: [String] = []
|
||||
var rows: [[String]] = []
|
||||
var message = ""
|
||||
}
|
||||
|
||||
enum PasswordStore {
|
||||
static func read(_ id: UUID) -> String {
|
||||
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrService as String: "WorkbenchReplacement.MySQL",
|
||||
kSecAttrAccount as String: id.uuidString,
|
||||
kSecReturnData as String: true,
|
||||
kSecMatchLimit as String: kSecMatchLimitOne]
|
||||
var value: CFTypeRef?
|
||||
guard SecItemCopyMatching(query as CFDictionary, &value) == errSecSuccess,
|
||||
let data = value as? Data else { return "" }
|
||||
return String(data: data, encoding: .utf8) ?? ""
|
||||
}
|
||||
static func save(_ password: String, id: UUID) {
|
||||
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrService as String: "WorkbenchReplacement.MySQL",
|
||||
kSecAttrAccount as String: id.uuidString]
|
||||
SecItemDelete(query as CFDictionary)
|
||||
guard !password.isEmpty else { return }
|
||||
var attributes = query
|
||||
attributes[kSecValueData as String] = Data(password.utf8)
|
||||
SecItemAdd(attributes as CFDictionary, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct WorkbenchQueryTab: Identifiable {
|
||||
let id: UUID
|
||||
var title: String
|
||||
var sql: String
|
||||
var result: QueryResult
|
||||
var fileURL: URL?
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
title: String,
|
||||
sql: String = "",
|
||||
result: QueryResult = QueryResult(),
|
||||
fileURL: URL? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.sql = sql
|
||||
self.result = result
|
||||
self.fileURL = fileURL
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class DatabaseModel: ObservableObject {
|
||||
@Published var profiles: [ConnectionProfile] = []
|
||||
@Published var selectedID: UUID?
|
||||
@Published var queryTabs: [WorkbenchQueryTab] = [
|
||||
WorkbenchQueryTab(
|
||||
title: "Query 1",
|
||||
sql: "SELECT VERSION() AS server_version;"
|
||||
)
|
||||
]
|
||||
@Published var activeQueryID: UUID?
|
||||
@Published var sql = "SELECT VERSION() AS server_version;"
|
||||
@Published var result = QueryResult()
|
||||
@Published var databases: [String] = []
|
||||
@Published var schemaTables: [String: [String]] = [:]
|
||||
@Published var schemaViews: [String: [String]] = [:]
|
||||
@Published var selectedDatabase = ""
|
||||
@Published var isRunning = false
|
||||
@Published var status = "Not connected"
|
||||
private let storageKey = "WorkbenchReplacement.connectionProfiles.native.v1"
|
||||
|
||||
init() {
|
||||
if let data = UserDefaults.standard.data(forKey: storageKey),
|
||||
let decoded = try? JSONDecoder().decode([ConnectionProfile].self, from: data) { profiles = decoded }
|
||||
if profiles.isEmpty { profiles = [ConnectionProfile()] }
|
||||
selectedID = profiles.first?.id
|
||||
activeQueryID = queryTabs.first?.id
|
||||
}
|
||||
|
||||
func newQueryTab() {
|
||||
saveActiveQuery()
|
||||
let tab = WorkbenchQueryTab(
|
||||
title: "Query \\(queryTabs.count + 1)"
|
||||
)
|
||||
queryTabs.append(tab)
|
||||
activeQueryID = tab.id
|
||||
sql = tab.sql
|
||||
result = tab.result
|
||||
}
|
||||
|
||||
func saveActiveQuery() {
|
||||
guard let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
queryTabs[index].sql = sql
|
||||
queryTabs[index].result = result
|
||||
}
|
||||
|
||||
func activateQuery(_ id: UUID) {
|
||||
saveActiveQuery()
|
||||
|
||||
guard let tab = queryTabs.first(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
activeQueryID = tab.id
|
||||
sql = tab.sql
|
||||
result = tab.result
|
||||
}
|
||||
|
||||
func closeQuery(_ id: UUID) {
|
||||
saveActiveQuery()
|
||||
queryTabs.removeAll { $0.id == id }
|
||||
|
||||
if queryTabs.isEmpty {
|
||||
let tab = WorkbenchQueryTab(title: "Query 1")
|
||||
queryTabs.append(tab)
|
||||
}
|
||||
|
||||
if activeQueryID == id {
|
||||
activeQueryID = nil
|
||||
activateQuery(queryTabs[0].id)
|
||||
}
|
||||
}
|
||||
|
||||
func openSQLScript() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.allowedContentTypes = [.plainText]
|
||||
panel.allowsOtherFileTypes = true
|
||||
panel.canChooseDirectories = false
|
||||
|
||||
guard panel.runModal() == .OK,
|
||||
let url = panel.url,
|
||||
let contents = try? String(contentsOf: url, encoding: .utf8)
|
||||
else { return }
|
||||
|
||||
saveActiveQuery()
|
||||
|
||||
let tab = WorkbenchQueryTab(
|
||||
title: url.lastPathComponent,
|
||||
sql: contents,
|
||||
fileURL: url
|
||||
)
|
||||
|
||||
queryTabs.append(tab)
|
||||
activateQuery(tab.id)
|
||||
status = "Opened \\(url.lastPathComponent)"
|
||||
}
|
||||
|
||||
func saveSQLScript(asNewFile: Bool = false) {
|
||||
saveActiveQuery()
|
||||
|
||||
guard let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
var destination = asNewFile ? nil : queryTabs[index].fileURL
|
||||
|
||||
if destination == nil {
|
||||
let panel = NSSavePanel()
|
||||
panel.nameFieldStringValue = "query.sql"
|
||||
panel.canCreateDirectories = true
|
||||
|
||||
guard panel.runModal() == .OK else { return }
|
||||
destination = panel.url
|
||||
}
|
||||
|
||||
guard let url = destination else { return }
|
||||
|
||||
do {
|
||||
try sql.write(to: url, atomically: true, encoding: .utf8)
|
||||
queryTabs[index].fileURL = url
|
||||
queryTabs[index].title = url.lastPathComponent
|
||||
status = "Saved \\(url.lastPathComponent)"
|
||||
} catch {
|
||||
status = "Save failed: \\(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
|
||||
var selected: ConnectionProfile? { profiles.first { $0.id == selectedID } }
|
||||
func save(_ profile: ConnectionProfile, password: String) {
|
||||
if let i = profiles.firstIndex(where: { $0.id == profile.id }) { profiles[i] = profile }
|
||||
else { profiles.append(profile) }
|
||||
PasswordStore.save(password, id: profile.id)
|
||||
selectedID = profile.id
|
||||
persist()
|
||||
}
|
||||
private func persist() {
|
||||
if let data = try? JSONEncoder().encode(profiles) { UserDefaults.standard.set(data, forKey: storageKey) }
|
||||
}
|
||||
|
||||
func formatSQL() {
|
||||
sql = SQLFormatter.uppercaseKeywords(sql)
|
||||
}
|
||||
|
||||
|
||||
func loadTables(database: String) {
|
||||
guard let profile = selected else {
|
||||
status = "Select a MySQL connection"
|
||||
return
|
||||
}
|
||||
|
||||
let password = PasswordStore.read(profile.id)
|
||||
let escaped = database.replacingOccurrences(
|
||||
of: "`",
|
||||
with: "``"
|
||||
)
|
||||
|
||||
status = "Loading tables from \(database)…"
|
||||
|
||||
Task {
|
||||
do {
|
||||
let parsed = try await NativeMySQLRunner.run(
|
||||
profile: profile,
|
||||
database: database,
|
||||
password: password,
|
||||
sql: "SHOW FULL TABLES FROM `\(escaped)`"
|
||||
)
|
||||
|
||||
var tables: [String] = []
|
||||
var views: [String] = []
|
||||
|
||||
for row in parsed.rows {
|
||||
guard let name = row.first else {
|
||||
continue
|
||||
}
|
||||
|
||||
if row.count > 1 && row[1] == "VIEW" {
|
||||
views.append(name)
|
||||
} else {
|
||||
tables.append(name)
|
||||
}
|
||||
}
|
||||
|
||||
schemaTables[database] = tables
|
||||
schemaViews[database] = views
|
||||
|
||||
status = "Loaded \(tables.count) tables and \(views.count) views from \(database)"
|
||||
} catch {
|
||||
status = "Unable to load tables: \(error.localizedDescription)"
|
||||
result = QueryResult(message: error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func selectTable(database: String, table: String) {
|
||||
let db = database.replacingOccurrences(
|
||||
of: "`",
|
||||
with: "``"
|
||||
)
|
||||
|
||||
let tbl = table.replacingOccurrences(
|
||||
of: "`",
|
||||
with: "``"
|
||||
)
|
||||
|
||||
selectedDatabase = database
|
||||
|
||||
let configuredLimit = UserDefaults.standard.integer(
|
||||
forKey: "preferences.defaultRowLimit"
|
||||
)
|
||||
|
||||
let rowLimit = configuredLimit > 0
|
||||
? min(configuredLimit, 100000)
|
||||
: 500
|
||||
|
||||
sql = "SELECT * FROM `\(db)`.`\(tbl)` LIMIT \(rowLimit);"
|
||||
|
||||
runSQL()
|
||||
}
|
||||
|
||||
func loadDatabases() { execute("SHOW DATABASES;", listingDatabases: true) }
|
||||
|
||||
func runSQL() {
|
||||
if UserDefaults.standard.object(
|
||||
forKey: "preferences.uppercaseKeywords"
|
||||
) as? Bool ?? true {
|
||||
formatSQL()
|
||||
}
|
||||
execute(sql, listingDatabases: false)
|
||||
}
|
||||
private func execute(_ statement: String, listingDatabases: Bool) {
|
||||
guard let profile = selected else { status = "Select a connection"; return }
|
||||
guard !statement.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return }
|
||||
isRunning = true
|
||||
status = "Connecting…"
|
||||
let activeDB = listingDatabases ? "" : (selectedDatabase.isEmpty ? profile.database : selectedDatabase)
|
||||
let password = PasswordStore.read(profile.id)
|
||||
Task {
|
||||
do {
|
||||
let parsed = try await NativeMySQLRunner.run(profile: profile, database: activeDB, password: password, sql: statement)
|
||||
if listingDatabases {
|
||||
databases = parsed.rows.compactMap { $0.first }
|
||||
status = "Connected to \(profile.name)"
|
||||
} else {
|
||||
result = parsed
|
||||
if let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id }) {
|
||||
queryTabs[index].sql = sql
|
||||
queryTabs[index].result = parsed
|
||||
}
|
||||
status = "Query completed (\(parsed.rows.count) rows)"
|
||||
}
|
||||
} catch {
|
||||
status = "Error"
|
||||
result = QueryResult(message: error.localizedDescription)
|
||||
}
|
||||
isRunning = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SQL Keyword Formatter
|
||||
|
||||
enum SQLFormatter {
|
||||
|
||||
private static let keywords: Set<String> = [
|
||||
"SELECT", "FROM", "WHERE", "INSERT", "INTO", "VALUES",
|
||||
"UPDATE", "DELETE", "CREATE", "ALTER", "DROP", "TABLE",
|
||||
"DATABASE", "SCHEMA", "USE", "SHOW", "DESCRIBE", "EXPLAIN",
|
||||
"JOIN", "INNER", "LEFT", "RIGHT", "FULL", "OUTER",
|
||||
"ON", "AS", "AND", "OR", "NOT", "NULL", "IS", "IN",
|
||||
"BETWEEN", "LIKE", "ORDER", "BY", "GROUP", "HAVING",
|
||||
"LIMIT", "OFFSET", "ASC", "DESC", "DISTINCT", "ALL",
|
||||
"PRIMARY", "KEY", "FOREIGN", "REFERENCES", "INDEX",
|
||||
"UNIQUE", "DEFAULT", "AUTO_INCREMENT", "IF", "EXISTS",
|
||||
"CASCADE", "RESTRICT", "SET", "BEGIN", "COMMIT",
|
||||
"ROLLBACK", "TRANSACTION", "UNION", "CASE", "WHEN",
|
||||
"THEN", "ELSE", "END", "TRUE", "FALSE", "COUNT",
|
||||
"SUM", "AVG", "MIN", "MAX", "HAVING", "WITH",
|
||||
"RECURSIVE", "TRUNCATE", "REPLACE", "VIEW",
|
||||
"PROCEDURE", "FUNCTION", "TRIGGER", "GRANT",
|
||||
"REVOKE", "DISTINCT", "CURRENT_TIMESTAMP"
|
||||
]
|
||||
|
||||
static func uppercaseKeywords(_ sql: String) -> String {
|
||||
let chars = Array(sql)
|
||||
var output = ""
|
||||
var index = 0
|
||||
|
||||
enum State {
|
||||
case normal
|
||||
case singleQuote
|
||||
case doubleQuote
|
||||
case backtick
|
||||
case lineComment
|
||||
case blockComment
|
||||
}
|
||||
|
||||
var state = State.normal
|
||||
|
||||
while index < chars.count {
|
||||
let ch = chars[index]
|
||||
let next: Character? = index + 1 < chars.count
|
||||
? chars[index + 1] : nil
|
||||
|
||||
switch state {
|
||||
case .normal:
|
||||
if ch == "'" {
|
||||
state = .singleQuote
|
||||
output.append(ch)
|
||||
index += 1
|
||||
} else if ch == "\"" {
|
||||
state = .doubleQuote
|
||||
output.append(ch)
|
||||
index += 1
|
||||
} else if ch == "`" {
|
||||
state = .backtick
|
||||
output.append(ch)
|
||||
index += 1
|
||||
} else if ch == "-" && next == "-" &&
|
||||
(index + 2 == chars.count ||
|
||||
chars[index + 2].isWhitespace) {
|
||||
state = .lineComment
|
||||
output += "--"
|
||||
index += 2
|
||||
} else if ch == "#" {
|
||||
state = .lineComment
|
||||
output.append(ch)
|
||||
index += 1
|
||||
} else if ch == "/" && next == "*" {
|
||||
state = .blockComment
|
||||
output += "/*"
|
||||
index += 2
|
||||
} else if ch.isLetter || ch == "_" {
|
||||
let start = index
|
||||
while index < chars.count &&
|
||||
(chars[index].isLetter ||
|
||||
chars[index].isNumber ||
|
||||
chars[index] == "_" ||
|
||||
chars[index] == "$") {
|
||||
index += 1
|
||||
}
|
||||
|
||||
let word = String(chars[start..<index])
|
||||
let upper = word.uppercased()
|
||||
|
||||
output += keywords.contains(upper) ? upper : word
|
||||
} else {
|
||||
output.append(ch)
|
||||
index += 1
|
||||
}
|
||||
|
||||
case .singleQuote:
|
||||
output.append(ch)
|
||||
index += 1
|
||||
if ch == "\\" && index < chars.count {
|
||||
output.append(chars[index])
|
||||
index += 1
|
||||
} else if ch == "'" {
|
||||
if index < chars.count && chars[index] == "'" {
|
||||
output.append(chars[index])
|
||||
index += 1
|
||||
} else {
|
||||
state = .normal
|
||||
}
|
||||
}
|
||||
|
||||
case .doubleQuote:
|
||||
output.append(ch)
|
||||
index += 1
|
||||
if ch == "\\" && index < chars.count {
|
||||
output.append(chars[index])
|
||||
index += 1
|
||||
} else if ch == "\"" {
|
||||
if index < chars.count && chars[index] == "\"" {
|
||||
output.append(chars[index])
|
||||
index += 1
|
||||
} else {
|
||||
state = .normal
|
||||
}
|
||||
}
|
||||
|
||||
case .backtick:
|
||||
output.append(ch)
|
||||
index += 1
|
||||
if ch == "`" {
|
||||
if index < chars.count && chars[index] == "`" {
|
||||
output.append(chars[index])
|
||||
index += 1
|
||||
} else {
|
||||
state = .normal
|
||||
}
|
||||
}
|
||||
|
||||
case .lineComment:
|
||||
output.append(ch)
|
||||
index += 1
|
||||
if ch == "\n" {
|
||||
state = .normal
|
||||
}
|
||||
|
||||
case .blockComment:
|
||||
output.append(ch)
|
||||
index += 1
|
||||
if ch == "*" && index < chars.count &&
|
||||
chars[index] == "/" {
|
||||
output.append("/")
|
||||
index += 1
|
||||
state = .normal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 530 KiB |
Binary file not shown.
-1
@@ -1 +0,0 @@
|
||||
{"case-sensitive":"false","roots":[],"version":0}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.get-task-allow</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
-383
@@ -1,383 +0,0 @@
|
||||
#if 0
|
||||
#elif defined(__arm64__) && __arm64__
|
||||
// Generated by Apple Swift version 6.4 effective-5.10 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)
|
||||
#ifndef WORKBENCHREPLACEMENT_SWIFT_H
|
||||
#define WORKBENCHREPLACEMENT_SWIFT_H
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgcc-compat"
|
||||
|
||||
#if !defined(__has_include)
|
||||
# define __has_include(x) 0
|
||||
#endif
|
||||
#if !defined(__has_attribute)
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
#if !defined(__has_warning)
|
||||
# define __has_warning(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<swift/objc-prologue.h>)
|
||||
# include <swift/objc-prologue.h>
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wauto-import"
|
||||
#if defined(__OBJC__)
|
||||
#include <Foundation/Foundation.h>
|
||||
#endif // defined(__OBJC__)
|
||||
#if defined(__cplusplus)
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-modular-include-in-framework-module"
|
||||
#if defined(__arm64e__) && __has_include(<ptrauth.h>)
|
||||
# include <ptrauth.h>
|
||||
#else
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreserved-macro-identifier"
|
||||
# ifndef __ptrauth_swift_value_witness_function_pointer
|
||||
# define __ptrauth_swift_value_witness_function_pointer(x)
|
||||
# endif
|
||||
# ifndef __ptrauth_swift_class_method_pointer
|
||||
# define __ptrauth_swift_class_method_pointer(x)
|
||||
# endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_TYPEDEFS)
|
||||
# define SWIFT_TYPEDEFS 1
|
||||
# if __has_include(<uchar.h>)
|
||||
# include <uchar.h>
|
||||
# elif !defined(__cplusplus)
|
||||
typedef unsigned char char8_t;
|
||||
typedef uint_least16_t char16_t;
|
||||
typedef uint_least32_t char32_t;
|
||||
# endif
|
||||
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_PASTE)
|
||||
# define SWIFT_PASTE_HELPER(x, y) x##y
|
||||
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
|
||||
#endif
|
||||
#if !defined(SWIFT_METATYPE)
|
||||
# define SWIFT_METATYPE(X) Class
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_PROPERTY)
|
||||
# if __has_feature(objc_class_property)
|
||||
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
|
||||
# else
|
||||
# define SWIFT_CLASS_PROPERTY(...)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RUNTIME_NAME)
|
||||
# if __has_attribute(objc_runtime_name)
|
||||
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
|
||||
# else
|
||||
# define SWIFT_RUNTIME_NAME(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_COMPILE_NAME)
|
||||
# if __has_attribute(swift_name)
|
||||
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
|
||||
# else
|
||||
# define SWIFT_COMPILE_NAME(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_METHOD_FAMILY)
|
||||
# if __has_attribute(objc_method_family)
|
||||
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
|
||||
# else
|
||||
# define SWIFT_METHOD_FAMILY(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_NOESCAPE)
|
||||
# if __has_attribute(noescape)
|
||||
# define SWIFT_NOESCAPE __attribute__((noescape))
|
||||
# else
|
||||
# define SWIFT_NOESCAPE
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RELEASES_ARGUMENT)
|
||||
# if __has_attribute(ns_consumed)
|
||||
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
|
||||
# else
|
||||
# define SWIFT_RELEASES_ARGUMENT
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_WARN_UNUSED_RESULT)
|
||||
# if __has_attribute(warn_unused_result)
|
||||
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
# else
|
||||
# define SWIFT_WARN_UNUSED_RESULT
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_NORETURN)
|
||||
# if __has_attribute(noreturn)
|
||||
# define SWIFT_NORETURN __attribute__((noreturn))
|
||||
# else
|
||||
# define SWIFT_NORETURN
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_EXTRA)
|
||||
# define SWIFT_CLASS_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_PROTOCOL_EXTRA)
|
||||
# define SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_EXTRA)
|
||||
# define SWIFT_ENUM_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS)
|
||||
# if __has_attribute(objc_subclassing_restricted)
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# else
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RESILIENT_CLASS)
|
||||
# if __has_attribute(objc_class_stub)
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# else
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_PROTOCOL)
|
||||
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_EXTENSION)
|
||||
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
|
||||
#endif
|
||||
#if !defined(OBJC_DESIGNATED_INITIALIZER)
|
||||
# if __has_attribute(objc_designated_initializer)
|
||||
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
||||
# else
|
||||
# define OBJC_DESIGNATED_INITIALIZER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_ATTR)
|
||||
# if __has_attribute(enum_extensibility)
|
||||
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
|
||||
# else
|
||||
# define SWIFT_ENUM_ATTR(_extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# if __has_feature(generalized_swift_name)
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# else
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
|
||||
# endif
|
||||
# else
|
||||
# define SWIFT_ENUM(_type, _name, _extensibility) _type _name; enum
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_TAG)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM_TAG enum
|
||||
# else
|
||||
# define SWIFT_ENUM_TAG
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_FWD_DECL)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM_FWD_DECL(_type, _name) enum _name : _type;
|
||||
# else
|
||||
# define SWIFT_ENUM_FWD_DECL(_type, _name) typedef _type _name;
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE)
|
||||
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE_MSG)
|
||||
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
|
||||
#endif
|
||||
#if !defined(SWIFT_AVAILABILITY)
|
||||
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_AVAILABILITY_DOMAIN)
|
||||
# define SWIFT_AVAILABILITY_DOMAIN(dom, ...) __attribute__((availability(domain: dom, __VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_WEAK_IMPORT)
|
||||
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED)
|
||||
# define SWIFT_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED_MSG)
|
||||
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED_OBJC)
|
||||
# if __has_feature(attribute_diagnose_if_objc)
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
|
||||
# else
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__OBJC__)
|
||||
#if !defined(IBSegueAction)
|
||||
# define IBSegueAction
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(SWIFT_EXTERN)
|
||||
# if defined(__cplusplus)
|
||||
# define SWIFT_EXTERN extern "C"
|
||||
# else
|
||||
# define SWIFT_EXTERN extern
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_CALL)
|
||||
# define SWIFT_CALL __attribute__((swiftcall))
|
||||
#endif
|
||||
#if !defined(SWIFT_INDIRECT_RESULT)
|
||||
# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result))
|
||||
#endif
|
||||
#if !defined(SWIFT_CONTEXT)
|
||||
# define SWIFT_CONTEXT __attribute__((swift_context))
|
||||
#endif
|
||||
#if !defined(SWIFT_ERROR_RESULT)
|
||||
# define SWIFT_ERROR_RESULT __attribute__((swift_error_result))
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
# define SWIFT_NOEXCEPT noexcept
|
||||
#else
|
||||
# define SWIFT_NOEXCEPT
|
||||
#endif
|
||||
#if !defined(SWIFT_C_INLINE_THUNK)
|
||||
# if __has_attribute(always_inline)
|
||||
# if __has_attribute(nodebug)
|
||||
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug))
|
||||
# else
|
||||
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline))
|
||||
# endif
|
||||
# else
|
||||
# define SWIFT_C_INLINE_THUNK inline
|
||||
# endif
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
|
||||
# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
|
||||
# define SWIFT_IMPORT_STDLIB_SYMBOL
|
||||
#endif
|
||||
#endif
|
||||
#if !__has_feature(nullability)
|
||||
# define _Nonnull
|
||||
# define _Nullable
|
||||
# define _Null_unspecified
|
||||
#elif !defined(__OBJC__)
|
||||
# pragma clang diagnostic ignored "-Wnullability-extension"
|
||||
#endif
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
# define _Nullable_result _Nullable
|
||||
#endif
|
||||
#if __has_feature(objc_modules)
|
||||
#if __has_warning("-Watimport-in-framework-header")
|
||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
|
||||
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
|
||||
#if __has_warning("-Wpragma-clang-attribute")
|
||||
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
#pragma clang diagnostic ignored "-Warc-bridge-casts-disallowed-in-nonarc"
|
||||
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma push_macro("any")
|
||||
# undef any
|
||||
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="WorkbenchReplacement",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
|
||||
# pragma pop_macro("any")
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma clang attribute pop
|
||||
#endif
|
||||
#if defined(__OBJC__)
|
||||
#if __has_feature(objc_modules)
|
||||
#if __has_warning("-Watimport-in-framework-header")
|
||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // defined(__OBJC__)
|
||||
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
|
||||
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
|
||||
#if __has_warning("-Wpragma-clang-attribute")
|
||||
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
#pragma clang diagnostic ignored "-Warc-bridge-casts-disallowed-in-nonarc"
|
||||
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma push_macro("any")
|
||||
# undef any
|
||||
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="WorkbenchReplacement",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
|
||||
# pragma pop_macro("any")
|
||||
#endif
|
||||
|
||||
#if defined(__OBJC__)
|
||||
|
||||
#endif // defined(__OBJC__)
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma clang attribute pop
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error unsupported Swift architecture
|
||||
#endif
|
||||
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
-224
@@ -1,224 +0,0 @@
|
||||
{
|
||||
"source": "/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/App.swift",
|
||||
"tables": {
|
||||
"Localizable": [
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Workbench Replacement",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "SQL Editor",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 99
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Query Execution",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 107
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Result Grid",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 115
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "General",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 123
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "%lld pt",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 137
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 146
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "2 spaces",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 147
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "4 spaces",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 148
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "8 spaces",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 149
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Automatically uppercase SQL keywords",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 157
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Show line numbers",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 164
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Controls the number of rows retrieved when opening a table from the schema navigator.",
|
||||
"location": {
|
||||
"startingColumn": 17,
|
||||
"startingLine": 195
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Examples",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 205
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 177
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 185
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "%lld px",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 224
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "%lld px",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 234
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Alternating row colours",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 244
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Automatically expand table folders",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 256
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Workbench Replacement",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 344
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Modern MySQL Client for macOS",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 347
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Starting Workbench Replacement…",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 364
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "New Query Tab",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 404
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Open SQL Script…",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 411
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Save SQL Script",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 418
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Save SQL Script As…",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 423
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
[]
|
||||
BIN
Binary file not shown.
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"source": "/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/DatabaseModel.swift",
|
||||
"tables": {},
|
||||
"version": 1
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
[]
|
||||
BIN
Binary file not shown.
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"source" : "ExtractedAppShortcutsMetadata",
|
||||
"tables" : {
|
||||
|
||||
},
|
||||
"version" : 2
|
||||
}
|
||||
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
-656
@@ -1,656 +0,0 @@
|
||||
{
|
||||
"source": "/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MainView.swift",
|
||||
"tables": {
|
||||
"Localizable": [
|
||||
{
|
||||
"comment": "",
|
||||
"key": "MySQL Workbench",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 99
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Navigator",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 188
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Administration",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 189
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Schemas",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 190
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "SCHEMAS",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 210
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Edit Connection",
|
||||
"location": {
|
||||
"startingColumn": 36,
|
||||
"startingLine": 264
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Set as Default Schema",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 381
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Refresh Tables",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 385
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Load Tables",
|
||||
"location": {
|
||||
"startingColumn": 28,
|
||||
"startingLine": 455
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Tables",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 428
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Select First 100 Rows",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 511
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "New Query Tab",
|
||||
"location": {
|
||||
"startingColumn": 19,
|
||||
"startingLine": 632
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Default Schema:",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 657
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "SQL Editor",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 667
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Execute SQL",
|
||||
"location": {
|
||||
"startingColumn": 19,
|
||||
"startingLine": 645
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Format SQL",
|
||||
"location": {
|
||||
"startingColumn": 19,
|
||||
"startingLine": 652
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "%lld",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 707
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Result Grid",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 739
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "No query results",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 757
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Action Output",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 779
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "UTF-8",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 854
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Connection Settings",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 1029
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Connection Name",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1034
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Hostname",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1039
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Port",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1044
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Username",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1050
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Password (macOS Keychain)",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1055
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Default Schema",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1060
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Cancel",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 1068
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Save",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 1072
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "The server did not return any columns.",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 1394
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Loading %@…",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1372
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "No Data",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1391
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Unable to Load %@",
|
||||
"location": {
|
||||
"startingColumn": 25,
|
||||
"startingLine": 1378
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Retry",
|
||||
"location": {
|
||||
"startingColumn": 28,
|
||||
"startingLine": 1384
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Refresh",
|
||||
"location": {
|
||||
"startingColumn": 23,
|
||||
"startingLine": 1433
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "SQL Editor",
|
||||
"location": {
|
||||
"startingColumn": 23,
|
||||
"startingLine": 1440
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Not loaded",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 1518
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Updated %@",
|
||||
"location": {
|
||||
"startingColumn": 21,
|
||||
"startingLine": 1515
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "%lld rows",
|
||||
"location": {
|
||||
"startingColumn": 18,
|
||||
"startingLine": 1523
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Import SQL into %@?",
|
||||
"location": {
|
||||
"startingColumn": 13,
|
||||
"startingLine": 1780
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Operation",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 1600
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Data Export",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 1601
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Data Import / Restore",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 1602
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "MySQL Connection",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 1609
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Export Options",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1633
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Import Options",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1689
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Progress",
|
||||
"location": {
|
||||
"startingColumn": 26,
|
||||
"startingLine": 1701
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Connection",
|
||||
"location": {
|
||||
"startingColumn": 36,
|
||||
"startingLine": 1611
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Database",
|
||||
"location": {
|
||||
"startingColumn": 28,
|
||||
"startingLine": 1615
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Select Database",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1616
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Refresh Databases",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1624
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "No tables found. Select a database or refresh the list.",
|
||||
"location": {
|
||||
"startingColumn": 34,
|
||||
"startingLine": 1655
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "InnoDB data is exported using a consistent snapshot and a single streamed query per table. Tables without unique indexes are supported.",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1684
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Table structure",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1635
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Table data",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1636
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Add DROP TABLE IF EXISTS",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1637
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Include views (definitions)",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1639
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Include triggers",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1641
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Include stored procedures and functions",
|
||||
"location": {
|
||||
"startingColumn": 32,
|
||||
"startingLine": 1643
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Loading tables…",
|
||||
"location": {
|
||||
"startingColumn": 57,
|
||||
"startingLine": 1653
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Tables (%lld selected)",
|
||||
"location": {
|
||||
"startingColumn": 34,
|
||||
"startingLine": 1646
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "All",
|
||||
"location": {
|
||||
"startingColumn": 36,
|
||||
"startingLine": 1648
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "None",
|
||||
"location": {
|
||||
"startingColumn": 36,
|
||||
"startingLine": 1649
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Refresh",
|
||||
"location": {
|
||||
"startingColumn": 36,
|
||||
"startingLine": 1650
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Views (%lld selected)",
|
||||
"location": {
|
||||
"startingColumn": 38,
|
||||
"startingLine": 1669
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "All",
|
||||
"location": {
|
||||
"startingColumn": 40,
|
||||
"startingLine": 1671
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "None",
|
||||
"location": {
|
||||
"startingColumn": 40,
|
||||
"startingLine": 1672
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Import SQL statements into the selected database.",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1691
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Supports MySQL DELIMITER directives, triggers and stored routines. Import is not transactional; use a verified backup before restoring.",
|
||||
"location": {
|
||||
"startingColumn": 30,
|
||||
"startingLine": 1694
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Close",
|
||||
"location": {
|
||||
"startingColumn": 24,
|
||||
"startingLine": 1720
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Verify Backup…",
|
||||
"location": {
|
||||
"startingColumn": 28,
|
||||
"startingLine": 1728
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Verify an SQL file against its SHA-256 checksum sidecar",
|
||||
"location": {
|
||||
"startingColumn": 27,
|
||||
"startingLine": 1731
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Cancel",
|
||||
"location": {
|
||||
"startingColumn": 28,
|
||||
"startingLine": 1735
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Export SQL…",
|
||||
"location": {
|
||||
"startingColumn": 31,
|
||||
"startingLine": 1742
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Import SQL…",
|
||||
"location": {
|
||||
"startingColumn": 31,
|
||||
"startingLine": 1743
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Import SQL",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 1783
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Cancel",
|
||||
"location": {
|
||||
"startingColumn": 20,
|
||||
"startingLine": 1791
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "SQL files can modify or delete existing database objects and data. Ensure you have a backup before continuing.",
|
||||
"location": {
|
||||
"startingColumn": 17,
|
||||
"startingLine": 1796
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Database Import / Export",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 1808
|
||||
}
|
||||
},
|
||||
{
|
||||
"comment": "",
|
||||
"key": "Built-in native MySQL database tools",
|
||||
"location": {
|
||||
"startingColumn": 22,
|
||||
"startingLine": 1811
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
[]
|
||||
BIN
Binary file not shown.
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"source": "/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MySQLProtocol.swift",
|
||||
"tables": {},
|
||||
"version": 1
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
[]
|
||||
BIN
Binary file not shown.
-49
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"" : {
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.dia",
|
||||
"emit-module-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-emit-module.d",
|
||||
"emit-module-diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-emit-module.dia",
|
||||
"pch" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-Bridging-header.pch",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.swiftdeps"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/App.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/DatabaseModel.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MainView.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MySQLProtocol.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol~partial.swiftmodule"
|
||||
}
|
||||
}
|
||||
-377
@@ -1,377 +0,0 @@
|
||||
// Generated by Apple Swift version 6.4 effective-5.10 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)
|
||||
#ifndef WORKBENCHREPLACEMENT_SWIFT_H
|
||||
#define WORKBENCHREPLACEMENT_SWIFT_H
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgcc-compat"
|
||||
|
||||
#if !defined(__has_include)
|
||||
# define __has_include(x) 0
|
||||
#endif
|
||||
#if !defined(__has_attribute)
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
#if !defined(__has_feature)
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
#if !defined(__has_warning)
|
||||
# define __has_warning(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<swift/objc-prologue.h>)
|
||||
# include <swift/objc-prologue.h>
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wauto-import"
|
||||
#if defined(__OBJC__)
|
||||
#include <Foundation/Foundation.h>
|
||||
#endif // defined(__OBJC__)
|
||||
#if defined(__cplusplus)
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-modular-include-in-framework-module"
|
||||
#if defined(__arm64e__) && __has_include(<ptrauth.h>)
|
||||
# include <ptrauth.h>
|
||||
#else
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreserved-macro-identifier"
|
||||
# ifndef __ptrauth_swift_value_witness_function_pointer
|
||||
# define __ptrauth_swift_value_witness_function_pointer(x)
|
||||
# endif
|
||||
# ifndef __ptrauth_swift_class_method_pointer
|
||||
# define __ptrauth_swift_class_method_pointer(x)
|
||||
# endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_TYPEDEFS)
|
||||
# define SWIFT_TYPEDEFS 1
|
||||
# if __has_include(<uchar.h>)
|
||||
# include <uchar.h>
|
||||
# elif !defined(__cplusplus)
|
||||
typedef unsigned char char8_t;
|
||||
typedef uint_least16_t char16_t;
|
||||
typedef uint_least32_t char32_t;
|
||||
# endif
|
||||
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
|
||||
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
|
||||
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
|
||||
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||
#endif
|
||||
|
||||
#if !defined(SWIFT_PASTE)
|
||||
# define SWIFT_PASTE_HELPER(x, y) x##y
|
||||
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
|
||||
#endif
|
||||
#if !defined(SWIFT_METATYPE)
|
||||
# define SWIFT_METATYPE(X) Class
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_PROPERTY)
|
||||
# if __has_feature(objc_class_property)
|
||||
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
|
||||
# else
|
||||
# define SWIFT_CLASS_PROPERTY(...)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RUNTIME_NAME)
|
||||
# if __has_attribute(objc_runtime_name)
|
||||
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
|
||||
# else
|
||||
# define SWIFT_RUNTIME_NAME(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_COMPILE_NAME)
|
||||
# if __has_attribute(swift_name)
|
||||
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
|
||||
# else
|
||||
# define SWIFT_COMPILE_NAME(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_METHOD_FAMILY)
|
||||
# if __has_attribute(objc_method_family)
|
||||
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
|
||||
# else
|
||||
# define SWIFT_METHOD_FAMILY(X)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_NOESCAPE)
|
||||
# if __has_attribute(noescape)
|
||||
# define SWIFT_NOESCAPE __attribute__((noescape))
|
||||
# else
|
||||
# define SWIFT_NOESCAPE
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RELEASES_ARGUMENT)
|
||||
# if __has_attribute(ns_consumed)
|
||||
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
|
||||
# else
|
||||
# define SWIFT_RELEASES_ARGUMENT
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_WARN_UNUSED_RESULT)
|
||||
# if __has_attribute(warn_unused_result)
|
||||
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
# else
|
||||
# define SWIFT_WARN_UNUSED_RESULT
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_NORETURN)
|
||||
# if __has_attribute(noreturn)
|
||||
# define SWIFT_NORETURN __attribute__((noreturn))
|
||||
# else
|
||||
# define SWIFT_NORETURN
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS_EXTRA)
|
||||
# define SWIFT_CLASS_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_PROTOCOL_EXTRA)
|
||||
# define SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_EXTRA)
|
||||
# define SWIFT_ENUM_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_CLASS)
|
||||
# if __has_attribute(objc_subclassing_restricted)
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# else
|
||||
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_RESILIENT_CLASS)
|
||||
# if __has_attribute(objc_class_stub)
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# else
|
||||
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
|
||||
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_PROTOCOL)
|
||||
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
|
||||
#endif
|
||||
#if !defined(SWIFT_EXTENSION)
|
||||
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
|
||||
#endif
|
||||
#if !defined(OBJC_DESIGNATED_INITIALIZER)
|
||||
# if __has_attribute(objc_designated_initializer)
|
||||
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
||||
# else
|
||||
# define OBJC_DESIGNATED_INITIALIZER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_ATTR)
|
||||
# if __has_attribute(enum_extensibility)
|
||||
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
|
||||
# else
|
||||
# define SWIFT_ENUM_ATTR(_extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# if __has_feature(generalized_swift_name)
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
|
||||
# else
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
|
||||
# endif
|
||||
# else
|
||||
# define SWIFT_ENUM(_type, _name, _extensibility) _type _name; enum
|
||||
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_TAG)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM_TAG enum
|
||||
# else
|
||||
# define SWIFT_ENUM_TAG
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_ENUM_FWD_DECL)
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || __has_feature(objc_fixed_enum)
|
||||
# define SWIFT_ENUM_FWD_DECL(_type, _name) enum _name : _type;
|
||||
# else
|
||||
# define SWIFT_ENUM_FWD_DECL(_type, _name) typedef _type _name;
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE)
|
||||
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
|
||||
#endif
|
||||
#if !defined(SWIFT_UNAVAILABLE_MSG)
|
||||
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
|
||||
#endif
|
||||
#if !defined(SWIFT_AVAILABILITY)
|
||||
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_AVAILABILITY_DOMAIN)
|
||||
# define SWIFT_AVAILABILITY_DOMAIN(dom, ...) __attribute__((availability(domain: dom, __VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_WEAK_IMPORT)
|
||||
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED)
|
||||
# define SWIFT_DEPRECATED __attribute__((deprecated))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED_MSG)
|
||||
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
|
||||
#endif
|
||||
#if !defined(SWIFT_DEPRECATED_OBJC)
|
||||
# if __has_feature(attribute_diagnose_if_objc)
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
|
||||
# else
|
||||
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__OBJC__)
|
||||
#if !defined(IBSegueAction)
|
||||
# define IBSegueAction
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(SWIFT_EXTERN)
|
||||
# if defined(__cplusplus)
|
||||
# define SWIFT_EXTERN extern "C"
|
||||
# else
|
||||
# define SWIFT_EXTERN extern
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(SWIFT_CALL)
|
||||
# define SWIFT_CALL __attribute__((swiftcall))
|
||||
#endif
|
||||
#if !defined(SWIFT_INDIRECT_RESULT)
|
||||
# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result))
|
||||
#endif
|
||||
#if !defined(SWIFT_CONTEXT)
|
||||
# define SWIFT_CONTEXT __attribute__((swift_context))
|
||||
#endif
|
||||
#if !defined(SWIFT_ERROR_RESULT)
|
||||
# define SWIFT_ERROR_RESULT __attribute__((swift_error_result))
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
# define SWIFT_NOEXCEPT noexcept
|
||||
#else
|
||||
# define SWIFT_NOEXCEPT
|
||||
#endif
|
||||
#if !defined(SWIFT_C_INLINE_THUNK)
|
||||
# if __has_attribute(always_inline)
|
||||
# if __has_attribute(nodebug)
|
||||
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug))
|
||||
# else
|
||||
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline))
|
||||
# endif
|
||||
# else
|
||||
# define SWIFT_C_INLINE_THUNK inline
|
||||
# endif
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
|
||||
# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
|
||||
# define SWIFT_IMPORT_STDLIB_SYMBOL
|
||||
#endif
|
||||
#endif
|
||||
#if !__has_feature(nullability)
|
||||
# define _Nonnull
|
||||
# define _Nullable
|
||||
# define _Null_unspecified
|
||||
#elif !defined(__OBJC__)
|
||||
# pragma clang diagnostic ignored "-Wnullability-extension"
|
||||
#endif
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
# define _Nullable_result _Nullable
|
||||
#endif
|
||||
#if __has_feature(objc_modules)
|
||||
#if __has_warning("-Watimport-in-framework-header")
|
||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
|
||||
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
|
||||
#if __has_warning("-Wpragma-clang-attribute")
|
||||
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
#pragma clang diagnostic ignored "-Warc-bridge-casts-disallowed-in-nonarc"
|
||||
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma push_macro("any")
|
||||
# undef any
|
||||
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="WorkbenchReplacement",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
|
||||
# pragma pop_macro("any")
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma clang attribute pop
|
||||
#endif
|
||||
#if defined(__OBJC__)
|
||||
#if __has_feature(objc_modules)
|
||||
#if __has_warning("-Watimport-in-framework-header")
|
||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // defined(__OBJC__)
|
||||
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
|
||||
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
|
||||
#if __has_warning("-Wpragma-clang-attribute")
|
||||
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
#pragma clang diagnostic ignored "-Warc-bridge-casts-disallowed-in-nonarc"
|
||||
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma push_macro("any")
|
||||
# undef any
|
||||
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="WorkbenchReplacement",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
|
||||
# pragma pop_macro("any")
|
||||
#endif
|
||||
|
||||
#if defined(__OBJC__)
|
||||
|
||||
#endif // defined(__OBJC__)
|
||||
#if __has_attribute(external_source_symbol)
|
||||
# pragma clang attribute pop
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
#endif
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
-703
@@ -1,703 +0,0 @@
|
||||
[
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "Accessibility",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Accessibility.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "AppKit",
|
||||
"modulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/AppKit-H8IDH8MPDKFF.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "ColorSync",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/ColorSync.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "Combine",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Combine.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreAudio",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreAudio.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreData",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreData.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreFoundation",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreFoundation.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreGraphics",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreGraphics.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreImage",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreImage.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreMedia",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreMedia.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreText",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreText.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreTransferable",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreTransferable.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CoreVideo",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CoreVideo.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "CryptoKit",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/CryptoKit.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Darwin",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Darwin.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "DataDetection",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/DataDetection.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "DeveloperToolsSupport",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/DeveloperToolsSupport.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Dispatch",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Dispatch.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "Foundation",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Foundation.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "IOKit",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/IOKit.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "ImageIO",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/ImageIO.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "LocalAuthentication",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/LocalAuthentication.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Metal",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Metal.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "OSLog",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/OSLog.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ObjectiveC",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/ObjectiveC.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Observation",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Observation.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "QuartzCore",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/QuartzCore.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Spatial",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Spatial.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Swift",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Swift.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "SwiftOnoneSupport",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/SwiftOnoneSupport.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "SwiftUI",
|
||||
"modulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/SwiftUI-3PKZHEDTAMMUE.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "SwiftUICore",
|
||||
"modulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/SwiftUICore-2XTMXI6ZSN5EQ.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : true,
|
||||
"moduleName" : "Symbols",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Symbols.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Synchronization",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/Synchronization.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "System",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/System.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "UniformTypeIdentifiers",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/UniformTypeIdentifiers.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "XPC",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/XPC.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_float",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_Builtin_float.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Concurrency",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_Concurrency.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation1",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_DarwinFoundation1.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation2",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_DarwinFoundation2.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation3",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_DarwinFoundation3.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_StringProcessing",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/_StringProcessing.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "os",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/os.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"isFramework" : false,
|
||||
"moduleName" : "simd",
|
||||
"modulePath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/swift\/macosx\/prebuilt-modules\/27.0\/simd.swiftmodule\/arm64e-apple-macos.swiftmodule"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/Accessibility.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Accessibility-DPGX2NRWMX0O48TTI8LGUX618.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Accessibility"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/AppKit.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/AppKit-CL9YTLJPOU9I6ZH8JT9DWO0D4.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "AppKit"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/ApplicationServices.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ApplicationServices-3BSKXHGPFFJGNJDUX4MJHAROJ.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ApplicationServices"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CFNetwork.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CFNetwork-PPAEVAYES3T1V01FG7N3BQIG.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CFNetwork"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/cups.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CUPS-57WLPWZ0ACOTR94MV37RVAV5N.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CUPS"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/ColorSync.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ColorSync-5IMHY8TOW2LEQC89ZGQZ3SE2.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ColorSync"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/CommonCrypto\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CommonCrypto-8EIK622R16HUB1HTESZKO8X91.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CommonCrypto"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreAudio.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreAudio-2T82IY3GJUAOBV3GCM185L413.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreAudio"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreAudioTypes.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreAudioTypes-414FRUDUSHE0NKQXWMBAKZ0LB.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreAudioTypes"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreData.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreData-365S85DEAB5MO16ZWK6H24GK0.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreData"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreFoundation.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreFoundation-5FDPRYALLSNT3V14CJHZFSENJ.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreFoundation"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreGraphics.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreGraphics-8M433BZBPSU56NLVMEW2VRNO3.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreGraphics"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreImage.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreImage-FGQVU0R8OIEEQIIUMDUUILMU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreImage"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreMedia.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreMedia-2FJXBVBJME8JU66536CKRAKPM.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreMedia"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreServices.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreServices-CFUHL0JHQ5BZ6JO9EU6U9ZFT2.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreServices"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreText.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreText-E1R0W0Y9CSZ897CAZN8WPG95C.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreText"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreTransferable.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreTransferable-3HTTC4B6RSGI7AMY7J9UNT2US.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreTransferable"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/CoreVideo.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/CoreVideo-EJL32H99KVX6Y1J5TJJGEMK5S.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "CoreVideo"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/Darwin.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Darwin-6KN4I1VCULLK6EFH4J9ITQ32R.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Darwin"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/DataDetection.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/DataDetection-4TKH0FTJUHLMOGOBICYVY82SJ.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "DataDetection"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/DeveloperToolsSupport.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/DeveloperToolsSupport-2G0OY5Y6O2AVW1VZ8C54EDQ9O.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "DeveloperToolsSupport"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/DiskArbitration.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/DiskArbitration-UH5H15Q4SG0MDJZNRGQDQ6UF.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "DiskArbitration"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/dispatch.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Dispatch-E168X8VQFIKYVAVVFOVYO15WH.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Dispatch"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/Foundation.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Foundation-7EMR5SDFA90I2YC1MIW01MOVL.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Foundation"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/IOKit.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/IOKit-DKQW29SB1ZTDE6ZAO5AADMA1S.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "IOKit"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/IOSurface.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/IOSurface-8ZVH3UFJ5E2RSXE7HEG17X5FN.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "IOSurface"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/ImageIO.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ImageIO-5J9HQ8F6U459VGN562S803HL5.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ImageIO"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/LocalAuthentication.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/LocalAuthentication-678PKH1D7S8W88AP15VFRNL98.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "LocalAuthentication"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinBasic.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/MachO-9GGXQQ5TIOCIBWIKR2CCZVSB1.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "MachO"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/Metal.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Metal-CT6H1MCTUNZDQSSNO61HFZLZE.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Metal"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/OSLog.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/OSLog-1693B6K17WI8Y5EYR3IJ2T13T.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "OSLog"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/ObjectiveC.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ObjectiveC-AYKBDSM6QHPMDWDQLVOZLM6LD.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ObjectiveC"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/OpenGL.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/OpenGL-1OAFZ5HF502S7XTONQ752M7MU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "OpenGL"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/QuartzCore.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/QuartzCore-D5VLT03F69HLIRAW7N9WCLS9Z.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "QuartzCore"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/Security.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Security-DRBVTNEPIZ0WOLQMXCDMTFKBD.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Security"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/Spatial\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Spatial-AORHAWQKQRCNZZE216QZ3LCWU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Spatial"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/lib\/swift\/shims\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/SwiftShims-7GQFCGGUXRYXHOVDWLS4DMRNU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "SwiftShims"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/SwiftUI.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/SwiftUI-XIL8POI980N33K0HETUJTYDG.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "SwiftUI"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/SwiftUICore.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/SwiftUICore-2Y04G6WWMZE8UDANXA2Y6OQEU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "SwiftUICore"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/Symbols.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/Symbols-9PHANA662J50AKDDU8SRE4Y2D.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "Symbols"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/System\/Library\/Frameworks\/UniformTypeIdentifiers.framework\/Modules\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/UniformTypeIdentifiers-5ZR71CNS0PF9KPP6CSDEK2SX4.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "UniformTypeIdentifiers"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/xpc.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/XPC-609XYKDGD6VXBC8ARWLTD1K49.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "XPC"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinFoundation1.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_AvailabilityInternal-DKCAO3K87LF31T67852G4DCJU.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_AvailabilityInternal"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_float-EMCOHEFNTJPICZJEFV6RJZ3O3.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_float"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_intrinsics-30FCRZ78EOU6JJIEWGYNNBAIA.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_intrinsics"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_inttypes-BHRGBMFO3Y6Q68VJPDIUTRYH6.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_inttypes"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_limits-6TTNDEB7UHOY33LFSFD6F36XJ.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_limits"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_stdarg-4EY8XNKQUAC345WEPR6YBEEA4.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_stdarg"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_stdatomic-1W7MP7XGF46FPBZMA5Z6NQTUB.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_stdatomic"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_stdbool-F6HY6XDJX8IQ935YV5ERYU9E.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_stdbool"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_stddef-7F2EHY6ITPAN3FM4F9L17B9SR.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_stddef"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_stdint-BBZI8293S6ROM23BKB4RS2NSA.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_stdint"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_Builtin_tgmath-BAAFSB9DEIVSNDPQ8KGQEA8A0.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_Builtin_tgmath"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinFoundation1.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_DarwinFoundation1-5MMHZM1WLEH8G5195181RF2VF.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation1"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinFoundation2.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_DarwinFoundation2-19ZVNUJ7MLO2RCUPM8UA9VF3D.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation2"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinFoundation3.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_DarwinFoundation3-8I77NUEUT13L61MIP7TBMS25A.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_DarwinFoundation3"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/lib\/swift\/shims\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/_SwiftConcurrencyShims-7I99W7D71NF1LKBY35KVIA9NI.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "_SwiftConcurrencyShims"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/launch.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/launch-EU5LE79LSVQWWZOXH11UNBYFC.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "launch"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/libDER\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/libDER-62KN659C29YNFUT2A79HM56GL.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "libDER"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/libkern.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/libkern-7N5WSDNOM8I5Q6ZE8VEO29KQF.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "libkern"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/os.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/os-2NYCDUKGDWWQRNK44ZTXFZ9NI.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "os"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/os.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/os_object-5BQFHOYI9T655N8MK6JDC0RKP.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "os_object"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/os.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/os_workgroup-1K6BHLEB7QAP14LQLYM4LWLB4.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "os_workgroup"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ptrauth-5IQJJRW7TMKUKMSELKTCUEWHP.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ptrauth"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/lib\/clang\/21\/include\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/ptrcheck-5X00TZ58XUX1IWW1ENLNN66D0.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "ptrcheck"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/simd\/module.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/simd-7S4CBA41E3B1FEXRLQHTT3K03.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "simd"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/c_standard_library.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/string_h-5S5KP08DIY39WNXXUI87DWVY3.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "string_h"
|
||||
},
|
||||
{
|
||||
"clangModuleMapPath" : "\/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX.sdk\/usr\/include\/DarwinFoundation2.modulemap",
|
||||
"clangModulePath" : "\/Volumes\/Developer\/Applications\/WorkbenchReplacement\/build\/SDKExplicitPrecompiledModules\/sys_types-9HGMUOK1SMV8T2HBR01FGBU22.pcm",
|
||||
"isBridgingHeaderDependency" : false,
|
||||
"isFramework" : false,
|
||||
"moduleName" : "sys_types"
|
||||
}
|
||||
]
|
||||
BIN
Binary file not shown.
-4
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftconstvalues
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/App.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MainView.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/DatabaseModel.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MySQLProtocol.swift
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ABIRoot": {
|
||||
"kind": "Root",
|
||||
"name": "NO_MODULE",
|
||||
"printedName": "NO_MODULE",
|
||||
"json_format_version": 8
|
||||
},
|
||||
"ConstValues": []
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
-1
@@ -1 +0,0 @@
|
||||
["AnyResolverProviding","AppEntity","AppEnum","AppExtension","AppIntent","AppIntentsPackage","AppShortcutProviding","AppShortcutsProvider","AppUnionValue","AppUnionValueCasesProviding","DynamicOptionsProvider","EntityQuery","ExtensionPointDefining","IntentValueQuery","Resolver","TransientEntity","_AssistantIntentsProvider","_GenerativeFunctionExtractable","_IntentValueRepresentable"]
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
-1
@@ -1 +0,0 @@
|
||||
@rpath/WorkbenchReplacement.debug.dylib
|
||||
-1
@@ -1 +0,0 @@
|
||||
WorkbenchReplacement.debug.dylib
|
||||
-1
@@ -1 +0,0 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/libPreviewsJITStubExecutor.a
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.get-task-allow</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
-1
@@ -1 +0,0 @@
|
||||
p-°(0&!com.apple.security.get-task-allowÿ
|
||||
BIN
Binary file not shown.
-5
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
-1
@@ -1 +0,0 @@
|
||||
@rpath/WorkbenchReplacement.debug.dylib
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"" : {
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.dia",
|
||||
"emit-module-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-emit-module.d",
|
||||
"emit-module-diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-emit-module.dia",
|
||||
"pch" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary-Bridging-header.pch",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/WorkbenchReplacement-primary.swiftdeps"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/App.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/DatabaseModel.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MainView.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView~partial.swiftmodule"
|
||||
},
|
||||
"/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MySQLProtocol.swift" : {
|
||||
"const-values" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftconstvalues",
|
||||
"dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.d",
|
||||
"diagnostics" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.dia",
|
||||
"index-unit-output-path" : "/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o",
|
||||
"llvm-bc" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.bc",
|
||||
"object" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o",
|
||||
"swift-dependencies" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftdeps",
|
||||
"swiftmodule" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol~partial.swiftmodule"
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
-1
@@ -1 +0,0 @@
|
||||
{"case-sensitive":"false","roots":[],"version":0}
|
||||
-1
@@ -1 +0,0 @@
|
||||
["AnyResolverProviding","AppEntity","AppEnum","AppExtension","AppIntent","AppIntentsPackage","AppShortcutProviding","AppShortcutsProvider","AppUnionValue","AppUnionValueCasesProviding","DynamicOptionsProvider","EntityQuery","ExtensionPointDefining","IntentValueQuery","Resolver","TransientEntity","_AssistantIntentsProvider","_GenerativeFunctionExtractable","_IntentValueRepresentable"]
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.o
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.o
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/App.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MainView.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/DatabaseModel.swiftconstvalues
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/WorkbenchReplacement.build/Debug/WorkbenchReplacement.build/Objects-normal/arm64/MySQLProtocol.swiftconstvalues
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/App.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MainView.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/DatabaseModel.swift
|
||||
/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement/MySQLProtocol.swift
|
||||
-1
@@ -1 +0,0 @@
|
||||
WorkbenchReplacement.debug.dylib
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.get-task-allow</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
Binary file not shown.
-66
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"buildCommand" : {
|
||||
"command" : "build",
|
||||
"skipDependencies" : false,
|
||||
"style" : "buildOnly"
|
||||
},
|
||||
"configuredTargets" : [
|
||||
{
|
||||
"guid" : "34f2007b1d0798da0712fb82baec90fb2878cdfbaa5fcb5fa30c8485a83dfb14"
|
||||
}
|
||||
],
|
||||
"containerPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/WorkbenchReplacement.xcodeproj",
|
||||
"continueBuildingAfterErrors" : false,
|
||||
"dependencyScope" : "workspace",
|
||||
"enableIndexBuildArena" : false,
|
||||
"hideShellScriptEnvironment" : false,
|
||||
"parameters" : {
|
||||
"action" : "build",
|
||||
"activeArchitecture" : "arm64",
|
||||
"activeRunDestination" : {
|
||||
"disableOnlyActiveArch" : false,
|
||||
"hostTargetedPlatform" : null,
|
||||
"platform" : "macosx",
|
||||
"sdk" : "macosx27.0",
|
||||
"sdkVariant" : "macos",
|
||||
"supportedArchitectures" : [
|
||||
"arm64e",
|
||||
"arm64",
|
||||
"x86_64"
|
||||
],
|
||||
"targetArchitecture" : "arm64"
|
||||
},
|
||||
"arenaInfo" : {
|
||||
"buildIntermediatesPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex",
|
||||
"buildProductsPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Products",
|
||||
"derivedDataPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build",
|
||||
"indexDataStoreFolderPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Index.noindex/DataStore",
|
||||
"indexEnableDataStore" : true,
|
||||
"indexPCHPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Index.noindex/PrecompiledHeaders",
|
||||
"pchPath" : "/Volumes/Developer/Applications/WorkbenchReplacement/build/Build/Intermediates.noindex/PrecompiledHeaders"
|
||||
},
|
||||
"configurationName" : "Debug",
|
||||
"overrides" : {
|
||||
"commandLine" : {
|
||||
"table" : {
|
||||
|
||||
}
|
||||
},
|
||||
"synthesized" : {
|
||||
"table" : {
|
||||
"ACTION" : "build",
|
||||
"ENABLE_PREVIEWS" : "NO",
|
||||
"ENABLE_XOJIT_PREVIEWS" : "YES",
|
||||
"ONLY_ACTIVE_ARCH" : "YES",
|
||||
"TOOLCHAINS" : "com.apple.dt.toolchain.Metal.32023.921.5 $(inherited)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schemeCommand" : "launch",
|
||||
"showNonLoggedProgress" : true,
|
||||
"useDryRun" : false,
|
||||
"useImplicitDependencies" : true,
|
||||
"useLegacyBuildLocations" : false,
|
||||
"useParallelTargets" : true
|
||||
}
|
||||
BIN
Binary file not shown.
-1
File diff suppressed because one or more lines are too long
-2
@@ -1,2 +0,0 @@
|
||||
Target dependency graph (1 target)
|
||||
Target 'WorkbenchReplacement' in project 'WorkbenchReplacement' (no dependencies)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user