@causa/workspace-google 1.4.0-beta.1 → 1.4.0-beta.3

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.
Files changed (80) hide show
  1. package/README.md +19 -3
  2. package/dist/functions/event-topic/count-events-bigquery.call.d.ts +3 -0
  3. package/dist/functions/event-topic/count-events-bigquery.call.js +75 -0
  4. package/dist/functions/event-topic/count-events-bigquery.d.ts +11 -0
  5. package/dist/functions/event-topic/count-events-bigquery.js +19 -0
  6. package/dist/functions/event-topic/create-backfill-source-bigquery.call.js +6 -0
  7. package/dist/functions/event-topic/create-backfill-source-bigquery.d.ts +1 -1
  8. package/dist/functions/event-topic/create-backfill-source-bigquery.js +1 -1
  9. package/dist/functions/event-topic/index.d.ts +1 -0
  10. package/dist/functions/event-topic/index.js +1 -0
  11. package/dist/functions/event-topic/query-events-bigquery.call.js +2 -0
  12. package/dist/functions/event-topic/query-events-bigquery.d.ts +1 -0
  13. package/dist/functions/event-topic/query-events-bigquery.js +1 -0
  14. package/dist/functions/google-app-check/generate-token.js +3 -1
  15. package/dist/functions/google-firebase-storage/merge-rules.js +3 -1
  16. package/dist/functions/google-firestore/merge-rules.js +3 -1
  17. package/dist/functions/google-identity-platform/generate-custom-token.js +7 -2
  18. package/dist/functions/google-pubsub/write-topics.js +7 -2
  19. package/dist/functions/google-services/enable.js +3 -1
  20. package/dist/functions/google-spanner/count-records.call.d.ts +16 -0
  21. package/dist/functions/google-spanner/count-records.call.js +120 -0
  22. package/dist/functions/google-spanner/count-records.d.ts +15 -0
  23. package/dist/functions/google-spanner/count-records.js +21 -0
  24. package/dist/functions/google-spanner/index.d.ts +3 -1
  25. package/dist/functions/google-spanner/index.js +3 -1
  26. package/dist/functions/google-spanner/list-databases.d.ts +22 -1
  27. package/dist/functions/google-spanner/list-databases.js +27 -15
  28. package/dist/functions/google-spanner/resolve-table.d.ts +25 -0
  29. package/dist/functions/google-spanner/resolve-table.js +44 -0
  30. package/dist/functions/google-spanner/write-databases.js +7 -2
  31. package/dist/functions/graph/fetch-environment-metric-series.call.d.ts +3 -0
  32. package/dist/functions/graph/fetch-environment-metric-series.call.js +107 -0
  33. package/dist/functions/graph/fetch-environment-metric-series.d.ts +23 -0
  34. package/dist/functions/graph/fetch-environment-metric-series.js +40 -0
  35. package/dist/functions/graph/get-environment-provider.d.ts +11 -0
  36. package/dist/functions/graph/get-environment-provider.js +20 -0
  37. package/dist/functions/graph/index.d.ts +2 -0
  38. package/dist/functions/graph/index.js +2 -0
  39. package/dist/functions/index.js +4 -4
  40. package/dist/graph/cloud-run.d.ts +2 -2
  41. package/dist/graph/cloud-run.js +2 -2
  42. package/dist/graph/environment/fetchers/cloud-monitoring-alerts.d.ts +6 -0
  43. package/dist/graph/environment/fetchers/cloud-monitoring-alerts.js +106 -0
  44. package/dist/graph/environment/fetchers/cloud-monitoring.d.ts +5 -0
  45. package/dist/graph/environment/fetchers/cloud-monitoring.js +13 -0
  46. package/dist/graph/environment/fetchers/cloud-run.d.ts +5 -0
  47. package/dist/graph/environment/fetchers/cloud-run.js +88 -0
  48. package/dist/graph/environment/fetchers/cloud-scheduler.d.ts +5 -0
  49. package/dist/graph/environment/fetchers/cloud-scheduler.js +95 -0
  50. package/dist/graph/environment/fetchers/console-links.d.ts +14 -0
  51. package/dist/graph/environment/fetchers/console-links.js +132 -0
  52. package/dist/graph/environment/fetchers/error-reporting.d.ts +5 -0
  53. package/dist/graph/environment/fetchers/error-reporting.js +98 -0
  54. package/dist/graph/environment/fetchers/index.d.ts +5 -0
  55. package/dist/graph/environment/fetchers/index.js +17 -0
  56. package/dist/graph/environment/index.d.ts +9 -0
  57. package/dist/graph/environment/index.js +9 -0
  58. package/dist/graph/environment/load-balancer-backends.d.ts +82 -0
  59. package/dist/graph/environment/load-balancer-backends.js +126 -0
  60. package/dist/graph/environment/monitoring-alerts.d.ts +60 -0
  61. package/dist/graph/environment/monitoring-alerts.js +67 -0
  62. package/dist/graph/environment/monitoring-catalog.d.ts +95 -0
  63. package/dist/graph/environment/monitoring-catalog.js +356 -0
  64. package/dist/graph/environment/monitoring-mappings.d.ts +133 -0
  65. package/dist/graph/environment/monitoring-mappings.js +97 -0
  66. package/dist/graph/environment/monitoring-query.d.ts +116 -0
  67. package/dist/graph/environment/monitoring-query.js +314 -0
  68. package/dist/graph/environment/monitoring-values.d.ts +41 -0
  69. package/dist/graph/environment/monitoring-values.js +119 -0
  70. package/dist/graph/environment/resource-resolvers.d.ts +7 -0
  71. package/dist/graph/environment/resource-resolvers.js +57 -0
  72. package/dist/graph/environment/resources.d.ts +45 -0
  73. package/dist/graph/environment/resources.js +49 -0
  74. package/dist/graph/index.d.ts +1 -0
  75. package/dist/graph/index.js +1 -0
  76. package/dist/graph/rules/configuration/service-container.js +4 -4
  77. package/dist/graph/rules/terraform/spanner-databases.js +4 -4
  78. package/dist/graph/spanner.d.ts +11 -60
  79. package/dist/graph/spanner.js +25 -69
  80. package/package.json +24 -24
@@ -0,0 +1,45 @@
1
+ import type { GraphEnvironmentContext, GraphNodeEntry } from '@causa/workspace-core/graph';
2
+ /**
3
+ * The segments of a Google Cloud resource name, keyed by collection.
4
+ * For example, `projects/my-project/locations/europe-west1/services/my-service` is
5
+ * `{ projects: 'my-project', locations: 'europe-west1', services: 'my-service' }`.
6
+ */
7
+ export type ResourceNameSegments = Record<string, string>;
8
+ /**
9
+ * Parses a Google Cloud resource name into its segments.
10
+ * The `global` segment, which is not followed by an ID (e.g. in `projects/my-project/global/urlMaps/api`), is skipped.
11
+ *
12
+ * @param name The resource name.
13
+ * @returns The segments, keyed by collection.
14
+ */
15
+ export declare function parseResourceName(name: string): ResourceNameSegments;
16
+ /**
17
+ * A node whose resource is a Google Cloud resource, along with its full name.
18
+ */
19
+ export type GoogleResource = {
20
+ /**
21
+ * The node.
22
+ */
23
+ readonly node: GraphNodeEntry;
24
+ /**
25
+ * The type of the resource, e.g. `run.googleapis.com/Service`.
26
+ */
27
+ readonly type: string;
28
+ /**
29
+ * The full resource name.
30
+ */
31
+ readonly name: string;
32
+ /**
33
+ * The segments of the resource name.
34
+ */
35
+ readonly segments: ResourceNameSegments;
36
+ };
37
+ /**
38
+ * Returns the Google Cloud resources of the graph, with the segments of their names.
39
+ *
40
+ * @param environment The context of the environment.
41
+ * @param resourceType The type of the resources. Defaults to all Google Cloud resource types.
42
+ * @param nodeType The type of the nodes. Defaults to all node types.
43
+ * @returns The resources, in the order of the graph.
44
+ */
45
+ export declare function googleResources(environment: GraphEnvironmentContext, resourceType?: string, nodeType?: string): GoogleResource[];
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Parses a Google Cloud resource name into its segments.
3
+ * The `global` segment, which is not followed by an ID (e.g. in `projects/my-project/global/urlMaps/api`), is skipped.
4
+ *
5
+ * @param name The resource name.
6
+ * @returns The segments, keyed by collection.
7
+ */
8
+ export function parseResourceName(name) {
9
+ const tokens = name.split('/');
10
+ const segments = {};
11
+ for (let index = 0; index < tokens.length;) {
12
+ const collection = tokens[index];
13
+ if (collection === 'global') {
14
+ index += 1;
15
+ continue;
16
+ }
17
+ segments[collection] = tokens[index + 1] ?? '';
18
+ index += 2;
19
+ }
20
+ return segments;
21
+ }
22
+ /**
23
+ * Returns whether a resource type is the type of a Google Cloud resource.
24
+ *
25
+ * @param type The type of the resource.
26
+ * @returns `true` for Google Cloud resource types, e.g. `run.googleapis.com/Service`.
27
+ */
28
+ function isGoogleResourceType(type) {
29
+ return type.includes('.googleapis.com/');
30
+ }
31
+ /**
32
+ * Returns the Google Cloud resources of the graph, with the segments of their names.
33
+ *
34
+ * @param environment The context of the environment.
35
+ * @param resourceType The type of the resources. Defaults to all Google Cloud resource types.
36
+ * @param nodeType The type of the nodes. Defaults to all node types.
37
+ * @returns The resources, in the order of the graph.
38
+ */
39
+ export function googleResources(environment, resourceType, nodeType) {
40
+ return environment
41
+ .resources(resourceType, nodeType)
42
+ .filter(({ resource }) => isGoogleResourceType(resource.type))
43
+ .map(({ node, resource: { type, id } }) => ({
44
+ node,
45
+ type,
46
+ name: id,
47
+ segments: parseResourceName(id),
48
+ }));
49
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './cloud-run.js';
2
+ export * from './environment/index.js';
2
3
  export * from './ids.js';
3
4
  export * from './rules/configuration/index.js';
4
5
  export * from './rules/terraform/index.js';
@@ -1,4 +1,5 @@
1
1
  export * from './cloud-run.js';
2
+ export * from './environment/index.js';
2
3
  export * from './ids.js';
3
4
  export * from './rules/configuration/index.js';
4
5
  export * from './rules/terraform/index.js';
@@ -1,7 +1,7 @@
1
1
  import { GraphOriginKind, } from '@causa/workspace-core';
2
2
  import { DomainsFact, ModelFact, projectId, ProjectsFact, topicId, triggerId, } from '@causa/workspace-core/graph';
3
3
  import { FIRESTORE_ENGINE, firestoreCollectionPath, SPANNER_ENGINE, } from '../../ids.js';
4
- import { ddlSource, resolveSpannerTable, SpannerFact } from '../../spanner.js';
4
+ import { ddlSource, resolveEntitySpannerTable, SpannerFact, } from '../../spanner.js';
5
5
  /**
6
6
  * The elements declared by the Google-specific parts of the `serviceContainer` configuration of every service container
7
7
  * project.
@@ -18,7 +18,7 @@ export const googleServiceContainerFromConfiguration = {
18
18
  kind: GraphOriginKind.Declared,
19
19
  description: 'One `delivers` edge from a topic to each trigger of type `google.pubSub` naming it, when an event schema defines the topic. One `accesses` edge from a project to each entity persisted in a Spanner database or a Firestore collection listed in its `serviceContainer.outputs`.',
20
20
  async run(graph) {
21
- const { locator } = graph;
21
+ const { locator, context } = graph;
22
22
  const [domains, projects, model, spanner] = await Promise.all([
23
23
  graph.get(DomainsFact),
24
24
  graph.get(ProjectsFact),
@@ -29,7 +29,7 @@ export const googleServiceContainerFromConfiguration = {
29
29
  const warnings = [];
30
30
  const entities = [...model.entities.values()];
31
31
  const spannerEntities = entities.flatMap((entity) => {
32
- const resolution = resolveSpannerTable(spanner, entity, domains);
32
+ const resolution = resolveEntitySpannerTable(spanner, entity, domains);
33
33
  return resolution?.kind === 'resolved' ? [{ entity, resolution }] : [];
34
34
  });
35
35
  for (const project of projects.filter((p) => p.type === 'serviceContainer')) {
@@ -78,7 +78,7 @@ export const googleServiceContainerFromConfiguration = {
78
78
  type: 'accesses',
79
79
  from: projectId(project.directory),
80
80
  to: entity.id,
81
- sources: [source, ddlSource(resolution.table)],
81
+ sources: [source, ddlSource(context.rootPath, resolution.table)],
82
82
  });
83
83
  }
84
84
  }
@@ -2,7 +2,7 @@ import { GraphOriginKind, } from '@causa/workspace-core';
2
2
  import { databaseId, tableId, tableLocator, DomainsFact, ModelFact, nodeId, } from '@causa/workspace-core/graph';
3
3
  import { terraformDeploys } from '@causa/workspace-terraform';
4
4
  import { SPANNER_ENGINE, spannerInstanceId } from '../../ids.js';
5
- import { ddlSource, resolveSpannerTable, SpannerFact } from '../../spanner.js';
5
+ import { ddlSource, resolveEntitySpannerTable, SpannerFact, } from '../../spanner.js';
6
6
  import { blockResource, infrastructureModules, argumentOrConfiguration, } from '../../terraform-modules.js';
7
7
  /**
8
8
  * The source of the Causa Terraform module creating the Spanner instance and databases.
@@ -135,13 +135,13 @@ export const spannerDatabasesModule = {
135
135
  locator: nodeLocator,
136
136
  parent: databaseId(database.locator),
137
137
  name: table.name,
138
- sources: [ddlSource(table), ...blocks],
138
+ sources: [ddlSource(context.rootPath, table), ...blocks],
139
139
  });
140
140
  edges.push(...spannerDatabases.flatMap((module) => terraformDeploys(module.block, nodeId('table', nodeLocator))));
141
141
  }
142
142
  }
143
143
  for (const entity of model.entities.values()) {
144
- const resolution = resolveSpannerTable(spanner, entity, domains);
144
+ const resolution = resolveEntitySpannerTable(spanner, entity, domains);
145
145
  if (!resolution) {
146
146
  continue;
147
147
  }
@@ -172,7 +172,7 @@ export const spannerDatabasesModule = {
172
172
  type: 'realizes',
173
173
  from: tableId(resolution.database.locator, resolution.table.name),
174
174
  to: entity.id,
175
- sources: [binding, ddlSource(resolution.table)],
175
+ sources: [binding, ddlSource(context.rootPath, resolution.table)],
176
176
  });
177
177
  }
178
178
  return { nodes, edges, warnings };
@@ -1,30 +1,10 @@
1
1
  import type { GraphOriginSource } from '@causa/workspace-core';
2
- import { GraphFact, type EntityFacts, type GraphContext, type GraphFactOutput, type WorkspaceDomain } from '@causa/workspace-core/graph';
2
+ import { GraphExtractionFact, type EntityFacts, type GraphContext, type GraphFactOutput, type WorkspaceDomain } from '@causa/workspace-core/graph';
3
+ import { type SpannerDatabase, type SpannerTable, type SpannerTableResolution } from '../functions/google-spanner/index.js';
3
4
  /**
4
- * A table created by a `CREATE TABLE` statement in a Spanner DDL file.
5
+ * A Spanner database of the workspace, as `GoogleSpannerListDatabases` lists it, and its graph identifiers.
5
6
  */
6
- export type SpannerTable = {
7
- /**
8
- * The name of the table.
9
- */
10
- readonly name: string;
11
- /**
12
- * The DDL file declaring the table, relative to the workspace root.
13
- */
14
- readonly file: string;
15
- /**
16
- * The line of the statement in the file.
17
- */
18
- readonly line: number;
19
- };
20
- /**
21
- * A Spanner database of the workspace, and the tables its DDL files create.
22
- */
23
- export type SpannerDatabaseFacts = {
24
- /**
25
- * The ID of the database, as `GoogleSpannerListDatabases` returns it.
26
- */
27
- readonly id: string;
7
+ export type SpannerDatabaseFacts = SpannerDatabase & {
28
8
  /**
29
9
  * The name of the database within its engine, `<instance>.<database>`, as `outputs['google.spanner']` lists it.
30
10
  */
@@ -37,14 +17,6 @@ export type SpannerDatabaseFacts = {
37
17
  * The directory holding the DDL files, relative to the workspace root.
38
18
  */
39
19
  readonly directory: string;
40
- /**
41
- * The domain the DDL files belong to.
42
- */
43
- readonly domain: WorkspaceDomain | undefined;
44
- /**
45
- * The tables created by the DDL files.
46
- */
47
- readonly tables: SpannerTable[];
48
20
  };
49
21
  /**
50
22
  * The Spanner databases of the workspace.
@@ -60,47 +32,26 @@ export type SpannerFacts = {
60
32
  readonly databases: SpannerDatabaseFacts[];
61
33
  };
62
34
  /**
63
- * The Spanner databases of the workspace, as `GoogleSpannerListDatabases` lists them, and the tables their DDL files
64
- * create.
35
+ * The Spanner databases of the workspace, as `GoogleSpannerListDatabases` lists them.
65
36
  */
66
- export declare class SpannerFact extends GraphFact<SpannerFacts> {
37
+ export declare class SpannerFact extends GraphExtractionFact<SpannerFacts> {
67
38
  compute(graph: GraphContext): Promise<GraphFactOutput<SpannerFacts>>;
68
- /**
69
- * Parses the tables created by the `CREATE TABLE` statements of DDL files.
70
- *
71
- * @param context The workspace context.
72
- * @param files The DDL files, relative to the workspace root.
73
- * @returns The tables, in the order of the files and statements.
74
- */
75
- private parseTables;
76
39
  }
77
40
  /**
78
- * The resolution of an entity's Spanner binding to a table.
79
- */
80
- export type SpannerTableResolution = {
81
- readonly kind: 'resolved';
82
- readonly database: SpannerDatabaseFacts;
83
- readonly table: SpannerTable;
84
- } | {
85
- readonly kind: 'ambiguous';
86
- readonly candidates: SpannerDatabaseFacts[];
87
- } | {
88
- readonly kind: 'missing';
89
- };
90
- /**
91
- * Resolves the Spanner binding of an entity to the database whose DDL creates a table of that name. When several
92
- * databases declare the name, the one in the entity's domain is chosen.
41
+ * Resolves the Spanner binding of an entity to the database whose DDL creates a table of that name, using
42
+ * {@link resolveSpannerTable}.
93
43
  *
94
44
  * @param spanner The Spanner databases.
95
45
  * @param entity The entity.
96
46
  * @param domains The domains of the workspace, in which the domain of the entity is looked up.
97
47
  * @returns The resolution, or `undefined` if the entity is not persisted in Spanner.
98
48
  */
99
- export declare function resolveSpannerTable(spanner: SpannerFacts, entity: EntityFacts, domains: readonly WorkspaceDomain[]): SpannerTableResolution | undefined;
49
+ export declare function resolveEntitySpannerTable(spanner: SpannerFacts, entity: EntityFacts, domains: readonly WorkspaceDomain[]): SpannerTableResolution<SpannerDatabaseFacts> | undefined;
100
50
  /**
101
51
  * Returns the origin source of a `CREATE TABLE` statement.
102
52
  *
53
+ * @param rootPath The absolute path of the workspace root.
103
54
  * @param table The table.
104
55
  * @returns The origin source.
105
56
  */
106
- export declare function ddlSource(table: SpannerTable): GraphOriginSource;
57
+ export declare function ddlSource(rootPath: string, table: SpannerTable): GraphOriginSource;
@@ -1,35 +1,27 @@
1
- import { domainAt, domainOfFile, DomainsFact, GraphFact, } from '@causa/workspace-core/graph';
2
- import { readFile } from 'fs/promises';
3
- import { dirname, join, relative } from 'path';
4
- import { GoogleSpannerListDatabases } from '../functions/google-spanner/index.js';
1
+ import { GraphExtractionFact, } from '@causa/workspace-core/graph';
2
+ import { splitSchemaPath } from '@causa/workspace-core/jsonschema';
3
+ import { dirname, relative } from 'path';
4
+ import { GoogleSpannerListDatabases, resolveSpannerTable, } from '../functions/google-spanner/index.js';
5
5
  import { SPANNER_ENGINE, spannerDatabaseLocator, spannerDatabaseName, } from './ids.js';
6
6
  /**
7
- * The Spanner databases of the workspace, as `GoogleSpannerListDatabases` lists them, and the tables their DDL files
8
- * create.
7
+ * The Spanner databases of the workspace, as `GoogleSpannerListDatabases` lists them.
9
8
  */
10
- export class SpannerFact extends GraphFact {
9
+ export class SpannerFact extends GraphExtractionFact {
11
10
  async compute(graph) {
12
11
  const { context } = graph;
13
12
  const instance = context
14
13
  .asConfiguration()
15
14
  .get('google.spanner.instance.name');
16
- const [listed, domains] = await Promise.all([
17
- context.call(GoogleSpannerListDatabases, {}),
18
- graph.get(DomainsFact),
19
- ]);
20
- const databases = await Promise.all(listed.map(async ({ id, ddlFiles }) => {
21
- const files = ddlFiles.map((f) => relative(context.rootPath, f)).sort();
22
- const tables = await this.parseTables(context, files);
23
- const directory = files[0] ? dirname(files[0]) : '';
15
+ const listed = await context.call(GoogleSpannerListDatabases, {});
16
+ const databases = listed.map((database) => {
17
+ const [file] = database.ddlFiles;
24
18
  return {
25
- id,
26
- name: spannerDatabaseName(instance ?? '', id),
27
- locator: spannerDatabaseLocator(instance ?? '', id),
28
- directory,
29
- domain: directory ? domainAt(domains, directory) : undefined,
30
- tables,
19
+ ...database,
20
+ name: spannerDatabaseName(instance ?? '', database.id),
21
+ locator: spannerDatabaseLocator(instance ?? '', database.id),
22
+ directory: file ? dirname(relative(context.rootPath, file)) : '',
31
23
  };
32
- }));
24
+ });
33
25
  databases.sort((a, b) => a.id.localeCompare(b.id));
34
26
  const warnings = [];
35
27
  for (const database of databases) {
@@ -38,7 +30,7 @@ export class SpannerFact extends GraphFact {
38
30
  if (names.has(table.name)) {
39
31
  warnings.push({
40
32
  message: `Table '${table.name}' is created twice in database '${database.id}'.`,
41
- sources: [ddlSource(table)],
33
+ sources: [ddlSource(context.rootPath, table)],
42
34
  });
43
35
  }
44
36
  names.add(table.name);
@@ -46,72 +38,36 @@ export class SpannerFact extends GraphFact {
46
38
  }
47
39
  return { value: { instance, databases }, warnings };
48
40
  }
49
- /**
50
- * Parses the tables created by the `CREATE TABLE` statements of DDL files.
51
- *
52
- * @param context The workspace context.
53
- * @param files The DDL files, relative to the workspace root.
54
- * @returns The tables, in the order of the files and statements.
55
- */
56
- async parseTables(context, files) {
57
- const tables = [];
58
- for (const file of files) {
59
- const content = await readFile(join(context.rootPath, file), 'utf-8');
60
- const withoutComments = content.replace(/--.*$/gm, (m) => ' '.repeat(m.length));
61
- const statements = withoutComments.matchAll(/\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"']?([A-Za-z_]\w*)[`"']?/gi);
62
- for (const match of statements) {
63
- tables.push({
64
- name: match[1],
65
- file,
66
- line: withoutComments.slice(0, match.index).split('\n').length,
67
- });
68
- }
69
- }
70
- return tables;
71
- }
72
41
  }
73
42
  /**
74
- * Resolves the Spanner binding of an entity to the database whose DDL creates a table of that name. When several
75
- * databases declare the name, the one in the entity's domain is chosen.
43
+ * Resolves the Spanner binding of an entity to the database whose DDL creates a table of that name, using
44
+ * {@link resolveSpannerTable}.
76
45
  *
77
46
  * @param spanner The Spanner databases.
78
47
  * @param entity The entity.
79
48
  * @param domains The domains of the workspace, in which the domain of the entity is looked up.
80
49
  * @returns The resolution, or `undefined` if the entity is not persisted in Spanner.
81
50
  */
82
- export function resolveSpannerTable(spanner, entity, domains) {
83
- const { definition, file } = entity.schema;
51
+ export function resolveEntitySpannerTable(spanner, entity, domains) {
52
+ const { definition, path } = entity.schema;
84
53
  const table = definition.databases.find((d) => d.engine === SPANNER_ENGINE)?.table;
85
54
  if (!table) {
86
55
  return undefined;
87
56
  }
88
- const candidates = spanner.databases.filter((d) => d.tables.some((t) => t.name === table));
89
- const pick = (database) => ({
90
- kind: 'resolved',
91
- database,
92
- table: database.tables.find((t) => t.name === table),
93
- });
94
- if (candidates.length === 1) {
95
- return pick(candidates[0]);
96
- }
97
- if (candidates.length === 0) {
98
- return { kind: 'missing' };
99
- }
100
- const domain = domainOfFile(domains, file);
101
- const sameDomain = candidates.filter((d) => domain && d.domain?.directory === domain.directory);
102
- return sameDomain.length === 1
103
- ? pick(sameDomain[0])
104
- : { kind: 'ambiguous', candidates };
57
+ return resolveSpannerTable(spanner.databases, table, splitSchemaPath(path).file,
58
+ // The working directory of a domain's context is the absolute path of the domain.
59
+ domains.map((d) => d.context.workingDirectory));
105
60
  }
106
61
  /**
107
62
  * Returns the origin source of a `CREATE TABLE` statement.
108
63
  *
64
+ * @param rootPath The absolute path of the workspace root.
109
65
  * @param table The table.
110
66
  * @returns The origin source.
111
67
  */
112
- export function ddlSource(table) {
68
+ export function ddlSource(rootPath, table) {
113
69
  return {
114
- path: table.file,
70
+ path: relative(rootPath, table.file),
115
71
  pointer: `CREATE TABLE ${table.name}`,
116
72
  location: { start: { line: table.line } },
117
73
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@causa/workspace-google",
3
- "version": "1.4.0-beta.1",
3
+ "version": "1.4.0-beta.3",
4
4
  "description": "The Causa workspace module providing many functionalities related to GCP and its services.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,49 +35,49 @@
35
35
  "generateConfigurationSchemas": "cs model genCode && perl -pi -e 's|\\@causa/runtime|\\@causa/workspace/validation|g' src/configurations/generated.ts"
36
36
  },
37
37
  "dependencies": {
38
- "@causa/cli": "^1.0.0",
39
- "@causa/workspace": "^1.2.0",
40
- "@causa/workspace-core": "^1.5.0-beta.1",
41
- "@causa/workspace-terraform": "^1.1.0-beta.1",
42
- "@causa/workspace-typescript": "^1.3.0",
43
- "@google-cloud/apikeys": "^3.1.0",
44
- "@google-cloud/bigquery": "^9.1.0",
45
- "@google-cloud/iam-credentials": "^5.0.0",
46
- "@google-cloud/logging": "^12.1.0",
47
- "@google-cloud/monitoring": "^6.1.0",
48
- "@google-cloud/pubsub": "^6.1.0",
49
- "@google-cloud/resource-manager": "^7.1.0",
50
- "@google-cloud/run": "^4.1.0",
51
- "@google-cloud/secret-manager": "^7.1.0",
52
- "@google-cloud/service-usage": "^5.1.0",
38
+ "@causa/cli": "^1.0.1-beta.1",
39
+ "@causa/workspace": "^1.3.0-beta.1",
40
+ "@causa/workspace-core": "^1.5.0-beta.3",
41
+ "@causa/workspace-terraform": "^1.1.0-beta.2",
42
+ "@causa/workspace-typescript": "^1.4.0-beta.1",
43
+ "@google-cloud/apikeys": "^3.1.1",
44
+ "@google-cloud/bigquery": "^9.2.0",
45
+ "@google-cloud/iam-credentials": "^5.0.1",
46
+ "@google-cloud/logging": "^12.2.0",
47
+ "@google-cloud/monitoring": "^6.1.1",
48
+ "@google-cloud/pubsub": "^6.2.0",
49
+ "@google-cloud/resource-manager": "^7.1.1",
50
+ "@google-cloud/run": "^4.1.1",
51
+ "@google-cloud/secret-manager": "^7.1.1",
52
+ "@google-cloud/service-usage": "^5.1.1",
53
53
  "@google-cloud/spanner": "^9.0.0",
54
- "@google-cloud/storage": "^8.2.0",
54
+ "@google-cloud/storage": "^8.4.0",
55
55
  "class-transformer": "^0.5.1",
56
56
  "class-validator": "^0.15.1",
57
- "firebase": "^12.19.0",
57
+ "firebase": "^13.0.0",
58
58
  "firebase-admin": "^14.5.0",
59
59
  "globby": "^16.2.4",
60
60
  "google-gax": "5.0.6",
61
- "googleapis": "^182.0.0",
61
+ "googleapis": "^185.0.0",
62
62
  "micromatch": "^4.0.8",
63
- "pino": "^10.3.1"
63
+ "pino": "^10.4.0"
64
64
  },
65
65
  "devDependencies": {
66
- "@swc/core": "^1.16.2",
66
+ "@swc/core": "^1.16.13",
67
67
  "@swc/jest": "^0.2.39",
68
68
  "@tsconfig/node22": "^22.0.6",
69
69
  "@types/jest": "^30.0.0",
70
70
  "@types/micromatch": "^4.0.10",
71
- "@types/node": "^22.20.4",
71
+ "@types/node": "^22.20.5",
72
72
  "copyfiles": "^2.4.1",
73
- "eslint": "^10.11.0",
73
+ "eslint": "^10.12.0",
74
74
  "eslint-config-prettier": "^10.1.8",
75
75
  "eslint-plugin-prettier": "^5.5.6",
76
76
  "jest": "^30.5.2",
77
77
  "jest-extended": "^7.0.0",
78
78
  "rimraf": "^6.1.3",
79
79
  "typescript": "^6.0.3",
80
- "typescript-eslint": "^8.70.1",
80
+ "typescript-eslint": "^8.71.1",
81
81
  "yaml": "^2.9.1"
82
82
  }
83
83
  }