Skip to content

Commit 5b48989

Browse files
edmundmillerclaude
andcommitted
feat: Add extension point interfaces for standalone plugin development
- Add PluginExtensionPoint base interface for all plugin extensions - Add Factory annotation for channel factory extensions - Add Function annotation for custom function extensions - Add Operator annotation for channel operator extensions - Add CommandExtensionPoint interface for first-class CLI commands These interfaces enable standalone plugin development by providing compile-time access to Nextflow extension points without requiring the full Nextflow runtime as a dependency. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent cbb65eb commit 5b48989

File tree

5 files changed

+236
-0
lines changed

5 files changed

+236
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
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+
package io.nextflow.gradle.extensions
18+
19+
import org.pf4j.ExtensionPoint
20+
21+
/**
22+
* Extension point interface for plugins that want to register top-level CLI commands.
23+
*
24+
* Plugins implementing this interface can provide commands that appear as first-class
25+
* citizens in the Nextflow CLI, accessible directly as 'nextflow <command>' rather than
26+
* through the legacy 'nextflow plugin <pluginId>:<command>' syntax.
27+
*
28+
* Example:
29+
* - Instead of: nextflow plugin nf-wave:get-container
30+
* - Enable: nextflow wave get-container
31+
*
32+
* @author Edmund Miller <[email protected]>
33+
*/
34+
interface CommandExtensionPoint extends ExtensionPoint {
35+
36+
/**
37+
* Get the primary command name that this plugin registers.
38+
* This will be the top-level command name (e.g., "wave", "launch").
39+
*
40+
* @return The command name that will be available at the top level
41+
*/
42+
String getCommandName()
43+
44+
/**
45+
* Get the command description for help output.
46+
* This description will appear in the main help listing.
47+
*
48+
* @return A brief description of what this command does
49+
*/
50+
String getCommandDescription()
51+
52+
/**
53+
* Get the priority for this command extension.
54+
* Higher priority commands will take precedence in case of name conflicts.
55+
* Built-in commands have priority 1000 by default.
56+
*
57+
* @return Priority value (higher = higher priority), defaults to 100
58+
*/
59+
default int getPriority() { return 100 }
60+
61+
/**
62+
* Create the actual command instance that will handle execution.
63+
* This method is called when the command needs to be instantiated.
64+
*
65+
* Note: This returns Object to avoid coupling the gradle plugin to Nextflow's CmdBase.
66+
* Implementations should return a nextflow.cli.CmdBase instance.
67+
*
68+
* @return A CmdBase instance that will handle the command execution
69+
*/
70+
Object createCommand()
71+
72+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
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+
18+
package io.nextflow.gradle.extensions
19+
20+
/**
21+
* An annotation interface for channel factories that the plugin want to expose
22+
* Nextflow will search for all methods annotated with @Factory in the ExtensionPoint and allow to the user imported them
23+
*
24+
* @author : jorge <[email protected]>
25+
*
26+
*/
27+
import java.lang.annotation.ElementType
28+
import java.lang.annotation.Retention
29+
import java.lang.annotation.RetentionPolicy
30+
import java.lang.annotation.Target
31+
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Target([ElementType.METHOD])
34+
@interface Factory {
35+
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
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+
18+
package io.nextflow.gradle.extensions
19+
20+
/**
21+
* An annotation interface for functions that the plugin want to expose
22+
* Nextflow will search for all methods annotated with @Functions in the ExtensionPoint and allow to the user imported them
23+
*
24+
* @author : jorge <[email protected]>
25+
*
26+
*/
27+
import java.lang.annotation.ElementType
28+
import java.lang.annotation.Retention
29+
import java.lang.annotation.RetentionPolicy
30+
import java.lang.annotation.Target
31+
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Target([ElementType.METHOD])
34+
@interface Function {
35+
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
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+
18+
package io.nextflow.gradle.extensions
19+
20+
/**
21+
* An annotation interface for operators that the plugin want to expose
22+
* Nextflow will search for all methods annotated with @Operators in the ExtensionPoint and allow to the user imported them
23+
*
24+
* @author : jorge <[email protected]>
25+
*
26+
*/
27+
import java.lang.annotation.ElementType
28+
import java.lang.annotation.Retention
29+
import java.lang.annotation.RetentionPolicy
30+
import java.lang.annotation.Target
31+
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Target([ElementType.METHOD])
34+
@interface Operator {
35+
36+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2013-2024, Seqera Labs
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+
18+
package io.nextflow.gradle.extensions
19+
20+
import groovy.transform.PackageScope
21+
import org.pf4j.ExtensionPoint
22+
23+
/**
24+
* Define plugin extension points. A plugin can provide extension methods
25+
* to add custom channel factories, channel operators and custom function
26+
* in the including context.
27+
*
28+
* The extending subclass should mark the extension methods with the
29+
* corresponding annotation {@link Factory}, {@link Operator} and {@link Function}
30+
*
31+
* Note: This returns Object for session to avoid coupling the gradle plugin
32+
* to Nextflow's internal Session class. Implementations should expect a
33+
* nextflow.Session instance.
34+
*
35+
* @author Paolo Di Tommaso <[email protected]>
36+
*/
37+
abstract class PluginExtensionPoint implements ExtensionPoint {
38+
39+
private boolean initialised
40+
41+
synchronized void checkInit(Object session) {
42+
if( !initialised ) {
43+
init(session)
44+
initialised = true
45+
}
46+
}
47+
48+
/**
49+
* Channel factory initialization. This method is invoked one and only once before
50+
* the before target extension method is called.
51+
*
52+
* @param session The current nextflow Session (passed as Object to avoid coupling)
53+
*/
54+
abstract protected void init(Object session)
55+
56+
}

0 commit comments

Comments
 (0)