Skip to content
Tool for processing common constants and assets between projects. Example use case is between iOS and Android. Takes a source JSON and copies files, and outputs a Swift and Java file for use.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Sango.xcodeproj
Source
images
test_example
.gitignore
.swift-version
LICENSE
Makefile
README.md

README.md

sango

Tool for processing common app constants and assets for iOS and Android. Takes a source JSON and copies files, and outputs a Swift and Java file for use.

Sango Pipeline

We have a need to share constants, and assets between iOS, Android and web projects. One solution that has worked well has a 3rd git depot that contains shared assets, and a source JSON file that is parsed by a tool for each platform.

Sango standardizes localization by using the iOS key/value format, and when writing out, transforms the source into XML for Android, and copies for iOS. For web a JSON format.

Basic data spec:
{
	"schemaVersion": 1,
	"java": {
		"package": "io.afero.example",
		"launcher_icon_name": "android_launcher_icon",
		"base": "Constants"
	},
	"swift": {
		"base": "Constants"
	},
	"javascript": {
		"base": "Constants"
	},
	"locale": {
		"default": "assets/locale/en.strings",
		"de": "assets/locale/de.strings",
		"it": "assets/locale/it.strings",
		"jp": "assets/locale/jp.strings"
	},
	"fonts": [
		"assets/GT-Walsheim-Black-Oblique.ttf",
		"assets/GT-Walsheim-Black.ttf"
	],
	"appIconAndroid": "assets/app_icons/android/release_app_icon.png",
	"appIconIos": "assets/app_icons/ios/release_app_icon.png",
	"imagesIos": [
		"assets/account_avatar2.png"
	],
	"layoutAndroid": [
		"assets/android/activity_object_detail.xml"
	],
	"imagesAndroid": [
		"assets/account_avatar1.png"
	],
	"images": [
		"assets/asr_1.png"
	],
	"copied": [
		"assets/file_data1",
		"assets/file_data2"
	],
	"imagesScaled": [
		"assets/vector_avatar.pdf",
		"assets/business_men.ai",
		"assets/green_guy.eps"
	],
	"Settings": {
		"UI_BASE_COLOR": "67,163,199,255",
		"UI_BASE_COLOR2": "67,163,199,20",
		"UI_SECONDARY_COLOR": "#431298",
		"UI_SECONDARY_COLOR_LOW": "#80431298",
		"DEFAULT_UI_FONT": "GT-Walsheim-Black.ttf",
		"DEFAULT_AVATAR": "account_avatar1",
		"PREF_ACCOUNT_NAME": "pref_account_display_name",
		"PREF_SERVICE": "pref_service_name",
		"DEFAULT_DISPLAY_UI_STYLE": 1,
		"SCALE": 1.5,
		"DEBUG_ENABLED": true,
		"SHOW_UI": false
	},
	"Empty": [
		""
	],
	"Hello": [
		"one",
		"two",
		"three"
	],
	"FloatyNumbers": [
		1,
		2,
		3.15,
		23,
		415.03
	],
	"InteryNumbers": [
		5,
		23,
		54,
		120,
		100
	],
	"RainbowColors": [
		"#535557",
		"#9D9C98",
		"#F2845B",
		"#F67D4B",
		"#EDAC93"
	],
	"Service": {
		"LOGIN_TYPE": "OAUTH2",
		"BROWSE_TYPE": "CARDS",
		"MENU_VIEW": "SETTINGS",
		"BASE_URL_PROD_USW2": "api.afero.io",
		"BASE_URL_STAGE": "api.dev.afero.io"
	},
	"Colors": {
		"GRAY01_50": "#F2EDEB",
		"GRAY02_50": "#D0CBC7",
		"GRAY03_50": "#A4A099",
		"GRAY04_50": "#7E7B77",
		"ORANGE01_50": "#F67D4B",
		"WHITE01_50": "#FFFFFF",
		"GRAY01": "#E1DFDC",
		"GRAY02": "#BFBCB7",
		"GRAY03": "#9D9C98",
		"GRAY04": "#85878A",
		"GRAY05": "#717375",
		"GRAY06": "#616264",
		"GRAY07": "#535557",
		"ORANGE06": "#F67D4B",
		"ORANGE05": "#F47344",
		"ORANGE04": "#F2845B",
		"ORANGE03": "#EF9471",
		"ORANGE02": "#EBA485",
		"ORANGE01": "#EDAC93",
		"WHITE01": "#FFFFFF"
	},
	"TemperatureUnits": [
		"FAHRENHEIT",
		"CELSIUS",
		"KELVIN"
	],
	"enums": {
		"TEMPERATURE_UNIT": [
			"CELSIUS",
			"FAHRENHEIT",
			"KELVIN"
		],
		"AUTH_TYPE": [
			"AFERO",
			"OAUTH2"
		],
		"MENU_VIEW_TYPE": [
			"CLASSIC",
			"SETTINGS"
		],
		"DEVICE_BROWSER_TYPE": [
			"HEX",
			"CARDS"
		],
		"DAY": [
			"MONDAY",
			"TUESDAY",
			"WEDNESDAY",
			"THURSDAY",
			"FRIDAY",
			"SATURDAY",
			"SUNDAY"
		],
		"TIME_OF_DAY": [
			"BREAKFAST",
			"LUNCH",
			"SNACK",
			"DINNER"
		],
		"SAFE_IMAGES": [
			"asr_1",
			"ac_icon_large"
		]
	}
}

Output: Constants.swift

/* Generated with Sango, by Afero.io */

import UIKit
public struct Constants {
	public struct Colors {
		static let Gray01 = UIColor(red: 0.882, green: 0.875, blue: 0.863, alpha: 1.0) /* #E1DFDC */
		static let Gray01_50 = UIColor(red: 0.949, green: 0.929, blue: 0.922, alpha: 1.0) /* #F2EDEB */
		static let Gray02 = UIColor(red: 0.749, green: 0.737, blue: 0.718, alpha: 1.0) /* #BFBCB7 */
		static let Gray02_50 = UIColor(red: 0.816, green: 0.796, blue: 0.78, alpha: 1.0) /* #D0CBC7 */
		static let Gray03 = UIColor(red: 0.616, green: 0.612, blue: 0.596, alpha: 1.0) /* #9D9C98 */
		static let Gray03_50 = UIColor(red: 0.643, green: 0.627, blue: 0.6, alpha: 1.0) /* #A4A099 */
		static let Gray04 = UIColor(red: 0.522, green: 0.529, blue: 0.541, alpha: 1.0) /* #85878A */
		static let Gray04_50 = UIColor(red: 0.494, green: 0.482, blue: 0.467, alpha: 1.0) /* #7E7B77 */
		static let Gray05 = UIColor(red: 0.443, green: 0.451, blue: 0.459, alpha: 1.0) /* #717375 */
		static let Gray06 = UIColor(red: 0.38, green: 0.384, blue: 0.392, alpha: 1.0) /* #616264 */
		static let Gray07 = UIColor(red: 0.325, green: 0.333, blue: 0.341, alpha: 1.0) /* #535557 */
		static let Orange01 = UIColor(red: 0.929, green: 0.675, blue: 0.576, alpha: 1.0) /* #EDAC93 */
		static let Orange01_50 = UIColor(red: 0.965, green: 0.49, blue: 0.294, alpha: 1.0) /* #F67D4B */
		static let Orange02 = UIColor(red: 0.922, green: 0.643, blue: 0.522, alpha: 1.0) /* #EBA485 */
		static let Orange03 = UIColor(red: 0.937, green: 0.58, blue: 0.443, alpha: 1.0) /* #EF9471 */
		static let Orange04 = UIColor(red: 0.949, green: 0.518, blue: 0.357, alpha: 1.0) /* #F2845B */
		static let Orange05 = UIColor(red: 0.957, green: 0.451, blue: 0.267, alpha: 1.0) /* #F47344 */
		static let Orange06 = UIColor(red: 0.965, green: 0.49, blue: 0.294, alpha: 1.0) /* #F67D4B */
		static let White01 = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) /* #FFFFFF */
		static let White01_50 = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) /* #FFFFFF */
	}
	public static let Empty = [
			""
		]
	public static let FloatyNumbers = [
			1,
			2,
			3.15,
			23,
			415.03
		]
	public static let Hello = [
			"one",
			"two",
			"three"
		]
	public static let InteryNumbers = [
			5,
			23,
			54,
			120,
			100
		]
	public static let RainbowColors = [
			UIColor(red: 0.325, green: 0.333, blue: 0.341, alpha: 1.0) /* #535557 */,
			UIColor(red: 0.616, green: 0.612, blue: 0.596, alpha: 1.0) /* #9D9C98 */,
			UIColor(red: 0.949, green: 0.518, blue: 0.357, alpha: 1.0) /* #F2845B */,
			UIColor(red: 0.965, green: 0.49, blue: 0.294, alpha: 1.0) /* #F67D4B */,
			UIColor(red: 0.929, green: 0.675, blue: 0.576, alpha: 1.0) /* #EDAC93 */
		]
	public struct Service {
		static let BaseUrlProdUsw2 = "api.afero.io"
		static let BaseUrlStage = "api.dev.afero.io"
		static let BrowseType = DeviceBrowserType.Cards
		static let LoginType = AuthType.Oauth2
		static let MenuView = MenuViewType.Settings
	}
	public struct Settings {
		static let DebugEnabled = true
		static let DefaultAvatar = "account_avatar1"
		static let DefaultDisplayUiStyle = 1
		static let DefaultUiFont = "GT-Walsheim-Black.ttf"
		static let PrefAccountName = "pref_account_display_name"
		static let PrefService = "pref_service_name"
		static let Scale = 1.5
		static let ShowUi = false
		static let UiBaseColor = UIColor(red: 0.263, green: 0.639, blue: 0.78, alpha: 1.0) /* 67,163,199,255 */
		static let UiBaseColor2 = UIColor(red: 0.263, green: 0.639, blue: 0.78, alpha: 0.078) /* 67,163,199,20 */
		static let UiSecondaryColor = UIColor(red: 0.263, green: 0.071, blue: 0.596, alpha: 1.0) /* #431298 */
		static let UiSecondaryColorLow = UIColor(red: 0.263, green: 0.071, blue: 0.596, alpha: 0.502) /* #80431298 */
	}
	public static let TemperatureUnits = [
			TemperatureUnit.Fahrenheit,
			TemperatureUnit.Celsius,
			TemperatureUnit.Kelvin
		]
	public enum AuthType {
		case Afero
		case Oauth2
	}
	public enum Day {
		case Monday
		case Tuesday
		case Wednesday
		case Thursday
		case Friday
		case Saturday
		case Sunday
	}
	public enum DeviceBrowserType {
		case Hex
		case Cards
	}
	public enum MenuViewType {
		case Classic
		case Settings
	}
	public enum SafeImages {
		case Asr_1
		case AcIconLarge
	}
	public enum TemperatureUnit {
		case Celsius
		case Fahrenheit
		case Kelvin
	}
	public enum TimeOfDay {
		case Breakfast
		case Lunch
		case Snack
		case Dinner
	}
}

Output R.swift

/* Generated with Sango, by Afero.io */

import Foundation
public struct R {
	public struct String {
		static let AppName = "app_name"
		static let ButtonTitleCancel = "button_title_cancel"
		static let ButtonTitleCancelAllCaps = "button_title_cancel_all_caps"
		static let ButtonTitleOk = "button_title_ok"
		static let DeviceOffline = "device_offline"
		static let DialogMessageRemoveDevice = "dialog_message_remove_device"
		static let DialogTitleRemoveDevice = "dialog_title_remove_device"
		static let DialogTitleScheduleTime = "dialog_title_schedule_time"
		static let NoNetworkWarning = "no_network_warning"
		static let PrimaryAccountName = "primary_account_name"
	}
	public struct Images {
		static let AccountAvatar2 = "account_avatar2"
		static let Asr1 = "asr_1"
		static let BusinessMen = "business_men"
		static let GreenGuy = "green_guy"
		static let VectorAvatar = "vector_avatar"
	}
}

Output Constants.java

/* Generated with Sango, by Afero.io */

package io.afero.example;
public final class Constants {
	public static final String Empty[] = {

	};
	public static final double FloatyNumbers[] = {
		1,
		2,
		3.15,
		23,
		415.03
	};
	public static final String Hello[] = {
		"one",
		"two",
		"three"
	};
	public static final int InteryNumbers[] = {
		5,
		23,
		54,
		120,
		100
	};
	public static final class Service {
		public static final String BASE_URL_PROD_USW2 = "prod.example.com";
		public static final String BASE_URL_STAGE = "dev.example.com";
		public static final DeviceBrowserType BROWSE_TYPE = DeviceBrowserType.CARDS;
		public static final AuthType LOGIN_TYPE = AuthType.OAUTH2;
		public static final MenuViewType MENU_VIEW = MenuViewType.SETTINGS;
	}
	public static final class Settings {
		public static final Boolean DEBUG_ENABLED = true;
		public static final String DEFAULT_AVATAR = "account_avatar1";
		public static final int DEFAULT_DISPLAY_UI_STYLE = 1;
		public static final String DEFAULT_UI_FONT = "GT-Walsheim-Black.ttf";
		public static final String PREF_ACCOUNT_NAME = "pref_account_display_name";
		public static final String PREF_SERVICE = "pref_service_name";
		public static final double SCALE = 1.5;
		public static final Boolean SHOW_UI = false;
	}
	public static final TemperatureUnit TemperatureUnits[] = {
		TemperatureUnit.FAHRENHEIT,
		TemperatureUnit.CELSIUS,
		TemperatureUnit.KELVIN
	};
	public enum AuthType {
		AFERO, OAUTH2
	}
	public enum Day {
		MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
	}
	public enum DeviceBrowserType {
		HEX, CARDS
	}
	public enum MenuViewType {
		CLASSIC, SETTINGS
	}
	public enum SafeImages {
		ASR_1
	}
	public enum TemperatureUnit {
		CELSIUS, FAHRENHEIT, KELVIN
	}
	public enum TimeOfDay {
		BREAKFAST, LUNCH, SNACK, DINNER
	}
}

And for Android a colors.xml file is generated:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generated with Sango, by Afero.io -->
<resources>
	<color name="colors_gray01">#E1DFDC</color>
	<color name="colors_gray01_50">#F2EDEB</color>
	<color name="colors_gray02">#BFBCB7</color>
	<color name="colors_gray02_50">#D0CBC7</color>
	<color name="colors_gray03">#9D9C98</color>
	<color name="colors_gray03_50">#A4A099</color>
	<color name="colors_gray04">#85878A</color>
	<color name="colors_gray04_50">#7E7B77</color>
	<color name="colors_gray05">#717375</color>
	<color name="colors_gray06">#616264</color>
	<color name="colors_gray07">#535557</color>
	<color name="colors_orange01">#EDAC93</color>
	<color name="colors_orange01_50">#F67D4B</color>
	<color name="colors_orange02">#EBA485</color>
	<color name="colors_orange03">#EF9471</color>
	<color name="colors_orange04">#F2845B</color>
	<color name="colors_orange05">#F47344</color>
	<color name="colors_orange06">#F67D4B</color>
	<color name="colors_white01">#FFFFFF</color>
	<color name="colors_white01_50">#FFFFFF</color>
	<color name="rainbowcolors_0">#535557</color>
	<color name="rainbowcolors_1">#9D9C98</color>
	<color name="rainbowcolors_2">#F2845B</color>
	<color name="rainbowcolors_3">#F67D4B</color>
	<color name="rainbowcolors_4">#EDAC93</color>
	<color name="settings_ui_base_color">#FF43A3C7</color>
	<color name="settings_ui_base_color2">#1443A3C7</color>
	<color name="settings_ui_secondary_color">#431298</color>
	<color name="settings_ui_secondary_color_low">#80431298</color>
</resources>

Output for javascript

/* Generated with Sango, by Afero.io */

var AuthType = {
	AFERO: 'AFERO', OAUTH2: 'OAUTH2'
}
var Day = {
	MONDAY: 'MONDAY', TUESDAY: 'TUESDAY', WEDNESDAY: 'WEDNESDAY', THURSDAY: 'THURSDAY', FRIDAY: 'FRIDAY', SATURDAY: 'SATURDAY', SUNDAY: 'SUNDAY'
}
var DeviceBrowserType = {
	HEX: 'HEX', CARDS: 'CARDS'
}
var MenuViewType = {
	CLASSIC: 'CLASSIC', SETTINGS: 'SETTINGS'
}
var SafeImages = {
	ASR_1: 'ASR_1'
}
var TemperatureUnit = {
	CELSIUS: 'CELSIUS', FAHRENHEIT: 'FAHRENHEIT', KELVIN: 'KELVIN'
}
var TimeOfDay = {
	BREAKFAST: 'BREAKFAST', LUNCH: 'LUNCH', SNACK: 'SNACK', DINNER: 'DINNER'
}
var Constants = {
	Dimen: {
		 BUTTON_GROUP_SPACING: "10dp",
		 BUTTON_RADIUS: "400dp",
		 OFFLINE_SCHEDULE_DAY_EDITOR_RING_WIDTH: "35dp",
		 OOBE_ARROW_SIZE: "120dp",
		 OOBE_ICON_SIZE: "100dp",
		 OOBE_MADAL_HLINE: "40dp",
		 OOBE_MODAL_VLINE: "80dp",
		 VIEW_ONBOARDING_BOARD: "400dp",
		 VIEW_ONBOARDING_BOARD_MARGIN_TOP: "50dp",
		 VIEW_ONBOARDING_BOARD_WRAPPER: "600dp",
		 VIEW_ONBOARDING_LABEL_MARGIN_SIDE: "20dp",
		 VIEW_ONBOARDING_LABEL_MARGIN_TOP: "75dp",
	},
	Empty: [

	],
	FloatyNumbers: [
		1,
		2,
		3.15,
		23,
		415.03
	],
	Hello: [
		"one",
		"two",
		"three"
	],
	InteryNumbers: [
		5,
		23,
		54,
		120,
		100
	],
	Service: {
		 BASE_URL_PROD_USW2: "prod.example.com",
		 BASE_URL_STAGE: "dev.example.com",
		 BROWSE_TYPE: DeviceBrowserType.CARDS,
		 LOGIN_TYPE: AuthType.OAUTH2,
		 MENU_VIEW: MenuViewType.SETTINGS,
	},
	Settings: {
		 DEBUG_ENABLED: true,
		 DEFAULT_AVATAR: "account_avatar1",
		 DEFAULT_DISPLAY_UI_STYLE: 1,
		 DEFAULT_UI_FONT: "GT-Walsheim-Black.ttf",
		 PREF_ACCOUNT_NAME: "pref_account_display_name",
		 PREF_SERVICE: "pref_service_name",
		 SCALE: 1.5,
		 SHOW_UI: false,
	},
	TemperatureUnits: [
		TemperatureUnit.FAHRENHEIT,
		TemperatureUnit.CELSIUS,
		TemperatureUnit.KELVIN
	],
}
module.exports = Constants;

And a SCSS file is generated:

// Generated with Sango, by Afero.io

$COLORS_GRAY01: #E1DFDC;
$COLORS_GRAY01_50: #F2EDEB;
$COLORS_GRAY02: #BFBCB7;
$COLORS_GRAY02_50: #D0CBC7;
$COLORS_GRAY03: #9D9C98;
$COLORS_GRAY03_50: #A4A099;
$COLORS_GRAY04: #85878A;
$COLORS_GRAY04_50: #7E7B77;
$COLORS_GRAY05: #717375;
$COLORS_GRAY06: #616264;
$COLORS_GRAY07: #535557;
$COLORS_ORANGE01: #EDAC93;
$COLORS_ORANGE01_50: #F67D4B;
$COLORS_ORANGE02: #EBA485;
$COLORS_ORANGE03: #EF9471;
$COLORS_ORANGE04: #F2845B;
$COLORS_ORANGE05: #F47344;
$COLORS_ORANGE06: #F67D4B;
$COLORS_WHITE01: #FFFFFF;
$COLORS_WHITE01_50: #FFFFFF;
$RAINBOWCOLORS_0: #535557;
$RAINBOWCOLORS_1: #9D9C98;
$RAINBOWCOLORS_2: #F2845B;
$RAINBOWCOLORS_3: #F67D4B;
$RAINBOWCOLORS_4: #EDAC93;
$SETTINGS_UI_BASE_COLOR: rbga(67, 163, 199, 1.0);
$SETTINGS_UI_BASE_COLOR2: rbga(67, 163, 199, 0.0784313725490196);
$SETTINGS_UI_SECONDARY_COLOR: #431298;
$SETTINGS_UI_SECONDARY_COLOR_LOW: rbga(67, 18, 152, 0.501960784313725);

The parsing tool is run from the source platform depot, and the resulting files are copied or generated and put into the correct place, as defined by the JSON file. Those changes are then verified and checked in.

Great thing about this process, is you can branch both the asset depot and the project depot to work on things in sync.

The ‘images’ key are tagged with @2, @3, etc that will be copied direct to drawable-hdpi, drawable-xhdpi, drawable-xxhdpi for equivalent. The ‘copied’ key are just copied into the resource tree of the target platform. The ‘fonts’ key are copied into the target platform for the specific place, and for iOS the bundle will be modified via UIAppFonts to add the fonts the application.

Sango command line options:


$ sango -help

Usage:
-asset_template        [basename]                      creates a json template, specifically for the assets
-config                [file.json]                     use config file for options, instead of command line
-config_template       [file.json]                     creates a json template, specifically for the app
-help_keys                                             display JSON keys and their use
-input                 [file.json]                     asset json file
-input_assets          [folder]                        asset source folder (read)
-input_assets_tag      [tag]                           optional git tag to pull repro at before processing
-inputs                [file1.json file2.json ...]     merges asset files and process
-java                                                  write java source
-javascript                                            write javascript source
-locale_only                                           when included, process localization files only
-nodejs                                                write nodejs source
-out_assets            [folder]                        asset root folder (write), typically iOS Resource, or Android app/src/main
-out_locales           [folder]                        locale folder to write results
-out_scss              [source.scss]                   when using javascript/node path to scss file
-out_source            [source.java|swift|js]          path to result of language
-swift                                                 write swift source
-swift3                                                write Swift 3 compatible Swift source (requires -swift)
-validate              [asset_file.json, ...]          validates asset JSON file(s), requires -input_assets
-validate_android      [asset_file.json, ...]          validates Android asset JSON file(s), requires -input_assets
-validate_ios          [asset_file.json, ...]          validates iOS asset JSON file(s), requires -input_assets
-validate_javascript   [asset_file.json, ...]          validates Javascript asset JSON file(s), requires -input_assets
-validate_nodejs       [asset_file.json, ...]          validates NodeJS asset JSON file(s), requires -input_assets
-verbose                                               be verbose in details
-version                                               version

$ sango -help_keys

JSON keys and their meaning:
appIcon                 string. path to app icon that is common and is scaled
appIconAndroid          string. path to app icon that is Android only and is scaled
appIconIos              string. path to app icon that is iOS  and is scaled
copied                  array. path to files that are common and are just copied
copiedAndroid           array. path to files that Android only and are just copied
copiedIos               array. path to files that are iOS only and are just copied
enums                   dictionary. keys are enum key:value name
fontRoot                path. Destination font root. Default is root of resources
fonts                   array. path to font files
globalTint              color. ie #F67D4B. apply as tint to all images saved
globalTintAndroid       color. ie #F67D4B. apply as tint to all images saved for Android
globalTintIos           color. ie #F67D4B. apply as tint to all images saved for iOS
images                  array. path to image files that are common.
imagesAndroid           array. path to image files that are Android only
imagesIos               array. path to image files that are iOS only
imagesScaled            array. path to image files that are common and will be scaled. Source is always scaled down
imagesScaledAndroid     array. path to image files that are Android only and will be scaled. Source is always scaled down
imagesScaledAndroidUp   array. path to image files that are Android only and will be scaled. Source is always scaled up
imagesScaledIos         array. path to image files that are iOS only and will be scaled. Source is always scaled down
imagesScaledIosUp       array. path to image files that are iOS only and will be scaled. Source is always scaled up
imagesScaledUp          array. path to image files that are common and will be scaled. Source is always scaled up
java                    dictionary. keys are base:class name, package:package name
javascript              dictionary. keys are base:class name
layoutAndroid           array. path to layout files that is Android only
locale                  dictionary. keys are IOS lang. Use 'default' for enUS, enES, path to strings file
nodejs                  dictionary. keys are base:class name
print                   debugging. value is a string and is printed to the console
schemaVersion           number. Version, which should be 1
swift                   dictionary. keys are base:class name

A complete example is located in this depot at:


$ cd test_example
$ ls
Makefile
config_android.json
config_ios.json
config_javascript.json
simple

Example to build sango data for iOS, Android, NodeJS, Javascript, used for testing.
 build_android
 build_ios
 build_js
 build_all
 validate
You can’t perform that action at this time.