Skip to content

Commit 2190810

Browse files
authored
firebase-dataconnect minimal demo app added (#6561)
1 parent 91a74cc commit 2190810

File tree

24 files changed

+1854
-0
lines changed

24 files changed

+1854
-0
lines changed

firebase-dataconnect/demo/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
.gradle/
16+
.idea/
17+
.kotlin/
18+
19+
build/
20+
local.properties
21+
22+
*.log
23+
*.hprof
24+
/dataConnectGeneratedSources/

firebase-dataconnect/demo/.idea/runConfigurations/spotlessApply.xml

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
18+
import java.nio.charset.StandardCharsets
19+
20+
plugins {
21+
// Use whichever versions of these dependencies suit your application.
22+
// The versions shown here were the latest versions as of December 03, 2024.
23+
// Note, however, that the version of kotlin("plugin.serialization") _must_,
24+
// in general, match the version of kotlin("android").
25+
id("com.android.application") version "8.7.3"
26+
id("com.google.gms.google-services") version "4.4.2"
27+
val kotlinVersion = "2.1.0"
28+
kotlin("android") version kotlinVersion
29+
kotlin("plugin.serialization") version kotlinVersion
30+
31+
// The following code in this "plugins" block can be omitted from customer
32+
// facing documentation as it is an implementation detail of this application.
33+
id("com.diffplug.spotless") version "7.0.0.BETA4"
34+
}
35+
36+
dependencies {
37+
// Use whichever versions of these dependencies suit your application.
38+
// The versions shown here were the latest versions as of December 03, 2024.
39+
implementation("com.google.firebase:firebase-dataconnect:16.0.0-beta03")
40+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
41+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
42+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3")
43+
implementation("androidx.appcompat:appcompat:1.7.0")
44+
implementation("androidx.activity:activity-ktx:1.9.3")
45+
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
46+
implementation("com.google.android.material:material:1.12.0")
47+
48+
// The following code in this "dependencies" block can be omitted from customer
49+
// facing documentation as it is an implementation detail of this application.
50+
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3")
51+
implementation("io.kotest:kotest-property:5.9.1")
52+
implementation("io.kotest.extensions:kotest-property-arbs:2.1.2")
53+
}
54+
55+
// The remaining code in this file can be omitted from customer facing
56+
// documentation. It's here just to make things compile and/or configure
57+
// optional components of the build (e.g. spotless code formatting).
58+
59+
android {
60+
namespace = "com.google.firebase.dataconnect.minimaldemo"
61+
compileSdk = 35
62+
defaultConfig {
63+
minSdk = 21
64+
targetSdk = 35
65+
versionCode = 1
66+
versionName = "1.0"
67+
}
68+
compileOptions {
69+
sourceCompatibility = JavaVersion.VERSION_1_8
70+
targetCompatibility = JavaVersion.VERSION_1_8
71+
isCoreLibraryDesugaringEnabled = true
72+
}
73+
buildFeatures.viewBinding = true
74+
kotlinOptions.jvmTarget = "1.8"
75+
}
76+
77+
spotless {
78+
val ktfmtVersion = "0.53"
79+
kotlin {
80+
target("**/*.kt")
81+
targetExclude("build/")
82+
ktfmt(ktfmtVersion).googleStyle()
83+
}
84+
kotlinGradle {
85+
target("**/*.gradle.kts")
86+
targetExclude("build/")
87+
ktfmt(ktfmtVersion).googleStyle()
88+
}
89+
json {
90+
target("**/*.json")
91+
targetExclude("build/")
92+
simple().indentWithSpaces(2)
93+
}
94+
yaml {
95+
target("**/*.yaml")
96+
targetExclude("build/")
97+
jackson()
98+
.yamlFeature("INDENT_ARRAYS", true)
99+
.yamlFeature("MINIMIZE_QUOTES", true)
100+
.yamlFeature("WRITE_DOC_START_MARKER", false)
101+
}
102+
format("xml") {
103+
target("**/*.xml")
104+
targetExclude("build/")
105+
trimTrailingWhitespace()
106+
indentWithSpaces(2)
107+
endWithNewline()
108+
}
109+
}
110+
111+
abstract class DataConnectGenerateSourcesTask : DefaultTask() {
112+
113+
@get:InputDirectory abstract val inputDirectory: DirectoryProperty
114+
115+
@get:OutputDirectory abstract val outputDirectory: DirectoryProperty
116+
117+
@get:Internal abstract val nodeExecutableDirectory: DirectoryProperty
118+
119+
@get:Internal abstract val firebaseCommand: Property<String>
120+
121+
@get:Internal abstract val workDirectory: DirectoryProperty
122+
123+
@get:Inject protected abstract val execOperations: ExecOperations
124+
125+
@get:Inject protected abstract val providerFactory: ProviderFactory
126+
127+
@get:Inject protected abstract val fileSystemOperations: FileSystemOperations
128+
129+
@TaskAction
130+
fun run(inputChanges: InputChanges) {
131+
if (inputChanges.isIncremental) {
132+
val onlyLogFilesChanged =
133+
inputChanges.getFileChanges(inputDirectory).all { it.file.name.endsWith(".log") }
134+
if (onlyLogFilesChanged) {
135+
didWork = false
136+
return
137+
}
138+
}
139+
140+
val inputDirectory: File = inputDirectory.get().asFile
141+
val outputDirectory: File = outputDirectory.get().asFile
142+
val nodeExecutableDirectory: File? = nodeExecutableDirectory.orNull?.asFile
143+
val firebaseCommand: String? = firebaseCommand.orNull
144+
val workDirectory: File = workDirectory.get().asFile
145+
146+
outputDirectory.deleteRecursively()
147+
outputDirectory.mkdirs()
148+
workDirectory.deleteRecursively()
149+
workDirectory.mkdirs()
150+
151+
val newPath: String? =
152+
if (nodeExecutableDirectory === null) {
153+
null
154+
} else {
155+
val nodeExecutableDirectoryAbsolutePath = nodeExecutableDirectory.absolutePath
156+
val oldPath = providerFactory.environmentVariable("PATH").orNull
157+
if (oldPath === null) {
158+
nodeExecutableDirectoryAbsolutePath
159+
} else {
160+
nodeExecutableDirectoryAbsolutePath + File.pathSeparator + oldPath
161+
}
162+
}
163+
164+
val logFile =
165+
if (logger.isInfoEnabled) {
166+
null
167+
} else {
168+
File(workDirectory, "dataconnect.sdk.generate.log.txt")
169+
}
170+
171+
val execResult =
172+
logFile?.outputStream().use { logStream ->
173+
execOperations.runCatching {
174+
exec {
175+
commandLine(firebaseCommand ?: "firebase", "--debug", "dataconnect:sdk:generate")
176+
workingDir(inputDirectory)
177+
isIgnoreExitValue = false
178+
if (newPath !== null) {
179+
environment("PATH", newPath)
180+
}
181+
if (logStream !== null) {
182+
standardOutput = logStream
183+
errorOutput = logStream
184+
}
185+
}
186+
}
187+
}
188+
189+
execResult.onFailure { exception ->
190+
logFile?.readText(StandardCharsets.UTF_8)?.lines()?.forEach { line ->
191+
logger.warn("{}", line.trimEnd())
192+
}
193+
throw exception
194+
}
195+
}
196+
}
197+
198+
abstract class CopyDirectoryTask : DefaultTask() {
199+
200+
@get:InputDirectory abstract val srcDirectory: DirectoryProperty
201+
202+
@get:OutputDirectory abstract val destDirectory: DirectoryProperty
203+
204+
@get:Inject protected abstract val fileSystemOperations: FileSystemOperations
205+
206+
@TaskAction
207+
fun run() {
208+
val srcDirectory: File = srcDirectory.get().asFile
209+
val destDirectory: File = destDirectory.get().asFile
210+
211+
logger.info("srcDirectory: {}", srcDirectory.absolutePath)
212+
logger.info("destDirectory: {}", destDirectory.absolutePath)
213+
214+
destDirectory.deleteRecursively()
215+
destDirectory.mkdirs()
216+
217+
fileSystemOperations.copy {
218+
from(srcDirectory)
219+
into(destDirectory)
220+
}
221+
}
222+
}
223+
224+
run {
225+
val dataConnectTaskGroupName = "Firebase Data Connect Minimal App"
226+
val projectDirectory = layout.projectDirectory
227+
228+
val generateSourcesTask =
229+
tasks.register<DataConnectGenerateSourcesTask>("dataConnectGenerateSources") {
230+
group = dataConnectTaskGroupName
231+
description =
232+
"Run firebase dataconnect:sdk:generate to generate the Data Connect Kotlin SDK sources"
233+
234+
inputDirectory = projectDirectory.dir("firebase")
235+
outputDirectory = projectDirectory.dir("dataConnectGeneratedSources")
236+
237+
nodeExecutableDirectory =
238+
project.providers.gradleProperty("dataConnect.minimalApp.nodeExecutableDirectory").map {
239+
projectDirectory.dir(it)
240+
}
241+
firebaseCommand = project.providers.gradleProperty("dataConnect.minimalApp.firebaseCommand")
242+
243+
workDirectory = layout.buildDirectory.dir(name)
244+
}
245+
246+
val androidComponents = extensions.getByType<ApplicationAndroidComponentsExtension>()
247+
androidComponents.onVariants { variant ->
248+
val variantNameTitleCase = variant.name[0].uppercase() + variant.name.substring(1)
249+
val copyTaskName = "dataConnectCopy${variantNameTitleCase}GeneratedSources"
250+
val copyTask =
251+
tasks.register<CopyDirectoryTask>(copyTaskName) {
252+
group = dataConnectTaskGroupName
253+
description =
254+
"Copy the generated Data Connect Kotlin SDK sources into the " +
255+
"generated code directory for the \"${variant.name}\" variant."
256+
srcDirectory = generateSourcesTask.flatMap { it.outputDirectory }
257+
}
258+
259+
variant.sources.java!!.addGeneratedSourceDirectory(copyTask, CopyDirectoryTask::destDirectory)
260+
}
261+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "fakeproject"
4+
}
5+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
/.dataconnect/
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
connectorId: ctry3q3tp6kzx
2+
generate:
3+
kotlinSdk:
4+
outputDir: ../../../dataConnectGeneratedSources
5+
package: com.google.firebase.dataconnect.minimaldemo.connector
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
mutation InsertItem(
16+
$string: String,
17+
$int: Int,
18+
$int64: Int64,
19+
$float: Float,
20+
$boolean: Boolean,
21+
$date: Date,
22+
$timestamp: Timestamp,
23+
$any: Any,
24+
) @auth(level: PUBLIC) {
25+
key: zwda6x9zyy_insert(data: {
26+
string: $string,
27+
int: $int,
28+
int64: $int64,
29+
float: $float,
30+
boolean: $boolean,
31+
date: $date,
32+
timestamp: $timestamp,
33+
any: $any,
34+
})
35+
}
36+
37+
query GetItemByKey(
38+
$key: zwda6x9zyy_Key!
39+
) @auth(level: PUBLIC) {
40+
item: zwda6x9zyy(key: $key) {
41+
string
42+
int
43+
int64
44+
float
45+
boolean
46+
date
47+
timestamp
48+
any
49+
}
50+
}

0 commit comments

Comments
 (0)