@@ -9,6 +9,11 @@ import { root } from '../helpers/root.js';
99
1010const LINK_FILENAME = 'link.yaml' ;
1111const PROJECT_DIR = 'powersync' ;
12+ const SERVICE_FILENAME = 'service.yaml' ;
13+
14+ function writeServiceYaml ( projectDir : string , type : 'cloud' | 'self-hosted' ) {
15+ writeFileSync ( join ( projectDir , SERVICE_FILENAME ) , `_type: ${ type } \n` , 'utf8' ) ;
16+ }
1217
1318describe ( 'link' , ( ) => {
1419 describe ( 'cloud' , ( ) => {
@@ -34,8 +39,28 @@ describe('link', () => {
3439 expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
3540 } ) ;
3641
37- it ( 'creates link .yaml with cloud config when directory exists ' , async ( ) => {
42+ it ( 'errors when service .yaml is missing ' , async ( ) => {
3843 mkdirSync ( join ( tmpDir , PROJECT_DIR ) , { recursive : true } ) ;
44+ const result = await runCommand ( 'link cloud --instance-id=inst --org-id=o --project-id=p' , { root } ) ;
45+ expect ( result . error ?. message ) . toMatch (
46+ new RegExp ( `No ${ SERVICE_FILENAME } found in "${ PROJECT_DIR } ". Run \`powersync init\` first` )
47+ ) ;
48+ expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
49+ } ) ;
50+
51+ it ( 'errors when service.yaml _type does not match (self-hosted)' , async ( ) => {
52+ const projectDir = join ( tmpDir , PROJECT_DIR ) ;
53+ mkdirSync ( projectDir , { recursive : true } ) ;
54+ writeServiceYaml ( projectDir , 'self-hosted' ) ;
55+ const result = await runCommand ( 'link cloud --instance-id=inst --org-id=o --project-id=p' , { root } ) ;
56+ expect ( result . error ?. message ) . toMatch ( / h a s ` _ t y p e : s e l f - h o s t e d ` b u t y o u a r e r u n n i n g ` l i n k c l o u d ` / ) ;
57+ expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
58+ } ) ;
59+
60+ it ( 'creates link.yaml with cloud config when directory exists and service _type is cloud' , async ( ) => {
61+ const projectDir = join ( tmpDir , PROJECT_DIR ) ;
62+ mkdirSync ( projectDir , { recursive : true } ) ;
63+ writeServiceYaml ( projectDir , 'cloud' ) ;
3964 const { stdout } = await runCommand ( 'link cloud --instance-id=inst-1 --org-id=org-1 --project-id=proj-1' , {
4065 root
4166 } ) ;
@@ -52,6 +77,7 @@ describe('link', () => {
5277 it ( 'updates existing link.yaml and preserves comments' , async ( ) => {
5378 const projectDir = join ( tmpDir , PROJECT_DIR ) ;
5479 mkdirSync ( projectDir , { recursive : true } ) ;
80+ writeServiceYaml ( projectDir , 'cloud' ) ;
5581 const linkPath = join ( projectDir , LINK_FILENAME ) ;
5682 const withComments = `# Managed by PowerSync CLI
5783# Run powersync link --help for info
@@ -72,6 +98,7 @@ type: cloud
7298 it ( 'respects --directory flag' , async ( ) => {
7399 const customDir = 'my-powersync' ;
74100 mkdirSync ( join ( tmpDir , customDir ) , { recursive : true } ) ;
101+ writeServiceYaml ( join ( tmpDir , customDir ) , 'cloud' ) ;
75102 const { stdout } = await runCommand (
76103 `link cloud --directory=${ customDir } --instance-id=i --org-id=o --project-id=p` ,
77104 { root }
@@ -106,8 +133,28 @@ type: cloud
106133 expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
107134 } ) ;
108135
109- it ( 'creates link .yaml with self-hosted config when directory exists ' , async ( ) => {
136+ it ( 'errors when service .yaml is missing ' , async ( ) => {
110137 mkdirSync ( join ( tmpDir , PROJECT_DIR ) , { recursive : true } ) ;
138+ const result = await runCommand ( 'link self-hosted --url=https://x.com --api-key=k' , { root } ) ;
139+ expect ( result . error ?. message ) . toMatch (
140+ new RegExp ( `No ${ SERVICE_FILENAME } found in "${ PROJECT_DIR } ". Run \`powersync init\` first` )
141+ ) ;
142+ expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
143+ } ) ;
144+
145+ it ( 'errors when service.yaml _type does not match (cloud)' , async ( ) => {
146+ const projectDir = join ( tmpDir , PROJECT_DIR ) ;
147+ mkdirSync ( projectDir , { recursive : true } ) ;
148+ writeServiceYaml ( projectDir , 'cloud' ) ;
149+ const result = await runCommand ( 'link self-hosted --url=https://x.com --api-key=k' , { root } ) ;
150+ expect ( result . error ?. message ) . toMatch ( / h a s ` _ t y p e : c l o u d ` b u t y o u a r e r u n n i n g ` l i n k s e l f - h o s t e d ` / ) ;
151+ expect ( result . error ?. oclif ?. exit ) . toBe ( 1 ) ;
152+ } ) ;
153+
154+ it ( 'creates link.yaml with self-hosted config when directory exists and service _type is self-hosted' , async ( ) => {
155+ const projectDir = join ( tmpDir , PROJECT_DIR ) ;
156+ mkdirSync ( projectDir , { recursive : true } ) ;
157+ writeServiceYaml ( projectDir , 'self-hosted' ) ;
111158 const { stdout } = await runCommand ( 'link self-hosted --url=https://sync.example.com --api-key=my-token' , {
112159 root
113160 } ) ;
@@ -123,6 +170,7 @@ type: cloud
123170 it ( 'updates existing link.yaml and preserves comments' , async ( ) => {
124171 const projectDir = join ( tmpDir , PROJECT_DIR ) ;
125172 mkdirSync ( projectDir , { recursive : true } ) ;
173+ writeServiceYaml ( projectDir , 'self-hosted' ) ;
126174 const linkPath = join ( projectDir , LINK_FILENAME ) ;
127175 const withComments = `# Self-hosted config
128176type: self-hosted
@@ -140,6 +188,7 @@ type: self-hosted
140188 it ( 'respects --directory flag' , async ( ) => {
141189 const customDir = 'my-powersync' ;
142190 mkdirSync ( join ( tmpDir , customDir ) , { recursive : true } ) ;
191+ writeServiceYaml ( join ( tmpDir , customDir ) , 'self-hosted' ) ;
143192 const { stdout } = await runCommand (
144193 `link self-hosted --directory=${ customDir } --url=https://example.com --api-key=k` ,
145194 {
0 commit comments