{"id":976,"url":"https://github.com/phimage/Prephirences","last_synced_at":"2025-08-06T13:32:19.644Z","repository":{"id":30837801,"uuid":"34395245","full_name":"phimage/Prephirences","owner":"phimage","description":"Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state. UserDefaults","archived":false,"fork":false,"pushed_at":"2023-05-23T19:24:22.000Z","size":1016,"stargazers_count":573,"open_issues_count":4,"forks_count":35,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-30T01:38:07.487Z","etag":null,"topics":["configuration","ios","ios-swift","keychain","plist","preferences","property-wrapper","swift","userdefaults"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phimage.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"phimage","patreon":"phimage","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2015-04-22T14:29:37.000Z","updated_at":"2024-09-26T02:32:43.000Z","dependencies_parsed_at":"2024-01-29T17:08:04.746Z","dependency_job_id":null,"html_url":"https://github.com/phimage/Prephirences","commit_stats":{"total_commits":143,"total_committers":12,"mean_commits":"11.916666666666666","dds":0.5734265734265734,"last_synced_commit":"333728f812c30e6e06519b06ed34cea75d9fc701"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phimage%2FPrephirences","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phimage%2FPrephirences/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phimage%2FPrephirences/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phimage%2FPrephirences/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phimage","download_url":"https://codeload.github.com/phimage/Prephirences/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905457,"owners_count":17989771,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","ios","ios-swift","keychain","plist","preferences","property-wrapper","swift","userdefaults"],"created_at":"2024-01-05T20:15:36.092Z","updated_at":"2024-12-09T14:30:48.970Z","avatar_url":"https://github.com/phimage.png","language":"Swift","readme":"# Prephirences - Preϕrences\n\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://mit-license.org)\n[![Platform](http://img.shields.io/badge/platform-ios_osx_tvos-lightgrey.svg?style=flat)](https://developer.apple.com/resources/)\n[![Language](http://img.shields.io/badge/language-swift-orange.svg?style=flat)](https://developer.apple.com/swift)\n[![Issues](https://img.shields.io/github/issues/phimage/Prephirences.svg?style=flat)](https://github.com/phimage/Prephirences/issues)\n[![Cocoapod](http://img.shields.io/cocoapods/v/Prephirences.svg?style=flat)](http://cocoadocs.org/docsets/Prephirences/)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Build Status](https://travis-ci.org/phimage/Prephirences.svg)](https://travis-ci.org/phimage/Prephirences)\n\n\u003ca href=\"https://www.patreon.com/phimage\"\u003e\n\u003cimg src=\"https://c5.patreon.com/external/logo/become_a_patron_button.png\" alt=\"Become a Patron!\" height=\"35\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://paypal.me/ericphimage\"\u003e\n\u003cimg src=\"https://buymecoffee.intm.org/img/button-paypal-white.png\" alt=\"Buy me a coffee\" height=\"35\"\u003e\n\u003c/a\u003e\n\n[\u003cimg align=\"left\" src=\"logo.png\" hspace=\"20\"\u003e](#logo) Prephirences is a Swift library that provides useful protocols and convenience methods to manage application preferences, configurations and app-state.\n\n```swift\n  @Preference(key: \"enabled\")\n  var enabled: Bool?\n\n  @UserDefaultsPreference(key: \"my.string.pref\")\n  var pref: String?\n\n  @MutablePreference(preferences: UserDefaults.standard, key: \"enabled\")\n  var enabled: Bool?\n```\n\n```swift\nlet userDefaults = UserDefaults.standard\nif let enabled = userDefaults[\"enabled\"] as? Bool {..}\nuserDefaults[\"mycolorkey\", archive] = UIColor.blue\n```\n\nPreferences is not only `UserDefaults`, it could be also :\n\n- [Keychain](https://en.wikipedia.org/wiki/Keychain_%28software%29) to store credential\n- Any dictionary\n- Application information from `Bundle`\n- File stored preferences (ex: *[plist](http://en.wikipedia.org/wiki/Property_list)*)\n- iCloud stored preferences `NSUbiquitousKeyValueStore`\n- or your own private application preferences\n\nie. any object which implement the simple protocol [PreferencesType](/Prephirences/PreferencesType.swift), which define key value store methods.\n\nYou can also **combine multiples preferences** and work with them transparently (see [Composing](#composing))\n\n## Contents ##\n\n- [Usage](#usage)\n  - [Creating](#creating) • [Accessing](#accessing) • [Modifying](#modifying) • [Transformation and Archiving](#transformation-and-archiving)\n  - [Some implementations](#some-implementations)\n    - [UserDefaults](#userdefaults) • [Bundle](#bundle) • [NSUbiquitousKeyValueStore](#nsubiquitouskeyvaluestore) • [Key Value Coding](#key-value-coding) • [Core Data](#core-data) • [Plist](#plist) • [Keychain](#keychain) • [NSCoder](#nscoder)\n  - [Custom implementations](#custom)\n  - [Proxying preferences with prefix](#proxying-preferences-with-prefix)\n  - [Composing](#composing)\n  - [Managing preferences instances](#managing-preferences-instances)\n  - [Remote preferences](#remote-preferences)\n  - [Encrypt your preferences](#encrypt-your-preferences)\n- [Setup](#setup)\n  - [Using Cocoapods](#using-cocoapods) • [Using Carthage](#using-carthage) • [Using xcode project](#using-xcode-project)\n- [Logo](#logo)\n\n# Usage #\n\n## Creating ##\n\nThe simplest implementation of [PreferencesType](/Prephirences/PreferencesType.swift) is [DictionaryPreferences](/Prephirences/DictionaryPreferences.swift)\n\n```swift\n// From Dictionary\nvar fromDico = DictionaryPreferences(myDictionary)\n// or literal\nvar fromDicoLiteral: DictionaryPreferences = [\"myKey\": \"myValue\", \"bool\": true]\n\n// From filepath\nif let fromFile = DictionaryPreferences(filePath: \"/my/file/path\") {..}\n// ...in main bundle ##\nif let fromFile = DictionaryPreferences(filename: \"prefs\", ofType: \"plist\") {..}\n```\n\n## Accessing ##\n\nYou can access with all methods defined in [PreferencesType](/Prephirences/PreferencesType.swift) protocol\n\n```swift\nif let myValue = fromDicoLiteral.object(forKey: \"myKey\") {..}\nif let myValue = fromDicoLiteral[\"bool\"] as? Bool {..}\n\nvar hasKey = fromDicoLiteral.hasObject(forKey: \"myKey\")\nvar myValue = fromDicoLiteral.bool(forKey: \"myKey\")\n..\n\n```\n\nIf you want to access using `RawRepresentable` `enum`.\n\n```swift\nenum MyKey: PreferenceKey/*String*/ {\n   case Key1, Key2, ...\n}\nif let myValue = fromDicoLiteral.object(forKey: MyKey.Key1) {..}\nvar myValue = fromDicoLiteral.bool(forKey: MyKey.Key2)\n\n```\n\n:warning: [RawRepresentableKey](/Prephirences/RawRepresentableKey/RawRepresentable+Prephirences.swift) must be imported, see [setup](#for-rawrepresentable-key).\n\n## Modifying ##\n\nModifiable preferences implement the protocol [MutablePreferencesTypes](/Prephirences/PreferencesType.swift)\n\nThe simplest implementation is [MutableDictionaryPreferences](/Prephirences/DictionaryPreferences.swift)\n\n```swift\nvar mutableFromDico: MutableDictionaryPreferences = [\"myKey\": \"myValue\"]\n\nmutableFromDico[\"newKey\"] = \"newValue\"\nmutableFromDico.set(\"myValue\", forKey: \"newKey\")\nmutableFromDico.set(true, forKey: \"newKey\")\n...\n```\n\nYou can append dictionary or other `PreferencesType` using operators\n\n```swift\nmutableFromDico += [\"newKey\": \"newValue\", \"otherKey\": true]\n```\n\nYou can also remove one preference\n\n```swift\nmutableFromDico -= \"myKey\"\n```\n\n### Apply operators to one preference ###\n\nYou can extract a `MutablePreference` from any `MutablePreferencesTypes` and apply operators according to its value type\n\n```swift\nvar intPref: MutablePreference\u003cInt\u003e = aPrefs.preference(forKey: \"intKey\")\nvar intPref: MutablePreference\u003cInt\u003e = aPrefs \u003c| \"intKey\"\n\nintPref++\nintPref--\nintPref += 30\nintPref -= 30\nintPref *= 20\nintPref %= 7\nintPref /= 3\n\nswitch(intPref) {\n   case 1: println(\"one\")\n   case 2...10: println(\"not one or zero but...\")\n   default: println(\"unkwown\")\n}\n\nvar boolPref: MutablePreference\u003cBool\u003e = aPrefs \u003c| \"boolKey\")\n\nboolPref \u0026= false\nboolPref |= true\nboolPref != true\n\n```\n\nYou can also use some methods to change value\n\n```swift\nvar stringPref: MutablePreference\u003cString\u003e = userDefaults \u003c| \"stringKey\"\nstringPref.apply { value in\n  return value?.uppercaseString\n}\n```\n\nor transform the value type using closures\n\n```swift\nlet intFromBoolPref : MutablePreference\u003cInt\u003e = boolPref.transform { value in\n  return (value ?? false) ? 1:0\n}\n```\n\n## Transformation and archiving ##\n\nBefore storing or accessing the value, transformation could be applied, which conform to protocol `PreferenceTransformation`.\n\nThis allow to archive, to change type, return default value if nil and many more.\n\nYou can get and set value using `subscript`\n\n```swift\nuserDefaults[\"aKey\", myTransformation] = myObject\n\nif let object = userDefaults[\"aKey\", myTransformation] {...}\n```\n\nIf you extract one preference, use `transformation` property to setup the transformation\n\n```swift\nvar aPref: MutablePreference\u003cMyObject\u003e = userDefaults \u003c| \"aKey\"\naPref.transformation = myTransformation\n```\n\nor you can use some utility functions to specify a default value when the stored value match a condition\n\n```swift\npublic var intValueMin10: MutablePreference\u003cInt\u003e {\n  get {\n    return userDefaults.preference(forKey: \"intKey\")\n          .whenNil(use: 100)\n          .ensure(when: lessThan100, use: 100)\n  }\n  set {..}\n}\n```\n\n### Archiving\n\nArchiving is particularly useful with `NSUserDefaults` because `NSUserDefaults` can't store all type of objects.\nThe following functions could help by transforming the value into an other type\n\nYou can archive into `Data` using this two methods\n\n```swift\nuserDefaults.set(objectToArchive: UIColor.blueColor(), forKey: \"colorKey\")\nuserDefaults[\"colorKey\", .Archive] = UIColor.blueColor()\n```\n\nand unarchive using\n\n```swift\nif let color = userDefaults.unarchiveObject(forKey: \"colorKey\") as? UIColor {..}\nif let color = userDefaults[\"colorKey\", .Archive]  as? UIColor {..}\n```\n\nIf you extract one preference, use `transformation` property to setup archive mode\n\n```swift\nvar colorPref: MutablePreference\u003cUIColor\u003e = userDefaults \u003c| \"colorKey\"\ncolorPref.transformation = TransformationKey.Archive\ncolorPref.value = UIColor.redColor()\nif let color = colorPref.value as? UIColor {..}\n```\n\n### NSValueTransformer\n\nYou can also apply for all objects type an [`NSValueTransformer`](https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSValueTransformer_Class/index.html), to transform into JSON for instance\n\n```swift\nuserDefaults[\"colorKey\", myValueTransformerToJson] = myComplexObject\n\nif let object = userDefaults[\"colorKey\", myValueTransformerToJson] {...}\n```\n\n:warning: `allowsReverseTransformation` must return `true`\n\n### Store RawRepresentable objects\n\nFor `RawRepresentable` objects like `enum` you can use the computed attribute `preferenceTransformation` as `transformation`\n\n```swift\nenum PrefEnum: String {\n    case One, Two, Three\n}\nvar pref: MutablePreference\u003cPrefEnum\u003e = preferences \u003c| \"enumKey\"\npref.transformation = PrefEnum.preferenceTransformation\npref.value = PrefEnum.Two\n```\n\n## Some implementations ##\n\n### UserDefaults ###\n\n`UserDefaults` implement `PreferencesType` and can be acceded with same methods\n\n```swift\nlet userDefaults = UserDefaults.standard\n\nif let myValue = userDefaults[\"mykey\"] as? Bool {..}\n```\n\nNSUserDefaults implement also `MutablePreferencesType` and can be modified with same methods\n\n```swift\nuserDefaults[\"mykey\"] = \"myvalue\"\n// with type to archive\nuserDefaults[\"mykey\", .Archive] = UIColor.blueColor()\n```\n\n### Bundle ###\n\nAll `Bundle` implement `PreferencesType`, allowing to access Info.plist file.\n\nFor instance the `Bundle.main` contains many useful informations about your application.\n\nPrephirences framework come with some predefined enums described in [apple documentations](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html) and defined in `PropertyListKeys.swift`\n\n```swift\nlet bundle = Bundle.main\nlet applicationName = bundle[.CFBundleName] as? String\n```\n\n### NSUbiquitousKeyValueStore ###\nTo store in iCloud, `NSUbiquitousKeyValueStore` implement also `PreferencesType`\n\nSee composing chapter to merge and synchronize iCloud preferences with other preferences.\n\n### Key Value Coding ###\n\n#### Foundation classes\n\nYou can wrap an object respond to implicit protocol [NSKeyValueCoding](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html) in `KVCPreferences` or `MutableKVCPreferences`\n\n```swift\nlet kvcPref = MutableKVCPreferences(myObject)\n```\nBe sure to affect the correct object type\n\n#### Swift classes\n\nUsing `ReflectingPreferences` you can easily access to a struct or swift class. Just add extension.\n\n```swift\nstruct PreferenceStruct {\n    var color: String = \"red\"\n    var age: Int\n    let enabled: Bool = true\n}\nextension PreferenceStruct: ReflectingPreferences {}\n```\n\nYou can then use all functions from `PreferencesType`\n\n```\nvar pref = PreferenceStruct(color: \"red\", age: 33)\nif pref[\"color\"] as? String { .. }\n```\n\n### Core Data ###\n\nYou can wrap on `NSManageObject` in `ManageObjectPreferences` or `MutableManageObjectPreferences`\n\n```swift\nlet managedPref = ManageObjectPreferences(myManagedObject)\n```\n\n### Plist ###\n\nThere is many way to play with plist files\n\n- You can use `Plist` (with the useful `write` method)\n- You can init `DictionaryPreferences` or `MutableDictionaryPreferences` with plist file\n- You can read dictionary from plist file and use `set(dictionary: ` on any mutable preferences\n\n### Keychain ###\n\nTo store into keychain, use an instance of ```KeychainPreferences```\n\n```swift\nKeychainPreferences.sharedInstance // default instance with main bundle id\nvar keychain = KeychainPreferences(service: \"com.github.example\")\n```\n\nthen store `String` or `Data`\n\n```swift\nkeychain[\"anUserName\"] = \"password-encoded\"\n\nif let pass = keychain.stringForKey(\"anUserName\") {..}\n```\n\n**Accessibility**\n\n```swift\nkeychain.accessibility = .AccessibleAfterFirstUnlock\n```\n\n**Sharing Keychain items**\n\n```swift\nkeychain.accessGroup = \"AKEY.shared\"\n```\n\n### NSCoder ###\n\n`NSCoder` is partially supported (`dictionary` is not available)\n\nWhen you implementing [NSCoding](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/) you can do\n\n```swift\ninit?(coder decoder: NSCoder) {\n  self.init()\n  self.intVar = decoder[\"intVarKey\"] as? Int ?? 0\n  // or self.intVar = decoder.integer(forKey: \"intVar\")\n  self.stringVar = decoder[\"stringVarKey\"] as? String ?? \"\"\n}\n\nfunc encodeWithCoder(coder: NSCoder) {\n  coder[\"intVarKey\"] = self.intVar\n  coder[\"stringVarKey\"] = self.stringVar\n}\n\n```\n\n## Custom implementations ##\n\n### Preferences\n\nCreate a custom object that conform to `PreferencesType` is very easy.\n\n```swift\nextension MyCustomPreferences: PreferencesType {\n    func object(forKey: String) -\u003e Any? {\n        // return an object according to key\n    }\n    func dictionary() -\u003e [String : Any] {\n        // return a full dictionary of key value\n    }\n}\n```\n\nOnly two functions are mandatory, others are automatically mapped but can be overrided for performance or readability.\n\n- In the same way you can implement `MutablePreferencesType` with `set` and `removeObject(forKey:` methods.\n- If you structure give a list of keys instead of a full dictionary, you can instead conform to `PreferencesAdapter` and implement `func keys() -\u003e [String]`.\n- You have a collection of object with each object could define a key and a value take a look at `CollectionPreferencesAdapter` or see `NSHTTPCookieStorage` implementation.\n\n### Accessing using custom key\n\nInstead of using `string` or `string` constants, you can use an `enum` to define a list of keys\n\nFirst create your `enum` with `String` raw value\n\n```swift\nenum MyEnum: String {\n  case MyFirstKey\n  case MySecondKey\n}\n```\n\nThen add a subscript for your key\n\n```swift\nextension PreferencesType {\n    subscript(key: MyEnum) -\u003e Any? {\n        return self[key.rawValue]\n    }\n}\n```\n\nFinally access your information\n\n```swift\nif let firstValue = bundle[.MyFirstKey] {..}\n```\n\nYou can do the same with `MutablePreferencesType`\n\n## Proxying preferences with prefix ##\n\nYou can defined a subcategory of preferences prefixed with your own string like that\n\n```swift\nlet myAppPrefs = MutableProxyPreferences(preferences: userDefaults, key: \"myAppKey.\")\n// We have :\nuserDefaults[\"myAppKey.myKey\"] == myAppPrefs[\"myKey\"] // is true\n```\n\nThis allow prefixing all your preferences (user defaults) with same key\n\n## Composing ##\n\nComposing allow to aggregate multiples PreferencesType objects into one PreferencesType\n\n```swift\nlet myPreferences = CompositePreferences([fromDico, fromFile, userDefaults])\n// With array literal\nlet myPreferences: CompositePreferences = [fromDico, fromFile, userDefaults]\n\n// Mutable, only first mutable will be affected\nlet myPreferences: MutableCompositePreferences = [fromDico, fromFile, userDefaults]\n```\n\nYou can access or modify this composite preferences like  any `PreferencesType`.\n\n1. When accessing, first preferences that define a value for a specified key will respond\n2. When modifying, first mutable preferences will be affected by default, but you can set `MutableCompositePreferences` attribute `affectOnlyFirstMutable` to `false` to affect all mutable preferences, allowing you for instance to duplicate preferences in iCloud\n\nThe main goal is to define read-only preferences for your app (in code or files) and some mutable preferences (like `UserDefaults`, `NSUbiquitousKeyValueStore`). You can then access to one preference value without care about the origin.\n\n## Managing preferences instances ##\n\nIf you want to use Prephirences into a framework or want to get a `Preferences` without adding dependencies between classes, you can register any `PreferencesType` into `Prephirences`\n\nas shared instance\n\n```swift\nPrephirences.sharedInstance = myPreferences\n```\n\n or by providing an `Hashable` key\n\n```swift\nPrephirences.register(preferences: myPreferences, forKey: \"myKey\")\nPrephirences.instances()[\"myKey\"] = myPreferences\nPrephirences.instances()[NSStringFromClass(self.dynamicType)] = currentClassPreferences\n```\n\nThen you can access it anywhere\n\n```swift\nif let pref = Prephirences.instance(forKey: \"myKey\") {..}\nif let pref = Prephirences.instances()[\"myKey\"] {..}\n```\n\n## Remote preferences ##\n\nBy using remote preferences you can remotely control the behavior of your app.\n\nIf you use [Alamofire](https://github.com/Alamofire/Alamofire), [Alamofire-Prephirences](https://github.com/phimage/Alamofire-Prephirences) will help you to load preferences from remote JSON or Plist\n\n## Encrypt your preferences ##\nYou can use framework [CryptoPrephirences](https://github.com/phimage/CryptoPrephirences) to encrypt/decrypt your preferences using cipher from [CryptoSwift](https://github.com/krzyzanowskim/CryptoSwift)\n\n# Setup #\n\n## Using Cocoapods ##\n[CocoaPods](https://cocoapods.org/) is a centralized dependency manager for\nObjective-C and Swift. Go [here](https://guides.cocoapods.org/using/index.html)\nto learn more.\n\n1. Add the project to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html).\n\n    ```ruby\n    use_frameworks!\n\n    pod 'Prephirences'\n    ```\n\n2. Run `pod install` and open the `.xcworkspace` file to launch Xcode.\n\n### For core data ###\n\nAdd `pod 'Prephirences/CoreData'`\n\n### For RawRepresentable key ###\n\nAdd `pod 'Prephirences/RawRepresentableKey'`\n\n### For PropertyListKeys ###\n\nAdd `pod 'Prephirences/Keys'`\n\n## Using Carthage ##\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager for Objective-C and Swift.\n\n1. Add the project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile).\n\n    ```\n    github \"phimage/Prephirences\"\n    ```\n\n2. Run `carthage update` and follow [the additional steps](https://github.com/Carthage/Carthage#getting-started)\n   in order to add Prephirences to your project.\n\n## Using xcode project ##\n\n1. Drag Prephirences.xcodeproj to your project/workspace or open it to compile it\n2. Add the Prephirences framework to your project\n\n# Logo #\nBy [kodlian](http://www.kodlian.com/)\n","funding_links":["https://github.com/sponsors/phimage","https://patreon.com/phimage","https://www.patreon.com/phimage","https://paypal.me/ericphimage"],"categories":["Database","Libs","Data Management [🔝](#readme)"],"sub_categories":["Getting Started","Data Management","Other free courses","Linter"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphimage%2FPrephirences","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphimage%2FPrephirences","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphimage%2FPrephirences/lists"}