From b5eb0d65c981e51103e3dfd5553a496a4676f88e Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 30 Jan 2026 15:51:35 +0545 Subject: [PATCH 1/9] feat(locate): add locate feature --- functions/definition/project/common.yaml | 2 ++ .../project/project_types/locate.yaml | 26 +++++++++++++++++++ .../pyfirebase/pyfirebase_mapswipe/models.py | 23 ++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 functions/definition/project/project_types/locate.yaml diff --git a/functions/definition/project/common.yaml b/functions/definition/project/common.yaml index 43a0763..319dc46 100644 --- a/functions/definition/project/common.yaml +++ b/functions/definition/project/common.yaml @@ -40,6 +40,8 @@ FbEnumProjectType: value: 4 - label: 'STREET' value: 7 + - label: 'LOCATE' + value: 8 FbProjectReadonlyType: model: alias diff --git a/functions/definition/project/project_types/locate.yaml b/functions/definition/project/project_types/locate.yaml new file mode 100644 index 0000000..b0048cf --- /dev/null +++ b/functions/definition/project/project_types/locate.yaml @@ -0,0 +1,26 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/toggle-corp/typesync/refs/tags/v1.0.0/schema.local.json + +FBEnumSubGridSize: + model: alias + type: + type: enum + members: + - label: 'SIZE_2X2' + value: '2x2' + - label: 'SIZE_4X4' + value: '4x4' + - label: 'SIZE_8X8' + value: '8x8' + +FbProjectLocateCreateOnlyInput: + model: alias + docs: Represents LOCATE project fields that are valid while creating a project + type: + type: object + fields: + zoomLevel: + type: int + tileServer: + type: FbObjRasterTileServer + subGridSize: + type: FBEnumSubGridSize diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index dc92a83..c2828b1 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -122,6 +122,7 @@ class FbEnumProjectType(enum.Enum): COMPARE = 3 COMPLETENESS = 4 STREET = 7 + LOCATE = 8 class FbProjectReadonlyType(TypesyncModel): @@ -356,6 +357,12 @@ class FbEnumOverlayTileServerType(enum.Enum): VECTOR = "vector" +class FBEnumSubGridSize(enum.Enum): + SIZE_2X2 = "2x2" + SIZE_4X4 = "4x4" + SIZE_8X8 = "8x8" + + class FbProjectStreetCreateOnlyInput(TypesyncModel): """Represents STREET project fields that are valid while creating a project""" @@ -589,6 +596,22 @@ def __setattr__(self, name: str, value: typing.Any) -> None: super().__setattr__(name, value) +class FbProjectLocateCreateOnlyInput(TypesyncModel): + """Represents LOCATE project fields that are valid while creating a project""" + + zoomLevel: int + tileServer: FbObjRasterTileServer + subGridSize: FBEnumSubGridSize + + class Config: + use_enum_values = False + extra = "forbid" + + @typing.override + def __setattr__(self, name: str, value: typing.Any) -> None: + super().__setattr__(name, value) + + class FbProjectValidateCreateOnlyInput(TypesyncModel): """Represents VALIDATE project fields that are valid while creating a project""" From b4421a1359ddc74206105aaa01fdf620f2c58e10 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Tue, 10 Feb 2026 14:14:34 +0545 Subject: [PATCH 2/9] feat(locate): add customOptions and exportMeta schema --- functions/definition/project/common.yaml | 2 +- functions/definition/project/project_types/locate.yaml | 10 ++++++++++ .../generated/pyfirebase/pyfirebase_mapswipe/models.py | 7 ++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/functions/definition/project/common.yaml b/functions/definition/project/common.yaml index 319dc46..099c56b 100644 --- a/functions/definition/project/common.yaml +++ b/functions/definition/project/common.yaml @@ -41,7 +41,7 @@ FbEnumProjectType: - label: 'STREET' value: 7 - label: 'LOCATE' - value: 8 + value: 9 FbProjectReadonlyType: model: alias diff --git a/functions/definition/project/project_types/locate.yaml b/functions/definition/project/project_types/locate.yaml index b0048cf..0388f7a 100644 --- a/functions/definition/project/project_types/locate.yaml +++ b/functions/definition/project/project_types/locate.yaml @@ -12,6 +12,7 @@ FBEnumSubGridSize: - label: 'SIZE_8X8' value: '8x8' + FbProjectLocateCreateOnlyInput: model: alias docs: Represents LOCATE project fields that are valid while creating a project @@ -24,3 +25,12 @@ FbProjectLocateCreateOnlyInput: type: FbObjRasterTileServer subGridSize: type: FBEnumSubGridSize + customOptions: + optional: true + type: + type: list + elementType: FbObjCustomOption + exportMetaKey: + type: string + exportMetaValue: + type: string diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index c2828b1..4eeb100 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -122,7 +122,7 @@ class FbEnumProjectType(enum.Enum): COMPARE = 3 COMPLETENESS = 4 STREET = 7 - LOCATE = 8 + LOCATE = 9 class FbProjectReadonlyType(TypesyncModel): @@ -602,6 +602,9 @@ class FbProjectLocateCreateOnlyInput(TypesyncModel): zoomLevel: int tileServer: FbObjRasterTileServer subGridSize: FBEnumSubGridSize + customOptions: list[FbObjCustomOption] | TypesyncUndefined | None = UNDEFINED + exportMetaKey: str + exportMetaValue: str class Config: use_enum_values = False @@ -609,6 +612,8 @@ class Config: @typing.override def __setattr__(self, name: str, value: typing.Any) -> None: + if name == "customOptions" and value is None: + raise ValueError("'customOptions' field cannot be set to None") super().__setattr__(name, value) From 784f0c9e946fbc2f53b3149ade5d62d54bd723bc Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Thu, 5 Feb 2026 10:38:21 +0545 Subject: [PATCH 3/9] feat(locate): add schema for locate feature tutorial --- .../tutorial/project_types/locate.yaml | 25 +++++++++++++++++ .../pyfirebase_mapswipe/extended_models.py | 10 +++++++ .../pyfirebase/pyfirebase_mapswipe/models.py | 27 +++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 functions/definition/tutorial/project_types/locate.yaml diff --git a/functions/definition/tutorial/project_types/locate.yaml b/functions/definition/tutorial/project_types/locate.yaml new file mode 100644 index 0000000..abc158c --- /dev/null +++ b/functions/definition/tutorial/project_types/locate.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/toggle-corp/typesync/refs/tags/v1.0.0/schema.local.json + +FbLocateTutorial: + model: alias + type: + type: object + fields: + projectType: + type: + type: literal + value: 9 + tileServer: + type: FbObjRasterTileServer + subGridSize: + type: FBEnumSubGridSize + zoomLevel: + type: int + +FbLocateTutorialTask: + model: alias + type: + type: object + fields: + url: + type: string diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/extended_models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/extended_models.py index 6f04f84..8957a26 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/extended_models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/extended_models.py @@ -76,3 +76,13 @@ class Config: # type: ignore[reportIncompatibleVariableOverride] use_enum_values = True frozen = True extra = "forbid" + + +class FbLocateTutorialTaskComplete( + models.FbTileMapServiceTutorialTask, + models.FbLocateTutorialTask, +): + class Config: # type: ignore[reportIncompatibleVariableOverride] + use_enum_values = True + frozen = True + extra = "forbid" diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index 4eeb100..37798bd 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -968,6 +968,33 @@ def __setattr__(self, name: str, value: typing.Any) -> None: super().__setattr__(name, value) +class FbLocateTutorial(TypesyncModel): + projectType: typing.Literal[9] + tileServer: FbObjRasterTileServer + subGridSize: FBEnumSubGridSize + zoomLevel: int + + class Config: + use_enum_values = False + extra = "forbid" + + @typing.override + def __setattr__(self, name: str, value: typing.Any) -> None: + super().__setattr__(name, value) + + +class FbLocateTutorialTask(TypesyncModel): + url: str + + class Config: + use_enum_values = False + extra = "forbid" + + @typing.override + def __setattr__(self, name: str, value: typing.Any) -> None: + super().__setattr__(name, value) + + class FbStreetTutorial(TypesyncModel): projectType: typing.Literal[7] customOptions: list[FbObjCustomOption] | TypesyncUndefined | None = UNDEFINED From 8f4494469ddc44c82b54539822b95ce23b1af18a Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 27 Feb 2026 10:56:43 +0545 Subject: [PATCH 4/9] feat(tutorial): add taskPartitionIndex schema --- .../definition/tutorial/project_types/tileMapService.yaml | 3 +++ functions/generated/pyfirebase/pyfirebase_mapswipe/models.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/functions/definition/tutorial/project_types/tileMapService.yaml b/functions/definition/tutorial/project_types/tileMapService.yaml index 7e7eb9f..ec3e58e 100644 --- a/functions/definition/tutorial/project_types/tileMapService.yaml +++ b/functions/definition/tutorial/project_types/tileMapService.yaml @@ -25,6 +25,9 @@ FbTileMapServiceTutorialTask: type: string referenceAnswer: type: int + taskPartitionIndex: + type: int + optional: true screen: type: int taskId: diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index 37798bd..81eb479 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -1047,6 +1047,7 @@ class FbTileMapServiceTutorialTask(TypesyncModel): groupId: int projectId: str referenceAnswer: int + taskPartitionIndex: int | TypesyncUndefined | None = UNDEFINED screen: int taskId: str taskId_real: str @@ -1059,6 +1060,8 @@ class Config: @typing.override def __setattr__(self, name: str, value: typing.Any) -> None: + if name == "taskPartitionIndex" and value is None: + raise ValueError("'taskPartitionIndex' field cannot be set to None") super().__setattr__(name, value) From 6226997f14cf88d64d007dc21a702bd0d53552f3 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Thu, 5 Feb 2026 10:38:21 +0545 Subject: [PATCH 5/9] feat(locate): add schema for locate feature tutorial --- .../pyfirebase/pyfirebase_mapswipe/models.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index 81eb479..6955e5c 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -16,7 +16,7 @@ class TypesyncUndefined: def __init__(self): if TypesyncUndefined._instance is not None: raise RuntimeError( - "TypesyncUndefined instances cannot be created directly. Import and use the UNDEFINED sentinel instead.", + "TypesyncUndefined instances cannot be created directly. Import and use the UNDEFINED sentinel instead." ) TypesyncUndefined._instance = self @@ -545,8 +545,7 @@ class FbObjRasterTileServer(TypesyncModel): apiKey: str | TypesyncUndefined | None = UNDEFINED wmtsLayerName: typing.Annotated[ - str | TypesyncUndefined | None, - pydantic.Field(deprecated=True), + str | TypesyncUndefined | None, pydantic.Field(deprecated=True) ] = UNDEFINED credits: str name: FbEnumRasterTileServerName @@ -830,12 +829,10 @@ def __setattr__(self, name: str, value: typing.Any) -> None: class FbBaseTutorial(TypesyncModel): exampleImage1: typing.Annotated[ - str | TypesyncUndefined | None, - pydantic.Field(deprecated=True), + str | TypesyncUndefined | None, pydantic.Field(deprecated=True) ] = UNDEFINED exampleImage2: typing.Annotated[ - str | TypesyncUndefined | None, - pydantic.Field(deprecated=True), + str | TypesyncUndefined | None, pydantic.Field(deprecated=True) ] = UNDEFINED contributorCount: int informationPages: list[FbInformationPage] | TypesyncUndefined | None = UNDEFINED @@ -1167,12 +1164,10 @@ class FbUserReadonlyType(TypesyncModel): created: datetime.datetime lastAppUse: datetime.datetime | TypesyncUndefined | None = UNDEFINED userName: typing.Annotated[ - str | TypesyncUndefined | None, - pydantic.Field(deprecated=True), + str | TypesyncUndefined | None, pydantic.Field(deprecated=True) ] = UNDEFINED userNameKey: typing.Annotated[ - str | TypesyncUndefined | None, - pydantic.Field(deprecated=True), + str | TypesyncUndefined | None, pydantic.Field(deprecated=True) ] = UNDEFINED username: str | TypesyncUndefined | None = UNDEFINED usernameKey: str | TypesyncUndefined | None = UNDEFINED From dd3b4021dae11532ecd1a83ab2c2b7c364e939a8 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Fri, 20 Feb 2026 16:51:14 +0545 Subject: [PATCH 6/9] feat(locate): create result schema for locate project --- .../project/project_types/locate.yaml | 32 ++++++++++++++ .../pyfirebase/pyfirebase_mapswipe/models.py | 42 ++++++++++++++++--- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/functions/definition/project/project_types/locate.yaml b/functions/definition/project/project_types/locate.yaml index 0388f7a..b27970d 100644 --- a/functions/definition/project/project_types/locate.yaml +++ b/functions/definition/project/project_types/locate.yaml @@ -34,3 +34,35 @@ FbProjectLocateCreateOnlyInput: type: string exportMetaValue: type: string + + +FbProjectLocateMappingResult: + model: alias + docs: Represents LOCATE mapswipe project results + # path: results/{projectId}/{groupId}/{userId} + type: + type: object + fields: + appVersion: + type: string + clientType: + # FIXME: this is an enum + type: string + optional: true + endTime: + type: timestamp + startTime: + type: timestamp + results: + optional: true + type: + type: map + valueType: + type: list + elementType: int + usergroups: + optional: true + type: + # NOTE: The key is usergroupId + type: map + valueType: boolean diff --git a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py index 6955e5c..2cb28c7 100644 --- a/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py +++ b/functions/generated/pyfirebase/pyfirebase_mapswipe/models.py @@ -16,7 +16,7 @@ class TypesyncUndefined: def __init__(self): if TypesyncUndefined._instance is not None: raise RuntimeError( - "TypesyncUndefined instances cannot be created directly. Import and use the UNDEFINED sentinel instead." + "TypesyncUndefined instances cannot be created directly. Import and use the UNDEFINED sentinel instead.", ) TypesyncUndefined._instance = self @@ -363,6 +363,31 @@ class FBEnumSubGridSize(enum.Enum): SIZE_8X8 = "8x8" +class FbProjectLocateMappingResult(TypesyncModel): + """Represents LOCATE mapswipe project results""" + + appVersion: str + clientType: str | TypesyncUndefined | None = UNDEFINED + endTime: datetime.datetime + startTime: datetime.datetime + results: dict[str, list[int]] | TypesyncUndefined | None = UNDEFINED + usergroups: dict[str, bool] | TypesyncUndefined | None = UNDEFINED + + class Config: + use_enum_values = False + extra = "forbid" + + @typing.override + def __setattr__(self, name: str, value: typing.Any) -> None: + if name == "clientType" and value is None: + raise ValueError("'clientType' field cannot be set to None") + if name == "results" and value is None: + raise ValueError("'results' field cannot be set to None") + if name == "usergroups" and value is None: + raise ValueError("'usergroups' field cannot be set to None") + super().__setattr__(name, value) + + class FbProjectStreetCreateOnlyInput(TypesyncModel): """Represents STREET project fields that are valid while creating a project""" @@ -545,7 +570,8 @@ class FbObjRasterTileServer(TypesyncModel): apiKey: str | TypesyncUndefined | None = UNDEFINED wmtsLayerName: typing.Annotated[ - str | TypesyncUndefined | None, pydantic.Field(deprecated=True) + str | TypesyncUndefined | None, + pydantic.Field(deprecated=True), ] = UNDEFINED credits: str name: FbEnumRasterTileServerName @@ -829,10 +855,12 @@ def __setattr__(self, name: str, value: typing.Any) -> None: class FbBaseTutorial(TypesyncModel): exampleImage1: typing.Annotated[ - str | TypesyncUndefined | None, pydantic.Field(deprecated=True) + str | TypesyncUndefined | None, + pydantic.Field(deprecated=True), ] = UNDEFINED exampleImage2: typing.Annotated[ - str | TypesyncUndefined | None, pydantic.Field(deprecated=True) + str | TypesyncUndefined | None, + pydantic.Field(deprecated=True), ] = UNDEFINED contributorCount: int informationPages: list[FbInformationPage] | TypesyncUndefined | None = UNDEFINED @@ -1164,10 +1192,12 @@ class FbUserReadonlyType(TypesyncModel): created: datetime.datetime lastAppUse: datetime.datetime | TypesyncUndefined | None = UNDEFINED userName: typing.Annotated[ - str | TypesyncUndefined | None, pydantic.Field(deprecated=True) + str | TypesyncUndefined | None, + pydantic.Field(deprecated=True), ] = UNDEFINED userNameKey: typing.Annotated[ - str | TypesyncUndefined | None, pydantic.Field(deprecated=True) + str | TypesyncUndefined | None, + pydantic.Field(deprecated=True), ] = UNDEFINED username: str | TypesyncUndefined | None = UNDEFINED usernameKey: str | TypesyncUndefined | None = UNDEFINED From 2ae12d1dbbe6b6809c8a184bf60239cc02fa271e Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Mon, 9 Mar 2026 11:00:26 +0545 Subject: [PATCH 7/9] chore(pre-commit): exclude uv.lock file formatting --- .pre-commit-config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2f124bf..451ca82 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,9 +36,11 @@ repos: - id: ruff types_or: [python, pyi, jupyter, toml] args: [--fix, --exit-non-zero-on-fix] + exclude: ^.*uv\.lock$ # Formatter - id: ruff-format types_or: [python, pyi, jupyter, toml] + exclude: ^.*uv\.lock$ - repo: https://github.com/RobertCraigie/pyright-python rev: v1.1.403 From 3fbc75af4f64e35fb99bb16aa3563996520125a5 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Wed, 6 May 2026 19:33:29 +0545 Subject: [PATCH 8/9] feat(pre-commit): upgrade pre-commit version to v0.15.4 --- .pre-commit-config.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 451ca82..9a58aa4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,17 +30,15 @@ repos: # Run the Ruff linter. - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.8 + rev: v0.15.4 hooks: # Linter - - id: ruff - types_or: [python, pyi, jupyter, toml] - args: [--fix, --exit-non-zero-on-fix] - exclude: ^.*uv\.lock$ + - id: ruff-check + args: [ --fix ] + types_or: [python, pyi, jupyter, pyproject] # Formatter - id: ruff-format - types_or: [python, pyi, jupyter, toml] - exclude: ^.*uv\.lock$ + types_or: [python, pyi, jupyter, pyproject] - repo: https://github.com/RobertCraigie/pyright-python rev: v1.1.403 From 96259da5300ea8dc5dc4a676596798bd347547d3 Mon Sep 17 00:00:00 2001 From: tnagorra Date: Thu, 9 Apr 2026 14:59:25 +0545 Subject: [PATCH 9/9] chore(functions): setup a cleanup policy - define SKIP_HOSTING to skip `hosting` deployment --- deploy.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/deploy.sh b/deploy.sh index 834a88c..a6871cb 100755 --- a/deploy.sh +++ b/deploy.sh @@ -17,7 +17,7 @@ cd "$FIREBASE_FUNCTIONS_DIR" cd "$BASE_DIR" -firebase use ${FIREBASE_PROJECT?error} +firebase use "${FIREBASE_PROJECT?error}" firebase target:apply hosting auth "$FIREBASE_AUTH_SITE" @@ -32,6 +32,11 @@ firebase functions:config:set \ osm.client_secret="$OSM_OAUTH_CLIENT_SECRET" \ osm.client_secret_web="$OSM_OAUTH_CLIENT_SECRET_WEB" -firebase deploy --only hosting +if [ "${SKIP_HOSTING:-false}" != "true" ]; then + firebase deploy --only hosting +fi + firebase deploy --only database -firebase deploy --only functions + +export FIREBASE_CLI_IMAGE_CLEANUP_DAYS=${FIREBASE_CLI_IMAGE_CLEANUP_DAYS:-30} +firebase deploy --only functions --non-interactive