contextbase-plugin-microsoft-planner-premium 0.0.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.3
2
+ Name: contextbase-plugin-microsoft-planner-premium
3
+ Version: 0.0.0a1
4
+ Summary: Microsoft Planner Premium / Project for the Web plugin for ContextBase
5
+ Author: Alizain Feerasta
6
+ Author-email: Alizain Feerasta <alizain.feerasta@gmail.com>
7
+ Requires-Dist: contextbase-base-client==0.0.0a1
8
+ Requires-Dist: contextbase-shared-plugins==0.0.0a1
9
+ Requires-Dist: dagster==1.12.14
10
+ Requires-Dist: dagster-dlt==0.28.14
11
+ Requires-Dist: dlt[duckdb]>=1.26.0
12
+ Requires-Dist: pydantic>=2.12.0
13
+ Requires-Python: >=3.12, <3.13
@@ -0,0 +1,9 @@
1
+ plugin_microsoft_planner_premium/__init__.py,sha256=IKZK1qTZr1ZFeRpERM1QyrdaimrSr79pJbrD-prTihk,78
2
+ plugin_microsoft_planner_premium/binding_config.py,sha256=ZRWmqzotiil91S5x-1JKgJNcWTSMS4pbRALasYrFlmQ,193
3
+ plugin_microsoft_planner_premium/component.py,sha256=bpYBZg3eO58nJTj5Z2O6eXHgE__FPuC3XEEp6T7gXRg,5908
4
+ plugin_microsoft_planner_premium/plugin.json,sha256=F8pOucFfytLLAyBs04VvWQ7YhrFo8eGDg_phHZmF2Qo,407
5
+ plugin_microsoft_planner_premium/tables.py,sha256=1Vp-OFU25IEUtqolxvYKQZdo6ebnxGw50mXH5yPmIE8,7514
6
+ contextbase_plugin_microsoft_planner_premium-0.0.0a1.dist-info/WHEEL,sha256=i9aSRDivn5iP9LaR1BLQX2GNAuriQWPsFwbbWygTX2k,81
7
+ contextbase_plugin_microsoft_planner_premium-0.0.0a1.dist-info/entry_points.txt,sha256=G4yo-9ZyPfl2EH3f8dX9CcVVS_LW9KaJQUszO9zpzJA,132
8
+ contextbase_plugin_microsoft_planner_premium-0.0.0a1.dist-info/METADATA,sha256=tcWBWowha5ECd3Za4zxVU-iqPUj-z7-Nqf9Nfqf4Muw,520
9
+ contextbase_plugin_microsoft_planner_premium-0.0.0a1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.15
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [contextlayer.plugins]
2
+ microsoft_planner_premium = plugin_microsoft_planner_premium.component:MicrosoftPlannerPremiumSyncComponent
3
+
@@ -0,0 +1 @@
1
+ """Microsoft Planner Premium / Project for the Web plugin for ContextBase."""
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from shared_plugins.microsoft_dataverse import DataverseBindingConfigBase
4
+
5
+
6
+ class MicrosoftPlannerPremiumBindingConfig(DataverseBindingConfigBase):
7
+ pass
@@ -0,0 +1,170 @@
1
+ import dagster as dg
2
+ from dagster import AssetExecutionContext
3
+ from dagster_dlt import DagsterDltResource
4
+ from shared_plugins.automation import non_overlapping_automation_condition
5
+ from shared_plugins.bindings import (
6
+ parse_binding_config,
7
+ resolve_binding_models,
8
+ )
9
+ from shared_plugins.base_platform import BasePlatformClient
10
+ from shared_plugins.dlt import resolve_partition_binding, run_dlt_pipeline
11
+ from shared_plugins.microsoft_dataverse import (
12
+ DataverseClient,
13
+ build_dataverse_dlt_source,
14
+ )
15
+ from shared_plugins.naming import (
16
+ dagster_asset_group_name,
17
+ dagster_asset_tags,
18
+ dagster_dlt_asset_key,
19
+ dagster_partition_def_name,
20
+ dagster_pool_name,
21
+ dlt_source_name,
22
+ plugin_id_from_module,
23
+ )
24
+ from shared_plugins.provider_token import DelegatedTokenProvider, ProviderTokenClient
25
+ from shared_plugins.resources import DLT_RESOURCE
26
+ from base_client import (
27
+ BindingAuth_AuthenticatedAccount,
28
+ BindingAuth_ClientCredentials,
29
+ DagsterAllPlanBinding,
30
+ )
31
+
32
+ from .binding_config import MicrosoftPlannerPremiumBindingConfig
33
+ from .tables import (
34
+ DEFAULT_ACTIVE_MODEL_NAMES,
35
+ SUPPORTED_MODEL_NAMES,
36
+ TABLE_SPECS,
37
+ )
38
+
39
+ PLUGIN_ID = plugin_id_from_module(__file__)
40
+ SYNC_JOB = "sync"
41
+ SYNC_SOURCE_NAME = dlt_source_name(PLUGIN_ID, SYNC_JOB)
42
+
43
+
44
+ def _build_dataverse_client(
45
+ cfg: MicrosoftPlannerPremiumBindingConfig,
46
+ binding: DagsterAllPlanBinding,
47
+ provider_token: ProviderTokenClient,
48
+ ) -> DataverseClient:
49
+ # Credential-agnostic sync (write-side MCP spec, R7): the Dataverse OData reads
50
+ # are byte-identical whichever credential produced the bearer, so binding.auth
51
+ # branches ONLY token acquisition — everything downstream is shared.
52
+ auth = binding.auth
53
+ if isinstance(auth, BindingAuth_ClientCredentials):
54
+ return DataverseClient(
55
+ org_url=cfg.org_url,
56
+ tenant_id=cfg.tenant_id,
57
+ client_id=auth.client_id,
58
+ client_secret=auth.client_secret,
59
+ )
60
+ if isinstance(auth, BindingAuth_AuthenticatedAccount):
61
+ return DataverseClient(
62
+ org_url=cfg.org_url,
63
+ access_token_provider=DelegatedTokenProvider(
64
+ auth=auth,
65
+ provider_token_client=provider_token,
66
+ ),
67
+ )
68
+ raise RuntimeError(
69
+ f"{binding.plugin_id} binding requires auth.type 'client_credentials' or "
70
+ f"'authenticated_account', got '{auth.type}'."
71
+ )
72
+
73
+
74
+ def _build_sync_specs(
75
+ partitions_def: dg.PartitionsDefinition,
76
+ automation_condition: dg.AutomationCondition,
77
+ ) -> list[dg.AssetSpec]:
78
+ shared = dict(
79
+ group_name=dagster_asset_group_name(PLUGIN_ID),
80
+ tags=dagster_asset_tags(PLUGIN_ID, extra_tags={"ctx_primary": "true"}),
81
+ automation_condition=automation_condition,
82
+ partitions_def=partitions_def,
83
+ )
84
+
85
+ return [
86
+ dg.AssetSpec(
87
+ key=dagster_dlt_asset_key(SYNC_SOURCE_NAME, spec.resource_name),
88
+ **shared,
89
+ )
90
+ for spec in TABLE_SPECS
91
+ ]
92
+
93
+
94
+ class MicrosoftPlannerPremiumSyncComponent(dg.Component):
95
+ def build_defs(self, context: dg.ComponentLoadContext) -> dg.Definitions:
96
+ partitions_def = dg.DynamicPartitionsDefinition(
97
+ name=dagster_partition_def_name(PLUGIN_ID)
98
+ )
99
+
100
+ sync_specs = _build_sync_specs(
101
+ partitions_def,
102
+ non_overlapping_automation_condition(
103
+ dg.AutomationCondition.on_missing()
104
+ | dg.AutomationCondition.on_cron("*/15 * * * *")
105
+ ),
106
+ )
107
+
108
+ @dg.multi_asset(
109
+ specs=sync_specs,
110
+ can_subset=True,
111
+ name="microsoft_planner_premium_sync",
112
+ pool=dagster_pool_name(PLUGIN_ID),
113
+ )
114
+ def microsoft_planner_premium_sync_assets(
115
+ context: AssetExecutionContext,
116
+ dlt_resource: DagsterDltResource,
117
+ base_platform: dg.ResourceParam[BasePlatformClient],
118
+ provider_token: dg.ResourceParam[ProviderTokenClient],
119
+ ):
120
+ binding = resolve_partition_binding(
121
+ context=context,
122
+ base_platform=base_platform,
123
+ plugin_id=PLUGIN_ID,
124
+ )
125
+ binding_id = binding.binding_id
126
+ cfg = parse_binding_config(binding, MicrosoftPlannerPremiumBindingConfig)
127
+ binding_models = resolve_binding_models(
128
+ binding,
129
+ supported_models=SUPPORTED_MODEL_NAMES,
130
+ default_active=DEFAULT_ACTIVE_MODEL_NAMES,
131
+ )
132
+ client = _build_dataverse_client(cfg, binding, provider_token)
133
+ try:
134
+ source = build_dataverse_dlt_source(
135
+ plugin_id=PLUGIN_ID,
136
+ job=SYNC_JOB,
137
+ binding_id=binding_id,
138
+ client=client,
139
+ binding_models=binding_models,
140
+ specs=TABLE_SPECS,
141
+ )
142
+ yield from run_dlt_pipeline(
143
+ context=context,
144
+ dlt_resource=dlt_resource,
145
+ source=source,
146
+ plugin_id=PLUGIN_ID,
147
+ binding_id=binding_id,
148
+ job_name=SYNC_JOB,
149
+ )
150
+ finally:
151
+ client.close()
152
+
153
+ automation_sensor = dg.AutomationConditionSensorDefinition(
154
+ name="microsoft_planner_premium_automation_sensor",
155
+ target=dg.AssetSelection.assets(
156
+ microsoft_planner_premium_sync_assets,
157
+ ),
158
+ default_status=dg.DefaultSensorStatus.RUNNING,
159
+ minimum_interval_seconds=30,
160
+ )
161
+
162
+ return dg.Definitions(
163
+ assets=[
164
+ microsoft_planner_premium_sync_assets,
165
+ ],
166
+ sensors=[automation_sensor],
167
+ resources={
168
+ "dlt_resource": DLT_RESOURCE,
169
+ },
170
+ )
@@ -0,0 +1,19 @@
1
+ {
2
+ "auth": {
3
+ "provider_id": "microsoft-dataverse",
4
+ "scopes": [],
5
+ "type": "oauth"
6
+ },
7
+ "mcpServers": {
8
+ "microsoft_planner_premium": {
9
+ "enabledTools": {
10
+ "submit_operation_set": {},
11
+ "wait_for_operation_set": { "autoAllow": true }
12
+ },
13
+ "module": "@usecontextlayer/mcp-microsoft-planner-premium",
14
+ "type": "module"
15
+ }
16
+ },
17
+ "mode": "dagster",
18
+ "plugin_id": "microsoft_planner_premium"
19
+ }
@@ -0,0 +1,219 @@
1
+ """Inventory of Dataverse entity sets this plugin syncs.
2
+
3
+ Each `DataverseTableSpec` names one OData entity set, its primary-key
4
+ attribute, and the sync mode (delta-tracked vs. full snapshot). Selected
5
+ columns are NOT carried on the spec — they are computed at warmup from
6
+ per-tenant `EntityDefinitions` metadata via
7
+ `shared_plugins.microsoft_dataverse.runtime_schema.build_runtime_table_schemas`,
8
+ which lets the typed-column rewrite pick up new attributes without
9
+ requiring code changes per tenant.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from shared_plugins.microsoft_dataverse import (
15
+ DataverseSyncMode,
16
+ DataverseTableSpec,
17
+ )
18
+
19
+ DELTA_TABLE_SPECS: tuple[DataverseTableSpec, ...] = (
20
+ DataverseTableSpec(
21
+ entity_set="msdyn_projects",
22
+ primary_key="msdyn_projectid",
23
+ sync_mode=DataverseSyncMode.DELTA,
24
+ resource_name="msdyn_projects",
25
+ ),
26
+ DataverseTableSpec(
27
+ entity_set="msdyn_projecttasks",
28
+ primary_key="msdyn_projecttaskid",
29
+ sync_mode=DataverseSyncMode.DELTA,
30
+ resource_name="msdyn_projecttasks",
31
+ ),
32
+ DataverseTableSpec(
33
+ entity_set="msdyn_projectteams",
34
+ primary_key="msdyn_projectteamid",
35
+ sync_mode=DataverseSyncMode.DELTA,
36
+ resource_name="msdyn_projectteams",
37
+ ),
38
+ DataverseTableSpec(
39
+ entity_set="msdyn_projectbuckets",
40
+ primary_key="msdyn_projectbucketid",
41
+ sync_mode=DataverseSyncMode.DELTA,
42
+ resource_name="msdyn_projectbuckets",
43
+ ),
44
+ DataverseTableSpec(
45
+ entity_set="msdyn_projecttaskdependencies",
46
+ primary_key="msdyn_projecttaskdependencyid",
47
+ sync_mode=DataverseSyncMode.DELTA,
48
+ resource_name="msdyn_projecttaskdependencies",
49
+ ),
50
+ DataverseTableSpec(
51
+ entity_set="msdyn_resourceassignments",
52
+ primary_key="msdyn_resourceassignmentid",
53
+ sync_mode=DataverseSyncMode.DELTA,
54
+ resource_name="msdyn_resourceassignments",
55
+ ),
56
+ DataverseTableSpec(
57
+ entity_set="msdyn_projectlabels",
58
+ primary_key="msdyn_projectlabelid",
59
+ sync_mode=DataverseSyncMode.DELTA,
60
+ resource_name="msdyn_projectlabels",
61
+ ),
62
+ DataverseTableSpec(
63
+ entity_set="msdyn_projecttasktolabels",
64
+ primary_key="msdyn_projecttasktolabelid",
65
+ sync_mode=DataverseSyncMode.DELTA,
66
+ resource_name="msdyn_projecttasktolabels",
67
+ ),
68
+ DataverseTableSpec(
69
+ entity_set="msdyn_projectstatusreports",
70
+ primary_key="msdyn_projectstatusreportid",
71
+ sync_mode=DataverseSyncMode.DELTA,
72
+ resource_name="msdyn_projectstatusreports",
73
+ ),
74
+ DataverseTableSpec(
75
+ entity_set="msdyn_projectissues",
76
+ primary_key="msdyn_projectissueid",
77
+ sync_mode=DataverseSyncMode.DELTA,
78
+ resource_name="msdyn_projectissues",
79
+ ),
80
+ DataverseTableSpec(
81
+ entity_set="msdyn_projectrisks",
82
+ primary_key="msdyn_projectriskid",
83
+ sync_mode=DataverseSyncMode.DELTA,
84
+ resource_name="msdyn_projectrisks",
85
+ ),
86
+ DataverseTableSpec(
87
+ entity_set="msdyn_projectchanges",
88
+ primary_key="msdyn_projectchangeid",
89
+ sync_mode=DataverseSyncMode.DELTA,
90
+ resource_name="msdyn_projectchanges",
91
+ ),
92
+ DataverseTableSpec(
93
+ entity_set="msdyn_projectparameters",
94
+ primary_key="msdyn_projectparameterid",
95
+ sync_mode=DataverseSyncMode.DELTA,
96
+ resource_name="msdyn_projectparameters",
97
+ ),
98
+ DataverseTableSpec(
99
+ entity_set="msdyn_workhourtemplates",
100
+ primary_key="msdyn_workhourtemplateid",
101
+ sync_mode=DataverseSyncMode.DELTA,
102
+ resource_name="msdyn_workhourtemplates",
103
+ ),
104
+ DataverseTableSpec(
105
+ entity_set="emails",
106
+ primary_key="activityid",
107
+ sync_mode=DataverseSyncMode.DELTA,
108
+ resource_name="emails",
109
+ ),
110
+ DataverseTableSpec(
111
+ entity_set="crff1_emaillogses",
112
+ primary_key="crff1_emaillogsid",
113
+ sync_mode=DataverseSyncMode.DELTA,
114
+ resource_name="crff1_emaillogses",
115
+ ),
116
+ DataverseTableSpec(
117
+ entity_set="appointments",
118
+ primary_key="activityid",
119
+ sync_mode=DataverseSyncMode.DELTA,
120
+ resource_name="appointments",
121
+ ),
122
+ DataverseTableSpec(
123
+ entity_set="activityparties",
124
+ primary_key="activitypartyid",
125
+ sync_mode=DataverseSyncMode.DELTA,
126
+ resource_name="activityparties",
127
+ ),
128
+ DataverseTableSpec(
129
+ entity_set="accounts",
130
+ primary_key="accountid",
131
+ sync_mode=DataverseSyncMode.DELTA,
132
+ resource_name="accounts",
133
+ ),
134
+ DataverseTableSpec(
135
+ entity_set="contacts",
136
+ primary_key="contactid",
137
+ sync_mode=DataverseSyncMode.DELTA,
138
+ resource_name="contacts",
139
+ ),
140
+ DataverseTableSpec(
141
+ entity_set="systemusers",
142
+ primary_key="systemuserid",
143
+ sync_mode=DataverseSyncMode.DELTA,
144
+ resource_name="systemusers",
145
+ ),
146
+ DataverseTableSpec(
147
+ entity_set="crff1_stagehistories",
148
+ primary_key="crff1_stagehistoryid",
149
+ sync_mode=DataverseSyncMode.DELTA,
150
+ resource_name="crff1_stagehistories",
151
+ ),
152
+ )
153
+
154
+ SNAPSHOT_TABLE_SPECS: tuple[DataverseTableSpec, ...] = (
155
+ DataverseTableSpec(
156
+ entity_set="msdyn_projectchecklists",
157
+ primary_key="msdyn_projectchecklistid",
158
+ sync_mode=DataverseSyncMode.SNAPSHOT,
159
+ resource_name="msdyn_projectchecklists",
160
+ ),
161
+ DataverseTableSpec(
162
+ entity_set="msdyn_projectsprints",
163
+ primary_key="msdyn_projectsprintid",
164
+ sync_mode=DataverseSyncMode.SNAPSHOT,
165
+ resource_name="msdyn_projectsprints",
166
+ ),
167
+ DataverseTableSpec(
168
+ entity_set="msdyn_projecttaskattachments",
169
+ primary_key="msdyn_projecttaskattachmentid",
170
+ sync_mode=DataverseSyncMode.SNAPSHOT,
171
+ resource_name="msdyn_projecttaskattachments",
172
+ ),
173
+ DataverseTableSpec(
174
+ entity_set="msdyn_projecttaskconversations",
175
+ primary_key="msdyn_projecttaskconversationid",
176
+ sync_mode=DataverseSyncMode.SNAPSHOT,
177
+ resource_name="msdyn_projecttaskconversations",
178
+ ),
179
+ DataverseTableSpec(
180
+ entity_set="msdyn_projecttasktogoals",
181
+ primary_key="msdyn_projecttasktogoalid",
182
+ sync_mode=DataverseSyncMode.SNAPSHOT,
183
+ resource_name="msdyn_projecttasktogoals",
184
+ ),
185
+ DataverseTableSpec(
186
+ entity_set="msdyn_projectgoals",
187
+ primary_key="msdyn_projectgoalid",
188
+ sync_mode=DataverseSyncMode.SNAPSHOT,
189
+ resource_name="msdyn_projectgoals",
190
+ ),
191
+ DataverseTableSpec(
192
+ entity_set="msdyn_projectbaselinedatas",
193
+ primary_key="msdyn_projectbaselinedataid",
194
+ sync_mode=DataverseSyncMode.SNAPSHOT,
195
+ resource_name="msdyn_projectbaselinedatas",
196
+ ),
197
+ DataverseTableSpec(
198
+ entity_set="msdyn_projectbaselinetaskdatas",
199
+ primary_key="msdyn_projectbaselinetaskdataid",
200
+ sync_mode=DataverseSyncMode.SNAPSHOT,
201
+ resource_name="msdyn_projectbaselinetaskdatas",
202
+ ),
203
+ DataverseTableSpec(
204
+ entity_set="msdyn_projectteamschannelmappings",
205
+ primary_key="msdyn_projectteamschannelmappingid",
206
+ sync_mode=DataverseSyncMode.SNAPSHOT,
207
+ resource_name="msdyn_projectteamschannelmappings",
208
+ ),
209
+ )
210
+
211
+ TABLE_SPECS: tuple[DataverseTableSpec, ...] = (
212
+ *DELTA_TABLE_SPECS,
213
+ *SNAPSHOT_TABLE_SPECS,
214
+ )
215
+
216
+ SUPPORTED_MODEL_NAMES: tuple[str, ...] = tuple(
217
+ spec.resource_name for spec in TABLE_SPECS
218
+ )
219
+ DEFAULT_ACTIVE_MODEL_NAMES: tuple[str, ...] = SUPPORTED_MODEL_NAMES